diff --git a/.config_files.xml b/.config_files.xml index d1a592e5db..7f0d6bb11a 100644 --- a/.config_files.xml +++ b/.config_files.xml @@ -19,11 +19,8 @@ $SRCROOT $SRCROOT/components/slim/ - $SRCROOT/components/cpl7/components/data_comps_$COMP_INTERFACE/dlnd $SRCROOT/components/cdeps/dlnd - $SRCROOT/components/cpl7/components/stub_comps_$COMP_INTERFACE/slnd $CIMEROOT/CIME/non_py/src/components/stub_comps_$COMP_INTERFACE/slnd - $SRCROOT/components/cpl7/components/xcpl_comps_$COMP_INTERFACE/xlnd $CIMEROOT/CIME/non_py/src/components/xcpl_comps_$COMP_INTERFACE/xlnd case_comps diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index f86a330408..fca4a8315b 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -25,6 +25,8 @@ a9d96219902cf609636886c7073a84407f450d9a d866510188d26d51bcd6d37239283db690af7e82 0dcd0a3c1abcaffe5529f8d79a6bc34734b195c7 e096358c832ab292ddfd22dd5878826c7c788968 +475831f0fb0e31e97f630eac4e078c886558b61c +fd5f177131d63d39e79a13918390bdfb642d781e # Ran SystemTests and python/ctsm through black python formatter 5364ad66eaceb55dde2d3d598fe4ce37ac83a93c 8056ae649c1b37f5e10aaaac79005d6e3a8b2380 @@ -35,6 +37,7 @@ e096358c832ab292ddfd22dd5878826c7c788968 6fccf682eaf718615407d9bacdd3903b8786a03d 2500534eb0a83cc3aff94b30fb62e915054030bf 78d05967c2b027dc9776a884716597db6ef7f57c +47839a77229c61555e3b8932927bb54cdc511b27 a0d014fae9550dd9ffbc934abd29ef16176f8208 c7b7ca1d94ac19abb9ecea9fb5b712ddbdd6645d b565b55ce7a9f8d812a573d716a5fd3d78cfea81 @@ -45,3 +48,7 @@ aa04d1f7d86cc2503b98b7e2b2d84dbfff6c316b 6c6f57e948bfa31e60b383536cc21663fedb8b70 9660667b1267dcd4150889f5f39db540158be74a 665cf86102e09b4c4c5a140700676dca23bc55a9 +1a49e547ba3c48fa483f9ae81a8f05adcd6b888c +045d90f1d80f713eb3ae0ac58f6c2352937f1eb0 +753fda3ff0147837231a73c9c728dd9ce47b5997 +f112ba0bbf96a61d5a4d354dc0dcbd8b0c68145c diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 7c9512c9c3..c4a381383b 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -16,7 +16,7 @@ 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/assign-to-project.yml b/.github/workflows/assign-to-project.yml deleted file mode 100644 index 225c223bde..0000000000 --- a/.github/workflows/assign-to-project.yml +++ /dev/null @@ -1,23 +0,0 @@ -name: Auto Assign to Project(s) - -on: - issues: - types: [opened, labeled] - pull_request: - types: [opened, labeled] - issue_comment: - types: [created] - -jobs: - assign_high_priority: - runs-on: ubuntu-latest - name: Assign to High Priority project - steps: - - name: Assign issues and pull requests with priority-high label to project 25 - uses: srggrs/assign-one-project-github-action@1.3.1 - if: | - contains(github.event.issue.labels.*.name, 'priority: high') || - contains(github.event.pull_request.labels.*.name, 'priority: high') - with: - project: 'https://github.com/ESCOMP/CTSM/projects/25' - column_name: 'Needs triage' diff --git a/.gitignore b/.gitignore index 1da8072fed..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,7 +60,6 @@ buildnmlc td.*.status td.*.log td.*.status.xFail -test_driver_*.sh # mksurfdata output surfdata_*.log @@ -101,9 +85,6 @@ ctsm.input_data_list.previous # mksurfdata unit tests unit_test_build -# Tools executables -/tools/mkprocdata_map/mkprocdata_map - # run_neon output directories /tools/site_and_regional/listing.csv /tools/site_and_regional/????/ diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000000..225f2f75ac --- /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/NGEET/fates +fxtag = sci.1.79.3_api.37.0.0 +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.2 +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/ESMCI/ccs_config_cesm.git +fxtag = ccs_config_cesm1.0.0 +fxrequired = ToplevelRequired +# Standard Fork to compare to with "git fleximod test" to ensure personal forks aren't committed +fxDONOTUSEurl = https://github.com/ESMCI/ccs_config_cesm.git + +[submodule "cime"] +path = cime +url = https://github.com/ESMCI/cime +fxtag = cime6.0.246 +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/ESCOMP/CMEPS.git +fxtag = cmeps0.14.77 +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.48 +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/ESCOMP/CESM_share +fxtag = share1.0.19 +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..6cb8102b94 --- /dev/null +++ b/.lib/git-fleximod/.github/workflows/pytest.yaml @@ -0,0 +1,80 @@ +# 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.12' + + # 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.8.2 + + # 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.8.2 + 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 + - name: Setup tmate session + if: ${{ failure() }} + uses: mxschmitt/action-tmate@v3 + 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/CODE_OF_CONDUCT.md b/.lib/git-fleximod/CODE_OF_CONDUCT.md new file mode 100644 index 0000000000..84f2925bba --- /dev/null +++ b/.lib/git-fleximod/CODE_OF_CONDUCT.md @@ -0,0 +1,107 @@ +# Contributor Code of Conduct +_The Contributor Code of Conduct is for participants in our software projects and community._ + +## Our Pledge +We, as contributors, creators, stewards, and maintainers (participants), of **git-fleximod** pledge to make participation in +our software, system or hardware project and community a safe, productive, welcoming and inclusive experience for everyone. +All participants are required to abide by this Code of Conduct. +This includes respectful treatment of everyone regardless of age, body size, disability, ethnicity, gender identity or expression, +level of experience, nationality, political affiliation, veteran status, pregnancy, genetic information, physical appearance, race, +religion, or sexual orientation, as well as any other characteristic protected under applicable US federal or state law. + +## Our Standards +Examples of behaviors that contribute to a positive environment include: + +* All participants are treated with respect and consideration, valuing a diversity of views and opinions +* Be considerate, respectful, and collaborative +* Communicate openly with respect for others, critiquing ideas rather than individuals and gracefully accepting criticism +* Acknowledging the contributions of others +* Avoid personal attacks directed toward other participants +* Be mindful of your surroundings and of your fellow participants +* Alert UCAR staff and suppliers/vendors if you notice a dangerous situation or someone in distress +* Respect the rules and policies of the project and venue + +Examples of unacceptable behavior include, but are not limited to: + +* Harassment, intimidation, or discrimination in any form +* Physical, verbal, or written abuse by anyone to anyone, including repeated use of pronouns other than those requested +* Unwelcome sexual attention or advances +* Personal attacks directed at other guests, members, participants, etc. +* Publishing others' private information, such as a physical or electronic address, without explicit permission +* Alarming, intimidating, threatening, or hostile comments or conduct +* Inappropriate use of nudity and/or sexual images +* Threatening or stalking anyone, including a participant +* Other conduct which could reasonably be considered inappropriate in a professional setting + +## Scope +This Code of Conduct applies to all spaces managed by the Project whether they be physical, online or face-to-face. +This includes project code, code repository, associated web pages, documentation, mailing lists, project websites and wiki pages, +issue tracker, meetings, telecons, events, project social media accounts, and any other forums created by the project team which the +community uses for communication. +In addition, violations of this Code of Conduct outside these spaces may affect a person's ability to participate within them. +Representation of a project may be further defined and clarified by project maintainers. + +## Community Responsibilities +Everyone in the community is empowered to respond to people who are showing unacceptable behavior. +They can talk to them privately or publicly. +Anyone requested to stop unacceptable behavior is expected to comply immediately. +If the behavior continues concerns may be brought to the project administrators or to any other party listed in the +[Reporting](#reporting) section below. + +## Project Administrator Responsibilities +Project administrators are responsible for clarifying the standards of acceptable behavior and are encouraged to model appropriate +behavior and provide support when people in the community point out inappropriate behavior. +Project administrator(s) are normally the ones that would be tasked to carry out the actions in the [Consequences](#consequences) +section below. + +Project administrators are also expected to keep this Code of Conduct updated with the main one housed at UCAR, as listed below in +the [Attribution](#attribution) section. + +## Reporting +Instances of unacceptable behavior can be brought to the attention of the project administrator(s) who may take any action as +outlined in the [Consequences](#consequences) section below. +However, making a report to a project administrator is not considered an 'official report' to UCAR. + +Instances of unacceptable behavior may also be reported directly to UCAR pursuant to [UCAR's Harassment Reporting and Complaint +Procedure](https://www2.fin.ucar.edu/procedures/hr/harassment-reporting-and-complaint-procedure), or anonymously through [UCAR's +EthicsPoint Hotline](https://www2.fin.ucar.edu/ethics/anonymous-reporting). + +Complaints received by UCAR will be handled pursuant to the procedures outlined in UCAR's Harassment Reporting and Complaint +Procedure. +Complaints to UCAR will be held as confidential as practicable under the circumstances, and retaliation against a person who +initiates a complaint or an inquiry about inappropriate behavior will not be tolerated. + +Any Contributor can use these reporting methods even if they are not directly affiliated with UCAR. +The Frequently Asked Questions (FAQ) page for reporting is [here](https://www2.fin.ucar.edu/procedures/hr/reporting-faqs). + +## Consequences +Upon receipt of a complaint, the project administrator(s) may take any action deemed necessary and appropriate under the +circumstances. +Such action can include things such as: removing, editing, or rejecting comments, commits, code, wiki edits, email, issues, and +other contributions that are not aligned to this Code of Conduct, or banning temporarily or permanently any contributor for other +behaviors that are deemed inappropriate, threatening, offensive, or harmful. +Project administrators also have the right to report violations to UCAR HR and/or UCAR's Office of Diversity, Equity and Inclusion +(ODEI), as well as a participant's home institution and/or law enforcement. +In the event an incident is reported to UCAR, UCAR will follow its Harassment Reporting and Complaint Procedure. + +## Process for Changes +All UCAR managed projects are required to adopt this Contributor Code of Conduct. +Adoption is assumed even if not expressly stated in the repository. +Projects should fill in sections where prompted with project-specific information, including, project name and adoption date. + +Projects that adopt this Code of Conduct need to stay up to date with UCAR's Contributor Code of Conduct, linked with a DOI in the +[Attribution](#attribution) section below. +Projects can make limited substantive changes to the Code of Conduct, however, the changes must be limited in scope and may not +contradict the UCAR Contributor Code of Conduct. + +## Attribution +This Code of Conduct was originally adapted from the [Contributor Covenant](http://contributor-covenant.org/version/1/4), version +1.4. +We then aligned it with the UCAR Participant Code of Conduct, which also borrows from the American Geophysical Union (AGU) Code of +Conduct. +The UCAR Participant Code of Conduct applies to both UCAR employees as well as participants in activities run by UCAR. +The original version of this for all software projects that have strong management from UCAR or UCAR staff is available on the UCAR +website at https://doi.org/10.5065/6w2c-a132. +The date that it was adopted by this project was **Feb/13/2018**. +When responding to complaints, UCAR HR and ODEI will do so based on the latest published version. +Therefore, any project-specific changes should follow the [Process for Changes](#process-for-changes) section above. 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/manage_externals/test/doc/Makefile b/.lib/git-fleximod/doc/Makefile similarity index 75% rename from manage_externals/test/doc/Makefile rename to .lib/git-fleximod/doc/Makefile index 18f4d5bf99..d4bb2cbb9e 100644 --- a/manage_externals/test/doc/Makefile +++ b/.lib/git-fleximod/doc/Makefile @@ -1,10 +1,10 @@ # Minimal makefile for Sphinx documentation # -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -SPHINXPROJ = ManageExternals +# 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 @@ -17,4 +17,4 @@ help: # 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 + @$(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/manage_externals/test/repos/simple-ext.svn/db/rep-cache.db-journal b/.lib/git-fleximod/git_fleximod/__init__.py similarity index 100% rename from manage_externals/test/repos/simple-ext.svn/db/rep-cache.db-journal 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..ac9493cfc3 --- /dev/null +++ b/.lib/git-fleximod/git_fleximod/cli.py @@ -0,0 +1,133 @@ +from pathlib import Path +import argparse +from git_fleximod import utils + +__version__ = "0.9.3" + +def find_root_dir(filename=".gitmodules"): + """ finds the highest directory in tree + which contains a file called filename """ + try: + root = utils.execute_subprocess(["git","rev-parse", "--show-toplevel"], + output_to_caller=True ).rstrip() + except: + 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 + return Path(root) + +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..13f35df959 --- /dev/null +++ b/.lib/git-fleximod/git_fleximod/git_fleximod.py @@ -0,0 +1,365 @@ +#!/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 git_fleximod.submodule import Submodule + +# logger variable is global +logger = None + + +def fxrequired_allowed_values(): + return ["ToplevelRequired", "ToplevelOptional", "AlwaysRequired", "AlwaysOptional", "TopLevelRequired", "TopLevelOptional"] + + +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 = fxrequired_allowed_values() + else: + fxrequired = ["ToplevelRequired", "AlwaysRequired", "TopLevelRequired"] + + 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 = git_toplevelroot(root_dir, logger) + + 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)) + _, remotelist = sprepo_git.git_operation("remote", "-v") + if url not in remotelist: + 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): + if os.path.isdir(os.path.join(topgit,".git")): + shutil.rmtree(os.path.join(topgit,".git")) + 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): + if os.path.isfile(sparsefile): + 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 init_submodule_from_gitmodules(gitmodules, name, root_dir, logger): + path = gitmodules.get(name, "path") + url = gitmodules.get(name, "url") + assert path and url, f"Malformed .gitmodules file {path} {url}" + tag = gitmodules.get(name, "fxtag") + fxurl = gitmodules.get(name, "fxDONOTUSEurl") + fxsparse = gitmodules.get(name, "fxsparse") + fxrequired = gitmodules.get(name, "fxrequired") + return Submodule(root_dir, name, path, url, fxtag=tag, fxurl=fxurl, fxsparse=fxsparse, fxrequired=fxrequired, logger=logger) + +def submodules_status(gitmodules, root_dir, toplevel=False, depth=0): + testfails = 0 + localmods = 0 + needsupdate = 0 + wrapper = textwrap.TextWrapper(initial_indent=' '*(depth*10), width=120,subsequent_indent=' '*(depth*20)) + for name in gitmodules.sections(): + submod = init_submodule_from_gitmodules(gitmodules, name, root_dir, logger) + + result,n,l,t = submod.status() + if toplevel or not submod.toplevel(): + print(wrapper.fill(result)) + testfails += t + localmods += l + needsupdate += n + subdir = os.path.join(root_dir, submod.path) + if os.path.exists(os.path.join(subdir, ".gitmodules")): + gsubmod = GitModules(logger, confpath=subdir) + t,l,n = submodules_status(gsubmod, subdir, depth=depth+1) + if toplevel or not submod.toplevel(): + testfails += t + localmods += l + needsupdate += n + + return testfails, localmods, needsupdate + +def git_toplevelroot(root_dir, logger): + rgit = GitInterface(root_dir, logger) + _, superroot = rgit.git_operation("rev-parse", "--show-superproject-working-tree") + return superroot + +def submodules_update(gitmodules, root_dir, requiredlist, force): + for name in gitmodules.sections(): + submod = init_submodule_from_gitmodules(gitmodules, name, root_dir, logger) + + _, needsupdate, localmods, testfails = submod.status() + if not submod.fxrequired: + submod.fxrequired = "AlwaysRequired" + fxrequired = submod.fxrequired + allowedvalues = fxrequired_allowed_values() + assert fxrequired in allowedvalues + + superroot = git_toplevelroot(root_dir, logger) + + if ( + fxrequired + and ((superroot and "Toplevel" in fxrequired) + or fxrequired not in requiredlist) + ): + if "Optional" in fxrequired and "Optional" not in requiredlist: + if fxrequired.startswith("Always"): + print(f"Skipping optional component {name:>20}") + continue + optional = "AlwaysOptional" in requiredlist + + if fxrequired in requiredlist: + submod.update() + repodir = os.path.join(root_dir, submod.path) + if os.path.exists(os.path.join(repodir, ".gitmodules")): + # recursively handle this checkout + print(f"Recursively checking out submodules of {name}") + gitsubmodules = GitModules(submod.logger, confpath=repodir) + newrequiredlist = ["AlwaysRequired"] + if optional: + newrequiredlist.append("AlwaysOptional") + + submodules_update(gitsubmodules, repodir, newrequiredlist, force=force) + +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) + +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, "fxDONOTUSEurl") + 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(f"No submodule components found, root_dir={root_dir}") + 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..fb20883cd0 --- /dev/null +++ b/.lib/git-fleximod/git_fleximod/gitinterface.py @@ -0,0 +1,92 @@ +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): + newargs = [] + for a in args: + # Do not use ssh interface + if isinstance(a, str): + a = a.replace("git@github.com:", "https://github.com/") + newargs.append(a) + + command = self._git_command(operation, *newargs) + if isinstance(command, list): + try: + status, output = utils.execute_subprocess(command, status_to_caller=True, output_to_caller=True) + return status, output.rstrip() + except Exception as e: + sys.exit(e) + else: + return 0, command + + def config_get_value(self, section, name): + if self._use_module: + config = self.repo.config_reader() + try: + val = config.get_value(section, name) + except: + val = None + return val + 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: + if "." in section: + section = section.replace("."," \"")+'"' + 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..cf8b350dd6 --- /dev/null +++ b/.lib/git-fleximod/git_fleximod/gitmodules.py @@ -0,0 +1,97 @@ +import shutil, os +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/submodule.py b/.lib/git-fleximod/git_fleximod/submodule.py new file mode 100644 index 0000000000..75d9dd4eb9 --- /dev/null +++ b/.lib/git-fleximod/git_fleximod/submodule.py @@ -0,0 +1,427 @@ +import os +import textwrap +import shutil +import string +from configparser import NoOptionError +from git_fleximod import utils +from git_fleximod.gitinterface import GitInterface + +class Submodule(): + """ + Represents a Git submodule with enhanced features for flexible management. + + Attributes: + name (str): The name of the submodule. + root_dir (str): The root directory of the main project. + path (str): The relative path from the root directory to the submodule. + url (str): The URL of the submodule repository. + fxurl (str): The URL for flexible submodule management (optional). + fxtag (str): The tag for flexible submodule management (optional). + fxsparse (str): Path to the sparse checkout file relative to the submodule path, see git-sparse-checkout for details (optional). + fxrequired (str): Indicates if the submodule is optional or required (optional). + logger (logging.Logger): Logger instance for logging (optional). + """ + def __init__(self, root_dir, name, path, url, fxtag=None, fxurl=None, fxsparse=None, fxrequired=None, logger=None): + """ + Initializes a new Submodule instance with the provided attributes. + """ + self.name = name + self.root_dir = root_dir + self.path = path + self.url = url + self.fxurl = fxurl + self.fxtag = fxtag + self.fxsparse = fxsparse + if fxrequired: + self.fxrequired = fxrequired + else: + self.fxrequired = "AlwaysRequired" + self.logger = logger + + def status(self): + """ + Checks the status of the submodule and returns 4 parameters: + - result (str): The status of the submodule. + - needsupdate (bool): An indicator if the submodule needs to be updated. + - localmods (bool): An indicator if the submodule has local modifications. + - testfails (bool): An indicator if the submodule has failed a test, this is used for testing purposes. + """ + + smpath = os.path.join(self.root_dir, self.path) + testfails = False + localmods = False + needsupdate = False + ahash = None + optional = "" + if "Optional" in self.fxrequired: + optional = " (optional)" + required = None + level = None + if not os.path.exists(os.path.join(smpath, ".git")): + rootgit = GitInterface(self.root_dir, self.logger) + # submodule commands use path, not name + status, tags = rootgit.git_operation("ls-remote", "--tags", self.url) + status, result = rootgit.git_operation("submodule","status",smpath) + result = result.split() + + if result: + ahash = result[0][1:] + hhash = None + atag = None + 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 self.fxtag and not hhash and htag.endswith(self.fxtag): + hhash = htag.split()[0] + if hhash and atag: + break + if self.fxtag and (ahash == hhash or atag == self.fxtag): + result = f"e {self.name:>20} not checked out, aligned at tag {self.fxtag}{optional}" + needsupdate = True + elif self.fxtag: + status, ahash = rootgit.git_operation( + "submodule", "status", "{}".format(self.path) + ) + ahash = ahash[1 : len(self.fxtag) + 1] + if self.fxtag == ahash: + result = f"e {self.name:>20} not checked out, aligned at hash {ahash}{optional}" + else: + result = f"e {self.name:>20} not checked out, out of sync at tag {atag}, expected tag is {self.fxtag}{optional}" + testfails = True + needsupdate = True + else: + result = f"e {self.name:>20} has no fxtag defined in .gitmodules{optional}" + testfails = False + else: + with utils.pushd(smpath): + git = GitInterface(smpath, self.logger) + status, remote = git.git_operation("remote") + if remote == '': + result = f"e {self.name:>20} has no associated remote" + testfails = True + needsupdate = True + return result, needsupdate, localmods, testfails + status, rurl = git.git_operation("ls-remote","--get-url") + status, lines = git.git_operation("log", "--pretty=format:\"%h %d\"") + line = lines.partition('\n')[0] + parts = line.split() + ahash = parts[0][1:] + atag = None + if len(parts) > 3: + idx = 0 + while idx < len(parts)-1: + idx = idx+1 + if parts[idx] == 'tag:': + atag = parts[idx+1] + while atag.endswith(')') or atag.endswith(',') or atag.endswith("\""): + atag = atag[:-1] + if atag == self.fxtag: + break + + + #print(f"line is {line} ahash is {ahash} atag is {atag} {parts}") + # atag = git.git_operation("describe", "--tags", "--always") + # ahash = git.git_operation("rev-list", "HEAD").partition("\n")[0] + + recurse = False + if rurl != self.url: + remote = self._add_remote(git) + git.git_operation("fetch", remote) + if self.fxtag and atag == self.fxtag: + result = f" {self.name:>20} at tag {self.fxtag}" + recurse = True + testfails = False + elif self.fxtag and (ahash[: len(self.fxtag)] == self.fxtag or (self.fxtag.find(ahash)==0)): + result = f" {self.name:>20} at hash {ahash}" + recurse = True + testfails = False + elif atag == ahash: + result = f" {self.name:>20} at hash {ahash}" + recurse = True + elif self.fxtag: + result = f"s {self.name:>20} {atag} {ahash} is out of sync with .gitmodules {self.fxtag}" + testfails = True + needsupdate = True + else: + if atag: + result = f"e {self.name:>20} has no fxtag defined in .gitmodules, module at {atag}" + else: + result = f"e {self.name:>20} has no fxtag defined in .gitmodules, module at {ahash}" + testfails = False + + status, output = git.git_operation("status", "--ignore-submodules", "-uno") + if "nothing to commit" not in output: + localmods = True + result = "M" + textwrap.indent(output, " ") +# print(f"result {result} needsupdate {needsupdate} localmods {localmods} testfails {testfails}") + return result, needsupdate, localmods, testfails + + + def _add_remote(self, git): + """ + Adds a new remote to the submodule if it does not already exist. + + This method checks the existing remotes of the submodule. If the submodule's URL is not already listed as a remote, + it attempts to add a new remote. The name for the new remote is generated dynamically to avoid conflicts. If no + remotes exist, it defaults to naming the new remote 'origin'. + + Args: + git (GitInterface): An instance of GitInterface to perform git operations. + + Returns: + str: The name of the new remote if added, or the name of the existing remote that matches the submodule's URL. + """ + status, remotes = git.git_operation("remote", "-v") + remotes = remotes.splitlines() + upstream = None + if remotes: + status, upstream = git.git_operation("ls-remote", "--get-url") + newremote = "newremote.00" + tmpurl = self.url.replace("git@github.com:", "https://github.com/") + line = next((s for s in remotes if self.url in s or tmpurl in s), None) + if line: + newremote = line.split()[0] + return newremote + else: + i = 0 + while newremote in remotes: + i = i + 1 + newremote = f"newremote.{i:02d}" + else: + newremote = "origin" + git.git_operation("remote", "add", newremote, self.url) + return newremote + + def toplevel(self): + """ + Returns True if the submodule is Toplevel (either Required or Optional) + """ + return True if "Top" in self.fxrequired else False + + def sparse_checkout(self): + """ + Performs a sparse checkout of the submodule. + + This method optimizes the checkout process by only checking out files specified in the submodule's sparse-checkout configuration, + rather than the entire submodule content. It achieves this by first ensuring the `.git/info/sparse-checkout` file is created and + configured in the submodule's directory. Then, it proceeds to checkout the desired tag. If the submodule has already been checked out, + this method will not perform the checkout again. + + This approach is particularly beneficial for submodules with a large number of files, as it significantly reduces the time and disk space + required for the checkout process by avoiding the unnecessary checkout and subsequent removal of unneeded files. + + Returns: + None + """ + self.logger.info("Called sparse_checkout for {}".format(self.name)) + rgit = GitInterface(self.root_dir, self.logger) + status, superroot = rgit.git_operation("rev-parse", "--show-superproject-working-tree") + if superroot: + gitroot = superroot.strip() + else: + gitroot = self.root_dir + # Now need to move the .git dir to the submodule location + rootdotgit = os.path.join(self.root_dir, ".git") + while os.path.isfile(rootdotgit): + with open(rootdotgit) as f: + line = f.readline().rstrip() + if line.startswith("gitdir: "): + rootdotgit = os.path.abspath(os.path.join(self.root_dir,line[8:])) + assert os.path.isdir(rootdotgit) + # first create the module directory + if not os.path.isdir(os.path.join(self.root_dir, self.path)): + os.makedirs(os.path.join(self.root_dir, self.path)) + + # initialize a new git repo and set the sparse checkout flag + sprep_repo = os.path.join(self.root_dir, self.path) + sprepo_git = GitInterface(sprep_repo, self.logger) + if os.path.exists(os.path.join(sprep_repo, ".git")): + try: + self.logger.info("Submodule {} found".format(self.name)) + chk = sprepo_git.config_get_value("core", "sparseCheckout") + if chk == "true": + self.logger.info("Sparse submodule {} already checked out".format(self.name)) + return + except (NoOptionError): + self.logger.debug("Sparse submodule {} not present".format(self.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 + + self.logger.info("Setting remote origin in {}/{}".format(self.root_dir, self.path)) + status, remotes = sprepo_git.git_operation("remote", "-v") + if self.url not in remotes: + sprepo_git.git_operation("remote", "add", "origin", self.url) + + topgit = os.path.join(gitroot, ".git") + + if gitroot != self.root_dir and os.path.isfile(os.path.join(self.root_dir, ".git")): + with open(os.path.join(self.root_dir, ".git")) as f: + gitpath = os.path.relpath( + os.path.join(self.root_dir, f.read().split()[1]), + start=os.path.join(self.root_dir, self.path), + ) + rootdotgit = os.path.join(gitpath, "modules", self.name) + else: + rootdotgit = os.path.relpath( + os.path.join(self.root_dir, ".git", "modules", self.name), + start=os.path.join(self.root_dir, self.path), + ) + + if os.path.isdir(os.path.join(self.root_dir, self.path, ".git")): + with utils.pushd(sprep_repo): + if os.path.isdir(os.path.join(rootdotgit,".git")): + shutil.rmtree(os.path.join(rootdotgit,".git")) + shutil.move(".git", rootdotgit) + with open(".git", "w") as f: + f.write("gitdir: " + os.path.relpath(rootdotgit)) + infodir = os.path.join(rootdotgit, "info") + if not os.path.isdir(infodir): + os.makedirs(infodir) + gitsparse = os.path.abspath(os.path.join(infodir, "sparse-checkout")) + if os.path.isfile(gitsparse): + self.logger.warning( + "submodule {} is already initialized {}".format(self.name, rootdotgit) + ) + return + + with utils.pushd(sprep_repo): + if os.path.isfile(self.fxsparse): + + shutil.copy(self.fxsparse, gitsparse) + + + # Finally checkout the repo + sprepo_git.git_operation("fetch", "origin", "--tags") + status,_ = sprepo_git.git_operation("checkout", self.fxtag) + if status: + print(f"Error checking out {self.name:>20} at {self.fxtag}") + else: + print(f"Successfully checked out {self.name:>20} at {self.fxtag}") + rgit.config_set_value('submodule.' + self.name, "active", "true") + rgit.config_set_value('submodule.' + self.name, "url", self.url) + rgit.config_set_value('submodule.' + self.name, "path", self.path) + + def update(self): + """ + Updates the submodule to the latest or specified version. + + This method handles the update process of the submodule, including checking out the submodule into the specified path, + handling sparse checkouts if configured, and updating the submodule's URL if necessary. It supports both SSH and HTTPS URLs, + automatically converting SSH URLs to HTTPS to avoid issues for users without SSH keys. + + The update process involves the following steps: + 1. If the submodule is configured for sparse checkout, it performs a sparse checkout. + 2. If the submodule is not already checked out, it clones the submodule using the provided URL. + 3. If a specific tag or hash is provided, it checks out that tag; otherwise, it checks out the latest version. + 4. If the root `.git` is a file (indicating a submodule or a worktree), additional steps are taken to integrate the submodule properly. + + Args: + None + Note: + - SSH URLs are automatically converted to HTTPS to accommodate users without SSH keys. + + Returns: + None + """ + git = GitInterface(self.root_dir, self.logger) + repodir = os.path.join(self.root_dir, self.path) + self.logger.info("Checkout {} into {}/{}".format(self.name, self.root_dir, self.path)) + # if url is provided update to the new url + tag = None + repo_exists = False + if os.path.exists(os.path.join(repodir, ".git")): + self.logger.info("Submodule {} already checked out".format(self.name)) + repo_exists = True + # Look for a .gitmodules file in the newly checkedout repo + if self.fxsparse: + print(f"Sparse checkout {self.name} fxsparse {self.fxsparse}") + self.sparse_checkout() + else: + if not repo_exists and self.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 self.url.startswith("git@"): + git.git_operation("clone", self.url, self.path) + smgit = GitInterface(repodir, self.logger) + if not tag: + status, tag = smgit.git_operation("describe", "--tags", "--always") + smgit.git_operation("checkout", tag) + # Now need to move the .git dir to the submodule location + rootdotgit = os.path.join(self.root_dir, ".git") + if os.path.isfile(rootdotgit): + with open(rootdotgit) as f: + line = f.readline() + if line.startswith("gitdir: "): + rootdotgit = line[8:] + + newpath = os.path.abspath(os.path.join(self.root_dir, rootdotgit, "modules", self.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", self.name, "--", self.url, self.path) + + if not repo_exists: + git.git_operation("submodule", "update", "--init", "--", self.path) + + if self.fxtag: + smgit = GitInterface(repodir, self.logger) + newremote = self._add_remote(smgit) + # Trying to distingush a tag from a hash + allowed = set(string.digits + 'abcdef') + if not set(self.fxtag) <= allowed: + # This is a tag + tag = f"refs/tags/{self.fxtag}:refs/tags/{self.fxtag}" + smgit.git_operation("fetch", newremote, tag) + smgit.git_operation("checkout", self.fxtag) + + if not os.path.exists(os.path.join(repodir, ".git")): + utils.fatal_error( + f"Failed to checkout {self.name} {repo_exists} {repodir} {self.path}" + ) + + + if os.path.exists(os.path.join(self.path, ".git")): + submoddir = os.path.join(self.root_dir, self.path) + with utils.pushd(submoddir): + git = GitInterface(submoddir, self.logger) + # first make sure the url is correct + newremote = self._add_remote(git) + status, tags = git.git_operation("tag", "-l") + fxtag = self.fxtag + if fxtag and fxtag not in tags: + git.git_operation("fetch", newremote, "--tags") + status, atag = git.git_operation("describe", "--tags", "--always") + if fxtag and fxtag != atag: + try: + status, _ = git.git_operation("checkout", fxtag) + if not status: + print(f"{self.name:>20} updated to {fxtag}") + except Exception as error: + print(error) + + + elif not fxtag: + print(f"No fxtag found for submodule {self.name:>20}") + else: + print(f"{self.name:>20} up to date.") + + + + return diff --git a/manage_externals/manic/utils.py b/.lib/git-fleximod/git_fleximod/utils.py similarity index 64% rename from manage_externals/manic/utils.py rename to .lib/git-fleximod/git_fleximod/utils.py index 9c63ffe65e..c4f43d5238 100644 --- a/manage_externals/manic/utils.py +++ b/.lib/git-fleximod/git_fleximod/utils.py @@ -4,23 +4,31 @@ """ -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 pathlib import Path -from .global_constants import LOCAL_PATH_INDICATOR - +LOCAL_PATH_INDICATOR = "." # --------------------------------------------------------------------- # -# screen and logging output and functions to massage text for output +# 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): @@ -30,7 +38,7 @@ def log_process_output(output): line. This makes it hard to filter with grep. """ - output = output.split('\n') + output = output.split("\n") for line in output: logging.debug(line) @@ -48,6 +56,18 @@ def printlog(msg, **kwargs): 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 @@ -68,9 +88,9 @@ def last_n_lines(the_string, n_lines, truncation_message=None): return_val = the_string else: lines_subset = lines[-n_lines:] - str_truncated = ''.join(lines_subset) + str_truncated = "".join(lines_subset) if truncation_message: - str_truncated = truncation_message + '\n' + str_truncated + str_truncated = truncation_message + "\n" + str_truncated return_val = str_truncated return return_val @@ -90,9 +110,10 @@ def indent_string(the_string, indent_level): """ lines = the_string.splitlines(True) - padding = ' ' * indent_level + padding = " " * indent_level lines_indented = [padding + line for line in lines] - return ''.join(lines_indented) + return "".join(lines_indented) + # --------------------------------------------------------------------- # @@ -121,24 +142,26 @@ def str_to_bool(bool_str): """ value = None str_lower = bool_str.lower() - if str_lower in ('true', 't'): + if str_lower in ("true", "t"): value = True - elif str_lower in ('false', 'f'): + 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)) + 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@'] +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. If so, it must be expanded to an absolute + path. """ remote_url = False @@ -150,7 +173,7 @@ def is_remote_url(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. If remote, try to strip off protocol info. """ remote_url = is_remote_url(url) @@ -158,13 +181,13 @@ def split_remote_url(url): return url for prefix in REMOTE_PREFIXES: - url = url.replace(prefix, '') + url = url.replace(prefix, "") - if '@' in url: - url = url.split('@')[1] + if "@" in url: + url = url.split("@")[1] - if ':' in url: - url = url.split(':')[1] + if ":" in url: + url = url.split(":")[1] return url @@ -186,10 +209,12 @@ def expand_local_url(url, field): 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)) + 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) @@ -208,27 +233,30 @@ def expand_local_url(url, field): def _hanging_msg(working_directory, command): - print(""" + 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): +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. @@ -242,32 +270,35 @@ def execute_subprocess(commands, status_to_caller=False, """ cwd = os.getcwd() - msg = 'In directory: {0}\nexecute_subprocess running command:'.format(cwd) + msg = "In directory: {0}\nexecute_subprocess running command:".format(cwd) logging.info(msg) - commands_str = ' '.join(commands) + 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}) + 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) + 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) + "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) + "DEV_ERROR: Invalid arguments trying to run subprocess", commands + ) logging.error(error) fatal_error(msg) except subprocess.CalledProcessError as error: @@ -276,11 +307,12 @@ def execute_subprocess(commands, status_to_caller=False, # simple status check. If returning, it is the callers # responsibility determine if an error occurred and handle it # appropriately. + msg_context = ( + "Process did not run successfully; " + "returned status {0}".format(error.returncode) + ) + msg = failed_command_msg(msg_context, commands, output=error.output) 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) @@ -309,22 +341,25 @@ def failed_command_msg(msg_context, command, output=None): """ 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: ') + 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 = '' + errmsg = "" - command_str = ' '.join(command) + command_str = " ".join(command) errmsg += """In directory {cwd} {context}: {command} -""".format(cwd=os.getcwd(), context=msg_context, command=command_str) +""".format( + cwd=os.getcwd(), context=msg_context, command=command_str + ) if output: - errmsg += 'See above for output from failed command.\n' + 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..ac82fb0d97 --- /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.15.0" +description = "Internationalization utilities" +optional = false +python-versions = ">=3.8" +files = [ + {file = "Babel-2.15.0-py3-none-any.whl", hash = "sha256:08706bdad8d0a3413266ab61bd6c34d0c28d6e1e7badf40a2cebe67644e2e1fb"}, + {file = "babel-2.15.0.tar.gz", hash = "sha256:8daf0e265d05768bc6c7a314cf1321e9a123afc328cc635c18622a2f30a04413"}, +] + +[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.8.30" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2024.8.30-py3-none-any.whl", hash = "sha256:922820b53db7a7257ffbda3f597266d435245903d80737e34f8a45ff3e3230d8"}, + {file = "certifi-2024.8.30.tar.gz", hash = "sha256:bec941d2aa8195e248a60b31ff9f0558284cf01a52591ceda73ea9afffd69fd9"}, +] + +[[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.1" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.2.1-py3-none-any.whl", hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"}, + {file = "exceptiongroup-1.2.1.tar.gz", hash = "sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16"}, +] + +[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.43" +description = "GitPython is a Python library used to interact with Git repositories" +optional = false +python-versions = ">=3.7" +files = [ + {file = "GitPython-3.1.43-py3-none-any.whl", hash = "sha256:eec7ec56b92aad751f9912a73404bc02ba212a23adb2c7098ee668417051a1ff"}, + {file = "GitPython-3.1.43.tar.gz", hash = "sha256:35f314a9f878467f5453cc1fee295c3e18e52f1b99f10f6cf5b1682e968a9e7c"}, +] + +[package.dependencies] +gitdb = ">=4.0.1,<5" + +[package.extras] +doc = ["sphinx (==4.3.2)", "sphinx-autodoc-typehints", "sphinx-rtd-theme", "sphinxcontrib-applehelp (>=1.0.2,<=1.0.4)", "sphinxcontrib-devhelp (==1.0.2)", "sphinxcontrib-htmlhelp (>=2.0.0,<=2.0.1)", "sphinxcontrib-qthelp (==1.0.3)", "sphinxcontrib-serializinghtml (==1.1.5)"] +test = ["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", "typing-extensions"] + +[[package]] +name = "idna" +version = "3.7" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.7-py3-none-any.whl", hash = "sha256:82fee1fc78add43492d3a1898bfa6d8a904cc97d8427f683ed8e798d07761aa0"}, + {file = "idna-3.7.tar.gz", hash = "sha256:028ff3aadf0609c1fd278d8ea3089299412a7a8b9bd005dd08b9f8285bcb5cfc"}, +] + +[[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 = "8.0.0" +description = "Read metadata from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_metadata-8.0.0-py3-none-any.whl", hash = "sha256:15584cf2b1bf449d98ff8a6ff1abef57bf20f3ac6454f431736cd3e660921b2f"}, + {file = "importlib_metadata-8.0.0.tar.gz", hash = "sha256:188bd24e4c346d3f0a933f275c2fec67050326a856b9a359881d7c2a697e8812"}, +] + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +perf = ["ipython"] +test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"] + +[[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.4" +description = "A very fast and expressive template engine." +optional = false +python-versions = ">=3.7" +files = [ + {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"}, + {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"}, +] + +[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 = "24.1" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, + {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, +] + +[[package]] +name = "pluggy" +version = "1.5.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669"}, + {file = "pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["pytest", "pytest-benchmark"] + +[[package]] +name = "pyfakefs" +version = "5.5.0" +description = "pyfakefs implements a fake file system that mocks the Python file system modules." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pyfakefs-5.5.0-py3-none-any.whl", hash = "sha256:8dbf203ab7bef1529f11f7d41b9478b898e95bf9f3b71262163aac07a518cd76"}, + {file = "pyfakefs-5.5.0.tar.gz", hash = "sha256:7448aaa07142f892d0a4eb52a5ed3206a9f02c6599e686cd97d624c18979c154"}, +] + +[[package]] +name = "pygments" +version = "2.18.0" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.8" +files = [ + {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, + {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, +] + +[package.extras] +windows-terminal = ["colorama (>=0.4.6)"] + +[[package]] +name = "pytest" +version = "8.2.2" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pytest-8.2.2-py3-none-any.whl", hash = "sha256:c434598117762e2bd304e526244f67bf66bbd7b5d6cf22138be51ff661980343"}, + {file = "pytest-8.2.2.tar.gz", hash = "sha256:de4bb8104e201939ccdc688b27a89a7be2079b22e2bd2b07f806b6ba71117977"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} +iniconfig = "*" +packaging = "*" +pluggy = ">=1.5,<2.0" +tomli = {version = ">=1", markers = "python_version < \"3.11\""} + +[package.extras] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "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.32.3" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.8" +files = [ + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, +] + +[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.2" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.8" +files = [ + {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"}, + {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"}, +] + +[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.19.2" +description = "Backport of pathlib-compatible object wrapper for zip files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "zipp-3.19.2-py3-none-any.whl", hash = "sha256:f091755f667055f2d02b32c53771a7a6c8b47e1fdbc4b72a8b9072b3eef8015c"}, + {file = "zipp-3.19.2.tar.gz", hash = "sha256:bf1dcf6450f873a13e952a29504887c89e6de7506209e5b1bcc3460135d4de19"}, +] + +[package.extras] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] + +[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..1d0419ad20 --- /dev/null +++ b/.lib/git-fleximod/pyproject.toml @@ -0,0 +1,41 @@ +[tool.poetry] +name = "git-fleximod" +version = "0.9.3" +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..b432206a54 --- /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.9.3" + +# 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..1dd1b86f34 --- /dev/null +++ b/.lib/git-fleximod/tests/conftest.py @@ -0,0 +1,150 @@ +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 MPIserial_2.5.1, 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 MPIserial_2.5.1, 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") + gitp.git_operation("checkout", "v0.0.1") + return test_dir + +@pytest.fixture +def complex_update(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") + gitp.git_operation("checkout", "v0.0.2") + + 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/.lib/git-fleximod/tests/test_e_complex_update.py b/.lib/git-fleximod/tests/test_e_complex_update.py new file mode 100644 index 0000000000..0c3ab4c6a6 --- /dev/null +++ b/.lib/git-fleximod/tests/test_e_complex_update.py @@ -0,0 +1,69 @@ +import pytest +from pathlib import Path +from git_fleximod.gitinterface import GitInterface + +def test_complex_update(git_fleximod, complex_update, logger): + status = git_fleximod(complex_update, "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, out of sync at tag testtag02, expected tag is testtag3" 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_update, "update") + assert result.returncode == 0 + + status = git_fleximod(complex_update, "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 testtag3" in status.stdout) + + # now check the complex_sub + root = (complex_update / "modules" / "complex") + assert(not (root / "libraries" / "gptl" / ".git").exists()) + assert(not (root / "libraries" / "mpi-serial" / ".git").exists()) + assert((root / "modules" / "mpi-serialAR" / ".git").exists()) + assert((root / "modules" / "mpi-serialSAR" / ".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_update, "update ToplevelOptional") + assert result.returncode == 0 + + status = git_fleximod(complex_update, "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 testtag3" 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_update, "update --optional") + assert result.returncode == 0 + + status = git_fleximod(complex_update, "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 testtag3" in status.stdout) + assert("AlwaysOptional at tag MPIserial_2.3.0" in status.stdout) + + # now check the complex_sub + root = (complex_update / "modules" / "complex" ) + assert(not (root / "libraries" / "gptl" / ".git").exists()) + assert(not (root / "libraries" / "mpi-serial" / ".git").exists()) + assert(not (root / "modules" / "mpi-serial" / ".git").exists()) + assert((root / "modules" / "mpi-serialAR" / ".git").exists()) + assert((root / "modules" / "mpi-serialSAR" / ".git").exists()) + assert((root / "modules" / "mpi-sparse" / ".git").exists()) + assert((root / "modules" / "mpi-serial2" / ".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 185f412cab..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_99 -externals = Externals_CISM.cfg -required = True - -[rtm] -local_path = components/rtm -protocol = git -repo_url = https://github.com/ESCOMP/RTM -tag = rtm1_0_79 -required = True - -[mosart] -local_path = components/mosart -protocol = git -repo_url = https://github.com/ESCOMP/MOSART -tag = mosart1_0_49 -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.92 -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.217_httpsbranch03 -required = True - -[cmeps] -tag = cmeps0.14.50 -protocol = git -repo_url = https://github.com/ESCOMP/CMEPS.git -local_path = components/cmeps -required = True - -[cdeps] -tag = cdeps1.0.28 -protocol = git -repo_url = https://github.com/ESCOMP/CDEPS.git -local_path = components/cdeps -externals = Externals_CDEPS.cfg -required = True - -[cpl7] -tag = cpl77.0.7 -protocol = git -repo_url = https://github.com/ESCOMP/CESM_CPL7andDataComps -local_path = components/cpl7 -required = True - -[share] -tag = share1.0.18 -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_6_2 -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 866b9ac5b2..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.73.0_api.35.0.0 -required = True - -[externals_description] -schema_version = 1.0.0 diff --git a/README b/README index 18cc2b1458..c5c06daae7 100644 --- a/README +++ b/README @@ -1,6 +1,6 @@ -$CTSMROOT/README 04/19/2023 +$CTSMROOT/README 09/05/2024 -Community Terrestrial Systems Model (CTSM) science version 5.2 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. @@ -47,17 +47,16 @@ doc --------------- Documentation of CTSM. bld --------------- build-namelist scripts for CTSM. src --------------- CTSM Source code. lilac ------------- Lightweight Infrastructure for Land-Atmosphere Coupling (for coupling to a host atmosphere model) -test -------------- CTSM Testing scripts for CTSM offline tools (deprecated) 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 (deprecated) +bin/git-fleximod -- Script to manage the needed sub-component source directories (handled with git submodule) py_env_create ----- Script to setup the python environment for CTSM python tools using conda -python ------------ Python modules used in tools and testing and automated checking of ALL CTSM python scirpts +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 (deprecated) +libraries --------- CESM libraries: PIO (deprecated) share ------------- CESM shared code ccs_config -------- CIME configure files (for grids, compsets, and machines) for CESM @@ -67,15 +66,17 @@ components/cmeps -------------------- CESM top level driver (for NUOPC driver [w components/cdeps -------------------- CESM top level data model shared code (for NUOPC driver). components/cism --------------------- CESM Community land Ice Sheet Model. components/mosart ------------------- Model for Scale Adaptive River Transport +components/mizuRoute ---------------- Reached based river transport model for water routing + (allows both gridded river and Hydrologic Responce Unit river grids) components/rtm ---------------------- CESM River Transport Model. -components/cpl7 --------------------- CESM top level driver for MCT driver (deprecated will be removed) 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 manage_externals for CTSM (deprecated) +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 @@ -99,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 external (deprecated) -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). @@ -109,17 +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 - CTSM, 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/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 build-namelist scripts. -bld/build-namelist ---------- Script to build CTSM namelists. +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 @@ -135,8 +132,6 @@ cime_config/usermods_dirs -------- Directories of sets of user-modification subd tools/mksurfdata_esmf --------- Directory to build program to create surface dataset at any resolution. -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 (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 @@ -154,15 +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 simulation) +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 diff --git a/README.md b/README.md index 045af9f6a1..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,7 +43,7 @@ CTSM code management is provided primarily by: Software engineering team: - [Erik Kluzek](https://github.com/ekluzek) - [Bill Sacks](https://github.com/billsacks) -- [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) diff --git a/README_EXTERNALS.rst b/README_EXTERNALS.rst deleted file mode 100644 index ed7a068991..0000000000 --- a/README_EXTERNALS.rst +++ /dev/null @@ -1,132 +0,0 @@ -Obtaining the full model code and associated scripting infrastructure -===================================================================== - -[!CAUTION] -This is deprecated and will be replaced with git submodules. See -https://github.com/ESCOMP/CTSM/pull/2443 - - -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 fb44023cd5..cfdb4e9278 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 @@ -97,22 +97,26 @@ OPTIONS 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 @@ -155,16 +159,20 @@ 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) @@ -200,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. @@ -366,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 } } @@ -517,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 @@ -783,9 +794,10 @@ sub setup_cmdl_fates_mode { # 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","fates_history_dimlevel","fates_seeddisp_cadence", - "use_fates_luh","fluh_timeseries" ); + "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)) ) { @@ -894,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" ) { @@ -952,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 @@ -1011,7 +1048,7 @@ sub setup_cmdl_fire_light_res { 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 { + } 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."); } } @@ -1156,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" ) { @@ -1196,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) ) { @@ -1205,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'}; @@ -1387,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 @@ -1408,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 { @@ -1417,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 ); } } } @@ -1582,7 +1656,6 @@ sub process_namelist_inline_logic { 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); @@ -1592,9 +1665,11 @@ sub process_namelist_inline_logic { setup_logic_demand($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); @@ -1688,24 +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 options for dust emissions - ###################################### - setup_logic_dust_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); ################################## @@ -1812,10 +1892,15 @@ sub process_namelist_inline_logic { ######################################### setup_logic_initinterp($opts, $nl_flags, $definition, $defaults, $nl); - ############################### - # namelist group: exice_streams # - ############################### - setup_logic_exice($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); } #------------------------------------------------------------------------------- @@ -1842,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."); } } @@ -1893,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 " . @@ -2197,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'} ) ) { @@ -2249,6 +2337,7 @@ 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'); } @@ -2272,7 +2361,7 @@ sub setup_logic_crop_inparm { } 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 ) { @@ -2317,7 +2406,6 @@ sub setup_logic_soilstate { add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'organic_frac_squared' ); add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_bedrock', 'use_fates'=>$nl_flags->{'use_fates'}, 'vichydro'=>$nl_flags->{'vichydro'} ); - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'use_excess_ice'); # excess ice flag should be read before stream vars my $var1 = "soil_layerstruct_predefined"; my $var2 = "soil_layerstruct_userdefined"; @@ -2419,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, $xmlvar_ref) = @_; + 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)) { @@ -2436,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 @@ -2461,7 +2555,7 @@ sub setup_logic_surface_dataset { 'use_crop'=>$nl_flags->{'use_crop'} ); } # - # Expand the XML variables for NEON cases so that NEONSITE will be used + # 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); @@ -2470,6 +2564,9 @@ sub setup_logic_surface_dataset { 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"); + } } } } @@ -2484,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); @@ -2536,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}; @@ -2557,6 +2653,7 @@ sub setup_logic_initial_conditions { my $done = 2; 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); @@ -2613,8 +2710,8 @@ SIMYR: foreach my $sim_yr ( @sim_years ) { 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 = " . + 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); @@ -2656,6 +2753,12 @@ SIMYR: foreach my $sim_yr ( @sim_years ) { $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 #------------------------------------------------------------------------------- @@ -3014,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) { @@ -3102,7 +3205,7 @@ sub setup_logic_spinup { 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" ) { + 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'}, @@ -3157,7 +3260,6 @@ sub setup_logic_supplemental_nitrogen { add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'suplnitro', 'use_fates'=>$nl_flags->{'use_fates'}); } - # # Error checking for suplnitro # @@ -3497,17 +3599,6 @@ 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" ); - } - } } #------------------------------------------------------------------------------- @@ -3525,11 +3616,16 @@ sub setup_logic_hillslope { 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" ); + } } #------------------------------------------------------------------------------- @@ -3581,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 @@ -3682,10 +3759,10 @@ sub setup_logic_nitrogen_deposition { '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'}, + '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'}, + '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'}, @@ -3838,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'}; @@ -3854,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 @@ -3896,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" ); @@ -3950,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"); + } + } } } @@ -3969,69 +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'} ) { - if ( &value_is_true( $nl_flags->{'use_fates'} ) ) { - $log->warning("Fire emission can NOT be on when FATES is also on.\n" . - " DON'T use the '-fire_emis' option when '-bgc fates' is activated"); - } 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'); - } 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"); - } } + 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 - my ($opts, $nl_flags, $definition, $defaults, $nl) = @_; + # Logic to handle the dust emissions namelists, both drv_flds_in and lnd_in files + my ($opts, $nl_flags, $definition, $defaults, $nl, $envxml_ref) = @_; - # 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_mod'=>$nl_flags->{'lnd_tuning_mode'} ); - } - } else { - foreach my $option ( @zender_files_in_lnd_opts ) { - if ( defined($nl->get_value($option)) ) { - $log->fatal_error("zender_soil_erod_source is NOT lnd, but the file option $option is being set" . - " and should NOT be unless you want it handled here in the LAND model, " . - "otherwise the equivalent option is set in CAM" ); - } - } - } + # 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 { - # 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" ); - } - } - if ( $dust_emis_method eq "Leung_2023" ) { - $log->warning("dust_emis_method is Leung_2023 and that option has NOT been brought into CTSM yet"); - } + 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 ); } } @@ -4052,17 +4144,15 @@ 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')) || + } + 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"); + check_megan_spec( $opts, $nl, $definition ); + 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"); } } } @@ -4172,52 +4262,137 @@ sub setup_logic_lai_streams { sub setup_logic_cropcal_streams { my ($opts, $nl_flags, $definition, $defaults, $nl) = @_; - # Set first and last stream years - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, 'stream_year_first_cropcal', - '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', - 'sim_year'=>$nl_flags->{'sim_year'}, - 'sim_year_range'=>$nl_flags->{'sim_year_range'}); - - # Set align year, if first and last years are different - if ( $nl->get_value('stream_year_first_cropcal') != - $nl->get_value('stream_year_last_cropcal') ) { - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, - 'model_year_align_cropcal', 'sim_year'=>$nl_flags->{'sim_year'}, - 'sim_year_range'=>$nl_flags->{'sim_year_range'}); - } - # 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." ); + } + } - # Option checks - my $generate_crop_gdds = $nl->get_value('generate_crop_gdds') ; - my $use_mxmat = $nl->get_value('use_mxmat') ; + # 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 ( ($swindow_start_file eq '' and $swindow_start_file ne '') or ($swindow_start_file ne '' and $swindow_start_file eq '') ) { - $log->fatal_error("When specifying sowing window dates, you must provide both swindow_start_file and swindow_end_file. To specify exact sowing dates, use the same file." ); + 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" ); + } } - if ( $generate_crop_gdds eq '.true.' ) { - if ( $use_mxmat eq '.true.' ) { + + # 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 ( $swindow_start_file eq '' or $swindow_end_file eq '' ) { + 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 ( $gdd_file ne '' ) { + 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 ( $mesh_file eq '' and ( $swindow_start_file ne '' or $gdd_file ne '' ) ) { - $log->fatal_error("If prescribing crop sowing dates and/or maturity requirements, you must specify stream_meshfile_cropcal") + 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") + } } } @@ -4337,8 +4512,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' ); } @@ -4357,7 +4530,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, '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'); @@ -4515,21 +4687,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","fates_seeddisp_cadence", - "use_fates_logging","fates_parteh_mode", "use_fates_cohort_age_tracking","use_fates_tree_damage", - "use_fates_luh","fates_history_dimlevel" ); + "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" . + $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 # @@ -4546,6 +4732,12 @@ sub setup_logic_fates { 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'); @@ -4564,34 +4756,261 @@ 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 = "fluh_timeseries"; - add_default($opts, $nl_flags->{'inputdata_rootdir'}, $definition, $defaults, $nl, $var, 'phys'=>$nl_flags->{'phys'}, 'hgrid'=>$nl_flags->{'res'}, 'sim_year_range'=>$nl_flags->{'sim_year_range'}, nofail=>1 ); + $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 use_fates_luh is set" ); + $log->fatal_error("$var is required when fates_harvest_mode is landuse_timeseries" ); } elsif ( ! -f "$fname" ) { - $log->fatal_error("$fname does NOT point to a valid filename" ); + $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 + # excess ice streams, must be set before initial conditions # - my ($opts, $nl_flags, $definition, $defaults, $nl) = @_; + 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' ); - # IF excess ice streams is on + 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)) { + 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 @@ -4628,6 +5047,46 @@ sub setup_logic_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 { @@ -4674,6 +5133,33 @@ sub setup_logic_misc { #------------------------------------------------------------------------------- +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" ); + } +} + +#------------------------------------------------------------------------------- + sub write_output_files { my ($opts, $nl_flags, $defaults, $nl) = @_; @@ -4723,8 +5209,10 @@ sub write_output_files { 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"; @@ -4736,7 +5224,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"); @@ -5209,27 +5697,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 1e9517b189..feb0b8495c 100644 --- a/bld/README +++ b/bld/README @@ -4,16 +4,16 @@ 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 @@ -26,17 +26,17 @@ unit_testers --- Directory of scripts to test scipts in this directory ---------- XML Files describing namelists in namelist_files namelist_files/namelist_defaults_ctsm.xml --------- List of default values for the ctsm namelist namelist_files/namelist_defaults_overall.xml ------ List of default values for overall settings -namelist_files/namelist_defaults_usr_files.xml ---- List of default values for the user-files -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 diff --git a/bld/config_files/config_definition_ctsm.xml b/bld/config_files/config_definition_ctsm.xml index dfe6378f17..e6628b1d94 100644 --- a/bld/config_files/config_definition_ctsm.xml +++ b/bld/config_files/config_definition_ctsm.xml @@ -18,11 +18,11 @@ Root directory of CLM source distribution (directory above CLM configure). Component framework interface to use -(Model Coupling Toolkit, or Earth System Modeling Framework) +(Earth System Modeling Framework) + diff --git a/bld/namelist_files/namelist_defaults_ctsm.xml b/bld/namelist_files/namelist_defaults_ctsm.xml index cc407961ff..54d3afd5c1 100644 --- a/bld/namelist_files/namelist_defaults_ctsm.xml +++ b/bld/namelist_files/namelist_defaults_ctsm.xml @@ -47,11 +47,13 @@ attributes from the config_cache.xml file (with keys converted to upper-case). off -2 -1 -2 -1 -0 +2 +1 +2 +1 +0 +0 +0 .true. @@ -66,7 +68,8 @@ attributes from the config_cache.xml file (with keys converted to upper-case). .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. @@ -115,8 +128,8 @@ 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 - -.false. + +.false. .true. .false. @@ -124,9 +137,10 @@ attributes from the config_cache.xml file (with keys converted to upper-case). .false. -1 -0 -0 +1 +0 +0 +0 NONE @@ -146,6 +160,10 @@ attributes from the config_cache.xml file (with keys converted to upper-case). FAST NONE + +.false. +.true. + .false. @@ -220,10 +238,16 @@ attributes from the config_cache.xml file (with keys converted to upper-case). .false. -li2021gswpfrc +li2024crujra li2016crufrc li2014qianfrc +90.d00 +4.0d00 +1.8d00 +0.3d00 +1.0d00 + 30.0d00 80.0d00 0.3d00 @@ -243,18 +267,24 @@ 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 0.010d00 0.010d00 +0.008d00 0.008d00 0.008d00 0.008d00 +0.008d00 0.008d00 0.008d00 0.008d00 +0.008d00 0.008d00 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. @@ -334,11 +413,7 @@ attributes from the config_cache.xml file (with keys converted to upper-case). .true. -1.0 -0.05 .false. -0.25 -1.0 1 @@ -414,9 +489,6 @@ attributes from the config_cache.xml file (with keys converted to upper-case). 'Slater2017' 'TruncatedAnderson1976' -175.d00 -100.d00 - 0.08d00 .false. @@ -430,33 +502,34 @@ attributes from the config_cache.xml file (with keys converted to upper-case). 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' -lnd/clm2/paramdata/ctsm60_params.c240208.nc -lnd/clm2/paramdata/ctsm51_params.c240208.nc -lnd/clm2/paramdata/clm50_params.c240208.nc -lnd/clm2/paramdata/clm45_params.c240208.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.35.0.0_12pft_c240326.nc +lnd/clm2/paramdata/fates_params_api.36.1.0_14pft_c241003.nc + @@ -525,9 +599,6 @@ attributes from the config_cache.xml file (with keys converted to upper-case). .false. .true. - -0.17 - unset @@ -567,9 +638,6 @@ attributes from the config_cache.xml file (with keys converted to upper-case). .true. - -.false. - .false. .true. @@ -595,12 +663,36 @@ attributes from the config_cache.xml file (with keys converted to upper-case). Standard Uniform .true. +.false. +.true. .false. .true. .false. + + +.false. +.true. + +.false. +.true. + +.false. +.false. +.false. +.true. +.true. +.false. +1 +20 + +1 +-999 +-999 + + .true. @@ -633,7 +725,57 @@ attributes from the config_cache.xml file (with keys converted to upper-case). For an exact match for these grids ======================================== --> + +.true. +.true. +.true. +.true. + +.true. + + +.true. + + +.true. +.true. + + +.true. + + + +.true. +.true. + +.true. +.true. + + +.true. + + .true. - -.true. -.true. + .true. .true. - -.true. - -.true. -.true. + .true. .true. - -.true. .true. .true. +.true. .true. @@ -725,240 +854,394 @@ attributes from the config_cache.xml file (with keys converted to upper-case). --> 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. - - - - -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_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_nex=10 do_transient_pfts=.false. lnd_tuning_mode=clm5_1_GSWP3v1 use_excess_ice=.true. - - -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=clm6_0_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. +mask=gx1v7 use_cn=.true. do_transient_pfts=.false. use_excess_ice=.true. use_crop=.false. irrigate=.false. - - -hgrid=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.false. glc_nec=10 do_transient_pfts=.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=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=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=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_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=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=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=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=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=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. irrigate=.true. glc_nec=10 do_transient_pfts=.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=0.9x1.25 maxpft=79 mask=gx1v7 use_cn=.true. use_crop=.true. 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. 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=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=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. - -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.2/clmi.I1850Clm50BgcCrop-ciso.1366-01-01.0.9x1.25_gx1v7_simyr1850_c240223.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.I1850Clm50SpCru.1706-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.2/clmi.I1850Clm50BgcCrop-ciso.1366-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.I1850Clm50Sp.0181-01-01.0.9x1.25_gx1v7_simyr1850_c200806.nc + lnd_tuning_mode="clm5_0_CRUv7" use_init_interp=".true." +>lnd/clm2/initdata_map/clmi.I1850Clm50SpCru.1706-01-01.0.9x1.25_gx1v7_simyr1850_c200806.nc - +lnd/clm2/initdata_esmf/ctsm5.2/clmi.I1850Clm50BgcCrop-ciso.1366-01-01.0.9x1.25_gx1v7_simyr1850_c240223.nc + phys="clm5_1" +>lnd/clm2/initdata_esmf/ctsm5.3/ctsm53n04ctsm52028_f09_g17_BgcCrop_exice_pSASU.clm60.r.0161-01-01.nc - - -lnd/clm2/initdata_map/clmi.B1850Clm50BgcCrop.0161-01-01.0.9x1.25_gx1v7_simyr1850_c200729.nc + phys="clm6_0" +>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.2/clmi.I2000Clm50BgcCrop.2011-01-01.1.9x2.5_gx1v7_gl4_simyr2000_c240223.nc + lnd_tuning_mode="clm5_0_GSWP3v1" use_init_interp=".false." +>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_tuning_mode="clm5_0_GSWP3v1" use_init_interp=".true." +>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.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.BHIST.2000-01-01.0.9x1.25_gx1v7_simyr2000_c200728.nc + phys="clm5_1" use_init_interp=".true." +>lnd/clm2/initdata_esmf/ctsm5.3/ctsm53n04ctsm52028_f09_g17_BgcCrop_exice_hist.clm60.r.2000-01-01.nc + + lnd/clm2/initdata_map/clmi.BHIST.2000-01-01.0.9x1.25_gx1v7_simyr2000_c200728.nc + phys="clm6_0" use_init_interp=".true." +>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.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.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_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.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.BHIST.2000-01-01.0.9x1.25_gx1v7_simyr2000_c200728.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_esmf/ctsm5.3/ctsm53n04ctsm52028_ne30pg3t232_BgcCrop_exice_hist.clm60.r.1979-01-01.nc - - +lnd/clm2/initdata_map/clmi.BHISTSp.2000-01-01.1.9x2.5_gx1v7_simyr2003_c200807.nc + lnd_tuning_mode="clm6_0_cam7.0" use_init_interp=".true." +>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.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 @@ -1340,156 +1741,154 @@ attributes from the config_cache.xml file (with keys converted to upper-case). -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_0.9x1.25_hist_2000_16pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_0.9x1.25_hist_2000_16pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_1.9x2.5_hist_2000_16pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_1.9x2.5_hist_2000_16pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_10x15_hist_2000_16pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_10x15_hist_2000_16pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_4x5_hist_2000_16pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_4x5_hist_2000_16pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_mpasa60_hist_2000_16pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_mpasa60_hist_2000_16pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_mpasa15_hist_2000_16pfts_c240216.nc - +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_mpasa15_hist_2000_16pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_mpasa3p75_hist_2000_16pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_mpasa3p75_hist_2000_16pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_0.9x1.25_hist_2000_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_0.9x1.25_hist_2000_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_0.9x1.25_hist_2000_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_0.9x1.25_hist_2000_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_1.9x2.5_hist_2000_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_1.9x2.5_hist_2000_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_1.9x2.5_hist_2000_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_1.9x2.5_hist_2000_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_10x15_hist_2000_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_10x15_hist_2000_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_10x15_hist_2000_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_10x15_hist_2000_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_4x5_hist_2000_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_4x5_hist_2000_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_4x5_hist_2000_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_4x5_hist_2000_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_1x1_brazil_hist_2000_78pfts_c240221.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_1x1_brazil_hist_2000_78pfts_c240912.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_5x5_amazon_hist_2000_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_5x5_amazon_hist_2000_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne30np4_hist_2000_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne30np4_hist_2000_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne30np4.pg2_hist_2000_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne30np4.pg2_hist_2000_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne30np4.pg3_hist_2000_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne30np4.pg3_hist_2000_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne16np4.pg3_hist_2000_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne16np4.pg3_hist_2000_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_0.125nldas2_hist_2000_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_0.125nldas2_hist_2000_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_T42_hist_2000_78pfts_c240425.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_T42_hist_2000_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_360x720cru_hist_2000_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_360x720cru_hist_2000_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_C96_hist_2000_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_C96_hist_2000_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_1x1_numaIA_hist_2000_78pfts_c240221.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_1x1_numaIA_hist_2000_78pfts_c240912.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_mpasa480_hist_2000_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_mpasa480_hist_2000_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_mpasa120_hist_2000_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_mpasa120_hist_2000_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne3np4.pg3_hist_2000_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne3np4.pg3_hist_2000_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne120np4.pg3_hist_2000_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne120np4.pg3_hist_2000_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne0np4.ARCTICGRIS.ne30x8_hist_2000_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne0np4.ARCTICGRIS.ne30x8_hist_2000_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne0np4.ARCTIC.ne30x4_hist_2000_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne0np4.ARCTIC.ne30x4_hist_2000_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne0np4CONUS.ne30x8_hist_2000_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne0np4CONUS.ne30x8_hist_2000_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_1x1_vancouverCAN_hist_2000_78pfts_c240221.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_1x1_vancouverCAN_hist_2000_78pfts_c240912.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_1x1_mexicocityMEX_hist_2000_78pfts_c240221.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_1x1_mexicocityMEX_hist_2000_78pfts_c240912.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_1x1_urbanc_alpha_hist_2000_78pfts_c240221.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/synthetic/surfdata_1x1_urbanc_alpha_synth_hist_2000_78pfts_c240912.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_360x720cru_hist_1850_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_360x720cru_hist_1850_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_0.9x1.25_hist_1850_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_0.9x1.25_hist_1850_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_1.9x2.5_hist_1850_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_1.9x2.5_hist_1850_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_10x15_hist_1850_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_10x15_hist_1850_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_4x5_hist_1850_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_4x5_hist_1850_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_mpasa480_hist_1850_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_mpasa480_hist_1850_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_mpasa120_hist_1850_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_mpasa120_hist_1850_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne30np4_hist_1850_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne30np4_hist_1850_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne30np4.pg2_hist_1850_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne30np4.pg2_hist_1850_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne30np4.pg3_hist_1850_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne30np4.pg3_hist_1850_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne3np4.pg3_hist_1850_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne3np4.pg3_hist_1850_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_C96_hist_1850_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_C96_hist_1850_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_1x1_smallvilleIA_hist_1850_78pfts_c240221.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.2.0/surfdata_1x1_brazil_hist_1850_78pfts_c240221.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_1x1_brazil_hist_1850_78pfts_c240912.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne3np4.pg3_hist_1850_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne3np4.pg3_hist_1850_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne16np4.pg3_hist_1850_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne16np4.pg3_hist_1850_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne120np4.pg3_hist_1850_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne120np4.pg3_hist_1850_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne0np4.ARCTICGRIS.ne30x8_hist_1850_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne0np4.ARCTICGRIS.ne30x8_hist_1979_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne0np4.ARCTIC.ne30x4_hist_1850_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne0np4.ARCTIC.ne30x4_hist_1979_78pfts_c240908.nc -lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_ne0np4CONUS.ne30x8_hist_1850_78pfts_c240216.nc +lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_ne0np4CONUS.ne30x8_hist_1979_78pfts_c240908.nc lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_0.9x1.25_PtVeg_nourb_1850_16pfts_c240216.nc +>lnd/clm2/surfdata_esmf/ctsm5.3.0/surfdata_0.9x1.25_PtVeg_nourb_1850_16pfts_c240908.nc -lnd/clm2/surfdata_esmf/NEON/16PFT_mixed/surfdata_1x1_NEON_${NEONSITE}_hist_2000_16pfts_c240206.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/surfdata_1x1_NEON_${NEONSITE}_hist_2000_78pfts_c240206.nc +lnd/clm2/surfdata_esmf/NEON/ctsm5.3.0/surfdata_1x1_NEON_${NEONSITE}_hist_2000_78pfts_c240912.nc @@ -1497,93 +1896,104 @@ lnd/clm2/surfdata_esmf/NEON/surfdata_1x1_NEON_TOOL_hist_78pfts_CMIP6_simyr2000_c + lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_0.9x1.25_SSP2-4.5_1850-2100_78pfts_c240216.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.2.0/landuse.timeseries_1.9x2.5_SSP2-4.5_1850-2100_78pfts_c240216.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.2.0/landuse.timeseries_4x5_SSP2-4.5_1850-2100_78pfts_c240216.nc + >lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_4x5_SSP2-4.5_1850-2100_78pfts_c240908.nc lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_10x15_SSP2-4.5_1850-2100_78pfts_c240216.nc + >lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_10x15_SSP2-4.5_1850-2100_78pfts_c240908.nc lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_360x720cru_SSP2-4.5_1850-2100_78pfts_c240216.nc +>lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_360x720cru_SSP2-4.5_1850-2100_78pfts_c240908.nc lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_1x1_brazil_SSP2-4.5_1850-2100_78pfts_c240221.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.2.0/landuse.timeseries_mpasa120_SSP2-4.5_1850-2100_78pfts_c240216.nc +>lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_mpasa120_SSP2-4.5_1850-2100_78pfts_c240908.nc lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_ne3np4.pg3_SSP2-4.5_1850-2100_78pfts_c240216.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.2.0/landuse.timeseries_ne16np4.pg3_SSP2-4.5_1850-2100_78pfts_c240216.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.2.0/landuse.timeseries_ne30np4.pg3_SSP2-4.5_1850-2100_78pfts_c240216.nc +>lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_ne30np4.pg3_SSP2-4.5_1850-2100_78pfts_c240908.nc lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_C96_SSP2-4.5_1850-2100_78pfts_c240216.nc +>lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_C96_SSP2-4.5_1850-2100_78pfts_c240908.nc - lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_1x1_smallvilleIA_SSP2-4.5_1850-1855_78pfts_c240221.nc +>lnd/clm2/surfdata_esmf/ctsm5.3.0/synthetic/landuse.timeseries_1x1_smallvilleIA_synth_1850-1855_78pfts_c240908.nc + + + lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_0.9x1.25_SSP1-2.6_1850-2100_78pfts_c240216.nc + >lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_0.9x1.25_SSP1-2.6_1850-2100_78pfts_c240908.nc lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_0.9x1.25_SSP2-4.5_1850-2100_78pfts_c240216.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.2.0/landuse.timeseries_1.9x2.5_SSP2-4.5_1850-2100_78pfts_c240216.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.2.0/landuse.timeseries_4x5_SSP2-4.5_1850-2100_78pfts_c240216.nc + >lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_4x5_SSP2-4.5_1850-2100_78pfts_c240908.nc lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_10x15_SSP2-4.5_1850-2100_78pfts_c240216.nc + >lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_10x15_SSP2-4.5_1850-2100_78pfts_c240908.nc lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_360x720cru_SSP2-4.5_1850-2100_78pfts_c240216.nc +>lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_360x720cru_SSP2-4.5_1850-2100_78pfts_c240908.nc lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_1x1_brazil_SSP2-4.5_1850-2100_78pfts_c240221.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.2.0/landuse.timeseries_mpasa120_SSP2-4.5_1850-2100_78pfts_c240216.nc +>lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_mpasa120_SSP2-4.5_1850-2100_78pfts_c240908.nc lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_ne3np4.pg3_SSP2-4.5_1850-2100_78pfts_c240216.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.2.0/landuse.timeseries_ne16np4.pg3_SSP2-4.5_1850-2100_78pfts_c240216.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.2.0/landuse.timeseries_ne30np4.pg3_SSP2-4.5_1850-2100_78pfts_c240216.nc +>lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_ne30np4.pg3_SSP2-4.5_1850-2100_78pfts_c240908.nc lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_C96_SSP2-4.5_1850-2100_78pfts_c240216.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.2.0/landuse.timeseries_0.9x1.25_SSP3-7.0_1850-2100_78pfts_c240216.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.2.0/landuse.timeseries_0.9x1.25_SSP4-6.0_1850-2100_78pfts_c240216.nc +>lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_0.9x1.25_SSP4-6.0_1850-2100_78pfts_c240908.nc lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_0.9x1.25_SSP5-8.5_1850-2100_78pfts_c240216.nc +>lnd/clm2/surfdata_esmf/ctsm5.3.0/landuse.timeseries_0.9x1.25_SSP5-8.5_1850-2100_78pfts_c240908.nc @@ -1594,14 +2004,17 @@ lnd/clm2/surfdata_esmf/NEON/surfdata_1x1_NEON_TOOL_hist_78pfts_CMIP6_simyr2000_c - + 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/fates-sci.1.77.0_api.36.0.0/fates_landuse_pft_map_4x5_240206.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/fates-sci.1.68.3_api.31.0.0_tools.1.0.1/LUH2_states_transitions_management.timeseries_4x5_hist_simyr0850-2015_c240216.nc .false. @@ -1640,6 +2053,7 @@ lnd/clm2/surfdata_esmf/NEON/surfdata_1x1_NEON_TOOL_hist_78pfts_CMIP6_simyr2000_c .false. .false. .true. +.true. .true. .false. @@ -1732,10 +2146,34 @@ lnd/clm2/surfdata_esmf/NEON/surfdata_1x1_NEON_TOOL_hist_78pfts_CMIP6_simyr2000_c nn nn - -1850 -2100 -1850 + +.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 @@ -1908,12 +2346,18 @@ lnd/clm2/surfdata_esmf/NEON/surfdata_1x1_NEON_TOOL_hist_78pfts_CMIP6_simyr2000_c 1850 2106 -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/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 @@ -1993,55 +2437,94 @@ lnd/clm2/surfdata_esmf/NEON/surfdata_1x1_NEON_TOOL_hist_78pfts_CMIP6_simyr2000_c -Zender_2003 -atm 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 + @@ -2058,22 +2541,31 @@ lnd/clm2/surfdata_esmf/NEON/surfdata_1x1_NEON_TOOL_hist_78pfts_CMIP6_simyr2000_c 0 +no_harvest .false. .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. + @@ -2103,7 +2595,12 @@ lnd/clm2/surfdata_esmf/NEON/surfdata_1x1_NEON_TOOL_hist_78pfts_CMIP6_simyr2000_c .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 diff --git a/bld/namelist_files/namelist_defaults_drydep.xml b/bld/namelist_files/namelist_defaults_drydep.xml index 08bb5adaef..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,7 +21,7 @@ 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' 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 479b2a02b7..5b7ae1bdd9 100644 --- a/bld/namelist_files/namelist_defaults_overall.xml +++ b/bld/namelist_files/namelist_defaults_overall.xml @@ -62,6 +62,7 @@ determine default values for namelists. 1x1_urbanc_alpha 1x1_numaIA 1x1_smallvilleIA +1x1_cidadinhoBR 2000 @@ -110,6 +111,7 @@ determine default values for namelists. test navy test +test gx1v7 diff --git a/bld/namelist_files/namelist_definition_ctsm.xml b/bld/namelist_files/namelist_definition_ctsm.xml index 37c457141c..351cdc5c80 100644 --- a/bld/namelist_files/namelist_definition_ctsm.xml +++ b/bld/namelist_files/namelist_definition_ctsm.xml @@ -252,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) @@ -377,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 @@ -550,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. @@ -563,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. @@ -577,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. @@ -598,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. @@ -669,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 @@ -734,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. 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. + + @@ -806,6 +859,18 @@ types to vary over time. (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 @@ -828,6 +893,11 @@ 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 @@ -877,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 @@ -1070,6 +1145,11 @@ Turn urban air conditioning/heating ON or OFF and add wasteheat: ON_WASTEHEAT = Air conditioning/heating is ON and waste-heat sent to urban canyon + +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). @@ -1136,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 + + @@ -1364,11 +1488,6 @@ 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 @@ -1609,23 +1728,28 @@ Mapping method from Nitrogen deposition input file to the model resolution - + - -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) + +If TRUE use the Prigent 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) + +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 @@ -1711,6 +1835,7 @@ If true, will ignore the prescribed soilm data for that point and let the model prescribed data. + @@ -1773,19 +1898,44 @@ Mapping method from LAI input file to the model resolution - +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 + + + -First year to loop over for crop calendar data +Simulation year that aligns with stream_year_first_cropcal_swindows value - -Last year to loop over for crop calendar data +First year to loop over for crop maturity requirements - -Simulation year that aligns with stream_year_first_cropcal value +Last year to loop over for crop maturity requirements + + + +Simulation year that aligns with stream_year_first_cropcal_cultivar_gdds value + +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 @@ -2035,10 +2215,10 @@ 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 @@ -2096,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 @@ -2649,11 +2829,6 @@ 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) @@ -2819,6 +2994,18 @@ 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 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/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/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/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 7b654337af..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", NEONSITE=>"" ); + 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}; @@ -163,10 +163,10 @@ sub cat_and_create_namelistinfile { # # Figure out number of tests that will run # -my $ntests = 2513; +my $ntests = 3997; if ( defined($opts{'compare'}) ) { - $ntests += 1545; + $ntests += 2437; } plan( tests=>$ntests ); @@ -314,7 +314,7 @@ 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 ( "-res 0.9x1.25 -configuration nwp", @@ -322,10 +322,15 @@ sub cat_and_create_namelistinfile { "-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 -namelist '&a use_excess_ice=.true. use_excess_ice_streams=.false./'", + "-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", + "-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", @@ -335,13 +340,7 @@ sub cat_and_create_namelistinfile { my $file = $startfile; &make_env_run(); my $base_options = "-envxml_dir . -driver $driver"; - if ( $driver eq "mct" ) { - $base_options = "$base_options -lnd_frac $DOMFILE"; - # Skip the MCT test for excess ice streams - if ( $options =~ /use_excess_ice_streams=.true./ ) { - next; - } - } else { + if ( $driver eq "nuopc" ) { $base_options = "$base_options -namelist '&a force_send_to_atm = .false./'"; } eval{ system( "$bldnml $base_options $options > $tempfile 2>&1 " ); }; @@ -394,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 --use_case 2018_control --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 ); @@ -420,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 2000_control -namelist '&a start_ymd=19790101/' -lnd_tuning_mode ${phys}_cam6.0", - "-res ne0np4.ARCTICGRIS.ne30x8 -bgc sp -use_case 1850_control -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 2000_control -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 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}_cam6.0", - "-res ne0np4.ARCTIC.ne30x4 -bgc sp -use_case 2000_control -namelist '&a start_ymd=20130101/' -lnd_tuning_mode ${phys}_cam6.0", + "-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 " ); }; @@ -448,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"; @@ -500,447 +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", }, + "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'", - GLC_TWO_WAY_COUPLING=>"FALSE", 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'", - GLC_TWO_WAY_COUPLING=>"FALSE", 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'", - GLC_TWO_WAY_COUPLING=>"FALSE", 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'", - GLC_TWO_WAY_COUPLING=>"FALSE", 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'", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, - "exice stream on, but mct" =>{ options=>"--res 0.9x1.25 --envxml_dir . --driver mct --lnd_frac $DOMFILE ", - namelst=>"use_excess_ice=.true., use_excess_ice_streams=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", - 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=>"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=>"", - GLC_TWO_WAY_COUPLING=>"FALSE", 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", }, "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=>"clm6_0", - }, "lnd_frac set but nuopc" =>{ options=>"-driver nuopc -lnd_frac $DOMFILE -envxml_dir .", namelst=>"", - GLC_TWO_WAY_COUPLING=>"FALSE", 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=>"clm6_0", }, "fatmlndfrc set but nuopc" =>{ options=>"-driver nuopc -envxml_dir .", namelst=>"fatmlndfrc='frac.nc'", - GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm6_0", - }, - "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=>"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 .", @@ -948,320 +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=>"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=>"clm6_0", }, "FireNoneButFATESfireon" =>{ options=>"-bgc fates -envxml_dir . -no-megan -light_res none", namelst=>"fates_spitfire_mode=4", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm6_0", }, "FATESwspitfireOffLigtOn" =>{ options=>"-bgc fates -envxml_dir . -no-megan -light_res 360x720", namelst=>"fates_spitfire_mode=0", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm6_0", }, "useFATESWluna" =>{ options=>"--bgc fates --envxml_dir . --no-megan", namelst=>"use_luna=TRUE", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm6_0", }, "useFATESWfun" =>{ options=>"--bgc fates --envxml_dir . --no-megan", namelst=>"use_fun=TRUE", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm6_0", }, "useFATESWOsuplnitro" =>{ options=>"--bgc fates --envxml_dir . --no-megan", namelst=>"suplnitro='NONE'", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm6_0", }, "FireNoneButBGCfireon" =>{ options=>"-bgc bgc -envxml_dir . -light_res none", namelst=>"fire_method='li2021gswpfrc'", - GLC_TWO_WAY_COUPLING=>"FALSE", 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.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "usefatesspusefateshydro" =>{ options=>"-envxml_dir . --bgc fates", namelst=>"use_fates_sp=.true.,use_fates_planthydro=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", 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", }, - "useinventorybutnotfile" =>{ options=>"--res 0.9x1.25 --bgc fates --envxml_dir . --no-megan", + "useFATESLUH2butnotfile" =>{ options=>"--res 0.9x1.25 --bgc fates --envxml_dir . --no-megan", namelst=>"use_fates_luh=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", + 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'", - GLC_TWO_WAY_COUPLING=>"FALSE", 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=>"", - GLC_TWO_WAY_COUPLING=>"FALSE", 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", }, - "useHYDSTwithdynroot" =>{ options=>"-bgc bgc -envxml_dir . -megan", - namelst=>"use_hydrstress=.true., use_dynroot=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", + "useFATESLUPFTWOLUH" =>{ options=>"-bgc fates -envxml_dir . -no-megan", + namelst=>"use_fates_lupft=T,use_fates_luh=F", phys=>"clm5_0", }, - "specWOfireemis" =>{ options=>"-envxml_dir . -no-fire_emis", - namelst=>"fire_emis_specifier='bc_a1 = BC'", - 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", }, - "elevWOfireemis" =>{ options=>"-envxml_dir . -no-fire_emis", - namelst=>"fire_emis_elevated=.false.", - 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", + }, + "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.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "dogrossandfates" =>{ options=>"--envxml_dir . --bgc fates --use_case 20thC_transient --no-megan", namelst=>"do_grossunrep=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "dogrossandnottrans" =>{ options=>"--envxml_dir . --bgc bgc --use_case 2000_control", namelst=>"do_grossunrep=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", 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.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "bgc_non_sp_laistreams" =>{ options=>"--envxml_dir . -bgc bgc", namelst=>"use_lai_streams=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "bgc_laistreams_input" =>{ options=>"--envxml_dir . --bgc bgc", namelst=>"stream_year_first_lai=1999", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "crop_laistreams_input" =>{ options=>"--envxml_dir . --bgc sp --crop", namelst=>"use_lai_streams=.true.", - GLC_TWO_WAY_COUPLING=>"FALSE", phys=>"clm5_0", }, "soil_erod_wo_Zender" =>{ options=>"--envxml_dir . --ignore_warnings", - namelst=>"dust_emis_method='Leung_2023', " . - "stream_meshfile_zendersoilerod = '/dev/null'", - GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + 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'", - GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", + 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" ); @@ -1276,63 +1314,75 @@ sub cat_and_create_namelistinfile { my %warntest = ( # Warnings without the -ignore_warnings option given - "dustemisLeung" =>{ options=>"-envxml_dir .", - namelst=>"dust_emis_method = 'Leung_2023'", - GLC_TWO_WAY_COUPLING=>"FALSE", - phys=>"clm5_1", - }, - "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=>"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=>"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'", - GLC_TWO_WAY_COUPLING=>"FALSE", + 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" ); @@ -1344,6 +1394,56 @@ 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 # @@ -1421,30 +1521,174 @@ sub cat_and_create_namelistinfile { } print "\n==================================================\n"; -print " Rest 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(); } @@ -1454,21 +1698,27 @@ sub cat_and_create_namelistinfile { print "==================================================\n"; # Check for crop resolutions -my $crop1850_res = "1x1_smallvilleIA"; -$options = "-bgc bgc -crop -res $crop1850_res -use_case 1850_control -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 ); +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(); } -&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 ) { @@ -1503,7 +1753,7 @@ 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 = ( +my @use_cases = ( "1850-2100_SSP2-4.5_transient", "1850_control", "2000_control", @@ -1511,7 +1761,7 @@ sub cat_and_create_namelistinfile { "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; @@ -1583,43 +1833,6 @@ sub cat_and_create_namelistinfile { # # End loop over versions # -# -# Test ALL SSP's for f09... -# -$phys = "clm6_0"; -$mode = "-phys $phys"; -&make_config_cache($phys); -my $res = "0.9x1.25"; -foreach my $usecase ( "1850-2100_SSP5-8.5_transient", "1850-2100_SSP2-4.5_transient", "1850-2100_SSP1-2.6_transient", "1850-2100_SSP3-7.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 " ); }; - 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(); -} - -# The SSP's that fail because of missing ndep files... -$phys = "clm5_0"; -$mode = "-phys $phys"; -&make_config_cache($phys); -my $res = "0.9x1.25"; -foreach my $usecase ( "1850-2100_SSP5-3.4_transient", "1850-2100_SSP4-3.4", "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/clm6_0 resolutions \n"; @@ -1729,7 +1942,7 @@ sub cat_and_create_namelistinfile { my $mode = "-phys $phys"; &make_config_cache($phys); my @forclist = (); - @forclist = ( "CRUv7", "GSWP3v1", "cam6.0", "cam5.0", "cam4.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}"; 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 c7cbfee488..380e614ea1 100644 --- a/bld/unit_testers/xFail/expectedClmTestFails.xml +++ b/bld/unit_testers/xFail/expectedClmTestFails.xml @@ -20,20 +20,6 @@ - - - - - - - - goldbach not recognized - goldbach not recognized - goldbach not recognized - - - - 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..69a958581e --- /dev/null +++ b/ccs_config @@ -0,0 +1 @@ +Subproject commit 69a958581ecd2d32ee9cb1c38bcd3847b8b920bf diff --git a/cime b/cime new file mode 160000 index 0000000000..422ddaa770 --- /dev/null +++ b/cime @@ -0,0 +1 @@ +Subproject commit 422ddaa770a3cea6e83a60c9700ebce77acaceed diff --git a/cime_config/SystemTests/lilacsmoke.py b/cime_config/SystemTests/lilacsmoke.py index 66a94068da..5bdbb31ec1 100644 --- a/cime_config/SystemTests/lilacsmoke.py +++ b/cime_config/SystemTests/lilacsmoke.py @@ -38,7 +38,7 @@ 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): @@ -407,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) diff --git a/cime_config/SystemTests/lvg.py b/cime_config/SystemTests/lvg.py index 4b990313f5..d73f4e707b 100644 --- a/cime_config/SystemTests/lvg.py +++ b/cime_config/SystemTests/lvg.py @@ -32,12 +32,12 @@ 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'", + 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'", + contents="glacier_region_behavior = 'single_at_atm_topo', 'UNSET', 'virtual', 'virtual'", ) 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 index acb63bb000..fb254c408f 100644 --- a/cime_config/SystemTests/rxcropmaturity.py +++ b/cime_config/SystemTests/rxcropmaturity.py @@ -20,17 +20,25 @@ 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 RXCROPMATURITY(SystemTestsCommon): +class RXCROPMATURITYSHARED(SystemTestsCommon): def __init__(self, case): # initialize an object interface to the SMS system test SystemTestsCommon.__init__(self, case) - # 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. + # 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 @@ -56,11 +64,20 @@ def __init__(self, case): f"STOP_OPTION ({stop_option_orig}) must be nsecond(s), nminute(s), " + "nhour(s), nday(s), nmonth(s), or nyear(s)" ) - elif stop_n < 5: + 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) @@ -69,7 +86,6 @@ def __init__(self, case): self._run_Nyears = int(stop_n) # Only allow RXCROPMATURITY to be called with test cropMonthOutput - casebaseid = self._case.get_value("CASEBASEID") if casebaseid.split("-")[-1] != "cropMonthOutput": error_message = ( "Only call RXCROPMATURITY with test cropMonthOutput " @@ -81,10 +97,16 @@ def __init__(self, case): # 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): + 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. @@ -113,6 +135,7 @@ def run_phase(self): 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.", " ", @@ -133,6 +156,12 @@ def run_phase(self): # 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() @@ -146,9 +175,19 @@ def run_phase(self): # "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 - self.run_indv(suffix=None, st_archive=True) - self._run_generate_gdds(case_gddgen) + # 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 @@ -174,7 +213,7 @@ def run_phase(self): # (4) Check Prescribed Calendars run # ------------------------------------------------------------------- logger.info("RXCROPMATURITY log: output check: Prescribed Calendars") - self._run_check_rxboth_run() + self._run_check_rxboth_run(skip_gen) # Get sowing and harvest dates for this resolution. def _get_rx_dates(self): @@ -331,11 +370,16 @@ def _create_config_file_evenlysplitcrop(self): 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): + def _run_check_rxboth_run(self, skip_gen): output_dir = os.path.join(self._get_caseroot(), "run") - first_usable_year = self._run_startyear + 2 - last_usable_year = self._run_startyear + self._run_Nyears - 2 + + 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" @@ -357,12 +401,14 @@ def _run_check_rxboth_run(self): 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 = 2000", - "stream_year_last_cropcal = 2000", - "model_year_align_cropcal = 2000", + "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'", @@ -386,6 +432,7 @@ def _run_generate_gdds(self, case_gddgen): 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" ) @@ -398,7 +445,7 @@ def _run_generate_gdds(self, case_gddgen): f"--sdates-file {sdates_file}", f"--hdates-file {hdates_file}", f"--output-dir generate_gdds_out", - f"--skip-crops miscanthus,irrigated_miscanthus", + f"--skip-crops miscanthus,irrigated_miscanthus,switchgrass,irrigated_switchgrass", ] ) stu.run_python_script( @@ -416,6 +463,31 @@ def _run_generate_gdds(self, case_gddgen): 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()) @@ -442,3 +514,8 @@ def _get_flanduse_timeseries_in(self, case): 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/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 index c5ac986abd..c252f73251 100644 --- a/cime_config/SystemTests/systemtest_utils.py +++ b/cime_config/SystemTests/systemtest_utils.py @@ -2,7 +2,8 @@ Reduce code duplication by putting reused functions here. """ -import os, subprocess +import os, subprocess, re, glob +from collections import OrderedDict def cmds_to_setup_conda(caseroot): @@ -84,3 +85,26 @@ def run_python_script(caseroot, this_conda_env, command_in, tool_path): 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/buildnml b/cime_config/buildnml old mode 100755 new mode 100644 index 8e93b77015..e06b9388c7 --- a/cime_config/buildnml +++ b/cime_config/buildnml @@ -50,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") @@ -59,6 +73,7 @@ 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") glc_use_antarctica = case.get_value("GLC_USE_ANTARCTICA") mask = case.get_value("MASK_GRID") @@ -203,11 +218,24 @@ def buildnml(case, caseroot, compname): clm_usrdat_name = case.get_value("CLM_USRDAT_NAME") clmusr = " -clm_usr_name %s " % clm_usrdat_name # Write warning about initial condition data - if "NEON" in clm_usrdat_name and clm_force_coldstart == "off": - 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" - ): + 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" @@ -252,7 +280,21 @@ def buildnml(case, caseroot, compname): 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") @@ -305,12 +347,19 @@ def buildnml(case, caseroot, compname): if run_type == "hybrid" or run_type == "branch": compnames = ["clm4", "clm5", "clm2"] for comp in compnames: + 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, - run_reftod, + tod, ) if os.path.exists(os.path.join(rundir, clm_startfile)): break @@ -329,7 +378,7 @@ def buildnml(case, caseroot, compname): 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) + logger.warning("WARNING: Could NOT find a start file named " + clm_startfile) clm_icfile = "%s = '%s'" % (startfile_type, clm_startfile) else: clm_icfile = "" diff --git a/cime_config/config_component.xml b/cime_config/config_component.xml index f7adab268f..540d285a85 100644 --- a/cime_config/config_component.xml +++ b/cime_config/config_component.xml @@ -16,7 +16,7 @@ clm4.5: clm5.0: clm5.1: - clm6.0: + clm6.0: Satellite phenology: Satellite phenology with VIC hydrology: @@ -78,7 +78,7 @@ UNSET - 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,clm5_1_CRUv7,clm5_1_GSWP3v1,clm5_1_cam6.0,clm5_1_QIAN,clm5_1_1PT,clm5_1_NLDAS2,clm5_1_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 + 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,clm5_1_CRUv7,clm5_1_GSWP3v1,clm5_1_cam6.0,clm5_1_QIAN,clm5_1_1PT,clm5_1_NLDAS2,clm5_1_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 @@ -87,10 +87,11 @@ clm4_5_CRUv7 clm4_5_GSWP3v1 clm4_5_cam6.0 - clm4_5_cam4.0 - clm4_5_cam5.0 - clm4_5_cam7.0 - 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 @@ -102,9 +103,10 @@ clm5_0_GSWP3v1 clm5_0_GSWP3v1 clm5_0_cam6.0 - clm5_0_cam4.0 - clm5_0_cam5.0 - clm5_0_cam7.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 @@ -112,22 +114,24 @@ clm5_0_NLDAS2 clm5_0_ERA5 - clm5_1_GSWP3v1 clm5_1_GSWP3v1 - clm5_1_cam6.0 - clm5_1_cam4.0 - clm5_1_cam5.0 - clm5_1_cam6.0 + INVALID_USE_CLM60_NOT_CLM51 + clm5_1_cam4.0 + clm5_1_cam5.0 + clm5_1_cam6.0 + INVALID_USE_CLM60_NOT_CLM51_FOR_CAM70 + INVALID_USE_CLM60_NOT_CLM51_FOR_CPLHIST 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_cam7.0 - 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 @@ -162,6 +166,21 @@ This is typically set by the compset. + + + logical + TRUE,FALSE + TRUE + + 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 @@ -199,23 +218,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 @@ -292,11 +312,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. @@ -311,7 +331,8 @@ 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. + use the variable NEONSITE to specify the exact site. PLUMBER cases use the variable + PLUMBER2SITE to specify the exact site. @@ -336,7 +357,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. @@ -350,6 +371,10 @@ $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 @@ -399,6 +424,28 @@ 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 2de911da86..e5d716384a 100644 --- a/cime_config/config_compsets.xml +++ b/cime_config/config_compsets.xml @@ -91,6 +91,8 @@ I2000Clm60Sp 2000_DATM%GSWP3v1_CLM60%SP_SICE_SOCN_MOSART_SGLC_SWAV + + @@ -182,6 +184,8 @@ I1850Clm60Sp 1850_DATM%GSWP3v1_CLM60%SP_SICE_SOCN_MOSART_SGLC_SWAV + + @@ -196,6 +200,10 @@ 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 + @@ -203,6 +211,10 @@ 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 + @@ -291,22 +303,24 @@ I1850Clm60BgcNoAnthro - 1850_DATM%GSWP3v1_CLM60%BGC-NOANTHRO_SICE_SOCN_MOSART_SGLC_SWAV + 1850_DATM%GSWP3v1_CLM60%BGC-NOANTHRO_SICE_SOCN_RTM_SGLC_SWAV + I1850Clm60SpNoAnthro - 1850_DATM%GSWP3v1_CLM60%SP-NOANTHRO_SICE_SOCN_MOSART_SGLC_SWAV + 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 @@ -319,12 +333,15 @@ I1850Clm60SpNoAnthro - 1850_DATM%GSWP3v1_CLM60%SP-NOANTHRO_SICE_SOCN_MOSART_SGLC_SWAV + 1850_DATM%GSWP3v1_CLM60%SP-NOANTHRO_SICE_SOCN_RTM_SGLC_SWAV + IHistClm60Sp HIST_DATM%GSWP3v1_CLM60%SP_SICE_SOCN_MOSART_SGLC_SWAV + + @@ -631,6 +648,17 @@ 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 + + + diff --git a/cime_config/config_tests.xml b/cime_config/config_tests.xml index c0b6afed9d..12859b9131 100644 --- a/cime_config/config_tests.xml +++ b/cime_config/config_tests.xml @@ -123,6 +123,18 @@ 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 @@ -133,6 +145,16 @@ This defines various CTSM-specific system tests $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 + + - + - PEND - #2460 + FAIL + CDEPS/#243 - + + FAIL - CDEPS/#243 + #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 - #2444 + #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 - #1887 + #2619 + This failure relates to the preceding ERP failure. + + + + + + FAIL + #2542 @@ -65,15 +117,11 @@ - + FAIL #2310 - - FAIL - #2310 - @@ -87,7 +135,7 @@ - + FAIL #2310 @@ -120,33 +168,37 @@ - + FAIL - #2373 + #2453 - - + + FAIL - #2373 + #2454 - - - - + FAIL - #2453 + #2325 - + FAIL #2454 + + + + FAIL + #2867 + + @@ -172,38 +224,27 @@ - - - FAIL - #2321 - - - - + FAIL - #2373 - - - FAIL - FATES#701 + #2653 - + FAIL - #2373 + FATES#1216 - - + + FAIL - FATES#701 + #2321 - + FAIL @@ -233,31 +274,82 @@ - - + + FAIL - #2423 + #2325 - + FAIL #2325 + + - - + + FAIL - #2325 + #2861 + + + + + + FAIL + #2861 + + + + + + FAIL + #2861 + + + + + + FAIL + #2861 + + + + + + FAIL + #2861 + + + + + + FAIL + #2861 + + + + + + FAIL + #2861 + + + + + + FAIL + #2861 - - + + FAIL - #2325 + #2861 @@ -266,13 +358,39 @@ FAIL #2310 + + + + + FAIL + #2810 + + + + FAIL - #2310 + #2861 + + + + + + + FAIL + #2861 + + + + + + + FAIL + #2810 - + diff --git a/cime_config/testdefs/testlist_clm.xml b/cime_config/testdefs/testlist_clm.xml index c2a90507ba..b118c863b1 100644 --- a/cime_config/testdefs/testlist_clm.xml +++ b/cime_config/testdefs/testlist_clm.xml @@ -10,6 +10,8 @@ prebeta: Run before CESM beta tags (more extensive, but should have tests outside of prealpha) (subset of aux_clm tests) aux_cime_baselines: CESM cime baselines (subset of aux_clm tests) hillslope: Experimental test list used for the hillslope option of the model + rxcropmaturity: Short tests to be run during development related to prescribed crop calendars + matrixcn: Tests exercising the matrix-CN capability --> @@ -21,22 +23,50 @@ - + + + + + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + - - @@ -56,6 +86,7 @@ + @@ -63,7 +94,7 @@ - + @@ -71,24 +102,25 @@ + - + - + - + - + @@ -102,7 +134,7 @@ - + @@ -111,16 +143,7 @@ - - - - - - - - - - + @@ -129,25 +152,26 @@ - + - + - + + - + @@ -174,100 +198,96 @@ - + + - + + - + + - + + - + + - + + - + + - - - + - + + - + + - @@ -312,14 +332,14 @@ - + - + @@ -328,13 +348,31 @@ - + + + + + + + + + + + + + + + + + + + + + - - @@ -395,15 +433,6 @@ - - - - - - - - - @@ -413,14 +442,6 @@ - - - - - - - - @@ -429,15 +450,15 @@ - + - + - + @@ -445,33 +466,31 @@ - + - + - + - - - - + - + + @@ -485,7 +504,6 @@ - @@ -501,6 +519,16 @@ + + + + + + + + + + @@ -512,8 +540,6 @@ - - @@ -521,13 +547,14 @@ - + - - + + + @@ -541,7 +568,6 @@ - @@ -549,6 +575,15 @@ + + + + + + + + + @@ -568,14 +603,14 @@ - + - + @@ -584,7 +619,7 @@ - + @@ -595,112 +630,124 @@ - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + - + + @@ -731,14 +778,14 @@ - + - + @@ -747,12 +794,11 @@ - + - @@ -760,9 +806,18 @@ + + + + + + + + + + - @@ -770,78 +825,144 @@ + + + + + + + + + + - - + - - - + + - + - + + + - - + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - + + + + + + + + + + + - + - + + - + - + - + - - + - @@ -886,13 +1007,14 @@ - + - + + - - + + @@ -904,27 +1026,38 @@ - + - + + - + + + + + + + + + + + + - @@ -932,15 +1065,17 @@ - + - + + - + + - + @@ -948,12 +1083,9 @@ - + - - - - + @@ -970,12 +1102,15 @@ - + - + + + + @@ -986,48 +1121,51 @@ - + - + + - + - + + - + - + - + - + - + - + - + - + + @@ -1038,12 +1176,14 @@ - + - + + + @@ -1054,12 +1194,14 @@ - + - + + + @@ -1070,15 +1212,6 @@ - - - - - - - - - @@ -1088,15 +1221,6 @@ - - - - - - - - - @@ -1106,15 +1230,6 @@ - - - - - - - - - @@ -1124,15 +1239,6 @@ - - - - - - - - - @@ -1144,8 +1250,6 @@ - - @@ -1163,38 +1267,29 @@ - + - - + + + + - + - - - - - - - - - - - - + - + @@ -1234,6 +1329,16 @@ + + + + + + + + + + @@ -1242,21 +1347,22 @@ - + + + - + - + - - + @@ -1268,23 +1374,23 @@ - + - - + + - - + + - + - - + - + + @@ -1297,14 +1403,6 @@ - - - - - - - - @@ -1313,13 +1411,14 @@ - + - + + - + @@ -1331,61 +1430,64 @@ - + - + - + - - + - + - + + - + - - + + + - + - + + - + - - + + - - + + + @@ -1398,16 +1500,6 @@ - - - - - - - - - - @@ -1418,15 +1510,6 @@ - - - - - - - - - @@ -1436,14 +1519,6 @@ - - - - - - - - @@ -1453,15 +1528,6 @@ - - - - - - - - - @@ -1471,16 +1537,6 @@ - - - - - - - - - - @@ -1491,14 +1547,6 @@ - - - - - - - - @@ -1507,15 +1555,6 @@ - - - - - - - - - @@ -1525,16 +1564,6 @@ - - - - - - - - - - @@ -1545,16 +1574,6 @@ - - - - - - - - - - @@ -1567,32 +1586,33 @@ - - + - + + - + - + + - + @@ -1603,7 +1623,6 @@ - @@ -1613,7 +1632,6 @@ - @@ -1623,7 +1641,6 @@ - @@ -1631,15 +1648,6 @@ - - - - - - - - - @@ -1651,10 +1659,6 @@ - - - - @@ -1664,19 +1668,8 @@ - - - - - - - - - - - @@ -1685,7 +1678,6 @@ - @@ -1694,8 +1686,6 @@ - - @@ -1714,7 +1704,6 @@ - @@ -1739,6 +1728,16 @@ + + + + + + + + + + @@ -1767,32 +1766,33 @@ - + - - + + - - + + + - + - + - + - + - + - + @@ -1804,15 +1804,6 @@ - - - - - - - - - @@ -1822,13 +1813,14 @@ - + - + + - - + + @@ -1842,7 +1834,6 @@ - @@ -1852,8 +1843,6 @@ - - @@ -1864,7 +1853,6 @@ - @@ -1882,6 +1870,17 @@ + + + + + + + + + + + @@ -1895,7 +1894,6 @@ - @@ -1903,13 +1901,14 @@ - + - + + - + @@ -1921,9 +1920,18 @@ + + + + + + + + + + - @@ -1933,8 +1941,6 @@ - - @@ -1943,10 +1949,19 @@ + + + + + + + + + + + - - @@ -1956,8 +1971,6 @@ - - @@ -1974,14 +1987,15 @@ - + - + + + - - + @@ -1994,10 +2008,20 @@ + + + + + + + + + + + - @@ -2007,18 +2031,16 @@ - + - + - - @@ -2026,53 +2048,67 @@ - + + + + - + + + + + + + + + + - + + - + + - + - + - + + - + @@ -2081,7 +2117,7 @@ - + @@ -2090,38 +2126,37 @@ - - + + - + - + - + - + - + - @@ -2131,7 +2166,6 @@ - @@ -2139,14 +2173,14 @@ - + - - + + @@ -2170,12 +2204,10 @@ - - @@ -2191,16 +2223,6 @@ - - - - - - - - - - @@ -2221,10 +2243,6 @@ - - - - @@ -2234,11 +2252,21 @@ + + + + + + + + + + + + + - - - @@ -2249,7 +2277,6 @@ - @@ -2258,8 +2285,6 @@ - - @@ -2288,7 +2313,7 @@ - + @@ -2299,6 +2324,19 @@ + + + + + + + + + + + + + @@ -2322,20 +2360,9 @@ - - - - - - - - - - - - + @@ -2371,14 +2398,23 @@ - + + + + + + + + + + - + - + @@ -2392,7 +2428,6 @@ - @@ -2402,7 +2437,6 @@ - @@ -2422,22 +2456,12 @@ - - - - - - - - - - @@ -2448,7 +2472,6 @@ - @@ -2458,7 +2481,6 @@ - @@ -2466,9 +2488,8 @@ - + - @@ -2548,9 +2569,18 @@ + + + + + + + + + + - @@ -2558,24 +2588,15 @@ - + - - - - - - - - - - + @@ -2596,9 +2617,17 @@ + + + + + + + + + - @@ -2608,7 +2637,6 @@ - @@ -2617,7 +2645,6 @@ - @@ -2626,8 +2653,6 @@ - - @@ -2654,9 +2679,8 @@ - + - @@ -2664,9 +2688,8 @@ - + - @@ -2676,7 +2699,6 @@ - @@ -2706,7 +2728,6 @@ - @@ -2725,8 +2746,6 @@ - - @@ -2737,7 +2756,6 @@ - @@ -2746,7 +2764,6 @@ - @@ -2756,7 +2773,6 @@ - @@ -2765,8 +2781,6 @@ - - @@ -2780,23 +2794,20 @@ - + - - + - - @@ -2804,14 +2815,6 @@ - - - - - - - - @@ -2822,12 +2825,9 @@ - - - @@ -2836,7 +2836,6 @@ - @@ -2845,7 +2844,6 @@ - @@ -2855,7 +2853,6 @@ - @@ -2866,7 +2863,6 @@ - @@ -2877,7 +2873,6 @@ - @@ -2888,7 +2883,6 @@ - @@ -2896,16 +2890,6 @@ - - - - - - - - - - @@ -2938,18 +2922,6 @@ - - - - - - - - - - - - @@ -2961,7 +2933,6 @@ - @@ -2969,18 +2940,6 @@ - - - - - - - - - - - - @@ -2993,7 +2952,6 @@ - @@ -3004,7 +2962,6 @@ - @@ -3014,7 +2971,6 @@ - @@ -3022,15 +2978,6 @@ - - - - - - - - - @@ -3042,7 +2989,6 @@ - @@ -3053,7 +2999,6 @@ - @@ -3064,7 +3009,6 @@ - @@ -3076,7 +3020,6 @@ - @@ -3087,18 +3030,44 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - @@ -3110,7 +3079,6 @@ - @@ -3121,7 +3089,6 @@ - @@ -3133,10 +3100,8 @@ - - @@ -3147,7 +3112,6 @@ - @@ -3158,7 +3122,6 @@ - @@ -3170,7 +3133,6 @@ - @@ -3181,7 +3143,6 @@ - @@ -3192,7 +3153,6 @@ - @@ -3203,7 +3163,6 @@ - @@ -3214,7 +3173,6 @@ - @@ -3224,7 +3182,6 @@ - @@ -3234,7 +3191,6 @@ - @@ -3244,7 +3200,6 @@ - @@ -3253,9 +3208,8 @@ - - + @@ -3264,7 +3218,6 @@ - @@ -3274,7 +3227,6 @@ - @@ -3285,7 +3237,6 @@ - @@ -3295,7 +3246,6 @@ - @@ -3305,7 +3255,6 @@ - @@ -3314,16 +3263,6 @@ - - - - - - - - - - @@ -3336,7 +3275,6 @@ - @@ -3346,7 +3284,6 @@ - @@ -3357,7 +3294,6 @@ - @@ -3368,8 +3304,6 @@ - - @@ -3380,7 +3314,6 @@ - @@ -3388,11 +3321,8 @@ - + - - - @@ -3414,7 +3344,6 @@ - @@ -3424,11 +3353,8 @@ - - - @@ -3437,7 +3363,6 @@ - @@ -3457,7 +3382,6 @@ - @@ -3467,6 +3391,18 @@ + + + + + + + + + + + + @@ -3485,7 +3421,7 @@ - + @@ -3505,8 +3441,6 @@ - - @@ -3527,16 +3461,6 @@ - - - - - - - - - - @@ -3546,16 +3470,6 @@ - - - - - - - - - - @@ -3565,16 +3479,6 @@ - - - - - - - - - - @@ -3584,15 +3488,6 @@ - - - - - - - - - @@ -3605,7 +3500,6 @@ - @@ -3616,7 +3510,6 @@ - @@ -3626,7 +3519,7 @@ - + @@ -3636,6 +3529,29 @@ + + + + + + + + + + + + + + + + + + + + + + + @@ -3655,23 +3571,24 @@ - + + - + - + - + @@ -3685,5 +3602,139 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/cime_config/testdefs/testmods_dirs/clm/ExcessIceStreams/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/ExcessIceStreams/include_user_mods index fe0e18cf88..1e4ddf5337 100644 --- a/cime_config/testdefs/testmods_dirs/clm/ExcessIceStreams/include_user_mods +++ b/cime_config/testdefs/testmods_dirs/clm/ExcessIceStreams/include_user_mods @@ -1 +1,2 @@ ../default +../nofireemis 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 406fb598f6..8bd9f01335 100644 --- a/cime_config/testdefs/testmods_dirs/clm/Fates/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/Fates/user_nl_clm @@ -16,7 +16,7 @@ hist_fincl1 = 'FATES_NCOHORTS', 'FATES_TRIMMING', 'FATES_AREA_PLANTS', 'FATES_SAPWOODC', 'FATES_LEAFC', 'FATES_FROOTC', 'FATES_REPROC', 'FATES_STRUCTC', 'FATES_NONSTRUCTC', 'FATES_VEGC_ABOVEGROUND', 'FATES_CANOPY_VEGC', 'FATES_USTORY_VEGC', 'FATES_PRIMARY_PATCHFUSION_ERR', -'FATES_HARVEST_CARBON_FLUX', 'FATES_DISTURBANCE_RATE_FIRE', +'FATES_HARVEST_WOODPROD_C_FLUX', 'FATES_DISTURBANCE_RATE_FIRE', 'FATES_DISTURBANCE_RATE_LOGGING', 'FATES_DISTURBANCE_RATE_TREEFALL', 'FATES_STOMATAL_COND', 'FATES_LBLAYER_COND', 'FATES_NPP', 'FATES_GPP', 'FATES_AUTORESP', 'FATES_GROWTH_RESP', 'FATES_MAINT_RESP', 'FATES_GPP_CANOPY', @@ -26,5 +26,4 @@ hist_fincl1 = 'FATES_NCOHORTS', 'FATES_TRIMMING', 'FATES_AREA_PLANTS', 'FATES_NEP', 'FATES_HET_RESP', 'FATES_FIRE_CLOSS', 'FATES_FIRE_FLUX_EL', 'FATES_CBALANCE_ERROR', 'FATES_ERROR_EL', 'FATES_LEAF_ALLOC', 'FATES_SEED_ALLOC', 'FATES_STEM_ALLOC', 'FATES_FROOT_ALLOC', -'FATES_CROOT_ALLOC', 'FATES_STORE_ALLOC', -'FATES_PATCHAREA_LU', 'FATES_DISTURBANCE_RATE_MATRIX_LULU' +'FATES_CROOT_ALLOC', 'FATES_STORE_ALLOC' diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdAllVars/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdAllVars/user_nl_clm index a426c775b0..92434df000 100644 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdAllVars/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdAllVars/user_nl_clm @@ -26,7 +26,7 @@ hist_fincl1 = 'FATES_TLONGTERM', '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_C13DISC_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', 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 index f0bdb388eb..318a34dfec 100644 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdHydro/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdHydro/user_nl_clm @@ -2,6 +2,7 @@ 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', 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/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2/user_nl_clm index 854c21407f..55650230a4 100644 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdLUH2/user_nl_clm @@ -1 +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/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 index 668f9c861d..f718010b07 100644 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdLandUse/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdLandUse/user_nl_clm @@ -1,2 +1 @@ -flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_4x5_hist_16_CMIP6_1850-2015_c230620.nc' -do_harvest = .true. +fates_harvest_mode = 'landuse_timeseries' diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdLogging/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdLogging/user_nl_clm index 3b74a4fd37..d2079d9e43 100644 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdLogging/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdLogging/user_nl_clm @@ -1 +1 @@ -use_fates_logging= .true. +fates_harvest_mode = 'event_code' 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 index 679f025b60..196d559cb7 100644 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdPRT2/user_nl_clm @@ -1,3 +1,4 @@ +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', diff --git a/cime_config/testdefs/testmods_dirs/clm/FatesColdST3/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/FatesColdST3/user_nl_clm index eca76c4b9c..860656e8d8 100644 --- a/cime_config/testdefs/testmods_dirs/clm/FatesColdST3/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/FatesColdST3/user_nl_clm @@ -1 +1,2 @@ use_fates_ed_st3= .true. +hist_fexcl1 = 'FATES_ERROR_EL' 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/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/sowingWindows/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/FireLi2021GSWP/include_user_mods similarity index 100% rename from cime_config/testdefs/testmods_dirs/clm/sowingWindows/include_user_mods rename to cime_config/testdefs/testmods_dirs/clm/FireLi2021GSWP/include_user_mods 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/shell_commands b/cime_config/testdefs/testmods_dirs/clm/Hillslope/shell_commands index 6f3602d2e6..9cef7eb66f 100644 --- a/cime_config/testdefs/testmods_dirs/clm/Hillslope/shell_commands +++ b/cime_config/testdefs/testmods_dirs/clm/Hillslope/shell_commands @@ -1,4 +1,19 @@ ./xmlchange CLM_BLDNML_OPTS="-bgc sp" DIN_LOC_ROOT=$(./xmlquery --value DIN_LOC_ROOT) -meshfile=$DIN_LOC_ROOT/lnd/clm2/testdata/ESMFmesh_10x15_synthetic_cosphill_1.0.nc -./xmlchange ATM_DOMAIN_MESH=${meshfile},LND_DOMAIN_MESH=${meshfile} + +# 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 index 4fc6fc2373..e108e93d91 100644 --- a/cime_config/testdefs/testmods_dirs/clm/Hillslope/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/Hillslope/user_nl_clm @@ -6,6 +6,4 @@ hillslope_transmissivity_method = 'LayerSum' hillslope_pft_distribution_method = 'PftLowlandUpland' hillslope_soil_profile_method = 'Uniform' -fsurdat = '$DIN_LOC_ROOT/lnd/clm2/testdata/surfdata_10x15_hist_2000_78pfts_c240216.synthetic_hillslopes.nc' - use_ssre = .false. 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/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/ciso_cwd_hr/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/ciso_cwd_hr/user_nl_clm index 3c686f08b9..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 = '$DIN_LOC_ROOT/lnd/clm2/paramdata/ctsm51_ciso_cwd_hr_params.c240208.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/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/clm45cam4LndTuningModeZDustSoilErod/user_nl_clm index 93b7ee2e48..d97fbbac57 100644 --- a/cime_config/testdefs/testmods_dirs/clm/clm45cam4LndTuningModeZDustSoilErod/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/clm45cam4LndTuningModeZDustSoilErod/user_nl_clm @@ -1,3 +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/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/clm50cam5LndTuningModeZDustSoilErod/user_nl_clm index 93b7ee2e48..d97fbbac57 100644 --- a/cime_config/testdefs/testmods_dirs/clm/clm50cam5LndTuningModeZDustSoilErod/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/clm50cam5LndTuningModeZDustSoilErod/user_nl_clm @@ -1,3 +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/clm51cam6LndTuningModeZDustSoilErod/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/clm51cam6LndTuningModeZDustSoilErod/user_nl_clm index 93b7ee2e48..d97fbbac57 100644 --- a/cime_config/testdefs/testmods_dirs/clm/clm51cam6LndTuningModeZDustSoilErod/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/clm51cam6LndTuningModeZDustSoilErod/user_nl_clm @@ -1,3 +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/clm60cam6LndTuningModeCiso/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningModeCiso/include_user_mods deleted file mode 100644 index 3dabdc9aeb..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningModeCiso/include_user_mods +++ /dev/null @@ -1 +0,0 @@ -../clm60cam6LndTuningMode diff --git a/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningModeCiso/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningModeCiso/user_nl_clm deleted file mode 100644 index e7627dea50..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningModeCiso/user_nl_clm +++ /dev/null @@ -1,5 +0,0 @@ -! Turn on Carbon isotopes -use_c13 = .true. -use_c14 = .true. -use_c13_timeseries = .true. -use_c14_bombspike = .true. diff --git a/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningModeZDustSoilErod/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningModeZDustSoilErod/include_user_mods deleted file mode 100644 index 3dabdc9aeb..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningModeZDustSoilErod/include_user_mods +++ /dev/null @@ -1 +0,0 @@ -../clm60cam6LndTuningMode diff --git a/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningModeZDustSoilErod/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningModeZDustSoilErod/user_nl_clm deleted file mode 100644 index 93b7ee2e48..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningModeZDustSoilErod/user_nl_clm +++ /dev/null @@ -1,3 +0,0 @@ -! Turn on using the soil eroditability file in CTSM -dust_emis_method = 'Zender_2003' -zender_soil_erod_source = 'lnd' diff --git a/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode_1979Start/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode_1979Start/include_user_mods deleted file mode 100644 index 3dabdc9aeb..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode_1979Start/include_user_mods +++ /dev/null @@ -1 +0,0 @@ -../clm60cam6LndTuningMode diff --git a/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode_2013Start/include_user_mods b/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode_2013Start/include_user_mods deleted file mode 100644 index 3dabdc9aeb..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode_2013Start/include_user_mods +++ /dev/null @@ -1 +0,0 @@ -../clm60cam6LndTuningMode 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/clm60cam6LndTuningMode_1979Start/shell_commands b/cime_config/testdefs/testmods_dirs/clm/clm60cam7LndTuningMode_1979Start/shell_commands similarity index 100% rename from cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode_1979Start/shell_commands rename to cime_config/testdefs/testmods_dirs/clm/clm60cam7LndTuningMode_1979Start/shell_commands 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/clm60cam6LndTuningMode_2013Start/shell_commands b/cime_config/testdefs/testmods_dirs/clm/clm60cam7LndTuningMode_2013Start/shell_commands similarity index 100% rename from cime_config/testdefs/testmods_dirs/clm/clm60cam6LndTuningMode_2013Start/shell_commands rename to cime_config/testdefs/testmods_dirs/clm/clm60cam7LndTuningMode_2013Start/shell_commands 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 dbd0696317..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,22 +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 -bld/namelist_files/namelist_defaults_ctsm.xml -the following two files used in this test -are default files for the following options: - -fsurdat = '$DIN_LOC_ROOT/lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_10x15_hist_1850_78pfts_c240216.nc' -hgrid="10x15" sim_year="1850" use_crop=".false." irrigate=".true." -hgrid="10x15" sim_year="1850" use_crop=".true." - -flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_10x15_SSP2-4.5_1850-2100_78pfts_c240216.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 d7be01280b..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 = '$DIN_LOC_ROOT/lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_10x15_hist_1850_78pfts_c240216.nc' -flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_10x15_SSP2-4.5_1850-2100_78pfts_c240216.nc' 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 67042ea01a..8ad588381e 100644 --- a/cime_config/testdefs/testmods_dirs/clm/crop/user_nl_clm +++ b/cime_config/testdefs/testmods_dirs/clm/crop/user_nl_clm @@ -9,9 +9,12 @@ hist_fincl2 += 'DYN_COL_SOIL_ADJUSTMENTS_C' -! Annual crop variables on per-sowing/per-harvest axes, per PFT. -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' -hist_nhtfrq(3) = 17520 -hist_mfilt(3) = 1 +! 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(3) = .false. +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 8f779ed011..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,4 +1,4 @@ - hist_nhtfrq = 0,-240,17520 + hist_nhtfrq = 0,-240,0 hist_mfilt = 1,1,1 ! NOTE slevis (2024/2/23) Adding option for tests to pass. In the long term 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/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/f09_dec1990Start_GU_LULCC/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/f09_dec1990Start_GU_LULCC/user_nl_clm index 0dbc0b4942..e9040ca841 100644 --- 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 @@ -1,5 +1,2 @@ - ! Specify a dataset that has non-zero Gross Unrepresented Land Use change fields on it - ! And turn it on - flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_0.9x1.25_SSP2-4.5_1850-2100_78pfts_c240216.nc' - fsurdat = '$DIN_LOC_ROOT/lnd/clm2/surfdata_esmf/ctsm5.2.0/surfdata_0.9x1.25_hist_1850_78pfts_c240216.nc' + ! 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/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/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/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/smallville_dynlakes_monthly/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/smallville_dynlakes_monthly/user_nl_clm index c86418dabd..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 @@ -6,7 +6,7 @@ do_transient_lakes = .true. ! 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_esmf/ctsm5.2.0/landuse.timeseries_1x1_smallvilleIA_SSP2-4.5_1850-1855_78pfts_dynLakes_c240221.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 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 a5bdb76ac3..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 @@ -7,7 +7,7 @@ do_transient_urban = .true. ! 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. -flanduse_timeseries = '$DIN_LOC_ROOT/lnd/clm2/surfdata_esmf/ctsm5.2.0/landuse.timeseries_1x1_smallvilleIA_SSP2-4.5_1850-1855_78pfts_dynUrban_c240221.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 diff --git a/cime_config/testdefs/testmods_dirs/clm/sowingWindows/user_nl_clm b/cime_config/testdefs/testmods_dirs/clm/sowingWindows/user_nl_clm deleted file mode 100644 index 03165bb306..0000000000 --- a/cime_config/testdefs/testmods_dirs/clm/sowingWindows/user_nl_clm +++ /dev/null @@ -1,5 +0,0 @@ -stream_fldFileName_swindow_start = '$DIN_LOC_ROOT/lnd/clm2/cropdata/calendars/processed/swindow_starts_ggcmi_crop_calendar_phase3_v1.01.2000-2000.20231005_145103.nc' -stream_fldFileName_swindow_end = '$DIN_LOC_ROOT/lnd/clm2/cropdata/calendars/processed/swindow_ends_ggcmi_crop_calendar_phase3_v1.01.2000-2000.20231005_145103.nc' -stream_meshfile_cropcal = '$DIN_LOC_ROOT/share/meshes/360x720_120830_ESMFmesh_c20210507_cdf5.nc' -stream_year_first_cropcal = 2000 -stream_year_last_cropcal = 2000 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/FATES/defaults/user_nl_clm b/cime_config/usermods_dirs/NEON/FATES/defaults/user_nl_clm index 1a9847a69b..e49d110d51 100644 --- a/cime_config/usermods_dirs/NEON/FATES/defaults/user_nl_clm +++ b/cime_config/usermods_dirs/NEON/FATES/defaults/user_nl_clm @@ -18,9 +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_esmf/NEON/16PFT_mixed/surfdata_1x1_NEON_${NEONSITE}_hist_2000_16pfts_c240206.nc" - ! 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' diff --git a/cime_config/usermods_dirs/NEON/defaults/user_nl_clm b/cime_config/usermods_dirs/NEON/defaults/user_nl_clm index b73da1f33e..f0e7142990 100644 --- a/cime_config/usermods_dirs/NEON/defaults/user_nl_clm +++ b/cime_config/usermods_dirs/NEON/defaults/user_nl_clm @@ -18,9 +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_esmf/NEON/surfdata_1x1_NEON_${NEONSITE}_hist_2000_78pfts_c240206.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/PLUMBER2/AR-SLu/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AR-SLu/shell_commands index f64d8759a2..f297937768 100644 --- a/cime_config/usermods_dirs/PLUMBER2/AR-SLu/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/AR-SLu/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_AR-SLu_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/AR-SLu/CLM1PT_data/CTSM_DATM_AR-SLu_2010-2010.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/AT-Neu/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AT-Neu/shell_commands index b8a54e5644..319c52a95d 100644 --- a/cime_config/usermods_dirs/PLUMBER2/AT-Neu/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/AT-Neu/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_AT-Neu_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/AT-Neu/CLM1PT_data/CTSM_DATM_AT-Neu_2002-2012.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-ASM/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-ASM/shell_commands index 2d5e0d85fd..afadee1c1e 100644 --- a/cime_config/usermods_dirs/PLUMBER2/AU-ASM/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/AU-ASM/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=133.24899299999998 -./xmlchange PTS_LAT=-22.283001000000002 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_AU-ASM_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/AU-ASM/CLM1PT_data/CTSM_DATM_AU-ASM_2011-2017.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Cow/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Cow/shell_commands index fe84b1e129..40187f1b46 100644 --- a/cime_config/usermods_dirs/PLUMBER2/AU-Cow/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Cow/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_AU-Cow_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/AU-Cow/CLM1PT_data/CTSM_DATM_AU-Cow_2010-2015.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Cpr/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Cpr/shell_commands index fcb7375d71..fc3b037ecc 100644 --- a/cime_config/usermods_dirs/PLUMBER2/AU-Cpr/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Cpr/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_AU-Cpr_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/AU-Cpr/CLM1PT_data/CTSM_DATM_AU-Cpr_2011-2017.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Ctr/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Ctr/shell_commands index 8d42bed60a..6710134c78 100644 --- a/cime_config/usermods_dirs/PLUMBER2/AU-Ctr/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Ctr/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_AU-Ctr_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/AU-Ctr/CLM1PT_data/CTSM_DATM_AU-Ctr_2010-2017.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Cum/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Cum/shell_commands index 17aed3a1dd..a2022818c6 100644 --- a/cime_config/usermods_dirs/PLUMBER2/AU-Cum/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Cum/shell_commands @@ -1,11 +1,11 @@ +./xmlchange PLUMBER2SITE=AU-Cum ./xmlchange PTS_LON=150.722473 -./xmlchange PTS_LAT=-33.613296999999996 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_AU-Cum_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/AU-Cum/CLM1PT_data/CTSM_DATM_AU-Cum_2013-2018.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-DaP/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-DaP/shell_commands index 816e4c78dc..28b5b4b446 100644 --- a/cime_config/usermods_dirs/PLUMBER2/AU-DaP/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/AU-DaP/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_AU-DaP_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/AU-DaP/CLM1PT_data/CTSM_DATM_AU-DaP_2009-2012.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-DaS/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-DaS/shell_commands index 0ea37fd95a..96acb7b7cf 100644 --- a/cime_config/usermods_dirs/PLUMBER2/AU-DaS/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/AU-DaS/shell_commands @@ -1,11 +1,11 @@ +./xmlchange PLUMBER2SITE=AU-DaS ./xmlchange PTS_LON=131.388 -./xmlchange PTS_LAT=-14.159282999999999 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_AU-DaS_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/AU-DaS/CLM1PT_data/CTSM_DATM_AU-DaS_2010-2017.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Dry/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Dry/shell_commands index 3cd8faecd9..da520bb88e 100644 --- a/cime_config/usermods_dirs/PLUMBER2/AU-Dry/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Dry/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_AU-Dry_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/AU-Dry/CLM1PT_data/CTSM_DATM_AU-Dry_2011-2015.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Emr/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Emr/shell_commands index 7822948582..a5ccf45884 100644 --- a/cime_config/usermods_dirs/PLUMBER2/AU-Emr/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Emr/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_AU-Emr_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/AU-Emr/CLM1PT_data/CTSM_DATM_AU-Emr_2012-2013.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-GWW/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-GWW/shell_commands index 258ee5f12a..637c921fae 100644 --- a/cime_config/usermods_dirs/PLUMBER2/AU-GWW/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/AU-GWW/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_AU-GWW_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/AU-GWW/CLM1PT_data/CTSM_DATM_AU-GWW_2013-2017.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Gin/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Gin/shell_commands index 31071a2ebb..e02f3482ed 100644 --- a/cime_config/usermods_dirs/PLUMBER2/AU-Gin/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Gin/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_AU-Gin_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/AU-Gin/CLM1PT_data/CTSM_DATM_AU-Gin_2012-2017.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-How/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-How/shell_commands index 411cec6d9c..448f24cc4f 100644 --- a/cime_config/usermods_dirs/PLUMBER2/AU-How/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/AU-How/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_AU-How_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/AU-How/CLM1PT_data/CTSM_DATM_AU-How_2003-2017.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Lit/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Lit/shell_commands index 7fc59ce824..6e69bbc5d2 100644 --- a/cime_config/usermods_dirs/PLUMBER2/AU-Lit/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Lit/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=130.79449499999998 -./xmlchange PTS_LAT=-13.179039999999999 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_AU-Lit_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/AU-Lit/CLM1PT_data/CTSM_DATM_AU-Lit_2016-2017.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Otw/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Otw/shell_commands index 6671c26040..c3962c1b33 100644 --- a/cime_config/usermods_dirs/PLUMBER2/AU-Otw/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Otw/shell_commands @@ -1,11 +1,11 @@ +./xmlchange PLUMBER2SITE=AU-Otw ./xmlchange PTS_LON=142.816803 -./xmlchange PTS_LAT=-38.532340999999995 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_AU-Otw_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/AU-Otw/CLM1PT_data/CTSM_DATM_AU-Otw_2009-2010.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Rig/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Rig/shell_commands index db70e72c89..fc5ecba950 100644 --- a/cime_config/usermods_dirs/PLUMBER2/AU-Rig/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Rig/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_AU-Rig_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/AU-Rig/CLM1PT_data/CTSM_DATM_AU-Rig_2011-2016.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Rob/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Rob/shell_commands index 33e2084f14..6e640a50fa 100644 --- a/cime_config/usermods_dirs/PLUMBER2/AU-Rob/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Rob/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_AU-Rob_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/AU-Rob/CLM1PT_data/CTSM_DATM_AU-Rob_2014-2017.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Sam/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Sam/shell_commands index 561ba257fa..1f48d3060f 100644 --- a/cime_config/usermods_dirs/PLUMBER2/AU-Sam/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Sam/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=152.87780800000002 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_AU-Sam_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/AU-Sam/CLM1PT_data/CTSM_DATM_AU-Sam_2011-2017.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Stp/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Stp/shell_commands index 97db87c821..949257e09f 100644 --- a/cime_config/usermods_dirs/PLUMBER2/AU-Stp/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Stp/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_AU-Stp_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/AU-Stp/CLM1PT_data/CTSM_DATM_AU-Stp_2010-2017.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-TTE/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-TTE/shell_commands index dee6244ef7..ca7b84c598 100644 --- a/cime_config/usermods_dirs/PLUMBER2/AU-TTE/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/AU-TTE/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_AU-TTE_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/AU-TTE/CLM1PT_data/CTSM_DATM_AU-TTE_2013-2017.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Tum/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Tum/shell_commands index 36cd89bc73..5ad2d9dce2 100644 --- a/cime_config/usermods_dirs/PLUMBER2/AU-Tum/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Tum/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_AU-Tum_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/AU-Tum/CLM1PT_data/CTSM_DATM_AU-Tum_2002-2017.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Whr/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Whr/shell_commands index 6b5d9415fe..250e8f049e 100644 --- a/cime_config/usermods_dirs/PLUMBER2/AU-Whr/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Whr/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_AU-Whr_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/AU-Whr/CLM1PT_data/CTSM_DATM_AU-Whr_2015-2016.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Wrr/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Wrr/shell_commands index e1751b8439..c96c57a93f 100644 --- a/cime_config/usermods_dirs/PLUMBER2/AU-Wrr/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Wrr/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_AU-Wrr_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/AU-Wrr/CLM1PT_data/CTSM_DATM_AU-Wrr_2016-2017.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/AU-Ync/shell_commands b/cime_config/usermods_dirs/PLUMBER2/AU-Ync/shell_commands index 861c844b14..cc5b8909d7 100644 --- a/cime_config/usermods_dirs/PLUMBER2/AU-Ync/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/AU-Ync/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_AU-Ync_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/AU-Ync/CLM1PT_data/CTSM_DATM_AU-Ync_2011-2017.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/BE-Bra/shell_commands b/cime_config/usermods_dirs/PLUMBER2/BE-Bra/shell_commands index 5aeefbc792..93bf56051e 100644 --- a/cime_config/usermods_dirs/PLUMBER2/BE-Bra/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/BE-Bra/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_BE-Bra_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/BE-Bra/CLM1PT_data/CTSM_DATM_BE-Bra_2004-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/BE-Lon/shell_commands b/cime_config/usermods_dirs/PLUMBER2/BE-Lon/shell_commands index 959a9e88fa..597961e426 100644 --- a/cime_config/usermods_dirs/PLUMBER2/BE-Lon/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/BE-Lon/shell_commands @@ -1,11 +1,11 @@ +./xmlchange PLUMBER2SITE=BE-Lon ./xmlchange PTS_LON=4.74613 -./xmlchange PTS_LAT=50.551590000000004 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_BE-Lon_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/BE-Lon/CLM1PT_data/CTSM_DATM_BE-Lon_2005-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/BE-Vie/shell_commands b/cime_config/usermods_dirs/PLUMBER2/BE-Vie/shell_commands index 008d71407c..2a97262b87 100644 --- a/cime_config/usermods_dirs/PLUMBER2/BE-Vie/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/BE-Vie/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_BE-Vie_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/BE-Vie/CLM1PT_data/CTSM_DATM_BE-Vie_1997-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/BR-Sa3/shell_commands b/cime_config/usermods_dirs/PLUMBER2/BR-Sa3/shell_commands index c1277c1198..ec8d9bc33a 100644 --- a/cime_config/usermods_dirs/PLUMBER2/BR-Sa3/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/BR-Sa3/shell_commands @@ -1,11 +1,11 @@ +./xmlchange PLUMBER2SITE=BR-Sa3 ./xmlchange PTS_LON=-54.971436 -./xmlchange PTS_LAT=-3.0180290000000003 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_BR-Sa3_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/BR-Sa3/CLM1PT_data/CTSM_DATM_BR-Sa3_2001-2003.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/BW-Ma1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/BW-Ma1/shell_commands index b2e5f88222..64af7dc90f 100644 --- a/cime_config/usermods_dirs/PLUMBER2/BW-Ma1/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/BW-Ma1/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_BW-Ma1_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/BW-Ma1/CLM1PT_data/CTSM_DATM_BW-Ma1_2000-2000.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-NS1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CA-NS1/shell_commands index adb752cea8..9b4f8d74ec 100644 --- a/cime_config/usermods_dirs/PLUMBER2/CA-NS1/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/CA-NS1/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_CA-NS1_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/CA-NS1/CLM1PT_data/CTSM_DATM_CA-NS1_2003-2003.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-NS2/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CA-NS2/shell_commands index bb25a4ad93..5563971afc 100644 --- a/cime_config/usermods_dirs/PLUMBER2/CA-NS2/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/CA-NS2/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_CA-NS2_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/CA-NS2/CLM1PT_data/CTSM_DATM_CA-NS2_2002-2004.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-NS4/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CA-NS4/shell_commands index 733537f009..d6ddd551af 100644 --- a/cime_config/usermods_dirs/PLUMBER2/CA-NS4/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/CA-NS4/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_CA-NS4_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/CA-NS4/CLM1PT_data/CTSM_DATM_CA-NS4_2003-2004.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-NS5/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CA-NS5/shell_commands index 491bc27b99..49a320a37d 100644 --- a/cime_config/usermods_dirs/PLUMBER2/CA-NS5/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/CA-NS5/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_CA-NS5_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/CA-NS5/CLM1PT_data/CTSM_DATM_CA-NS5_2003-2004.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-NS6/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CA-NS6/shell_commands index 3a1b6a7b0f..c5097e87ec 100644 --- a/cime_config/usermods_dirs/PLUMBER2/CA-NS6/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/CA-NS6/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_CA-NS6_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/CA-NS6/CLM1PT_data/CTSM_DATM_CA-NS6_2002-2004.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-NS7/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CA-NS7/shell_commands index 735c947bfe..583c102ae0 100644 --- a/cime_config/usermods_dirs/PLUMBER2/CA-NS7/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/CA-NS7/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=-99.94830300000001 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_CA-NS7_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/CA-NS7/CLM1PT_data/CTSM_DATM_CA-NS7_2003-2004.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-Qcu/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CA-Qcu/shell_commands index c7123ae573..892029da56 100644 --- a/cime_config/usermods_dirs/PLUMBER2/CA-Qcu/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/CA-Qcu/shell_commands @@ -1,11 +1,11 @@ +./xmlchange PLUMBER2SITE=CA-Qcu ./xmlchange PTS_LON=-74.03653 -./xmlchange PTS_LAT=49.267078000000005 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_CA-Qcu_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/CA-Qcu/CLM1PT_data/CTSM_DATM_CA-Qcu_2002-2006.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-Qfo/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CA-Qfo/shell_commands index fb7fc215c9..3f61fbd901 100644 --- a/cime_config/usermods_dirs/PLUMBER2/CA-Qfo/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/CA-Qfo/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_CA-Qfo_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/CA-Qfo/CLM1PT_data/CTSM_DATM_CA-Qfo_2004-2010.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-SF1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CA-SF1/shell_commands index ed6c584b7c..49de04986c 100644 --- a/cime_config/usermods_dirs/PLUMBER2/CA-SF1/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/CA-SF1/shell_commands @@ -1,11 +1,11 @@ +./xmlchange PLUMBER2SITE=CA-SF1 ./xmlchange PTS_LON=-105.817596 -./xmlchange PTS_LAT=54.485001000000004 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_CA-SF1_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/CA-SF1/CLM1PT_data/CTSM_DATM_CA-SF1_2004-2006.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-SF2/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CA-SF2/shell_commands index 1fffcfdac9..5cc0da8be1 100644 --- a/cime_config/usermods_dirs/PLUMBER2/CA-SF2/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/CA-SF2/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_CA-SF2_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/CA-SF2/CLM1PT_data/CTSM_DATM_CA-SF2_2003-2005.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/CA-SF3/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CA-SF3/shell_commands index 03096c96fa..3f94c02ca9 100644 --- a/cime_config/usermods_dirs/PLUMBER2/CA-SF3/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/CA-SF3/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=-106.00531000000001 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_CA-SF3_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/CA-SF3/CLM1PT_data/CTSM_DATM_CA-SF3_2003-2005.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/CH-Cha/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CH-Cha/shell_commands index 1e2590a7ae..ca0ad87518 100644 --- a/cime_config/usermods_dirs/PLUMBER2/CH-Cha/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/CH-Cha/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_CH-Cha_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/CH-Cha/CLM1PT_data/CTSM_DATM_CH-Cha_2006-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/CH-Dav/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CH-Dav/shell_commands index c170c8b840..254c30865a 100644 --- a/cime_config/usermods_dirs/PLUMBER2/CH-Dav/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/CH-Dav/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_CH-Dav_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/CH-Dav/CLM1PT_data/CTSM_DATM_CH-Dav_1997-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/CH-Fru/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CH-Fru/shell_commands index 31e5163045..617ed84d7c 100644 --- a/cime_config/usermods_dirs/PLUMBER2/CH-Fru/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/CH-Fru/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_CH-Fru_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/CH-Fru/CLM1PT_data/CTSM_DATM_CH-Fru_2007-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/CH-Oe1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CH-Oe1/shell_commands index ee091e134e..6fb4f3a844 100644 --- a/cime_config/usermods_dirs/PLUMBER2/CH-Oe1/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/CH-Oe1/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_CH-Oe1_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/CH-Oe1/CLM1PT_data/CTSM_DATM_CH-Oe1_2002-2008.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/CN-Cha/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CN-Cha/shell_commands index cde3fed3be..f6da50bde1 100644 --- a/cime_config/usermods_dirs/PLUMBER2/CN-Cha/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/CN-Cha/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=128.09579499999998 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_CN-Cha_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/CN-Cha/CLM1PT_data/CTSM_DATM_CN-Cha_2003-2005.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/CN-Cng/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CN-Cng/shell_commands index d5ec208a05..648c844408 100644 --- a/cime_config/usermods_dirs/PLUMBER2/CN-Cng/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/CN-Cng/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_CN-Cng_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/CN-Cng/CLM1PT_data/CTSM_DATM_CN-Cng_2008-2009.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/CN-Dan/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CN-Dan/shell_commands index 674ce4dda4..9616c9d792 100644 --- a/cime_config/usermods_dirs/PLUMBER2/CN-Dan/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/CN-Dan/shell_commands @@ -1,11 +1,11 @@ +./xmlchange PLUMBER2SITE=CN-Dan ./xmlchange PTS_LON=91.066399 -./xmlchange PTS_LAT=30.497801000000003 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_CN-Dan_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/CN-Dan/CLM1PT_data/CTSM_DATM_CN-Dan_2004-2005.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/CN-Din/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CN-Din/shell_commands index b9149c7d8a..c30e651178 100644 --- a/cime_config/usermods_dirs/PLUMBER2/CN-Din/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/CN-Din/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_CN-Din_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/CN-Din/CLM1PT_data/CTSM_DATM_CN-Din_2003-2005.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/CN-Du2/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CN-Du2/shell_commands index 42502b41ce..d46dec7f7d 100644 --- a/cime_config/usermods_dirs/PLUMBER2/CN-Du2/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/CN-Du2/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_CN-Du2_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/CN-Du2/CLM1PT_data/CTSM_DATM_CN-Du2_2007-2008.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/CN-HaM/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CN-HaM/shell_commands index 95c4167bf0..91d489b75b 100644 --- a/cime_config/usermods_dirs/PLUMBER2/CN-HaM/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/CN-HaM/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_CN-HaM_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/CN-HaM/CLM1PT_data/CTSM_DATM_CN-HaM_2002-2003.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/CN-Qia/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CN-Qia/shell_commands index 401534e487..484175aa93 100644 --- a/cime_config/usermods_dirs/PLUMBER2/CN-Qia/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/CN-Qia/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_CN-Qia_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/CN-Qia/CLM1PT_data/CTSM_DATM_CN-Qia_2003-2005.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/CZ-wet/shell_commands b/cime_config/usermods_dirs/PLUMBER2/CZ-wet/shell_commands index 20309cdcb3..7c753c4183 100644 --- a/cime_config/usermods_dirs/PLUMBER2/CZ-wet/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/CZ-wet/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_CZ-wet_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/CZ-wet/CLM1PT_data/CTSM_DATM_CZ-wet_2007-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Bay/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DE-Bay/shell_commands index 6495d46b57..55c14aac5f 100644 --- a/cime_config/usermods_dirs/PLUMBER2/DE-Bay/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Bay/shell_commands @@ -1,11 +1,11 @@ +./xmlchange PLUMBER2SITE=DE-Bay ./xmlchange PTS_LON=11.86694 -./xmlchange PTS_LAT=50.141940999999996 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_DE-Bay_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/DE-Bay/CLM1PT_data/CTSM_DATM_DE-Bay_1997-1999.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Geb/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DE-Geb/shell_commands index d43c3bd94d..d57138be71 100644 --- a/cime_config/usermods_dirs/PLUMBER2/DE-Geb/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Geb/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_DE-Geb_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/DE-Geb/CLM1PT_data/CTSM_DATM_DE-Geb_2001-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Gri/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DE-Gri/shell_commands index fe165d2bf3..5a27ee5e20 100644 --- a/cime_config/usermods_dirs/PLUMBER2/DE-Gri/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Gri/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=13.512529999999998 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_DE-Gri_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/DE-Gri/CLM1PT_data/CTSM_DATM_DE-Gri_2004-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Hai/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DE-Hai/shell_commands index fa5671c663..55124b7900 100644 --- a/cime_config/usermods_dirs/PLUMBER2/DE-Hai/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Hai/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_DE-Hai_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/DE-Hai/CLM1PT_data/CTSM_DATM_DE-Hai_2000-2012.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Kli/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DE-Kli/shell_commands index 28fb89a2d0..860b100586 100644 --- a/cime_config/usermods_dirs/PLUMBER2/DE-Kli/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Kli/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=13.522379999999998 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_DE-Kli_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/DE-Kli/CLM1PT_data/CTSM_DATM_DE-Kli_2005-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Meh/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DE-Meh/shell_commands index 250432bd9f..b94a90e206 100644 --- a/cime_config/usermods_dirs/PLUMBER2/DE-Meh/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Meh/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_DE-Meh_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/DE-Meh/CLM1PT_data/CTSM_DATM_DE-Meh_2004-2006.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Obe/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DE-Obe/shell_commands index ef17febde0..e633f65987 100644 --- a/cime_config/usermods_dirs/PLUMBER2/DE-Obe/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Obe/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_DE-Obe_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/DE-Obe/CLM1PT_data/CTSM_DATM_DE-Obe_2008-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Seh/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DE-Seh/shell_commands index db837ac070..c6808b0bf1 100644 --- a/cime_config/usermods_dirs/PLUMBER2/DE-Seh/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Seh/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_DE-Seh_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/DE-Seh/CLM1PT_data/CTSM_DATM_DE-Seh_2008-2010.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-SfN/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DE-SfN/shell_commands index bcff32c36a..639a2c5195 100644 --- a/cime_config/usermods_dirs/PLUMBER2/DE-SfN/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/DE-SfN/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_DE-SfN_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/DE-SfN/CLM1PT_data/CTSM_DATM_DE-SfN_2013-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Tha/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DE-Tha/shell_commands index aa6beb5913..66055b2ee2 100644 --- a/cime_config/usermods_dirs/PLUMBER2/DE-Tha/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Tha/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=13.566939999999999 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_DE-Tha_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/DE-Tha/CLM1PT_data/CTSM_DATM_DE-Tha_1998-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/DE-Wet/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DE-Wet/shell_commands index 12d6f2024d..de0ad17a95 100644 --- a/cime_config/usermods_dirs/PLUMBER2/DE-Wet/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/DE-Wet/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_DE-Wet_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/DE-Wet/CLM1PT_data/CTSM_DATM_DE-Wet_2002-2006.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/DK-Fou/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DK-Fou/shell_commands index a4a472424e..581fd31324 100644 --- a/cime_config/usermods_dirs/PLUMBER2/DK-Fou/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/DK-Fou/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_DK-Fou_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/DK-Fou/CLM1PT_data/CTSM_DATM_DK-Fou_2005-2005.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/DK-Lva/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DK-Lva/shell_commands index 962775613e..b1a1955519 100644 --- a/cime_config/usermods_dirs/PLUMBER2/DK-Lva/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/DK-Lva/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_DK-Lva_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/DK-Lva/CLM1PT_data/CTSM_DATM_DK-Lva_2005-2006.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/DK-Ris/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DK-Ris/shell_commands index 4c806cea45..86fcb0ba10 100644 --- a/cime_config/usermods_dirs/PLUMBER2/DK-Ris/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/DK-Ris/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_DK-Ris_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/DK-Ris/CLM1PT_data/CTSM_DATM_DK-Ris_2004-2005.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/DK-Sor/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DK-Sor/shell_commands index 1748d52204..046e9559d2 100644 --- a/cime_config/usermods_dirs/PLUMBER2/DK-Sor/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/DK-Sor/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=11.644639999999999 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_DK-Sor_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/DK-Sor/CLM1PT_data/CTSM_DATM_DK-Sor_1997-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/DK-ZaH/shell_commands b/cime_config/usermods_dirs/PLUMBER2/DK-ZaH/shell_commands index ea72cc14c4..234c5e8ba7 100644 --- a/cime_config/usermods_dirs/PLUMBER2/DK-ZaH/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/DK-ZaH/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_DK-ZaH_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/DK-ZaH/CLM1PT_data/CTSM_DATM_DK-ZaH_2000-2013.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/ES-ES1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/ES-ES1/shell_commands index 38e841b51c..9947bb0014 100644 --- a/cime_config/usermods_dirs/PLUMBER2/ES-ES1/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/ES-ES1/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_ES-ES1_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/ES-ES1/CLM1PT_data/CTSM_DATM_ES-ES1_1999-2006.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/ES-ES2/shell_commands b/cime_config/usermods_dirs/PLUMBER2/ES-ES2/shell_commands index 47fae079e6..235ddfbb32 100644 --- a/cime_config/usermods_dirs/PLUMBER2/ES-ES2/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/ES-ES2/shell_commands @@ -1,11 +1,11 @@ +./xmlchange PLUMBER2SITE=ES-ES2 ./xmlchange PTS_LON=-0.315277 -./xmlchange PTS_LAT=39.275558000000004 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_ES-ES2_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/ES-ES2/CLM1PT_data/CTSM_DATM_ES-ES2_2005-2006.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/ES-LMa/shell_commands b/cime_config/usermods_dirs/PLUMBER2/ES-LMa/shell_commands index f8a0283232..c0c83dbbd2 100644 --- a/cime_config/usermods_dirs/PLUMBER2/ES-LMa/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/ES-LMa/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_ES-LMa_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/ES-LMa/CLM1PT_data/CTSM_DATM_ES-LMa_2004-2006.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/ES-LgS/shell_commands b/cime_config/usermods_dirs/PLUMBER2/ES-LgS/shell_commands index 8590e61f79..454de1a378 100644 --- a/cime_config/usermods_dirs/PLUMBER2/ES-LgS/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/ES-LgS/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_ES-LgS_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/ES-LgS/CLM1PT_data/CTSM_DATM_ES-LgS_2007-2007.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/ES-VDA/shell_commands b/cime_config/usermods_dirs/PLUMBER2/ES-VDA/shell_commands index bec50968d6..0de3a761a7 100644 --- a/cime_config/usermods_dirs/PLUMBER2/ES-VDA/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/ES-VDA/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_ES-VDA_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/ES-VDA/CLM1PT_data/CTSM_DATM_ES-VDA_2004-2004.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/FI-Hyy/shell_commands b/cime_config/usermods_dirs/PLUMBER2/FI-Hyy/shell_commands index 46cd461773..1861c4a0b6 100644 --- a/cime_config/usermods_dirs/PLUMBER2/FI-Hyy/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/FI-Hyy/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_FI-Hyy_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/FI-Hyy/CLM1PT_data/CTSM_DATM_FI-Hyy_1996-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/FI-Kaa/shell_commands b/cime_config/usermods_dirs/PLUMBER2/FI-Kaa/shell_commands index db4e320ca0..9f7b8a0763 100644 --- a/cime_config/usermods_dirs/PLUMBER2/FI-Kaa/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/FI-Kaa/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=27.295030999999998 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_FI-Kaa_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/FI-Kaa/CLM1PT_data/CTSM_DATM_FI-Kaa_2000-2002.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/FI-Lom/shell_commands b/cime_config/usermods_dirs/PLUMBER2/FI-Lom/shell_commands index 844403dfc4..14c28c1475 100644 --- a/cime_config/usermods_dirs/PLUMBER2/FI-Lom/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/FI-Lom/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_FI-Lom_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/FI-Lom/CLM1PT_data/CTSM_DATM_FI-Lom_2007-2009.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/FI-Sod/shell_commands b/cime_config/usermods_dirs/PLUMBER2/FI-Sod/shell_commands index be6e3a2eba..7eccb754fb 100644 --- a/cime_config/usermods_dirs/PLUMBER2/FI-Sod/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/FI-Sod/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_FI-Sod_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/FI-Sod/CLM1PT_data/CTSM_DATM_FI-Sod_2008-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/FR-Fon/shell_commands b/cime_config/usermods_dirs/PLUMBER2/FR-Fon/shell_commands index 946c9b84fc..76a71ab3b2 100644 --- a/cime_config/usermods_dirs/PLUMBER2/FR-Fon/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/FR-Fon/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=2.7801400000000003 -./xmlchange PTS_LAT=48.476397999999996 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_FR-Fon_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/FR-Fon/CLM1PT_data/CTSM_DATM_FR-Fon_2005-2013.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/FR-Gri/shell_commands b/cime_config/usermods_dirs/PLUMBER2/FR-Gri/shell_commands index fd29463244..5c575b0e97 100644 --- a/cime_config/usermods_dirs/PLUMBER2/FR-Gri/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/FR-Gri/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=1.9519099999999998 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_FR-Gri_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/FR-Gri/CLM1PT_data/CTSM_DATM_FR-Gri_2005-2013.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/FR-Hes/shell_commands b/cime_config/usermods_dirs/PLUMBER2/FR-Hes/shell_commands index 88900143b1..1d8ab25532 100644 --- a/cime_config/usermods_dirs/PLUMBER2/FR-Hes/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/FR-Hes/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=7.0655600000000005 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_FR-Hes_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/FR-Hes/CLM1PT_data/CTSM_DATM_FR-Hes_1997-2006.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/FR-LBr/shell_commands b/cime_config/usermods_dirs/PLUMBER2/FR-LBr/shell_commands index 29c9c95ab7..6b9eb48062 100644 --- a/cime_config/usermods_dirs/PLUMBER2/FR-LBr/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/FR-LBr/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=-0.7692869999999999 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_FR-LBr_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/FR-LBr/CLM1PT_data/CTSM_DATM_FR-LBr_2003-2008.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/FR-Lq1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/FR-Lq1/shell_commands index 676f8af611..000fc6d746 100644 --- a/cime_config/usermods_dirs/PLUMBER2/FR-Lq1/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/FR-Lq1/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_FR-Lq1_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/FR-Lq1/CLM1PT_data/CTSM_DATM_FR-Lq1_2004-2006.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/FR-Lq2/shell_commands b/cime_config/usermods_dirs/PLUMBER2/FR-Lq2/shell_commands index b407160bb9..a851919f73 100644 --- a/cime_config/usermods_dirs/PLUMBER2/FR-Lq2/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/FR-Lq2/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_FR-Lq2_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/FR-Lq2/CLM1PT_data/CTSM_DATM_FR-Lq2_2004-2006.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/FR-Pue/shell_commands b/cime_config/usermods_dirs/PLUMBER2/FR-Pue/shell_commands index b226175943..1981d675fc 100644 --- a/cime_config/usermods_dirs/PLUMBER2/FR-Pue/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/FR-Pue/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=3.5958300000000003 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_FR-Pue_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/FR-Pue/CLM1PT_data/CTSM_DATM_FR-Pue_2000-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/GF-Guy/shell_commands b/cime_config/usermods_dirs/PLUMBER2/GF-Guy/shell_commands index 1fef6cf769..1f10f4a2e1 100644 --- a/cime_config/usermods_dirs/PLUMBER2/GF-Guy/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/GF-Guy/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_GF-Guy_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/GF-Guy/CLM1PT_data/CTSM_DATM_GF-Guy_2004-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/HU-Bug/shell_commands b/cime_config/usermods_dirs/PLUMBER2/HU-Bug/shell_commands index a4cf969235..54b635a2a2 100644 --- a/cime_config/usermods_dirs/PLUMBER2/HU-Bug/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/HU-Bug/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=19.601298999999997 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_HU-Bug_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/HU-Bug/CLM1PT_data/CTSM_DATM_HU-Bug_2003-2006.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/ID-Pag/shell_commands b/cime_config/usermods_dirs/PLUMBER2/ID-Pag/shell_commands index 794fdabba3..13ac0e386f 100644 --- a/cime_config/usermods_dirs/PLUMBER2/ID-Pag/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/ID-Pag/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=114.03639199999999 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_ID-Pag_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/ID-Pag/CLM1PT_data/CTSM_DATM_ID-Pag_2002-2003.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/IE-Ca1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IE-Ca1/shell_commands index 376f21bf88..2bd80343c3 100644 --- a/cime_config/usermods_dirs/PLUMBER2/IE-Ca1/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/IE-Ca1/shell_commands @@ -1,11 +1,11 @@ +./xmlchange PLUMBER2SITE=IE-Ca1 ./xmlchange PTS_LON=-6.918152 -./xmlchange PTS_LAT=52.858791000000004 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_IE-Ca1_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/IE-Ca1/CLM1PT_data/CTSM_DATM_IE-Ca1_2004-2006.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/IE-Dri/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IE-Dri/shell_commands index 34bf806e19..4f27411509 100644 --- a/cime_config/usermods_dirs/PLUMBER2/IE-Dri/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/IE-Dri/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=-8.751800999999999 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_IE-Dri_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/IE-Dri/CLM1PT_data/CTSM_DATM_IE-Dri_2003-2005.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Amp/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-Amp/shell_commands index d0f80bd240..aa7fef51ae 100644 --- a/cime_config/usermods_dirs/PLUMBER2/IT-Amp/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Amp/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_IT-Amp_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/IT-Amp/CLM1PT_data/CTSM_DATM_IT-Amp_2003-2006.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-BCi/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-BCi/shell_commands index 5c95ebd5cb..0c620a348c 100644 --- a/cime_config/usermods_dirs/PLUMBER2/IT-BCi/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/IT-BCi/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_IT-BCi_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/IT-BCi/CLM1PT_data/CTSM_DATM_IT-BCi_2005-2010.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-CA1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-CA1/shell_commands index 4218939b8e..831b7897c0 100644 --- a/cime_config/usermods_dirs/PLUMBER2/IT-CA1/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/IT-CA1/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_IT-CA1_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/IT-CA1/CLM1PT_data/CTSM_DATM_IT-CA1_2012-2013.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-CA2/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-CA2/shell_commands index f3e82597af..dfae27f215 100644 --- a/cime_config/usermods_dirs/PLUMBER2/IT-CA2/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/IT-CA2/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_IT-CA2_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/IT-CA2/CLM1PT_data/CTSM_DATM_IT-CA2_2012-2013.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-CA3/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-CA3/shell_commands index de8970f1e3..a3a2ab6c25 100644 --- a/cime_config/usermods_dirs/PLUMBER2/IT-CA3/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/IT-CA3/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_IT-CA3_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/IT-CA3/CLM1PT_data/CTSM_DATM_IT-CA3_2012-2013.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Col/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-Col/shell_commands index 37ab868476..eb817ab43c 100644 --- a/cime_config/usermods_dirs/PLUMBER2/IT-Col/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Col/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_IT-Col_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/IT-Col/CLM1PT_data/CTSM_DATM_IT-Col_2007-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Cpz/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-Cpz/shell_commands index e7bc47b3b0..cfad8adb35 100644 --- a/cime_config/usermods_dirs/PLUMBER2/IT-Cpz/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Cpz/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_IT-Cpz_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/IT-Cpz/CLM1PT_data/CTSM_DATM_IT-Cpz_2001-2008.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Isp/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-Isp/shell_commands index 6cf225d172..125257acd7 100644 --- a/cime_config/usermods_dirs/PLUMBER2/IT-Isp/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Isp/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_IT-Isp_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/IT-Isp/CLM1PT_data/CTSM_DATM_IT-Isp_2013-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-LMa/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-LMa/shell_commands index 8b388aedb4..bca26018b9 100644 --- a/cime_config/usermods_dirs/PLUMBER2/IT-LMa/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/IT-LMa/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_IT-LMa_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/IT-LMa/CLM1PT_data/CTSM_DATM_IT-LMa_2003-2004.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Lav/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-Lav/shell_commands index 1f7f728803..87f8e9d947 100644 --- a/cime_config/usermods_dirs/PLUMBER2/IT-Lav/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Lav/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_IT-Lav_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/IT-Lav/CLM1PT_data/CTSM_DATM_IT-Lav_2005-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-MBo/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-MBo/shell_commands index 26ffc80458..ab42d7a3d8 100644 --- a/cime_config/usermods_dirs/PLUMBER2/IT-MBo/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/IT-MBo/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_IT-MBo_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/IT-MBo/CLM1PT_data/CTSM_DATM_IT-MBo_2003-2012.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Mal/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-Mal/shell_commands index 6559976180..8cf5fdd6d0 100644 --- a/cime_config/usermods_dirs/PLUMBER2/IT-Mal/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Mal/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=11.703339999999999 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_IT-Mal_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/IT-Mal/CLM1PT_data/CTSM_DATM_IT-Mal_2003-2003.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Noe/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-Noe/shell_commands index 58be23bcd1..8b12cb84db 100644 --- a/cime_config/usermods_dirs/PLUMBER2/IT-Noe/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Noe/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_IT-Noe_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/IT-Noe/CLM1PT_data/CTSM_DATM_IT-Noe_2004-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Non/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-Non/shell_commands index 785443e0f1..c8b4f77f4d 100644 --- a/cime_config/usermods_dirs/PLUMBER2/IT-Non/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Non/shell_commands @@ -1,11 +1,11 @@ +./xmlchange PLUMBER2SITE=IT-Non ./xmlchange PTS_LON=11.09109 -./xmlchange PTS_LAT=44.690189000000004 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_IT-Non_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/IT-Non/CLM1PT_data/CTSM_DATM_IT-Non_2002-2002.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-PT1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-PT1/shell_commands index e7c30a4e36..629382cea8 100644 --- a/cime_config/usermods_dirs/PLUMBER2/IT-PT1/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/IT-PT1/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_IT-PT1_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/IT-PT1/CLM1PT_data/CTSM_DATM_IT-PT1_2003-2004.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Ren/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-Ren/shell_commands index dc1b5630d0..ebf7cdb500 100644 --- a/cime_config/usermods_dirs/PLUMBER2/IT-Ren/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Ren/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=11.433689999999999 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_IT-Ren_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/IT-Ren/CLM1PT_data/CTSM_DATM_IT-Ren_2010-2013.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Ro1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-Ro1/shell_commands index 865f76ae9b..b400216f9b 100644 --- a/cime_config/usermods_dirs/PLUMBER2/IT-Ro1/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Ro1/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=11.930010000000001 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_IT-Ro1_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/IT-Ro1/CLM1PT_data/CTSM_DATM_IT-Ro1_2002-2006.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-Ro2/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-Ro2/shell_commands index 401cfcf30b..195c0fdbc9 100644 --- a/cime_config/usermods_dirs/PLUMBER2/IT-Ro2/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/IT-Ro2/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_IT-Ro2_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/IT-Ro2/CLM1PT_data/CTSM_DATM_IT-Ro2_2002-2008.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-SR2/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-SR2/shell_commands index 7926235386..d981029a77 100644 --- a/cime_config/usermods_dirs/PLUMBER2/IT-SR2/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/IT-SR2/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_IT-SR2_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/IT-SR2/CLM1PT_data/CTSM_DATM_IT-SR2_2013-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/IT-SRo/shell_commands b/cime_config/usermods_dirs/PLUMBER2/IT-SRo/shell_commands index 8dbeedc751..c40b2d8f71 100644 --- a/cime_config/usermods_dirs/PLUMBER2/IT-SRo/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/IT-SRo/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_IT-SRo_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/IT-SRo/CLM1PT_data/CTSM_DATM_IT-SRo_2003-2012.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/JP-SMF/shell_commands b/cime_config/usermods_dirs/PLUMBER2/JP-SMF/shell_commands index 6af519cf5d..c93dfef557 100644 --- a/cime_config/usermods_dirs/PLUMBER2/JP-SMF/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/JP-SMF/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=137.07879599999998 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_JP-SMF_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/JP-SMF/CLM1PT_data/CTSM_DATM_JP-SMF_2003-2006.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/NL-Ca1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/NL-Ca1/shell_commands index 26b6fda5a4..ccb1290e78 100644 --- a/cime_config/usermods_dirs/PLUMBER2/NL-Ca1/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/NL-Ca1/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_NL-Ca1_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/NL-Ca1/CLM1PT_data/CTSM_DATM_NL-Ca1_2003-2006.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/NL-Hor/shell_commands b/cime_config/usermods_dirs/PLUMBER2/NL-Hor/shell_commands index ec509840af..08eb58d8a1 100644 --- a/cime_config/usermods_dirs/PLUMBER2/NL-Hor/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/NL-Hor/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_NL-Hor_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/NL-Hor/CLM1PT_data/CTSM_DATM_NL-Hor_2008-2011.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/NL-Loo/shell_commands b/cime_config/usermods_dirs/PLUMBER2/NL-Loo/shell_commands index 3bcbfbbc35..a09cf39408 100644 --- a/cime_config/usermods_dirs/PLUMBER2/NL-Loo/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/NL-Loo/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=5.7435599999999996 -./xmlchange PTS_LAT=52.166579999999996 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_NL-Loo_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/NL-Loo/CLM1PT_data/CTSM_DATM_NL-Loo_1997-2013.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/PL-wet/shell_commands b/cime_config/usermods_dirs/PLUMBER2/PL-wet/shell_commands index 4eb88c995a..eb79334eeb 100644 --- a/cime_config/usermods_dirs/PLUMBER2/PL-wet/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/PL-wet/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_PL-wet_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/PL-wet/CLM1PT_data/CTSM_DATM_PL-wet_2004-2005.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/PT-Esp/shell_commands b/cime_config/usermods_dirs/PLUMBER2/PT-Esp/shell_commands index 224920cbf7..4186dea491 100644 --- a/cime_config/usermods_dirs/PLUMBER2/PT-Esp/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/PT-Esp/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_PT-Esp_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/PT-Esp/CLM1PT_data/CTSM_DATM_PT-Esp_2002-2004.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/PT-Mi1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/PT-Mi1/shell_commands index 74413f5f5e..36a1899bfc 100644 --- a/cime_config/usermods_dirs/PLUMBER2/PT-Mi1/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/PT-Mi1/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_PT-Mi1_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/PT-Mi1/CLM1PT_data/CTSM_DATM_PT-Mi1_2005-2005.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/PT-Mi2/shell_commands b/cime_config/usermods_dirs/PLUMBER2/PT-Mi2/shell_commands index f9aa12224c..e2986dfac8 100644 --- a/cime_config/usermods_dirs/PLUMBER2/PT-Mi2/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/PT-Mi2/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_PT-Mi2_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/PT-Mi2/CLM1PT_data/CTSM_DATM_PT-Mi2_2005-2006.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/RU-Che/shell_commands b/cime_config/usermods_dirs/PLUMBER2/RU-Che/shell_commands index 4abca52cae..f5172ddb53 100644 --- a/cime_config/usermods_dirs/PLUMBER2/RU-Che/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/RU-Che/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_RU-Che_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/RU-Che/CLM1PT_data/CTSM_DATM_RU-Che_2003-2004.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/RU-Fyo/shell_commands b/cime_config/usermods_dirs/PLUMBER2/RU-Fyo/shell_commands index 74c3693f71..69bab319bc 100644 --- a/cime_config/usermods_dirs/PLUMBER2/RU-Fyo/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/RU-Fyo/shell_commands @@ -1,11 +1,11 @@ +./xmlchange PLUMBER2SITE=RU-Fyo ./xmlchange PTS_LON=32.922081 -./xmlchange PTS_LAT=56.461529000000006 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_RU-Fyo_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/RU-Fyo/CLM1PT_data/CTSM_DATM_RU-Fyo_2003-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/RU-Zot/shell_commands b/cime_config/usermods_dirs/PLUMBER2/RU-Zot/shell_commands index b68d328625..27144db3cb 100644 --- a/cime_config/usermods_dirs/PLUMBER2/RU-Zot/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/RU-Zot/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_RU-Zot_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/RU-Zot/CLM1PT_data/CTSM_DATM_RU-Zot_2003-2003.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/SD-Dem/shell_commands b/cime_config/usermods_dirs/PLUMBER2/SD-Dem/shell_commands index b2e63de838..6d245703d6 100644 --- a/cime_config/usermods_dirs/PLUMBER2/SD-Dem/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/SD-Dem/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_SD-Dem_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/SD-Dem/CLM1PT_data/CTSM_DATM_SD-Dem_2005-2009.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/SE-Deg/shell_commands b/cime_config/usermods_dirs/PLUMBER2/SE-Deg/shell_commands index dfc8e4b83f..0a426dee38 100644 --- a/cime_config/usermods_dirs/PLUMBER2/SE-Deg/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/SE-Deg/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_SE-Deg_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/SE-Deg/CLM1PT_data/CTSM_DATM_SE-Deg_2002-2005.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/UK-Gri/shell_commands b/cime_config/usermods_dirs/PLUMBER2/UK-Gri/shell_commands index efa3a6f1ae..c016bf89a7 100644 --- a/cime_config/usermods_dirs/PLUMBER2/UK-Gri/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/UK-Gri/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=-3.7980650000000002 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_UK-Gri_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/UK-Gri/CLM1PT_data/CTSM_DATM_UK-Gri_2000-2001.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/UK-Ham/shell_commands b/cime_config/usermods_dirs/PLUMBER2/UK-Ham/shell_commands index 47143973d4..f92b9a6d69 100644 --- a/cime_config/usermods_dirs/PLUMBER2/UK-Ham/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/UK-Ham/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=-0.8583069999999999 -./xmlchange PTS_LAT=51.153529999999996 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_UK-Ham_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/UK-Ham/CLM1PT_data/CTSM_DATM_UK-Ham_2004-2004.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/UK-PL3/shell_commands b/cime_config/usermods_dirs/PLUMBER2/UK-PL3/shell_commands index 161de2a08e..10b82dee40 100644 --- a/cime_config/usermods_dirs/PLUMBER2/UK-PL3/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/UK-PL3/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=-1.2666629999999999 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_UK-PL3_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/UK-PL3/CLM1PT_data/CTSM_DATM_UK-PL3_2005-2006.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-AR1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-AR1/shell_commands index 727e21a389..8b3bb18871 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-AR1/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-AR1/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-AR1_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-AR1/CLM1PT_data/CTSM_DATM_US-AR1_2010-2012.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-AR2/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-AR2/shell_commands index 5de187cd7a..0eeaef4fe2 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-AR2/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-AR2/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-AR2_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-AR2/CLM1PT_data/CTSM_DATM_US-AR2_2010-2011.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-ARM/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-ARM/shell_commands index da1de52a6e..4045912f3c 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-ARM/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-ARM/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-ARM_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-ARM/CLM1PT_data/CTSM_DATM_US-ARM_2003-2012.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Aud/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Aud/shell_commands index 47ae3dd4d9..043730b19e 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-Aud/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-Aud/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-Aud_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-Aud/CLM1PT_data/CTSM_DATM_US-Aud_2003-2005.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Bar/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Bar/shell_commands index 2d24f07e53..4fb0562433 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-Bar/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-Bar/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=-71.28808599999999 -./xmlchange PTS_LAT=44.064640000000004 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-Bar_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-Bar/CLM1PT_data/CTSM_DATM_US-Bar_2005-2005.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Bkg/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Bkg/shell_commands index 9fb49876da..a05f46e871 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-Bkg/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-Bkg/shell_commands @@ -1,11 +1,11 @@ +./xmlchange PLUMBER2SITE=US-Bkg ./xmlchange PTS_LON=-96.836182 -./xmlchange PTS_LAT=44.345290999999996 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-Bkg_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-Bkg/CLM1PT_data/CTSM_DATM_US-Bkg_2005-2006.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Blo/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Blo/shell_commands index c208c920f7..fb79abb36e 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-Blo/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-Blo/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-Blo_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-Blo/CLM1PT_data/CTSM_DATM_US-Blo_2000-2006.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Bo1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Bo1/shell_commands index c802acf23c..b6e243115f 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-Bo1/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-Bo1/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-Bo1_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-Bo1/CLM1PT_data/CTSM_DATM_US-Bo1_1997-2006.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Cop/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Cop/shell_commands index d66d11a697..0957a02037 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-Cop/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-Cop/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-Cop_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-Cop/CLM1PT_data/CTSM_DATM_US-Cop_2002-2003.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-FPe/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-FPe/shell_commands index 621e4156ed..bd5760bfc0 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-FPe/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-FPe/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=-105.10189799999999 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-FPe_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-FPe/CLM1PT_data/CTSM_DATM_US-FPe_2000-2006.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-GLE/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-GLE/shell_commands index a7548fbb53..fc1b2c4fba 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-GLE/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-GLE/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-GLE_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-GLE/CLM1PT_data/CTSM_DATM_US-GLE_2009-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Goo/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Goo/shell_commands index ee1cf13767..be9ff715aa 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-Goo/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-Goo/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=-89.87350500000001 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-Goo_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-Goo/CLM1PT_data/CTSM_DATM_US-Goo_2004-2006.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Ha1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Ha1/shell_commands index 43d55bdbd1..bb97980e53 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-Ha1/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-Ha1/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-Ha1_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-Ha1/CLM1PT_data/CTSM_DATM_US-Ha1_1992-2012.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Ho1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Ho1/shell_commands index 7e9bda46b2..803711f8af 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-Ho1/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-Ho1/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-Ho1_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-Ho1/CLM1PT_data/CTSM_DATM_US-Ho1_1996-2004.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-KS2/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-KS2/shell_commands index 161a377821..74ad2113d9 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-KS2/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-KS2/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-KS2_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-KS2/CLM1PT_data/CTSM_DATM_US-KS2_2003-2006.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Los/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Los/shell_commands index b606ac7e9e..dbc8d3b004 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-Los/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-Los/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-Los_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-Los/CLM1PT_data/CTSM_DATM_US-Los_2000-2008.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-MMS/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-MMS/shell_commands index b817bac303..8e8804a887 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-MMS/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-MMS/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=-86.41308599999999 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-MMS_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-MMS/CLM1PT_data/CTSM_DATM_US-MMS_1999-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-MOz/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-MOz/shell_commands index a666ccbaf0..223e43a3d6 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-MOz/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-MOz/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-MOz_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-MOz/CLM1PT_data/CTSM_DATM_US-MOz_2005-2006.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Me2/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Me2/shell_commands index e07240f14f..8555ceb993 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-Me2/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-Me2/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-Me2_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-Me2/CLM1PT_data/CTSM_DATM_US-Me2_2002-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Me4/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Me4/shell_commands index 6b26c589d9..b191f984a5 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-Me4/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-Me4/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=-121.62240600000001 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-Me4_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-Me4/CLM1PT_data/CTSM_DATM_US-Me4_1996-2000.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Me6/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Me6/shell_commands index 6056ec6552..8ffbbe4855 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-Me6/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-Me6/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-Me6_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-Me6/CLM1PT_data/CTSM_DATM_US-Me6_2011-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Myb/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Myb/shell_commands index 89c79b88bc..2d3103546a 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-Myb/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-Myb/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-Myb_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-Myb/CLM1PT_data/CTSM_DATM_US-Myb_2011-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-NR1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-NR1/shell_commands index 7185333ba0..cd795160d0 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-NR1/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-NR1/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-NR1_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-NR1/CLM1PT_data/CTSM_DATM_US-NR1_1999-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Ne1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Ne1/shell_commands index 5ec7590921..4b205b471d 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-Ne1/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-Ne1/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=-96.47659300000001 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-Ne1_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-Ne1/CLM1PT_data/CTSM_DATM_US-Ne1_2002-2012.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Ne2/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Ne2/shell_commands index 75d2215e6c..beca45f248 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-Ne2/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-Ne2/shell_commands @@ -1,11 +1,11 @@ +./xmlchange PLUMBER2SITE=US-Ne2 ./xmlchange PTS_LON=-96.470093 -./xmlchange PTS_LAT=41.164902000000005 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-Ne2_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-Ne2/CLM1PT_data/CTSM_DATM_US-Ne2_2002-2012.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Ne3/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Ne3/shell_commands index ceb48a35c0..59644ec285 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-Ne3/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-Ne3/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-Ne3_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-Ne3/CLM1PT_data/CTSM_DATM_US-Ne3_2002-2012.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-PFa/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-PFa/shell_commands index e214fa5d26..979dd2adbe 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-PFa/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-PFa/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-PFa_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-PFa/CLM1PT_data/CTSM_DATM_US-PFa_1995-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Prr/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Prr/shell_commands index 0be161a3f5..34949905d4 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-Prr/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-Prr/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-Prr_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-Prr/CLM1PT_data/CTSM_DATM_US-Prr_2011-2013.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-SP1/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-SP1/shell_commands index b1944933fe..07c1611661 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-SP1/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-SP1/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-SP1_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-SP1/CLM1PT_data/CTSM_DATM_US-SP1_2005-2005.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-SP2/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-SP2/shell_commands index 9ec9b25681..0640843357 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-SP2/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-SP2/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-SP2_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-SP2/CLM1PT_data/CTSM_DATM_US-SP2_2000-2004.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-SP3/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-SP3/shell_commands index 72c94ad6a5..559f2e9282 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-SP3/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-SP3/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-SP3_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-SP3/CLM1PT_data/CTSM_DATM_US-SP3_1999-2004.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-SRG/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-SRG/shell_commands index 53c07383d3..25269ecc91 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-SRG/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-SRG/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-SRG_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-SRG/CLM1PT_data/CTSM_DATM_US-SRG_2009-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-SRM/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-SRM/shell_commands index f8ab5b5b89..97c155f639 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-SRM/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-SRM/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-SRM_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-SRM/CLM1PT_data/CTSM_DATM_US-SRM_2004-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Syv/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Syv/shell_commands index 7bd8324a6d..f78805c4d8 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-Syv/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-Syv/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-Syv_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-Syv/CLM1PT_data/CTSM_DATM_US-Syv_2002-2008.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Ton/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Ton/shell_commands index 2ac988eb2f..81a47579f4 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-Ton/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-Ton/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-Ton_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-Ton/CLM1PT_data/CTSM_DATM_US-Ton_2001-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Tw4/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Tw4/shell_commands index 0895943d1c..6a76794659 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-Tw4/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-Tw4/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-Tw4_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-Tw4/CLM1PT_data/CTSM_DATM_US-Tw4_2014-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Twt/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Twt/shell_commands index 77649de143..0a36252097 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-Twt/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-Twt/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-Twt_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-Twt/CLM1PT_data/CTSM_DATM_US-Twt_2010-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-UMB/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-UMB/shell_commands index 511e7e05c3..6587b7967c 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-UMB/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-UMB/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-UMB_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-UMB/CLM1PT_data/CTSM_DATM_US-UMB_2000-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Var/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Var/shell_commands index 8cbb483737..ecdf5c95e3 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-Var/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-Var/shell_commands @@ -1,11 +1,11 @@ -./xmlchange PTS_LON=-120.95072900000001 +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-Var_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-Var/CLM1PT_data/CTSM_DATM_US-Var_2001-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-WCr/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-WCr/shell_commands index adcfb2eec4..4f2ca3a65e 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-WCr/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-WCr/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-WCr_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-WCr/CLM1PT_data/CTSM_DATM_US-WCr_1999-2006.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Whs/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Whs/shell_commands index 0f091925f1..458db116f3 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-Whs/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-Whs/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-Whs_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-Whs/CLM1PT_data/CTSM_DATM_US-Whs_2008-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/US-Wkg/shell_commands b/cime_config/usermods_dirs/PLUMBER2/US-Wkg/shell_commands index da4a18b3f9..0870b9233d 100644 --- a/cime_config/usermods_dirs/PLUMBER2/US-Wkg/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/US-Wkg/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_US-Wkg_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/US-Wkg/CLM1PT_data/CTSM_DATM_US-Wkg_2005-2014.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/ZA-Kru/shell_commands b/cime_config/usermods_dirs/PLUMBER2/ZA-Kru/shell_commands index 016f4e4038..8c3463a936 100644 --- a/cime_config/usermods_dirs/PLUMBER2/ZA-Kru/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/ZA-Kru/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_ZA-Kru_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/ZA-Kru/CLM1PT_data/CTSM_DATM_ZA-Kru_2000-2002.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/ZM-Mon/shell_commands b/cime_config/usermods_dirs/PLUMBER2/ZM-Mon/shell_commands index 2729227ecc..448a26c040 100644 --- a/cime_config/usermods_dirs/PLUMBER2/ZM-Mon/shell_commands +++ b/cime_config/usermods_dirs/PLUMBER2/ZM-Mon/shell_commands @@ -1,11 +1,11 @@ +./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 "fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_ZM-Mon_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' " >> user_nl_clm -echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/ZM-Mon/CLM1PT_data/CTSM_DATM_ZM-Mon_2008-2008.nc " >> user_nl_datm_streams 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 diff --git a/cime_config/usermods_dirs/PLUMBER2/defaults/user_nl_clm b/cime_config/usermods_dirs/PLUMBER2/defaults/user_nl_clm index fe23065798..5216afb381 100644 --- a/cime_config/usermods_dirs/PLUMBER2/defaults/user_nl_clm +++ b/cime_config/usermods_dirs/PLUMBER2/defaults/user_nl_clm @@ -19,6 +19,6 @@ !---------------------------------------------------------------------------------- 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/surfdata_1x1_PLUMBER2_${PLUMBER2SITE}_hist_2000_16pfts_c240326.nc" +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_datm_streams b/cime_config/usermods_dirs/PLUMBER2/defaults/user_nl_datm_streams index 35071ff415..29a8c675ac 100644 --- a/cime_config/usermods_dirs/PLUMBER2/defaults/user_nl_datm_streams +++ b/cime_config/usermods_dirs/PLUMBER2/defaults/user_nl_datm_streams @@ -21,7 +21,7 @@ ! foo:year_first = 1950 ! would change the stream year_first stream_entry to 1950 for the foo stream block !------------------------------------------------------------------------ -! This will come out when cdeps externals are updated +! This will come out when the cdeps submodule are updated CLM_USRDAT.PLUMBER2:datavars = ZBOT Sa_z, \ TBOT Sa_tbot, \ QBOT Sa_shum, \ 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/fates_sp/user_nl_clm b/cime_config/usermods_dirs/fates_sp/user_nl_clm index 093ecd7eda..37da8d1c67 100644 --- a/cime_config/usermods_dirs/fates_sp/user_nl_clm +++ b/cime_config/usermods_dirs/fates_sp/user_nl_clm @@ -22,7 +22,7 @@ hist_fexcl1 = 'FATES_TRIMMING', 'FATES_COLD_STATUS', 'FATES_GDD', 'FATES_NCHILLD '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_FIRE', 'FATES_DISTURBANCE_RATE_LOGGING', 'FATES_DISTURBANCE_RATE_TREEFALL', - '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/components/cdeps b/components/cdeps new file mode 160000 index 0000000000..7b0b3a8272 --- /dev/null +++ b/components/cdeps @@ -0,0 +1 @@ +Subproject commit 7b0b3a827241c53d296ec877cb1f59966bf5e5bf 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..47fb4e633a --- /dev/null +++ b/components/cmeps @@ -0,0 +1 @@ +Subproject commit 47fb4e633a76ec6d60969b1af751f90790387246 diff --git a/components/mizuRoute b/components/mizuRoute new file mode 160000 index 0000000000..81c720c7ee --- /dev/null +++ b/components/mizuRoute @@ -0,0 +1 @@ +Subproject commit 81c720c7ee51f9c69f2934f696078c42f4493565 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 f6a6dbd2f8..c95ea482e3 100644 --- a/doc/.ChangeLog_template +++ b/doc/.ChangeLog_template @@ -98,7 +98,7 @@ infrastructure should be run when appropriate, as described below. 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 @@ -157,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/ChangeLog b/doc/ChangeLog index e0a5e45cb6..fc4ee9f376 100644 --- a/doc/ChangeLog +++ b/doc/ChangeLog @@ -1,4 +1,3888 @@ =============================================================== +Tag name: ctsm5.3.013 +Originator(s): erik (Erik Kluzek,UCAR/TSS,303-497-1326) +Date: Tue 26 Nov 2024 02:59:49 PM MST +One-line Summary: Merge b4b-dev + +Purpose and description of changes +---------------------------------- + +Bring in latest b4b-dev branch to main CTSM development. + +- Update git-fleximod +- Fix equation number in tech note +- Implement urbanl and urbanc coszen filters +- Make ALBGRD and ALBGRI active by default +- Some adjustments to control pylint for the RXCROPMATURITY python tests +- Run_sys_tests: Print test list in --verbose/--debug. + +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 #17 albgrd and albgri history fields depend on decomposition, for urban points + Fixes #747 In UrbanAlbedo: Create a filter for coszen>0 and operate over that + +Notes of particular relevance for users +--------------------------------------- + +Changes made to namelist defaults (e.g., changed parameter values): + ALBGRD/ALBGRI are now active by default on the h0 files + +Changes to documentation: Fixed equation number + +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: + Testlist that will be run is now output when --verbose/--debug is given to run_sys_tests + +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) + #2893 -- Merge b4b-dev + #2786 -- git fleximod + #2848 -- equation number in tech note + #2875 -- run_sys_tests log testlist for --verbose/--debug options + #2860 -- Remove num_solar and implement coszen filters in UrbanAlbedoMod.F90 + +=============================================================== +=============================================================== +Tag name: ctsm5.3.012 +Originator(s): afoster (Adrianna Foster,UCAR/TSS,303-497-1728) +Date: Wed 13 Nov 2024 09:53:51 AM MST +One-line Summary: update fates tag + +Purpose and description of changes +---------------------------------- + +Updates FATES tag to latest fates main (sci.1.79.3_api.37.0.0), and updates API to go +along with latest FATES update to refactor it's fire equations + + +Significant changes to scientifically-supported configurations +-------------------------------------------------------------- + + +[ ] 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 + + fates tests: + derecho ----- OK + izumi ------- OK + + +Answer changes +-------------- + +Changes answers relative to baseline: + +Round-off differences for FATES compsets where fire is active. +NLCOMP differences for some FATES compsets + + +Pull Requests that document the changes (include PR ids): +- ESCOMP/CTSM#2782: Fates fuel refactor (https://github.com/ESCOMP/CTSM/pull/2782) + +=============================================================== +=============================================================== +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 diff --git a/doc/ChangeSum b/doc/ChangeSum index b48e04889d..85e347513b 100644 --- a/doc/ChangeSum +++ b/doc/ChangeSum @@ -1,5 +1,48 @@ Tag Who Date Summary ============================================================================================================================ + ctsm5.3.013 erik 11/26/2024 Merge b4b-dev + ctsm5.3.012 afoster 11/13/2024 update fates tag + 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 diff --git a/doc/README.CHECKLIST.master_tags b/doc/README.CHECKLIST.master_tags index ed7794130b..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 diff --git a/README.NUOPC_driver.md b/doc/README.NUOPC_driver.md similarity index 85% rename from README.NUOPC_driver.md rename to doc/README.NUOPC_driver.md index ba0b70c2c0..6caf63a9bd 100644 --- a/README.NUOPC_driver.md +++ b/doc/README.NUOPC_driver.md @@ -40,12 +40,3 @@ 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 MCT driver? - -The MCT driver is now deprecated, and will be removed. So at this point we don't -suggest using it anymore. - -For more notes see: - -https://docs.google.com/presentation/d/1yjiKSEV53JDAJbYxhpY2T9GTxlWFzQAn 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/python_script_user_interface.rst b/doc/design/python_script_user_interface.rst index 87c1b3e8fc..d639117810 100644 --- a/doc/design/python_script_user_interface.rst +++ b/doc/design/python_script_user_interface.rst @@ -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: 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/how-to-make-mesh.md b/doc/source/how-to-make-mesh.md deleted file mode 100644 index 0620598e05..0000000000 --- a/doc/source/how-to-make-mesh.md +++ /dev/null @@ -1,98 +0,0 @@ -# Creating an ESMF mesh file from a netCDF file - -This gist includes instructions for creating and visualizing a mesh file from a netcdf file with valid 1D or 2D lats and lons coordinates. - -* **ESMF Mesh file** aka **Unstructured Grid File Format** is a netcdf file (format) that includes the information about the grids coordinates and their connectivity to each other. - -Additional information about ESMF mesh files are available [here](https://earthsystemmodeling.org/docs/release/ESMF_8_0_1/ESMF_refdoc/node3.html#SECTION03028200000000000000). - ------- - -In this example, we will use `./mesh_maker.py` which uses `mesh_type.py` to create a mesh file and visualize it. - -1- First clone my fork and branch that includes these capabilities: -``` Shell -git clone https://github.com/negin513/ctsm.git ctsm_mesh -cd ctsm_mesh - -git checkout subset_mesh_dask -``` - -2- Next run mesh_maker.py for a netcdf file: - -``` -cd tools/site_and_regional -``` -Check all the avaialble options: - -``` -./mesh_maker.py --help -``` - -The output shows all available options for this script: -``` -|------------------------------------------------------------------| -|--------------------- 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 - - ``` - -Let's create a mesh file from a netcdf file with 1D lats and lons. On the sample files provided 1D lat and long coordinates are saved on `lsmlat` and `lsmlon` variables. - -``` -./mesh_maker.py --input /glade/scratch/negins/example_files/surfdata_4x5_hist_78pfts_CMIP6_simyr1850_275.0-330.0_-40-15_c220705.nc --output test_mesh_1d.nc --lat lsmlat --lon lsmlon --overwrite -``` -`--verbose` option also provide additional information for debugging. - -This script will create regional and global mesh plots. For example for the above files, the plos are: -test_mesh_1d_regional.png -![image](https://user-images.githubusercontent.com/17344536/200441736-972a8136-5c05-4bc9-9bca-b498d972914a.png) - - -test_mesh_1d_global.png - -![image](https://user-images.githubusercontent.com/17344536/200441753-d06e95d1-d85b-4216-9c23-d11ba89a31e4.png) - - - ------- - ## Creating Mesh files for a WRF domain: -For running WRF-CTSM cases, we need to create ESMF mesh files for the WRF domain. We can create mesh file from wrfinput (wrf initial condition files). wrfinput has 2D coordinate information on `XLAT` and `XLONG` variable. - -For example, let's create a mesh file from a WRF input file for WRF-CTSM run. - ``` -./mesh_maker.py --input /glade/scratch/negins/example_files/wrfinput_d01 --output test_mesh_wrf.nc --lat XLAT --lon XLONG --overwrite -``` - -This produce mesh files for running for our WRF domain. - -Here is how the regional plot looks like for this mesh file: - - ![image](https://user-images.githubusercontent.com/17344536/200442002-1ee5595c-9252-4934-a07c-2f6ad86aff1b.png) - - - \ No newline at end of file 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 c0e510c017..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 diff --git a/doc/source/lilac/specific-atm-models/wrf-nesting.rst b/doc/source/lilac/specific-atm-models/wrf-nesting.rst index f4c4570f2f..81428495f0 100644 --- a/doc/source/lilac/specific-atm-models/wrf-nesting.rst +++ b/doc/source/lilac/specific-atm-models/wrf-nesting.rst @@ -6,12 +6,9 @@ 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 @@ -37,9 +34,7 @@ There are currently two types of nesting available within WRF: 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. +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. @@ -50,26 +45,25 @@ A full description of all steps for a WRF-CTSM run are included here. 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: +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:: @@ -77,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, @@ -101,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. @@ -111,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,21 +120,17 @@ At this point, you should see ungrib output (intermediate files) in your WPS dir 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.* @@ -150,25 +138,19 @@ below:: 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. +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. -To run WRF-CTSM, in your namelist change land-surface option to 6 for both -domains:: +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 @@ -178,6 +160,8 @@ The boundary condition file is only created for the outer domain. Check the last line of the real log file for the following message: +.. todo:: What message? + Rename wrfinput_d02 ------------------- Next, rename the ``wrfinput_d02`` file to ``wrfndi_d02``:: @@ -186,8 +170,7 @@ 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``:: @@ -197,20 +180,15 @@ Run ndown.exe to create ``wrfinput_d02`` and ``wrfbdy_d02``. 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:: @@ -219,8 +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 @@ -230,13 +207,9 @@ are defined within these three files: 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 diff --git a/doc/source/lilac/specific-atm-models/wrf-tools.rst b/doc/source/lilac/specific-atm-models/wrf-tools.rst index f67a05ea0a..1222a16f10 100644 --- a/doc/source/lilac/specific-atm-models/wrf-tools.rst +++ b/doc/source/lilac/specific-atm-models/wrf-tools.rst @@ -48,10 +48,16 @@ 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 +.. 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 diff --git a/doc/source/lilac/specific-atm-models/wrf.rst b/doc/source/lilac/specific-atm-models/wrf.rst index 5d104778ec..ad85fee777 100644 --- a/doc/source/lilac/specific-atm-models/wrf.rst +++ b/doc/source/lilac/specific-atm-models/wrf.rst @@ -44,7 +44,7 @@ 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: 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 c759d11f92..05b35d8b34 100644 --- a/doc/source/tech_note/Fluxes/CLM50_Tech_Note_Fluxes.rst +++ b/doc/source/tech_note/Fluxes/CLM50_Tech_Note_Fluxes.rst @@ -1213,7 +1213,7 @@ The numerical solution for vegetation temperature and the fluxes of momentum, se #. 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.122` ) #. Aerodynamic resistances :math:`r_{ah} ^{{'} }` and :math:`r_{aw} ^{{'} }`(:eq:`5.116` ) 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 3e510561bb..9ed8fe280e 100644 --- a/doc/source/tech_note/Glacier/CLM50_Tech_Note_Glacier.rst +++ b/doc/source/tech_note/Glacier/CLM50_Tech_Note_Glacier.rst @@ -58,7 +58,7 @@ It is also possible to run CESM with an evolving ice sheet. In this case, CLM re 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: @@ -80,7 +80,7 @@ The world's glaciers and ice sheets are broken down into a number of different r 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. +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: @@ -93,13 +93,6 @@ The default behaviors for the world's glacier and ice sheet regions are describe | 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 | | +---------------+---------------+---------------+---------------+ @@ -109,7 +102,11 @@ The default behaviors for the world's glacier and ice sheet regions are describe .. 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: 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 78edaaf629..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 @@ -6,9 +6,9 @@ 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. +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. +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_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. +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 216de19f54..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 @@ -6,7 +6,7 @@ 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? @@ -30,4 +29,5 @@ In the following table we list the different files used by CLM, they are listed 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/index.rst b/doc/source/users_guide/index.rst index 75a2949bec..0bb2dbd75d 100644 --- a/doc/source/users_guide/index.rst +++ b/doc/source/users_guide/index.rst @@ -24,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 74765d1ad0..7c33071db9 100644 --- a/doc/source/users_guide/overview/getting-help.rst +++ b/doc/source/users_guide/overview/getting-help.rst @@ -146,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/introduction.rst b/doc/source/users_guide/overview/introduction.rst index bc7c1fd82c..8056e6ab16 100644 --- a/doc/source/users_guide/overview/introduction.rst +++ b/doc/source/users_guide/overview/introduction.rst @@ -60,9 +60,7 @@ As a followup to the tools chapter, :ref:`adding-new-resolutions-section` tells 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. -: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. 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. - -Need :ref:`running-PTCLM` 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. :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. @@ -109,7 +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: diff --git a/doc/source/users_guide/overview/quickstart.rst b/doc/source/users_guide/overview/quickstart.rst index 5414963c4d..63f4afea6f 100644 --- a/doc/source/users_guide/overview/quickstart.rst +++ b/doc/source/users_guide/overview/quickstart.rst @@ -16,7 +16,7 @@ List of utilities required for CESM in the `Software/OS Prerequisites `_. 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: +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: - :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`. 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 b95831427f..0000000000 --- a/doc/source/users_guide/running-PTCLM/adding-ptclm-site-data.rst +++ /dev/null @@ -1,88 +0,0 @@ -.. include:: ../substitutions.rst - -.. _adding-ptclm-site-data: - -============================ -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_esmf** can read that has an entry for each year for the range of years valid for the compset in question. - -.. _converting-ameriflux-for-ptclmmkdata: - ------------------------------------------------- -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 shown in :ref:`converting-ameriflux-for-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/introduction-to-ptclm.rst b/doc/source/users_guide/running-PTCLM/introduction-to-ptclm.rst deleted file mode 100644 index 9ae4186d2c..0000000000 --- a/doc/source/users_guide/running-PTCLM/introduction-to-ptclm.rst +++ /dev/null @@ -1,135 +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 :ref:`converting-ameriflux-for-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 6801c5f3d8..0000000000 --- a/doc/source/users_guide/running-PTCLM/ptclm-examples.rst +++ /dev/null @@ -1,33 +0,0 @@ -.. include:: ../substitutions.rst - -.. _ptclm-examples: - -============================== - 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 e7be79bee6..0000000000 --- a/doc/source/users_guide/running-PTCLM/using-ptclm.rst +++ /dev/null @@ -1,114 +0,0 @@ -.. include:: ../substitutions.rst - -.. _using-ptclm.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 :ref:`adding-ptclm-site-data` 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 :ref:`converting-ameriflux-for-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/running-pts_mode-configurations.rst b/doc/source/users_guide/running-single-points/running-pts_mode-configurations.rst index d3b14e6184..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 @@ -8,10 +8,10 @@ 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. -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 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 9d2b68456b..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 @@ -45,7 +45,7 @@ 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 > cd testSPDATASET @@ -59,7 +59,7 @@ The urban Mexico City test site has its own atmosphere forcing data (see Sect. : :: - > 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 @@ -74,14 +74,17 @@ 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. -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. + +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: 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 @@ -121,7 +124,7 @@ Example: Using CLM_USRDAT_NAME to run a simulation using user datasets for a spe ----------------------------------------------------------------------------------------------------------------------- :: - > 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 @@ -142,6 +145,9 @@ The first step is to create the domain and surface datasets using the process ou 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 @@ -176,6 +182,13 @@ 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. @@ -188,7 +201,7 @@ Example: Setting up a case from the single-point surface dataset just created # naming convention (leave off the creation date) > 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 @@ -199,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 34a199ebe8..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 @@ -8,7 +8,7 @@ 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. -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. @@ -16,11 +16,6 @@ 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: ========================================= @@ -29,11 +24,9 @@ There are three different ways to do this for normal-supported site 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. -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 **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. +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. 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. -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, :ref:`running-PTCLM`. - -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. :ref:`converting-ameriflux-for-ptclmmkdata` 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 f93bcca2f0..0000000000 --- a/doc/source/users_guide/running-special-cases/Running-stand-alone-CLM-with-transient-historical-CO2-concentration.rst +++ /dev/null @@ -1,39 +0,0 @@ -.. include:: ../substitutions.rst - -.. _running-with-historical-co2-forcing: - -===================================== - 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 index 7e19af8678..56620b2fde 100644 --- 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 @@ -6,13 +6,13 @@ 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``). +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 + > cd cime/scripts > ./create_newcase -case CROP -res f19_g17_gl4 -compset I1850Clm50BgcCropCru > cd CROP 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 dbe01c497c..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 @@ -6,22 +6,25 @@ Running with MOAR data ======================== +.. 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 :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 + > ./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 0c6009f3fe..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 @@ -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 index b19ebcdb09..878cc0d353 100644 --- 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 @@ -28,8 +28,8 @@ However, geographically- and temporally-varying maps can also be used to prescri 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 = 2000 - stream_year_last_cropcal = 2000 + stream_year_first_cropcal_swindows = 2000 + stream_year_last_cropcal_swindows = 2000 Sowing date ----------- @@ -39,7 +39,7 @@ Specific sowing *dates* can be prescribed for any crop in any gridcell by settin 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``, and ``stream_year_last_cropcal``---see above---are all also required.) +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 -------------------------------- @@ -52,8 +52,8 @@ In a GDD-generating run, crops are planted on the specified sowing dates and are 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 = YEAR - stream_year_last_cropcal = YEAR + stream_year_first_cropcal_swindows = YEAR + stream_year_last_cropcal_swindows = YEAR ! Special settings for "GDD-generating" run generate_crop_gdds = .true. 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 index f19b489731..5e9adb4b6a 100644 --- a/doc/source/users_guide/running-special-cases/Running-with-irrigation.rst +++ b/doc/source/users_guide/running-special-cases/Running-with-irrigation.rst @@ -6,14 +6,17 @@ 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_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``. +.. 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 scripts + > cd cime/scripts > ./create_newcase -case IRRIG -res f19_g17_gl4 -compset I1850Clm50BgcCrop > cd IRRIG 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 ff05836f6e..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 @@ -14,7 +14,7 @@ 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 @@ -44,14 +44,14 @@ 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 # (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! 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 cc266506a8..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 @@ -6,7 +6,7 @@ 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: @@ -14,7 +14,7 @@ To get the |version|-BGC model to a steady state, you first run it from arbitrar 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: @@ -41,13 +41,13 @@ You can also start from a default initial file that is setup as part of the sele 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: + 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 +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 @@ -67,7 +67,7 @@ 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: @@ -75,7 +75,7 @@ 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 diff --git a/doc/source/users_guide/running-special-cases/index.rst b/doc/source/users_guide/running-special-cases/index.rst index 9173825d04..31d5a3b148 100644 --- a/doc/source/users_guide/running-special-cases/index.rst +++ b/doc/source/users_guide/running-special-cases/index.rst @@ -24,5 +24,4 @@ Running Special Cases 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/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 f8b5fee002..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 @@ -6,17 +6,17 @@ 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 (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. +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 :ref:`def-nl-items-and-defaults`). +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 `_. @@ -38,12 +38,12 @@ 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 :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. + 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. (See :ref:`precedence-of-opts` for the precedence of this option relative to the others.) To list the valid options do the following: @@ -101,7 +101,7 @@ CLM_NML_USE_CASE stdurbpt_pd = Standard Urban Point Namelist Settings 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 @@ -140,10 +140,17 @@ CLM_BLDNML_OPTS 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) + 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 @@ -185,10 +192,12 @@ CLM_BLDNML_OPTS -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 @@ -247,41 +256,45 @@ CLM_BLDNML_OPTS (i.e. CLM_NML_USE_CASE env_run variable) 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" is set (to ``CLM_USRDAT_NAME >``when the grid is set 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`` (to ``CLM_USRDAT_NAME``). Hence only the following different options can be set: -1. --bgc_spinup +#. ``-bgc_spinup`` -#. -chk_res +#. ``-chk_res`` -#. -clm_demand +#. ``-clm_demand`` -#. -drydep +#. ``-drydep`` -#. -ignore_ic_date +#. ``-fire_emis`` -#. -ignore_ic_year +#. ``-ignore_ic_date`` -#. -irrig +#. ``-ignore_ic_year`` -#. -no-megan +#. ``-irrig`` -#. -note +#. ``-no-megan`` -#. -rcp +#. ``-note`` -#. -sim_year +#. ``-rcp`` -#. -verbose +#. ``-sim_year`` -"-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. +#. ``-verbose`` -"-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. +``-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. -"-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. +.. 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. + +``-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: :: @@ -291,25 +304,25 @@ To see a list of valid variables that you could set do this: .. 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 @@ -335,8 +348,11 @@ When "-irrig on" is used **build-namelist** will try to find surface datasets th ``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. +.. 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: + 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 @@ -345,13 +361,13 @@ When "-irrig on" is used **build-namelist** will try to find surface datasets th 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. See :ref:`running-with-historical-co2-forcing` for more information on how to send CO2 from the data atmosphere model. + 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 @@ -363,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', @@ -397,9 +415,9 @@ 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:** 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. @@ -409,17 +427,17 @@ Obviously, all of this would be difficult to put in the CLM_NAMELIST_OPTS variab 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. @@ -438,7 +456,7 @@ Especially with CLMBGC and CLMCN starting from initial conditions is very import - :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: @@ -446,11 +464,11 @@ Especially with CLMBGC and CLMCN starting from initial conditions is very import 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: @@ -485,23 +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. + 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): @@ -527,7 +542,7 @@ For running "I" cases there are several other noteworthy configuration items tha 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: 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 :ref:`clm1pt-and-its-datm` for more information. + 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. @@ -551,26 +566,17 @@ For running "I" cases there are several other noteworthy configuration items tha ``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_CPL_CASE - ``DATM_CPL_CASE`` sets the casename to use for the ``CPLHISTForcing`` mode. +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_YR_START - ``DATM_CPL_YR_START`` sets the beginning year to cycle the atmospheric data over 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_END - ``DATM_CPL_YR_END`` sets the ending 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_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 @@ -578,20 +584,20 @@ 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: @@ -604,7 +610,7 @@ The CLM ``configure`` script defines the details of a clm configuration and summ 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 @@ -638,7 +644,7 @@ The output to the above command is as follows: -vichydro Turn VIC hydrologic parameterizations : [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) + -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. @@ -681,4 +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 ff76a841c9..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 @@ -6,7 +6,7 @@ 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. @@ -138,14 +138,14 @@ Example 1-5. Example user_nl_clm namelist removing all history fields 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 ------------------------------------------------------------------------------------- @@ -165,7 +165,7 @@ Example: user_nl_clm namelist with various ways to average history fields 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. @@ -189,8 +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/history_fields_fates.rst b/doc/source/users_guide/setting-up-and-running-a-case/history_fields_fates.rst index ec10de5080..84caf92465 100644 --- 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 @@ -1,18 +1,18 @@ ============================= 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 @@ -22,13 +22,27 @@ ALTMAX - maximum annual active layer 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 none 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 @@ -43,7 +57,15 @@ DPVLTRB3 - turbulent deposition veloci 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 @@ -52,6 +74,7 @@ DWT_PROD10C_GAIN - landcover change-driven add 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 @@ -95,10 +118,6 @@ FATES_DAYSINCE_COLDLEAFON - site-level days elapsed sin 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_P2P - disturbance rate from primary to primary lands m2 m-2 yr-1 T -FATES_DISTURBANCE_RATE_P2S - disturbance rate from primary to secondary lands m2 m-2 yr-1 T -FATES_DISTURBANCE_RATE_POTENTIAL - potential (i.e., including unresolved) disturbance rate m2 m-2 yr-1 T -FATES_DISTURBANCE_RATE_S2S - disturbance rate from secondary to secondary lands 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 @@ -128,6 +147,7 @@ FATES_HARVEST_DEBT - Accumulated carbon failed 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 @@ -139,7 +159,7 @@ FATES_LITTER_OUT - litter flux out in kg carbo 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 F +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 @@ -148,6 +168,7 @@ FATES_NCOHORTS_SECONDARY - total number of cohorts per 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 @@ -155,7 +176,6 @@ FATES_NPP - net primary production in k 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_RAD_ERROR - radiation error in FATES RTM W m-2 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 @@ -181,8 +201,12 @@ FATES_UNGERM_SEED_BANK - ungerminated seed mass of a 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 @@ -194,6 +218,8 @@ FGR_R - Rural heat flux into soil/s 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 @@ -202,8 +228,9 @@ FIRE - emitted infrared (longwave) 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 to columns in glacier regions) W/m^2 T -FLDS_ICE - atmospheric longwave radiation (downscaled to columns in glacier regions) (ice landunits only) 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 @@ -214,7 +241,7 @@ FSA_R - Rural absorbed solar radiat 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 W/m^2 T +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 @@ -222,6 +249,7 @@ FSDSVD - direct vis incident solar r 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 @@ -320,7 +348,7 @@ LIT_MET_N - LIT_MET N 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 to columns in glacier regions) W/m^2 F +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 @@ -337,13 +365,19 @@ M_SOM_PAS_N_TO_LEACHING - passive soil organic N leac 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 to columns in glacier regions) Pa 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 @@ -356,10 +390,11 @@ PROD10C - 10-yr wood product C 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 to columns in glacier regions) Pa 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 @@ -396,6 +431,7 @@ QIRRIG_FROM_GW_UNCONFINED - water added through unconfi 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 @@ -436,7 +472,7 @@ RAW2 - aerodynamical resistance RB - leaf boundary resistance s/m F RH - atmospheric relative humidity % F RH2M - 2m relative humidity % T -RH2M_R - Rural 2m specific humidity % F +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 @@ -444,6 +480,7 @@ RSCANOPY - canopy resistance 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 @@ -546,21 +583,24 @@ T10 - 10-day running mean of 2-m 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 to columns in glacier regions) K 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 to columns in glacier regions) 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 @@ -600,8 +640,9 @@ TV - vegetation temperature 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 to columns in glacier regions) K F +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 @@ -611,6 +652,7 @@ URBAN_AC - urban air conditioning flux 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 @@ -618,11 +660,13 @@ VOLRMCH - river channel main channel 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 @@ -633,6 +677,7 @@ ZBOT - atmospheric reference heigh 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 @@ -660,39 +705,28 @@ FATES_SCORCH_HEIGHT_APPF fates_levagepft SPITFIRE flame Scorch Heigh 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 total crown area in each canopy layer m2 m-2 T -FATES_FABD_SHA_TOPLF_CL fates_levcan shade fraction of direct light absorbed by the top leaf layer of each canopy layer 1 F -FATES_FABD_SUN_TOPLF_CL fates_levcan sun fraction of direct light absorbed by the top leaf layer of each canopy layer 1 F -FATES_FABI_SHA_TOPLF_CL fates_levcan shade fraction of indirect light absorbed by the top leaf layer of each canopy layer 1 F -FATES_FABI_SUN_TOPLF_CL fates_levcan sun fraction of indirect light absorbed by the top leaf layer of each canopy layer 1 F -FATES_LAISHA_TOP_CL fates_levcan LAI in the shade by the top leaf layer of each canopy layer m2 m-2 F -FATES_LAISUN_TOP_CL fates_levcan LAI in the sun by the top leaf layer of each canopy layer m2 m-2 F -FATES_PARSHA_Z_CL fates_levcan PAR absorbed in the shade by top leaf layer in each canopy layer W m-2 F -FATES_PARSUN_Z_CL fates_levcan PAR absorbed in the sun by top leaf layer in each canopy layer W m-2 F +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 total crown area that is occupied by leaves in each canopy and leaf layer m2 m-2 F -FATES_FABD_SHA_CLLL fates_levcnlf shade fraction of direct light absorbed by each canopy and leaf layer 1 F -FATES_FABD_SUN_CLLL fates_levcnlf sun fraction of direct light absorbed by each canopy and leaf layer 1 F -FATES_FABI_SHA_CLLL fates_levcnlf shade fraction of indirect light absorbed by each canopy and leaf layer 1 F -FATES_FABI_SUN_CLLL fates_levcnlf sun fraction of indirect light absorbed by each canopy and leaf layer 1 F -FATES_LAISHA_Z_CLLL fates_levcnlf LAI in the shade by each canopy and leaf layer m2 m-2 F -FATES_LAISUN_Z_CLLL fates_levcnlf LAI in the sun by each canopy and leaf layer m2 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_Z_CLLL fates_levcnlf PAR absorbed in the shade by each canopy and leaf layer W m-2 F -FATES_PARSUN_Z_CLLL fates_levcnlf PAR absorbed in the sun by each canopy and leaf layer W m-2 F -FATES_FABD_SHA_CLLLPF fates_levcnlfpf shade fraction of direct light absorbed by each canopy, leaf, and PFT 1 F -FATES_FABD_SUN_CLLLPF fates_levcnlfpf sun fraction of direct light absorbed by each canopy, leaf, and PFT 1 F -FATES_FABI_SHA_CLLLPF fates_levcnlfpf shade fraction of indirect light absorbed by each canopy, leaf, and PFT 1 F -FATES_FABI_SUN_CLLLPF fates_levcnlfpf sun fraction of indirect light absorbed by each canopy, leaf, and PFT 1 F -FATES_LAISHA_Z_CLLLPF fates_levcnlfpf LAI in the shade by each canopy, leaf, and PFT m2 m-2 F -FATES_LAISUN_Z_CLLLPF fates_levcnlfpf LAI in the sun by each canopy, leaf, and PFT m2 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_Z_CLLLPF fates_levcnlfpf PAR absorbed in the shade by each canopy, leaf, and PFT W m-2 F -FATES_PARSUN_Z_CLLLPF fates_levcnlfpf PAR absorbed in the sun by 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 @@ -718,6 +752,8 @@ FATES_FUEL_BURNT_BURNFRAC_FC fates_levfuel product of fraction (0-1) o 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 @@ -726,14 +762,17 @@ FATES_DROUGHT_STATUS_PF fates_levpft PFT-level drought status, < 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 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 @@ -776,8 +815,8 @@ FATES_LEAF_ALLOC_CANOPY_SZ fates_levscls allocation to leaves for ca 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 N/ha/yr F -FATES_M3_MORTALITY_USTORY_SZ fates_levscls C starvation mortality of understory plants by size N/ha/yr 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 @@ -787,7 +826,7 @@ FATES_MORTALITY_BACKGROUND_SZ fates_levscls background mortality by siz 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 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 @@ -798,7 +837,7 @@ FATES_MORTALITY_LOGGING_SE_SZ fates_levscls logging mortality by size i 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 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 @@ -845,6 +884,8 @@ FATES_BGSAPMAINTAR_SZPF fates_levscpf below-ground sapwood mainte 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 @@ -863,22 +904,22 @@ FATES_LEAFC_CANOPY_SZPF fates_levscpf biomass in leaves of canopy 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 N/ha/yr F -FATES_M3_MORTALITY_USTORY_SZPF fates_levscpf C starvation mortality of understory plants by pft/size N/ha/yr 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 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 by pft/size in number pf 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 @@ -1008,8 +1049,11 @@ ratio_k1 levdcmp ratio_k1 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 @@ -1035,6 +1079,8 @@ SNO_TK_ICE levsno Thermal conductivity (ice l 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 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 index 89e7dd23fc..67868f75b1 100644 --- 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 @@ -8,11 +8,11 @@ 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 @@ -36,10 +36,14 @@ ATM_O3 - atmospheric ozone partial p 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 @@ -66,7 +70,8 @@ COL_NTRUNC - column-level sink for N tru 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 none F +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 @@ -158,7 +163,15 @@ DPVLTRB3 - turbulent deposition veloci 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 @@ -246,8 +259,9 @@ FIRE - emitted infrared (longwave) 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 to columns in glacier regions) W/m^2 T -FLDS_ICE - atmospheric longwave radiation (downscaled to columns in glacier regions) (ice landunits only) 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 @@ -278,7 +292,7 @@ FSA_R - Rural absorbed solar radiat 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 W/m^2 T +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 @@ -286,6 +300,7 @@ FSDSVD - direct vis incident solar r 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 @@ -426,6 +441,7 @@ LEAFC_STORAGE_XFER_ACC - Accumulated leaf C transfer 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 @@ -487,6 +503,7 @@ LIVESTEMC_STORAGE - live stem C storage 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 @@ -498,7 +515,7 @@ LIVESTEMN_XFER - live stem N transfer 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 to columns in glacier regions) W/m^2 F +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 @@ -700,6 +717,9 @@ NUPTAKE_NPP_FRACTION - frac of NPP used in N uptak 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 @@ -719,8 +739,9 @@ PAR24_sun - sunlit PAR (24 hrs) 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 to columns in glacier regions) Pa T +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 @@ -754,10 +775,11 @@ PSNSHA - shaded leaf photosynthesis 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 to columns in glacier regions) Pa 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 @@ -839,7 +861,7 @@ RETRANSN - plant pool of retranslocate 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 specific humidity % F +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 @@ -849,6 +871,7 @@ RR - root respiration (fine root 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 @@ -977,9 +1000,11 @@ T10 - 10-day running mean of 2-m 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 to columns in glacier regions) K 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 @@ -992,7 +1017,7 @@ TG_ICE - ground temperature (ice lan 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 to columns in glacier regions) 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 @@ -1060,8 +1085,9 @@ TV240 - vegetation temperature (las 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 to columns in glacier regions) K F +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 @@ -1072,6 +1098,7 @@ URBAN_AC - urban air conditioning flux 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 @@ -1081,6 +1108,7 @@ VOLRMCH - river channel main channel 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 @@ -1261,7 +1289,7 @@ STEM_PROF levdcmp profile for litter C and N 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 (from nitrification-denitrification) m^2/s 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 diff --git a/doc/source/users_guide/testing/testing.rst b/doc/source/users_guide/testing/testing.rst index bad1183fff..a9b0be0462 100644 --- a/doc/source/users_guide/testing/testing.rst +++ b/doc/source/users_guide/testing/testing.rst @@ -6,18 +6,15 @@ Testing ******* -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 **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 ======================= @@ -42,14 +39,3 @@ If something went wrong, you can find the failing tests like so: :: > grep -E "^[0-9]+/[0-9]+ < [a-zA-Z]+" namelist_test.log | grep -v "PASS" - -Testing PTCLM -============= - -.. include:: ../../../../tools/PTCLM/README - :literal: - -To run on cheyenne, you do the following: - -.. include:: ../../../../tools/PTCLM/test/README.run_cheyenne - :literal: diff --git a/doc/source/users_guide/trouble-shooting/trouble-shooting.rst b/doc/source/users_guide/trouble-shooting/trouble-shooting.rst index e139796f71..a971b7f2cb 100644 --- a/doc/source/users_guide/trouble-shooting/trouble-shooting.rst +++ b/doc/source/users_guide/trouble-shooting/trouble-shooting.rst @@ -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 @@ -112,22 +122,22 @@ The second method is to use the local index along with the processor number:: By placing these write statements in the code, one can get a sense of how leafc is evolving toward a negative state and why. This is a very complex example of troubleshooting. To make a long story short, as described `here `_, the error turned out to be caused by a few lines in the phenology code that weren't handling a 20 minute time step properly, thus an actual bug in the code. This was also a good example of where a much less computationally expensive land-only simulation was able to be used for debugging instead of the orginal expensive fully-coupled simulation. -Another method of troubleshooting is to use the **point_of_interest** module. +Another method of troubleshooting is to 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 @@ -136,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 @@ -152,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 @@ -193,5 +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 95e0333d6d..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,102 +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_esmf** 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_esmf**) with the OPT flag so that the tool will run faster. - -Options used by all: **mksurfdata_esmf** - -- ``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_esmf** - -- ``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_esmf** 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 05a2ca8279..81418877c9 100644 --- a/doc/source/users_guide/using-clm-tools/cprnc.rst +++ b/doc/source/users_guide/using-clm-tools/cprnc.rst @@ -6,7 +6,7 @@ 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: 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 d4ebd6c4e7..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 @@ -6,7 +6,10 @@ 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 :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``. +.. 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. @@ -19,7 +22,7 @@ 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 :ref:`using-mkocnmap`). Next we create domain files for a single-point or regional domain. @@ -32,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 a727631a6c..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 @@ -18,7 +18,10 @@ SCRIP grid files for all the standard model resolutions and the raw surface data 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 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 d2e2ef7c89..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 @@ -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_esmf** 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_esmf (if NOT already done) +3. Create mapping files for ``mksurfdata_esmf`` (if NOT already done) - 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. + 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_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. + 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/observational-sites-datasets.rst b/doc/source/users_guide/using-clm-tools/observational-sites-datasets.rst index 50a7969281..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 @@ -6,6 +6,9 @@ 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 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`. ``PTCLM`` uses these methods to customize datasets; see Chapter :numref:`running-PTCLM`. +.. todo:: + Update this. -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. :ref:`converting-ameriflux-for-ptclmmkdata` has information on using the AmeriFlux tower site data as atmospheric forcing. +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 :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 664e23a220..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 @@ -6,27 +6,32 @@ What are the CLM tools ======================== +.. todo:: + Remove references to mkprocdata_map? + 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 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. The list of generally important scripts and programs are as follows. -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. - -#. *./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_esmf* 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. + +#. ``$CIMEROOT/tools/cprnc`` to compare two NetCDF files. 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. -The FORTRAN tools (mksurfdata_esmf and mkprocdata_map) run, with a namelist (mksurfdata_esmf) to provide options, or with command line arguments (mkprocdata_map). +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. @@ -34,34 +39,21 @@ In the following sections, we will outline how to make these files available for Running FORTRAN tools with namelists ------------------------------------ -**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: +``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_esmf/mksurfdata_esmf.namleist`` that shows you what the namelist should look like. **mksurfdata_esmf** 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: - ---------- -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/running-PTCLM/index.rst b/doc/source/users_guide/using-mesh-maker/index.rst similarity index 72% rename from doc/source/users_guide/running-PTCLM/index.rst rename to doc/source/users_guide/using-mesh-maker/index.rst index 0b44c01b49..ecc20bab9c 100644 --- a/doc/source/users_guide/running-PTCLM/index.rst +++ b/doc/source/users_guide/using-mesh-maker/index.rst @@ -5,16 +5,13 @@ .. include:: ../substitutions.rst -.. _running-PTCLM: +.. _using-mesh-maker-index: ##################################### -Running PTCLM +Using mesh_maker ##################################### .. toctree:: :maxdepth: 2 - introduction-to-ptclm.rst - using-ptclm.rst - ptclm-examples.rst - adding-ptclm-site-data.rst + 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/mosart_in b/lilac/bld_templates/mosart_in index 091ec69285..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/campaign/cesm/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/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/.github/workflows/bumpversion.yml b/manage_externals/.github/workflows/bumpversion.yml deleted file mode 100644 index f4dc9b7ca5..0000000000 --- a/manage_externals/.github/workflows/bumpversion.yml +++ /dev/null @@ -1,19 +0,0 @@ -name: Bump version -on: - push: - branches: - - main -jobs: - build: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Bump version and push tag - id: tag_version - uses: mathieudutour/github-tag-action@v5.5 - with: - github_token: ${{ secrets.GITHUB_TOKEN }} - create_annotated_tag: true - default_bump: patch - dry_run: false - tag_prefix: manic- diff --git a/manage_externals/.github/workflows/tests.yml b/manage_externals/.github/workflows/tests.yml deleted file mode 100644 index dd75b91b49..0000000000 --- a/manage_externals/.github/workflows/tests.yml +++ /dev/null @@ -1,30 +0,0 @@ -# This is a workflow to compile the cmeps source without cime -name: Test Manic - -# Controls when the action will run. Triggers the workflow on push or pull request -# events but only for the master branch -on: - push: - branches: [ main ] - pull_request: - branches: [ main ] - -# A workflow run is made up of one or more jobs that can run sequentially or in parallel -jobs: - test-manic: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - name: Test Manic - run: | - pushd test - git config --global user.email "devnull@example.com" - git config --global user.name "GITHUB tester" - git config --global protocol.file.allow always - make utest - make stest - popd - - - name: Setup tmate session - if: ${{ failure() }} - uses: mxschmitt/action-tmate@v3 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 9475301b5d..0000000000 --- a/manage_externals/README.md +++ /dev/null @@ -1,231 +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'. - Note that by default, `checkout_externals` will clone an external's - submodules. As a special case, the entry, `externals = None`, will - prevent this behavior. For more control over which externals are - checked out, create an externals file (and see the `from_submodule` - configuration entry below). - - * 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 3f5537adce..0000000000 --- a/manage_externals/manic/checkout.py +++ /dev/null @@ -1,446 +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. - - Note that by default, checkout_externals will clone an external's - submodules. As a special case, the entry, "externals = None", will - prevent this behavior. For more control over which externals are - checked out, create an externals file (and see the from_submodule - configuration entry below). - - * 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 - -def _dirty_local_repo_msg(program_name, config_file): - return """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=config_file) -# --------------------------------------------------------------------- -# -# 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 is a dict mapping local path - to ExternalStatus -- if no checkout is happening. If checkout is happening, tree_status - is None. - """ - 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()) - model_data = read_externals_description_file(root_dir, args.externals) - ext_description = create_externals_description( - model_data, components=args.components, exclude=args.exclude) - - for comp in args.components: - if comp not in ext_description.keys(): - # Note we can't print out the list of found externals because - # they were filtered in create_externals_description above. - fatal_error( - "No component {} found in {}".format( - comp, args.externals)) - - source_tree = SourceTree(root_dir, ext_description, svn_ignore_ancestry=args.svn_ignore_ancestry) - if args.components: - components_str = 'specified components' - else: - components_str = 'required & optional components' - printlog('Checking local status of ' + components_str + ': ', end='') - tree_status = source_tree.status(print_progress=True) - 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 - printlog('-' * 70) - printlog(_dirty_local_repo_msg(program_name, args.externals)) - 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('') - # New tree status is unknown, don't return anything. - tree_status = None - - 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 546e7fdcb4..0000000000 --- a/manage_externals/manic/externals_description.py +++ /dev/null @@ -1,830 +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} ({1})'.format(file_name, - root_dir)) - - 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 - cmd = 'git -C {repo_dir} submodule status'.format( - repo_dir=repo_dir).split() - 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} - - 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) - - 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 in dir:\n {1}'.format(file_name, root_dir)) - 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 - - components: list of component names to include, None to include all. If a - name isn't found, it is silently omitted from the return value. - exclude: list of component names to skip. - """ - 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; these - # are brought together by the schema below. - EXTERNALS = 'externals' # path to externals file. - 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' - - # Dictionary keys are component names. The corresponding values are laid out - # according to this schema. - _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())) - - printlog( - 'Processing submodules description file : {0} ({1})'.format( - submod_file, repo_path)) - submod_model_data= _read_gitmodules_file(repo_path, submod_file) - submod_desc = create_externals_description(submod_model_data) - - # 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 - - components: list of component names to include, None to include all. - exclude: list of component names to skip. - """ - 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. - - components: list of component names to include, None to include all. - exclude: list of component names to skip. - """ - 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 6bc29e9732..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). - - """ - # sync_state and clean_state can be one of the following: - DEFAULT = '-' # not set yet (sync_state). clean_state can be this if sync_state is EMPTY. - UNKNOWN = '?' - EMPTY = 'e' - MODEL_MODIFIED = 's' # repo version != externals (sync_state only) - DIRTY = 'M' # repo is dirty (clean_state only) - STATUS_OK = ' ' # repo is clean (clean_state) or matches externals version (sync_state) - STATUS_ERROR = '!' - - # source_type can be one of the following: - 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 - """ - printlog(self._default_status_message()) - if verbosity >= VERBOSITY_VERBOSE: - printlog(self._verbose_status_message()) - if verbosity >= VERBOSITY_DUMP: - printlog(self._dump_status_message()) - - def __repr__(self): - return self._default_status_message() - - def _default_status_message(self): - """Return the default terse status message string - """ - return '{sync}{clean}{src_type} {path}'.format( - sync=self.sync_state, clean=self.clean_state, - src_type=self.source_type, path=self.path) - - 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) - return ' {clean}, {sync}'.format(clean=clean_str, sync=sync_str) - - def _dump_status_message(self): - """Return the dump status message string - """ - return indent_string(self.status_output, 12) - - 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 18c73ffc4b..0000000000 --- a/manage_externals/manic/repository_factory.py +++ /dev/null @@ -1,30 +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. - - Can return None (e.g. if protocol is 'externals_only'). - """ - 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 aab1a468a8..0000000000 --- a/manage_externals/manic/repository_git.py +++ /dev/null @@ -1,859 +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 -import sys - -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 -C {dirname} ...'.format(dirname=dirname).split() - - 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): - """ - repo: ExternalsDescription. - """ - 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): - """Clones repo_dir_name into base_dir_path. - """ - self._git_clone(self._url, os.path.join(base_dir_path, repo_dir_name), - verbosity=verbosity) - - def _current_ref(self, dirname): - """Determine the *name* associated with HEAD at dirname. - - 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(dirname) - 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(dirname) - 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(dirname) - 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 - - # get the full hash of the current commit - _, current_ref = self._git_current_hash(repo_dir_path) - - if self._branch: - if self._url == LOCAL_PATH_INDICATOR: - expected_ref = self._branch - else: - remote_name = self._remote_name_for_url(self._url, - repo_dir_path) - 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(repo_dir_path) - 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, repo_dir_path) - 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) - - @classmethod - def _remote_name_for_url(cls, remote_url, dirname): - """Return the remote name matching remote_url (or None) - - """ - git_output = cls._git_remote_verbose(dirname) - git_output = git_output.splitlines() - for line in git_output: - data = line.strip() - if not data: - continue - data = data.split() - name = data[0].strip() - url = data[1].strip() - if remote_url == url: - return name - return None - - 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() - if self._url.strip() == LOCAL_PATH_INDICATOR: - self._checkout_local_ref(verbosity, submodules, repo_dir) - else: - self._checkout_external_ref(verbosity, submodules, repo_dir) - - if self._sparse: - self._sparse_checkout(repo_dir, verbosity) - - - def _checkout_local_ref(self, verbosity, submodules, dirname): - """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, remote_name=None, - dirname=dirname) - self._git_checkout_ref(ref, verbosity, submodules, dirname) - - def _checkout_external_ref(self, verbosity, submodules, dirname): - """Checkout the reference from a remote repository into dirname. - if is True, recursively initialize and update - the repo's submodules. - Note that this results in a 'detached HEAD' state if checking out - a branch, because we check out the remote branch rather than the - local. See https://github.com/ESMCI/manage_externals/issues/34 for - more discussion. - """ - if self._tag: - ref = self._tag - elif self._branch: - ref = self._branch - else: - ref = self._hash - - remote_name = self._remote_name_for_url(self._url, dirname) - if not remote_name: - remote_name = self._create_remote_name() - self._git_remote_add(remote_name, self._url, dirname) - self._git_fetch(remote_name, dirname) - - # 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, dirname) - - if self._branch: - # Prepend remote name to branch. This means we avoid various - # special cases if the local branch is not tracking the remote or - # cannot be trivially fast-forwarded to match; but, it also - # means we end up in a 'detached HEAD' state. - ref = '{0}/{1}'.format(remote_name, ref) - self._git_checkout_ref(ref, verbosity, submodules, dirname) - - def _sparse_checkout(self, repo_dir, verbosity): - """Use git read-tree to thin the working tree.""" - cmd = ['cp', os.path.join(repo_dir, self._sparse), - os.path.join(repo_dir, - '.git/info/sparse-checkout')] - if verbosity >= VERBOSITY_VERBOSE: - printlog(' {0}'.format(' '.join(cmd))) - execute_subprocess(cmd) - self._git_sparse_checkout(verbosity, repo_dir) - - def _check_for_valid_ref(self, ref, remote_name, dirname): - """Try some basic sanity checks on the user supplied reference so we - can provide a more useful error message than calledprocess - error... - - remote_name can be NOne - """ - is_tag = self._ref_is_tag(ref, dirname) - is_branch = self._ref_is_branch(ref, remote_name, dirname) - is_hash = self._ref_is_hash(ref, dirname) - 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, - dirname) - 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, dirname): - """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, dirname) - is_branch = self._ref_is_branch(ref, remote_name, dirname) - is_hash = self._ref_is_hash(ref, dirname) - - 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, dirname): - """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, dirname) - if value == 0: - is_tag = True - return is_tag - - def _ref_is_branch(self, ref, remote_name, dirname): - """Verify if a ref is any kind of branch (local, tracked remote, - untracked remote). - - remote_name can be None. - """ - local_branch = False - remote_branch = False - if remote_name: - remote_branch = self._ref_is_remote_branch(ref, remote_name, - dirname) - local_branch = self._ref_is_local_branch(ref, dirname) - - is_branch = False - if local_branch or remote_branch: - is_branch = True - return is_branch - - def _ref_is_local_branch(self, ref, dirname): - """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, dirname) - if value == 0: - is_branch = True - return is_branch - - def _ref_is_remote_branch(self, ref, remote_name, dirname): - """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, dirname) - if value == 0: - is_branch = True - return is_branch - - def _ref_is_commit(self, ref, dirname): - """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, dirname) - if value == 0: - is_commit = True - return is_commit - - def _ref_is_hash(self, ref, dirname): - """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, dirname) - 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 - - """ - git_output = self._git_status_porcelain_v1z(repo_dir_path) - 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(repo_dir_path) - - @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(dirname): - """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", - dirname) - hash_found = not status - if not hash_found: - git_output = '' - return hash_found, git_output - - @staticmethod - def _git_current_remote_branch(dirname): - """Determines the name of the current remote branch, if any. - - if dir is None, uses the cwd. - - Returns a tuple, (branch_found, branch_name), where branch_found - is a bool specifying whether a branch name was found for - HEAD. (If branch_found is False, then branch_name is ''). - branch_name is in the format '$remote/$branch', e.g. 'origin/foo'. - """ - branch_found = False - branch_name = '' - - cmd = 'git -C {dirname} log -n 1 --pretty=%d HEAD'.format( - dirname=dirname).split() - status, git_output = execute_subprocess(cmd, - output_to_caller=True, - status_to_caller=True) - branch_found = 'HEAD,' in git_output - if branch_found: - # git_output is of the form " (HEAD, origin/blah)" - branch_name = git_output.split(',')[1].strip()[:-1] - return branch_found, branch_name - - @staticmethod - def _git_current_branch(dirname): - """Determines the name of the current local branch. - - Returns a tuple, (branch_found, branch_name), where branch_found - is a bool specifying whether a branch name was found for - HEAD. (If branch_found is False, then branch_name is ''.) - Note that currently we check out the remote branch rather than - the local, so this command does not return the just-checked-out - branch. See _git_current_remote_branch. - """ - cmd = 'git -C {dirname} symbolic-ref --short -q HEAD'.format( - dirname=dirname).split() - 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(dirname): - """Determines the name tag corresponding to HEAD (if any). - - if dirname is None, uses the cwd. - - Returns a tuple, (tag_found, tag_name), where tag_found is a - bool specifying whether we found a tag name corresponding to - HEAD. (If tag_found is False, then tag_name is ''.) - """ - cmd = 'git -C {dirname} describe --exact-match --tags HEAD'.format( - dirname=dirname).split() - 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, dirname): - """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 -C {dirname} show-ref --quiet --verify refs/tags/{ref}' - .format(dirname=dirname, ref=ref).split()) - status = execute_subprocess(cmd, status_to_caller=True) - return status - - @staticmethod - def _git_showref_branch(ref, dirname): - """Run git show-ref check if the user supplied ref is a local or - tracked remote branch. - - """ - cmd = ('git -C {dirname} show-ref --quiet --verify refs/heads/{ref}' - .format(dirname=dirname, ref=ref).split()) - status = execute_subprocess(cmd, status_to_caller=True) - return status - - @staticmethod - def _git_lsremote_branch(ref, remote_name, dirname): - """Run git ls-remote to check if the user supplied ref is a remote - branch that is not being tracked - - """ - cmd = ('git -C {dirname} ls-remote --exit-code --heads ' - '{remote_name} {ref}').format( - dirname=dirname, remote_name=remote_name, ref=ref).split() - status, output = execute_subprocess(cmd, status_to_caller=True, output_to_caller=True) - if not status and not f"refs/heads/{ref}" in output: - # In this case the ref is contained in the branch name but is not the complete branch name - return -1 - return status - - @staticmethod - def _git_revparse_commit(ref, dirname): - """Run git rev-parse to detect if a reference is a SHA, HEAD or other - valid commit. - - """ - cmd = ('git -C {dirname} rev-parse --quiet --verify {ref}^{commit}' - .format(dirname=dirname, ref=ref, commit='{commit}').split()) - 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(dirname): - """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 -C {dirname} status --untracked-files=no --porcelain -z' - .format(dirname=dirname)).split() - git_output = execute_subprocess(cmd, output_to_caller=True) - return git_output - - @staticmethod - def _git_status_verbose(dirname): - """Run the git status command to obtain repository information. - """ - cmd = 'git -C {dirname} status'.format(dirname=dirname).split() - git_output = execute_subprocess(cmd, output_to_caller=True) - return git_output - - @staticmethod - def _git_remote_verbose(dirname): - """Run the git remote command to obtain repository information. - - Returned string is of the form: - myfork git@github.com:johnpaulalex/manage_externals_jp.git (fetch) - myfork git@github.com:johnpaulalex/manage_externals_jp.git (push) - """ - cmd = 'git -C {dirname} remote --verbose'.format( - dirname=dirname).split() - return execute_subprocess(cmd, output_to_caller=True) - - @staticmethod - def has_submodules(repo_dir_path): - """Return True iff the repository at has a - '.gitmodules' file - """ - 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): - """Clones url into repo_dir_name. - """ - cmd = 'git clone --quiet {url} {repo_dir_name}'.format( - url=url, repo_dir_name=repo_dir_name).split() - if verbosity >= VERBOSITY_VERBOSE: - printlog(' {0}'.format(' '.join(cmd))) - execute_subprocess(cmd) - - @staticmethod - def _git_remote_add(name, url, dirname): - """Run the git remote command for the side effect of adding a remote - """ - cmd = 'git -C {dirname} remote add {name} {url}'.format( - dirname=dirname, name=name, url=url).split() - execute_subprocess(cmd) - - @staticmethod - def _git_fetch(remote_name, dirname): - """Run the git fetch command for the side effect of updating the repo - """ - cmd = 'git -C {dirname} fetch --quiet --tags {remote_name}'.format( - dirname=dirname, remote_name=remote_name).split() - execute_subprocess(cmd) - - @staticmethod - def _git_checkout_ref(ref, verbosity, submodules, dirname): - """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 -C {dirname} checkout --quiet {ref}'.format( - dirname=dirname, ref=ref).split() - if verbosity >= VERBOSITY_VERBOSE: - printlog(' {0}'.format(' '.join(cmd))) - execute_subprocess(cmd) - if submodules: - GitRepository._git_update_submodules(verbosity, dirname) - - @staticmethod - def _git_sparse_checkout(verbosity, dirname): - """Configure repo via read-tree.""" - cmd = 'git -C {dirname} config core.sparsecheckout true'.format( - dirname=dirname).split() - if verbosity >= VERBOSITY_VERBOSE: - printlog(' {0}'.format(' '.join(cmd))) - execute_subprocess(cmd) - cmd = 'git -C {dirname} read-tree -mu HEAD'.format( - dirname=dirname).split() - if verbosity >= VERBOSITY_VERBOSE: - printlog(' {0}'.format(' '.join(cmd))) - execute_subprocess(cmd) - - @staticmethod - def _git_update_submodules(verbosity, dirname): - """Run git submodule update for the side effect of updating this - repo's submodules. - """ - # due to https://vielmetti.typepad.com/logbook/2022/10/git-security-fixes-lead-to-fatal-transport-file-not-allowed-error-in-ci-systems-cve-2022-39253.html - # submodules from file doesn't work without overriding the protocol, this is done - # for testing submodule support but should not be done in practice - file_protocol = "" - if 'unittest' in sys.modules.keys(): - file_protocol = "-c protocol.file.allow=always" - - # First, verify that we have a .gitmodules file - if os.path.exists( - os.path.join(dirname, - ExternalsDescription.GIT_SUBMODULES_FILENAME)): - cmd = ('git {file_protocol} -C {dirname} submodule update --init --recursive' - .format(file_protocol=file_protocol, dirname=dirname)).split() - 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 32a71184b4..0000000000 --- a/manage_externals/manic/repository_svn.py +++ /dev/null @@ -1,291 +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) - if 'github.com' in self._url: - msg = "SVN access to github.com is no longer supported" - fatal_error(msg) - self._ignore_ancestry = ignore_ancestry - if self._url.endswith('/'): - # there is already a '/' separator in the URL; no need to add another - url_sep = '' - else: - url_sep = '/' - if self._branch: - self._url = self._url + url_sep + self._branch - elif self._tag: - self._url = self._url + url_sep + 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 cf2a5b7569..0000000000 --- a/manage_externals/manic/sourcetree.py +++ /dev/null @@ -1,425 +0,0 @@ -""" -Classes to represent an externals config file (SourceTree) and the components -within it (_External). -""" - -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): - """ - A single component hosted in an external repository (and any children). - - The component may or may not be checked-out upon construction. - """ - # pylint: disable=R0902 - - def __init__(self, root_dir, name, local_path, required, subexternals_path, - repo, svn_ignore_ancestry, subexternal_sourcetree): - """Create a single external component (checked out or not). - - Input: - root_dir : string - the (checked-out) parent repo's root dir. - local_path : string - this external's (checked-out) subdir relative - to root_dir, e.g. "components/mom" - repo: Repository - the repo object for this external. Can be None (e.g. if this external just refers to another external file). - - name : string - name of this external (as named by the parent - reference). 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 - - subexternals_path: string - path to sub-externals config file, if any. Relative to local_path, or special value 'none'. - subexternal_sourcetree: SourceTree - corresponding to subexternals_path, if subexternals_path exists (it might not, if it is not checked out yet). - """ - self._name = name - self._required = required - - self._stat = None # Populated in status() - - self._local_path = local_path - # _repo_dir_path : full repository directory, e.g. - # "/components/mom" - repo_dir = os.path.join(root_dir, local_path) - self._repo_dir_path = os.path.abspath(repo_dir) - # _base_dir_path : base directory *containing* the repository, e.g. - # "/components" - self._base_dir_path = os.path.dirname(self._repo_dir_path) - # _repo_dir_name : base_dir_path + repo_dir_name = repo_dir_path - # e.g., "mom" - self._repo_dir_name = os.path.basename(self._repo_dir_path) - self._repo = repo - - # Does this component have subcomponents aka an externals config? - self._subexternals_path = subexternals_path - self._subexternal_sourcetree = subexternal_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 get_repo_dir_path(self): - return self._repo_dir_path - - def get_subexternals_path(self): - return self._subexternals_path - - def get_repo(self): - return self._repo - - def status(self, force=False, print_progress=False): - """ - Returns status of this component and all subcomponents. - - Returns a dict mapping our local path (not component name!) to an - ExternalStatus dict. Any subcomponents will have their own top-level - path keys. Note the return value includes entries for this and all - subcomponents regardless of whether they are locally installed or not. - - Side-effect: If self._stat is empty or force is True, calculates _stat. - """ - calc_stat = force or not self._stat - - if calc_stat: - self._stat = ExternalStatus() - 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_subexternals. - self._stat.source_type = ExternalStatus.STANDALONE - else: - # managed by checkout_subexternals - self._stat.source_type = ExternalStatus.MANAGED - - subcomponent_stats = {} - if not os.path.exists(self._repo_dir_path): - if calc_stat: - # No local repository. - 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: - # Merge local repository state (e.g. clean/dirty) into self._stat. - if calc_stat and self._repo: - self._repo.status(self._stat, self._repo_dir_path) - - # Status of subcomponents, if any. - if self._subexternals_path and self._subexternal_sourcetree: - cwd = os.getcwd() - # SourceTree.status() expects to be called from the correct - # root directory. - os.chdir(self._repo_dir_path) - subcomponent_stats = self._subexternal_sourcetree.status(self._local_path, force=force, print_progress=print_progress) - os.chdir(cwd) - - # Merge our status + subcomponent statuses into one return dict keyed - # by component path. - 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 the local_path, not comp name so - # it will be sorted correctly - all_stats[self._stat.path] = self._stat - - if subcomponent_stats: - all_stats.update(subcomponent_stats) - - return all_stats - - def checkout(self, verbosity): - """ - If the repo destination directory exists, ensure it is correct (from - correct URL, correct branch or tag), and possibly updateit. - If the repo destination directory does not exist, checkout the correct - branch or tag. - Does not check out sub-externals, see SourceTree.checkout(). - """ - # 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 not self._stat: - self.status() - assert self._stat - - 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 replace_subexternal_sourcetree(self, sourcetree): - self._subexternal_sourcetree = sourcetree - - def clone_recursive(self): - 'Return True iff any .gitmodules files should be processed' - # Try recursive .gitmodules unless there is an externals entry - recursive = not self._subexternals_path - - return recursive - - -class SourceTree(object): - """ - SourceTree represents a group of managed externals. - - Those externals may not be checked out locally yet, they might only - have Repository objects pointing to their respective repositories. - """ - - @classmethod - def from_externals_file(cls, parent_repo_dir_path, parent_repo, - externals_path): - """Creates a SourceTree representing the given externals file. - - Looks up a git submodules file as an optional backup if there is no - externals file specified. - - Returns None if there is no externals file (i.e. it's None or 'none'), - or if the externals file hasn't been checked out yet. - - parent_repo_dir_path: parent repo root dir - parent_repo: parent repo. - externals_path: path to externals file, relative to parent_repo_dir_path. - """ - if not os.path.exists(parent_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 None - - if externals_path.lower() == 'none': - # With explicit 'none', do not look for git submodules file. - return None - - cwd = os.getcwd() - os.chdir(parent_repo_dir_path) - - if not externals_path: - if GitRepository.has_submodules(parent_repo_dir_path): - externals_path = ExternalsDescription.GIT_SUBMODULES_FILENAME - else: - return None - - if not os.path.exists(externals_path): - # NOTE(bja, 2017-10) this check is redundant with the one - # in read_externals_description_file! - msg = ('Externals description file "{0}" ' - 'does not exist! In directory: {1}'.format( - externals_path, parent_repo_dir_path)) - fatal_error(msg) - - externals_root = parent_repo_dir_path - # model_data is a dict-like object which mirrors the file format. - model_data = read_externals_description_file(externals_root, - externals_path) - # ext_description is another dict-like object (see ExternalsDescription) - ext_description = create_externals_description(model_data, - parent_repo=parent_repo) - externals_sourcetree = SourceTree(externals_root, ext_description) - os.chdir(cwd) - return externals_sourcetree - - def __init__(self, root_dir, ext_description, svn_ignore_ancestry=False): - """ - Build a SourceTree object from an ExternalDescription. - - root_dir: the (checked-out) parent repo root dir. - """ - self._root_dir = os.path.abspath(root_dir) - self._all_components = {} # component_name -> _External - self._required_compnames = [] - for comp, desc in ext_description.items(): - local_path = desc[ExternalsDescription.PATH] - required = desc[ExternalsDescription.REQUIRED] - repo_info = desc[ExternalsDescription.REPO] - subexternals_path = desc[ExternalsDescription.EXTERNALS] - - repo = create_repository(comp, - repo_info, - svn_ignore_ancestry=svn_ignore_ancestry) - - sourcetree = None - # Treat a .gitmodules file as a backup externals config - if not subexternals_path: - parent_repo_dir_path = os.path.abspath(os.path.join(root_dir, - local_path)) - if GitRepository.has_submodules(parent_repo_dir_path): - subexternals_path = ExternalsDescription.GIT_SUBMODULES_FILENAME - - # Might return None (if the subexternal isn't checked out yet, or subexternal is None or 'none') - subexternal_sourcetree = SourceTree.from_externals_file( - os.path.join(self._root_dir, local_path), - repo, - subexternals_path) - src = _External(self._root_dir, comp, local_path, required, - subexternals_path, repo, svn_ignore_ancestry, - subexternal_sourcetree) - - self._all_components[comp] = src - if required: - self._required_compnames.append(comp) - - def status(self, relative_path_base=LOCAL_PATH_INDICATOR, - force=False, print_progress=False): - """Return a dictionary of local path->ExternalStatus. - - Notes about the returned dictionary: - * It is keyed by local path (e.g. 'components/mom'), not by - component name (e.g. 'mom'). - * It contains top-level keys for all traversed components, whether - discovered by recursion or top-level. - * It contains entries for all components regardless of whether they - are locally installed or not, or required or optional. -x """ - load_comps = self._all_components.keys() - - summary = {} # Holds merged statuses from all components. - for comp in load_comps: - if print_progress: - printlog('{0}, '.format(comp), end='') - stat = self._all_components[comp].status(force=force, - print_progress=print_progress) - - # Returned status dictionary is keyed by local path; prepend - # relative_path_base if not already there. - stat_final = {} - for name in stat.keys(): - if stat[name].path.startswith(relative_path_base): - stat_final[name] = stat[name] - else: - 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 _find_installed_optional_components(self): - """Returns a list of installed optional component names, if any.""" - installed_comps = [] - for comp_name, ext in self._all_components.items(): - if comp_name in self._required_compnames: - continue - # Note that in practice we expect this status to be cached. - path_to_stat = ext.status() - - # If any part of this component exists locally, consider it - # installed and therefore eligible for updating. - if any(s.sync_state != ExternalStatus.EMPTY - for s in path_to_stat.values()): - installed_comps.append(comp_name) - return installed_comps - - def checkout(self, verbosity, load_all, load_comp=None): - """ - Checkout or update indicated components into the configured subdirs. - - If load_all is True, checkout all externals (required + optional), recursively. - If load_all is False and load_comp is set, checkout load_comp (and any required subexternals, plus any optional subexternals that are already checked out, recursively) - If load_all is False and load_comp is None, checkout all required externals, plus any optionals that are already checked out, recursively. - """ - if load_all: - tmp_comps = self._all_components.keys() - elif load_comp is not None: - tmp_comps = [load_comp] - else: - local_optional_compnames = self._find_installed_optional_components() - tmp_comps = self._required_compnames + local_optional_compnames - if local_optional_compnames: - printlog('Found locally installed optional components: ' + - ', '.join(local_optional_compnames)) - bad_compnames = set(local_optional_compnames) - set(self._all_components.keys()) - if bad_compnames: - printlog('Internal error: found locally installed components that are not in the global list of all components: ' + ','.join(bad_compnames)) - - if verbosity >= VERBOSITY_VERBOSE: - printlog('Checking out externals: ') - else: - printlog('Checking out externals: ', end='') - - # 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. - for comp_name in load_comps: - if verbosity < VERBOSITY_VERBOSE: - printlog('{0}, '.format(comp_name), end='') - else: - # verbose output handled by the _External object, just - # output a newline - printlog(EMPTY_STR) - c = self._all_components[comp_name] - # Does not recurse. - c.checkout(verbosity) - # Recursively check out subexternals, if any. Returns None - # if there's no subexternals path. - component_subexternal_sourcetree = SourceTree.from_externals_file( - c.get_repo_dir_path(), - c.get_repo(), - c.get_subexternals_path()) - c.replace_subexternal_sourcetree(component_subexternal_sourcetree) - if component_subexternal_sourcetree: - component_subexternal_sourcetree.checkout(verbosity, load_all) - printlog('') 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 1e8f2eaa77..0000000000 --- a/manage_externals/test/README.md +++ /dev/null @@ -1,53 +0,0 @@ -# Testing for checkout_externals - -## Unit tests - -```SH - cd checkout_externals/test - make utest -``` - -## System tests - -```SH - cd checkout_externals/test - make stest -``` - -Example to run a single test: -```SH - cd checkout_externals - python -m unittest test.test_sys_checkout.TestSysCheckout.test_container_simple_required -``` - -## 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 - make lint -``` - -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 - make coverage - open -a Firefox.app htmlcov/index.html -``` - - 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/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/README.md b/manage_externals/test/repos/README.md deleted file mode 100644 index 026b684ea3..0000000000 --- a/manage_externals/test/repos/README.md +++ /dev/null @@ -1,33 +0,0 @@ -Git and svn repositories for testing git and svn-related behavior. For usage and terminology notes, see test/test_sys_checkout.py. - -For git repos: To list files and view file contents at HEAD: -``` -cd -git ls-tree --full-tree -r --name-only HEAD -git cat-file -p HEAD: -``` - -File contents at a glance: -``` -container.git/ - readme.txt - -simple-ext.git/ - (has branches: feature2, feature3) - (has tags: tag1, tag2) - readme.txt - simple_subdir/subdir_file.txt - -simple-ext-fork.git/ - (has tags: abandoned-feature, forked-feature-v1, tag1) - (has branch: feature2) - readme.txt - -mixed-cont-ext.git/ - (has branch: new-feature) - readme.txt - sub-externals.cfg ('simp_branch' section refers to 'feature2' branch in simple-ext.git/ repo) - -error/ - (no git repo here, just a readme.txt in the clear) -``` 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/repos/simple-ext.svn/README.txt b/manage_externals/test/repos/simple-ext.svn/README.txt deleted file mode 100644 index 9935818a1b..0000000000 --- a/manage_externals/test/repos/simple-ext.svn/README.txt +++ /dev/null @@ -1,5 +0,0 @@ -This is a Subversion repository; use the 'svnadmin' and 'svnlook' -tools to examine it. Do not add, delete, or modify files here -unless you know how to avoid corrupting the repository. - -Visit http://subversion.apache.org/ for more information. diff --git a/manage_externals/test/repos/simple-ext.svn/conf/authz b/manage_externals/test/repos/simple-ext.svn/conf/authz deleted file mode 100644 index 0b9a41074e..0000000000 --- a/manage_externals/test/repos/simple-ext.svn/conf/authz +++ /dev/null @@ -1,32 +0,0 @@ -### This file is an example authorization file for svnserve. -### Its format is identical to that of mod_authz_svn authorization -### files. -### As shown below each section defines authorizations for the path and -### (optional) repository specified by the section name. -### The authorizations follow. An authorization line can refer to: -### - a single user, -### - a group of users defined in a special [groups] section, -### - an alias defined in a special [aliases] section, -### - all authenticated users, using the '$authenticated' token, -### - only anonymous users, using the '$anonymous' token, -### - anyone, using the '*' wildcard. -### -### A match can be inverted by prefixing the rule with '~'. Rules can -### grant read ('r') access, read-write ('rw') access, or no access -### (''). - -[aliases] -# joe = /C=XZ/ST=Dessert/L=Snake City/O=Snake Oil, Ltd./OU=Research Institute/CN=Joe Average - -[groups] -# harry_and_sally = harry,sally -# harry_sally_and_joe = harry,sally,&joe - -# [/foo/bar] -# harry = rw -# &joe = r -# * = - -# [repository:/baz/fuz] -# @harry_and_sally = rw -# * = r diff --git a/manage_externals/test/repos/simple-ext.svn/conf/hooks-env.tmpl b/manage_externals/test/repos/simple-ext.svn/conf/hooks-env.tmpl deleted file mode 100644 index ee965c316c..0000000000 --- a/manage_externals/test/repos/simple-ext.svn/conf/hooks-env.tmpl +++ /dev/null @@ -1,19 +0,0 @@ -### This file is an example hook script environment configuration file. -### Hook scripts run in an empty environment by default. -### As shown below each section defines environment variables for a -### particular hook script. The [default] section defines environment -### variables for all hook scripts, unless overridden by a hook-specific -### section. - -### This example configures a UTF-8 locale for all hook scripts, so that -### special characters, such as umlauts, may be printed to stderr. -### If UTF-8 is used with a mod_dav_svn server, the SVNUseUTF8 option must -### also be set to 'yes' in httpd.conf. -### With svnserve, the LANG environment variable of the svnserve process -### must be set to the same value as given here. -[default] -LANG = en_US.UTF-8 - -### This sets the PATH environment variable for the pre-commit hook. -[pre-commit] -PATH = /usr/local/bin:/usr/bin:/usr/sbin diff --git a/manage_externals/test/repos/simple-ext.svn/conf/passwd b/manage_externals/test/repos/simple-ext.svn/conf/passwd deleted file mode 100644 index ecaa08dcec..0000000000 --- a/manage_externals/test/repos/simple-ext.svn/conf/passwd +++ /dev/null @@ -1,8 +0,0 @@ -### This file is an example password file for svnserve. -### Its format is similar to that of svnserve.conf. As shown in the -### example below it contains one section labelled [users]. -### The name and password for each user follow, one account per line. - -[users] -# harry = harryssecret -# sally = sallyssecret diff --git a/manage_externals/test/repos/simple-ext.svn/conf/svnserve.conf b/manage_externals/test/repos/simple-ext.svn/conf/svnserve.conf deleted file mode 100644 index 6cefc17b3e..0000000000 --- a/manage_externals/test/repos/simple-ext.svn/conf/svnserve.conf +++ /dev/null @@ -1,81 +0,0 @@ -### This file controls the configuration of the svnserve daemon, if you -### use it to allow access to this repository. (If you only allow -### access through http: and/or file: URLs, then this file is -### irrelevant.) - -### Visit http://subversion.apache.org/ for more information. - -[general] -### The anon-access and auth-access options control access to the -### repository for unauthenticated (a.k.a. anonymous) users and -### authenticated users, respectively. -### Valid values are "write", "read", and "none". -### Setting the value to "none" prohibits both reading and writing; -### "read" allows read-only access, and "write" allows complete -### read/write access to the repository. -### The sample settings below are the defaults and specify that anonymous -### users have read-only access to the repository, while authenticated -### users have read and write access to the repository. -# anon-access = read -# auth-access = write -### The password-db option controls the location of the password -### database file. Unless you specify a path starting with a /, -### the file's location is relative to the directory containing -### this configuration file. -### If SASL is enabled (see below), this file will NOT be used. -### Uncomment the line below to use the default password file. -# password-db = passwd -### The authz-db option controls the location of the authorization -### rules for path-based access control. Unless you specify a path -### starting with a /, the file's location is relative to the -### directory containing this file. The specified path may be a -### repository relative URL (^/) or an absolute file:// URL to a text -### file in a Subversion repository. If you don't specify an authz-db, -### no path-based access control is done. -### Uncomment the line below to use the default authorization file. -# authz-db = authz -### The groups-db option controls the location of the file with the -### group definitions and allows maintaining groups separately from the -### authorization rules. The groups-db file is of the same format as the -### authz-db file and should contain a single [groups] section with the -### group definitions. If the option is enabled, the authz-db file cannot -### contain a [groups] section. Unless you specify a path starting with -### a /, the file's location is relative to the directory containing this -### file. The specified path may be a repository relative URL (^/) or an -### absolute file:// URL to a text file in a Subversion repository. -### This option is not being used by default. -# groups-db = groups -### This option specifies the authentication realm of the repository. -### If two repositories have the same authentication realm, they should -### have the same password database, and vice versa. The default realm -### is repository's uuid. -# realm = My First Repository -### The force-username-case option causes svnserve to case-normalize -### usernames before comparing them against the authorization rules in the -### authz-db file configured above. Valid values are "upper" (to upper- -### case the usernames), "lower" (to lowercase the usernames), and -### "none" (to compare usernames as-is without case conversion, which -### is the default behavior). -# force-username-case = none -### The hooks-env options specifies a path to the hook script environment -### configuration file. This option overrides the per-repository default -### and can be used to configure the hook script environment for multiple -### repositories in a single file, if an absolute path is specified. -### Unless you specify an absolute path, the file's location is relative -### to the directory containing this file. -# hooks-env = hooks-env - -[sasl] -### This option specifies whether you want to use the Cyrus SASL -### library for authentication. Default is false. -### Enabling this option requires svnserve to have been built with Cyrus -### SASL support; to check, run 'svnserve --version' and look for a line -### reading 'Cyrus SASL authentication is available.' -# use-sasl = true -### These options specify the desired strength of the security layer -### that you want SASL to provide. 0 means no encryption, 1 means -### integrity-checking only, values larger than 1 are correlated -### to the effective key length for encryption (e.g. 128 means 128-bit -### encryption). The values below are the defaults. -# min-encryption = 0 -# max-encryption = 256 diff --git a/manage_externals/test/repos/simple-ext.svn/db/current b/manage_externals/test/repos/simple-ext.svn/db/current deleted file mode 100644 index 00750edc07..0000000000 --- a/manage_externals/test/repos/simple-ext.svn/db/current +++ /dev/null @@ -1 +0,0 @@ -3 diff --git a/manage_externals/test/repos/simple-ext.svn/db/format b/manage_externals/test/repos/simple-ext.svn/db/format deleted file mode 100644 index 5dd0c22198..0000000000 --- a/manage_externals/test/repos/simple-ext.svn/db/format +++ /dev/null @@ -1,3 +0,0 @@ -8 -layout sharded 1000 -addressing logical diff --git a/manage_externals/test/repos/simple-ext.svn/db/fs-type b/manage_externals/test/repos/simple-ext.svn/db/fs-type deleted file mode 100644 index 4fdd95313f..0000000000 --- a/manage_externals/test/repos/simple-ext.svn/db/fs-type +++ /dev/null @@ -1 +0,0 @@ -fsfs diff --git a/manage_externals/test/repos/simple-ext.svn/db/fsfs.conf b/manage_externals/test/repos/simple-ext.svn/db/fsfs.conf deleted file mode 100644 index ac6877a727..0000000000 --- a/manage_externals/test/repos/simple-ext.svn/db/fsfs.conf +++ /dev/null @@ -1,200 +0,0 @@ -### This file controls the configuration of the FSFS filesystem. - -[memcached-servers] -### These options name memcached servers used to cache internal FSFS -### data. See http://www.danga.com/memcached/ for more information on -### memcached. To use memcached with FSFS, run one or more memcached -### servers, and specify each of them as an option like so: -# first-server = 127.0.0.1:11211 -# remote-memcached = mymemcached.corp.example.com:11212 -### The option name is ignored; the value is of the form HOST:PORT. -### memcached servers can be shared between multiple repositories; -### however, if you do this, you *must* ensure that repositories have -### distinct UUIDs and paths, or else cached data from one repository -### might be used by another accidentally. Note also that memcached has -### no authentication for reads or writes, so you must ensure that your -### memcached servers are only accessible by trusted users. - -[caches] -### When a cache-related error occurs, normally Subversion ignores it -### and continues, logging an error if the server is appropriately -### configured (and ignoring it with file:// access). To make -### Subversion never ignore cache errors, uncomment this line. -# fail-stop = true - -[rep-sharing] -### To conserve space, the filesystem can optionally avoid storing -### duplicate representations. This comes at a slight cost in -### performance, as maintaining a database of shared representations can -### increase commit times. The space savings are dependent upon the size -### of the repository, the number of objects it contains and the amount of -### duplication between them, usually a function of the branching and -### merging process. -### -### The following parameter enables rep-sharing in the repository. It can -### be switched on and off at will, but for best space-saving results -### should be enabled consistently over the life of the repository. -### 'svnadmin verify' will check the rep-cache regardless of this setting. -### rep-sharing is enabled by default. -# enable-rep-sharing = true - -[deltification] -### To conserve space, the filesystem stores data as differences against -### existing representations. This comes at a slight cost in performance, -### as calculating differences can increase commit times. Reading data -### will also create higher CPU load and the data will be fragmented. -### Since deltification tends to save significant amounts of disk space, -### the overall I/O load can actually be lower. -### -### The options in this section allow for tuning the deltification -### strategy. Their effects on data size and server performance may vary -### from one repository to another. Versions prior to 1.8 will ignore -### this section. -### -### The following parameter enables deltification for directories. It can -### be switched on and off at will, but for best space-saving results -### should be enabled consistently over the lifetime of the repository. -### Repositories containing large directories will benefit greatly. -### In rarely accessed repositories, the I/O overhead may be significant -### as caches will most likely be low. -### directory deltification is enabled by default. -# enable-dir-deltification = true -### -### The following parameter enables deltification for properties on files -### and directories. Overall, this is a minor tuning option but can save -### some disk space if you merge frequently or frequently change node -### properties. You should not activate this if rep-sharing has been -### disabled because this may result in a net increase in repository size. -### property deltification is enabled by default. -# enable-props-deltification = true -### -### During commit, the server may need to walk the whole change history of -### of a given node to find a suitable deltification base. This linear -### process can impact commit times, svnadmin load and similar operations. -### This setting limits the depth of the deltification history. If the -### threshold has been reached, the node will be stored as fulltext and a -### new deltification history begins. -### Note, this is unrelated to svn log. -### Very large values rarely provide significant additional savings but -### can impact performance greatly - in particular if directory -### deltification has been activated. Very small values may be useful in -### repositories that are dominated by large, changing binaries. -### Should be a power of two minus 1. A value of 0 will effectively -### disable deltification. -### For 1.8, the default value is 1023; earlier versions have no limit. -# max-deltification-walk = 1023 -### -### The skip-delta scheme used by FSFS tends to repeatably store redundant -### delta information where a simple delta against the latest version is -### often smaller. By default, 1.8+ will therefore use skip deltas only -### after the linear chain of deltas has grown beyond the threshold -### specified by this setting. -### Values up to 64 can result in some reduction in repository size for -### the cost of quickly increasing I/O and CPU costs. Similarly, smaller -### numbers can reduce those costs at the cost of more disk space. For -### rarely read repositories or those containing larger binaries, this may -### present a better trade-off. -### Should be a power of two. A value of 1 or smaller will cause the -### exclusive use of skip-deltas (as in pre-1.8). -### For 1.8, the default value is 16; earlier versions use 1. -# max-linear-deltification = 16 -### -### After deltification, we compress the data to minimize on-disk size. -### This setting controls the compression algorithm, which will be used in -### future revisions. It can be used to either disable compression or to -### select between available algorithms (zlib, lz4). zlib is a general- -### purpose compression algorithm. lz4 is a fast compression algorithm -### which should be preferred for repositories with large and, possibly, -### incompressible files. Note that the compression ratio of lz4 is -### usually lower than the one provided by zlib, but using it can -### significantly speed up commits as well as reading the data. -### lz4 compression algorithm is supported, starting from format 8 -### repositories, available in Subversion 1.10 and higher. -### The syntax of this option is: -### compression = none | lz4 | zlib | zlib-1 ... zlib-9 -### Versions prior to Subversion 1.10 will ignore this option. -### The default value is 'lz4' if supported by the repository format and -### 'zlib' otherwise. 'zlib' is currently equivalent to 'zlib-5'. -# compression = lz4 -### -### DEPRECATED: The new 'compression' option deprecates previously used -### 'compression-level' option, which was used to configure zlib compression. -### For compatibility with previous versions of Subversion, this option can -### still be used (and it will result in zlib compression with the -### corresponding compression level). -### compression-level = 0 ... 9 (default is 5) - -[packed-revprops] -### This parameter controls the size (in kBytes) of packed revprop files. -### Revprops of consecutive revisions will be concatenated into a single -### file up to but not exceeding the threshold given here. However, each -### pack file may be much smaller and revprops of a single revision may be -### much larger than the limit set here. The threshold will be applied -### before optional compression takes place. -### Large values will reduce disk space usage at the expense of increased -### latency and CPU usage reading and changing individual revprops. -### Values smaller than 4 kByte will not improve latency any further and -### quickly render revprop packing ineffective. -### revprop-pack-size is 16 kBytes by default for non-compressed revprop -### pack files and 64 kBytes when compression has been enabled. -# revprop-pack-size = 16 -### -### To save disk space, packed revprop files may be compressed. Standard -### revprops tend to allow for very effective compression. Reading and -### even more so writing, become significantly more CPU intensive. -### Compressing packed revprops is disabled by default. -# compress-packed-revprops = false - -[io] -### Parameters in this section control the data access granularity in -### format 7 repositories and later. The defaults should translate into -### decent performance over a wide range of setups. -### -### When a specific piece of information needs to be read from disk, a -### data block is being read at once and its contents are being cached. -### If the repository is being stored on a RAID, the block size should be -### either 50% or 100% of RAID block size / granularity. Also, your file -### system blocks/clusters should be properly aligned and sized. In that -### setup, each access will hit only one disk (minimizes I/O load) but -### uses all the data provided by the disk in a single access. -### For SSD-based storage systems, slightly lower values around 16 kB -### may improve latency while still maximizing throughput. If block-read -### has not been enabled, this will be capped to 4 kBytes. -### Can be changed at any time but must be a power of 2. -### block-size is given in kBytes and with a default of 64 kBytes. -# block-size = 64 -### -### The log-to-phys index maps data item numbers to offsets within the -### rev or pack file. This index is organized in pages of a fixed maximum -### capacity. To access an item, the page table and the respective page -### must be read. -### This parameter only affects revisions with thousands of changed paths. -### If you have several extremely large revisions (~1 mio changes), think -### about increasing this setting. Reducing the value will rarely result -### in a net speedup. -### This is an expert setting. Must be a power of 2. -### l2p-page-size is 8192 entries by default. -# l2p-page-size = 8192 -### -### The phys-to-log index maps positions within the rev or pack file to -### to data items, i.e. describes what piece of information is being -### stored at any particular offset. The index describes the rev file -### in chunks (pages) and keeps a global list of all those pages. Large -### pages mean a shorter page table but a larger per-page description of -### data items in it. The latency sweetspot depends on the change size -### distribution but covers a relatively wide range. -### If the repository contains very large files, i.e. individual changes -### of tens of MB each, increasing the page size will shorten the index -### file at the expense of a slightly increased latency in sections with -### smaller changes. -### For source code repositories, this should be about 16x the block-size. -### Must be a power of 2. -### p2l-page-size is given in kBytes and with a default of 1024 kBytes. -# p2l-page-size = 1024 - -[debug] -### -### Whether to verify each new revision immediately before finalizing -### the commit. This is disabled by default except in maintainer-mode -### builds. -# verify-before-commit = false diff --git a/manage_externals/test/repos/simple-ext.svn/db/min-unpacked-rev b/manage_externals/test/repos/simple-ext.svn/db/min-unpacked-rev deleted file mode 100644 index 573541ac97..0000000000 --- a/manage_externals/test/repos/simple-ext.svn/db/min-unpacked-rev +++ /dev/null @@ -1 +0,0 @@ -0 diff --git a/manage_externals/test/repos/simple-ext.svn/db/rep-cache.db b/manage_externals/test/repos/simple-ext.svn/db/rep-cache.db deleted file mode 100644 index 3193b2eaad..0000000000 Binary files a/manage_externals/test/repos/simple-ext.svn/db/rep-cache.db and /dev/null differ diff --git a/manage_externals/test/repos/simple-ext.svn/db/revprops/0/0 b/manage_externals/test/repos/simple-ext.svn/db/revprops/0/0 deleted file mode 100644 index 92768005d3..0000000000 --- a/manage_externals/test/repos/simple-ext.svn/db/revprops/0/0 +++ /dev/null @@ -1,5 +0,0 @@ -K 8 -svn:date -V 27 -2023-11-16T20:11:46.318861Z -END diff --git a/manage_externals/test/repos/simple-ext.svn/db/revprops/0/1 b/manage_externals/test/repos/simple-ext.svn/db/revprops/0/1 deleted file mode 100644 index aa95a9de9f..0000000000 --- a/manage_externals/test/repos/simple-ext.svn/db/revprops/0/1 +++ /dev/null @@ -1,13 +0,0 @@ -K 10 -svn:author -V 5 -sacks -K 8 -svn:date -V 27 -2023-11-16T20:15:56.917904Z -K 7 -svn:log -V 30 -Setting up directory structure -END diff --git a/manage_externals/test/repos/simple-ext.svn/db/revprops/0/2 b/manage_externals/test/repos/simple-ext.svn/db/revprops/0/2 deleted file mode 100644 index 3d04d8909a..0000000000 --- a/manage_externals/test/repos/simple-ext.svn/db/revprops/0/2 +++ /dev/null @@ -1,13 +0,0 @@ -K 10 -svn:author -V 5 -sacks -K 8 -svn:date -V 27 -2023-11-16T20:27:31.407916Z -K 7 -svn:log -V 10 -Add README -END diff --git a/manage_externals/test/repos/simple-ext.svn/db/revprops/0/3 b/manage_externals/test/repos/simple-ext.svn/db/revprops/0/3 deleted file mode 100644 index de20268415..0000000000 --- a/manage_externals/test/repos/simple-ext.svn/db/revprops/0/3 +++ /dev/null @@ -1,13 +0,0 @@ -K 10 -svn:author -V 5 -sacks -K 8 -svn:date -V 27 -2023-11-16T21:14:43.366717Z -K 7 -svn:log -V 27 -Creating cesm2.0.beta07 tag -END diff --git a/manage_externals/test/repos/simple-ext.svn/db/revs/0/0 b/manage_externals/test/repos/simple-ext.svn/db/revs/0/0 deleted file mode 100644 index 9a56c280c4..0000000000 Binary files a/manage_externals/test/repos/simple-ext.svn/db/revs/0/0 and /dev/null differ diff --git a/manage_externals/test/repos/simple-ext.svn/db/revs/0/1 b/manage_externals/test/repos/simple-ext.svn/db/revs/0/1 deleted file mode 100644 index c6982eeab7..0000000000 Binary files a/manage_externals/test/repos/simple-ext.svn/db/revs/0/1 and /dev/null differ diff --git a/manage_externals/test/repos/simple-ext.svn/db/revs/0/2 b/manage_externals/test/repos/simple-ext.svn/db/revs/0/2 deleted file mode 100644 index 99a14cf4b7..0000000000 Binary files a/manage_externals/test/repos/simple-ext.svn/db/revs/0/2 and /dev/null differ diff --git a/manage_externals/test/repos/simple-ext.svn/db/revs/0/3 b/manage_externals/test/repos/simple-ext.svn/db/revs/0/3 deleted file mode 100644 index f437a6d530..0000000000 Binary files a/manage_externals/test/repos/simple-ext.svn/db/revs/0/3 and /dev/null differ diff --git a/manage_externals/test/repos/simple-ext.svn/db/txn-current b/manage_externals/test/repos/simple-ext.svn/db/txn-current deleted file mode 100644 index 00750edc07..0000000000 --- a/manage_externals/test/repos/simple-ext.svn/db/txn-current +++ /dev/null @@ -1 +0,0 @@ -3 diff --git a/manage_externals/test/repos/simple-ext.svn/db/txn-current-lock b/manage_externals/test/repos/simple-ext.svn/db/txn-current-lock deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/manage_externals/test/repos/simple-ext.svn/db/uuid b/manage_externals/test/repos/simple-ext.svn/db/uuid deleted file mode 100644 index 0b16502652..0000000000 --- a/manage_externals/test/repos/simple-ext.svn/db/uuid +++ /dev/null @@ -1,2 +0,0 @@ -1c80dd47-0c07-4207-8ee0-e60dd9d98853 -31d57ab1-759c-4129-a63d-898c774d96c9 diff --git a/manage_externals/test/repos/simple-ext.svn/db/write-lock b/manage_externals/test/repos/simple-ext.svn/db/write-lock deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/manage_externals/test/repos/simple-ext.svn/format b/manage_externals/test/repos/simple-ext.svn/format deleted file mode 100644 index 7ed6ff82de..0000000000 --- a/manage_externals/test/repos/simple-ext.svn/format +++ /dev/null @@ -1 +0,0 @@ -5 diff --git a/manage_externals/test/repos/simple-ext.svn/hooks/post-commit.tmpl b/manage_externals/test/repos/simple-ext.svn/hooks/post-commit.tmpl deleted file mode 100755 index 988f041fa5..0000000000 --- a/manage_externals/test/repos/simple-ext.svn/hooks/post-commit.tmpl +++ /dev/null @@ -1,62 +0,0 @@ -#!/bin/sh - -# POST-COMMIT HOOK -# -# The post-commit hook is invoked after a commit. Subversion runs -# this hook by invoking a program (script, executable, binary, etc.) -# named 'post-commit' (for which this file is a template) with the -# following ordered arguments: -# -# [1] REPOS-PATH (the path to this repository) -# [2] REV (the number of the revision just committed) -# [3] TXN-NAME (the name of the transaction that has become REV) -# -# Because the commit has already completed and cannot be undone, -# the exit code of the hook program is ignored. The hook program -# can use the 'svnlook' utility to help it examine the -# newly-committed tree. -# -# The default working directory for the invocation is undefined, so -# the program should set one explicitly if it cares. -# -# On a Unix system, the normal procedure is to have 'post-commit' -# invoke other programs to do the real work, though it may do the -# work itself too. -# -# Note that 'post-commit' must be executable by the user(s) who will -# invoke it (typically the user httpd runs as), and that user must -# have filesystem-level permission to access the repository. -# -# On a Windows system, you should name the hook program -# 'post-commit.bat' or 'post-commit.exe', -# but the basic idea is the same. -# -# The hook program runs in an empty environment, unless the server is -# explicitly configured otherwise. For example, a common problem is for -# the PATH environment variable to not be set to its usual value, so -# that subprograms fail to launch unless invoked via absolute path. -# If you're having unexpected problems with a hook program, the -# culprit may be unusual (or missing) environment variables. -# -# CAUTION: -# For security reasons, you MUST always properly quote arguments when -# you use them, as those arguments could contain whitespace or other -# problematic characters. Additionally, you should delimit the list -# of options with "--" before passing the arguments, so malicious -# clients cannot bootleg unexpected options to the commands your -# script aims to execute. -# For similar reasons, you should also add a trailing @ to URLs which -# are passed to SVN commands accepting URLs with peg revisions. -# -# Here is an example hook script, for a Unix /bin/sh interpreter. -# For more examples and pre-written hooks, see those in -# the Subversion repository at -# http://svn.apache.org/repos/asf/subversion/trunk/tools/hook-scripts/ and -# http://svn.apache.org/repos/asf/subversion/trunk/contrib/hook-scripts/ - - -REPOS="$1" -REV="$2" -TXN_NAME="$3" - -mailer.py commit "$REPOS" "$REV" /path/to/mailer.conf diff --git a/manage_externals/test/repos/simple-ext.svn/hooks/post-lock.tmpl b/manage_externals/test/repos/simple-ext.svn/hooks/post-lock.tmpl deleted file mode 100755 index 96f2165209..0000000000 --- a/manage_externals/test/repos/simple-ext.svn/hooks/post-lock.tmpl +++ /dev/null @@ -1,64 +0,0 @@ -#!/bin/sh - -# POST-LOCK HOOK -# -# The post-lock hook is run after a path is locked. Subversion runs -# this hook by invoking a program (script, executable, binary, etc.) -# named 'post-lock' (for which this file is a template) with the -# following ordered arguments: -# -# [1] REPOS-PATH (the path to this repository) -# [2] USER (the user who created the lock) -# -# The paths that were just locked are passed to the hook via STDIN. -# -# Because the locks have already been created and cannot be undone, -# the exit code of the hook program is ignored. The hook program -# can use the 'svnlook' utility to examine the paths in the repository -# but since the hook is invoked asynchronously the newly-created locks -# may no longer be present. -# -# The default working directory for the invocation is undefined, so -# the program should set one explicitly if it cares. -# -# On a Unix system, the normal procedure is to have 'post-lock' -# invoke other programs to do the real work, though it may do the -# work itself too. -# -# Note that 'post-lock' must be executable by the user(s) who will -# invoke it (typically the user httpd runs as), and that user must -# have filesystem-level permission to access the repository. -# -# On a Windows system, you should name the hook program -# 'post-lock.bat' or 'post-lock.exe', -# but the basic idea is the same. -# -# The hook program runs in an empty environment, unless the server is -# explicitly configured otherwise. For example, a common problem is for -# the PATH environment variable to not be set to its usual value, so -# that subprograms fail to launch unless invoked via absolute path. -# If you're having unexpected problems with a hook program, the -# culprit may be unusual (or missing) environment variables. -# -# CAUTION: -# For security reasons, you MUST always properly quote arguments when -# you use them, as those arguments could contain whitespace or other -# problematic characters. Additionally, you should delimit the list -# of options with "--" before passing the arguments, so malicious -# clients cannot bootleg unexpected options to the commands your -# script aims to execute. -# For similar reasons, you should also add a trailing @ to URLs which -# are passed to SVN commands accepting URLs with peg revisions. -# -# Here is an example hook script, for a Unix /bin/sh interpreter. -# For more examples and pre-written hooks, see those in -# the Subversion repository at -# http://svn.apache.org/repos/asf/subversion/trunk/tools/hook-scripts/ and -# http://svn.apache.org/repos/asf/subversion/trunk/contrib/hook-scripts/ - - -REPOS="$1" -USER="$2" - -# Send email to interested parties, let them know a lock was created: -mailer.py lock "$REPOS" "$USER" /path/to/mailer.conf diff --git a/manage_externals/test/repos/simple-ext.svn/hooks/post-revprop-change.tmpl b/manage_externals/test/repos/simple-ext.svn/hooks/post-revprop-change.tmpl deleted file mode 100755 index de1b914648..0000000000 --- a/manage_externals/test/repos/simple-ext.svn/hooks/post-revprop-change.tmpl +++ /dev/null @@ -1,69 +0,0 @@ -#!/bin/sh - -# POST-REVPROP-CHANGE HOOK -# -# The post-revprop-change hook is invoked after a revision property -# has been added, modified or deleted. Subversion runs this hook by -# invoking a program (script, executable, binary, etc.) named -# 'post-revprop-change' (for which this file is a template), with the -# following ordered arguments: -# -# [1] REPOS-PATH (the path to this repository) -# [2] REV (the revision that was tweaked) -# [3] USER (the username of the person tweaking the property) -# [4] PROPNAME (the property that was changed) -# [5] ACTION (the property was 'A'dded, 'M'odified, or 'D'eleted) -# -# [STDIN] PROPVAL ** the old property value is passed via STDIN. -# -# Because the propchange has already completed and cannot be undone, -# the exit code of the hook program is ignored. The hook program -# can use the 'svnlook' utility to help it examine the -# new property value. -# -# The default working directory for the invocation is undefined, so -# the program should set one explicitly if it cares. -# -# On a Unix system, the normal procedure is to have 'post-revprop-change' -# invoke other programs to do the real work, though it may do the -# work itself too. -# -# Note that 'post-revprop-change' must be executable by the user(s) who will -# invoke it (typically the user httpd runs as), and that user must -# have filesystem-level permission to access the repository. -# -# On a Windows system, you should name the hook program -# 'post-revprop-change.bat' or 'post-revprop-change.exe', -# but the basic idea is the same. -# -# The hook program runs in an empty environment, unless the server is -# explicitly configured otherwise. For example, a common problem is for -# the PATH environment variable to not be set to its usual value, so -# that subprograms fail to launch unless invoked via absolute path. -# If you're having unexpected problems with a hook program, the -# culprit may be unusual (or missing) environment variables. -# -# CAUTION: -# For security reasons, you MUST always properly quote arguments when -# you use them, as those arguments could contain whitespace or other -# problematic characters. Additionally, you should delimit the list -# of options with "--" before passing the arguments, so malicious -# clients cannot bootleg unexpected options to the commands your -# script aims to execute. -# For similar reasons, you should also add a trailing @ to URLs which -# are passed to SVN commands accepting URLs with peg revisions. -# -# Here is an example hook script, for a Unix /bin/sh interpreter. -# For more examples and pre-written hooks, see those in -# the Subversion repository at -# http://svn.apache.org/repos/asf/subversion/trunk/tools/hook-scripts/ and -# http://svn.apache.org/repos/asf/subversion/trunk/contrib/hook-scripts/ - - -REPOS="$1" -REV="$2" -USER="$3" -PROPNAME="$4" -ACTION="$5" - -mailer.py propchange2 "$REPOS" "$REV" "$USER" "$PROPNAME" "$ACTION" /path/to/mailer.conf diff --git a/manage_externals/test/repos/simple-ext.svn/hooks/post-unlock.tmpl b/manage_externals/test/repos/simple-ext.svn/hooks/post-unlock.tmpl deleted file mode 100755 index e33f793c25..0000000000 --- a/manage_externals/test/repos/simple-ext.svn/hooks/post-unlock.tmpl +++ /dev/null @@ -1,61 +0,0 @@ -#!/bin/sh - -# POST-UNLOCK HOOK -# -# The post-unlock hook runs after a path is unlocked. Subversion runs -# this hook by invoking a program (script, executable, binary, etc.) -# named 'post-unlock' (for which this file is a template) with the -# following ordered arguments: -# -# [1] REPOS-PATH (the path to this repository) -# [2] USER (the user who destroyed the lock) -# -# The paths that were just unlocked are passed to the hook via STDIN. -# -# Because the lock has already been destroyed and cannot be undone, -# the exit code of the hook program is ignored. -# -# The default working directory for the invocation is undefined, so -# the program should set one explicitly if it cares. -# -# On a Unix system, the normal procedure is to have 'post-unlock' -# invoke other programs to do the real work, though it may do the -# work itself too. -# -# Note that 'post-unlock' must be executable by the user(s) who will -# invoke it (typically the user httpd runs as), and that user must -# have filesystem-level permission to access the repository. -# -# On a Windows system, you should name the hook program -# 'post-unlock.bat' or 'post-unlock.exe', -# but the basic idea is the same. -# -# The hook program runs in an empty environment, unless the server is -# explicitly configured otherwise. For example, a common problem is for -# the PATH environment variable to not be set to its usual value, so -# that subprograms fail to launch unless invoked via absolute path. -# If you're having unexpected problems with a hook program, the -# culprit may be unusual (or missing) environment variables. -# -# CAUTION: -# For security reasons, you MUST always properly quote arguments when -# you use them, as those arguments could contain whitespace or other -# problematic characters. Additionally, you should delimit the list -# of options with "--" before passing the arguments, so malicious -# clients cannot bootleg unexpected options to the commands your -# script aims to execute. -# For similar reasons, you should also add a trailing @ to URLs which -# are passed to SVN commands accepting URLs with peg revisions. -# -# Here is an example hook script, for a Unix /bin/sh interpreter. -# For more examples and pre-written hooks, see those in -# the Subversion repository at -# http://svn.apache.org/repos/asf/subversion/trunk/tools/hook-scripts/ and -# http://svn.apache.org/repos/asf/subversion/trunk/contrib/hook-scripts/ - - -REPOS="$1" -USER="$2" - -# Send email to interested parties, let them know a lock was removed: -mailer.py unlock "$REPOS" "$USER" /path/to/mailer.conf diff --git a/manage_externals/test/repos/simple-ext.svn/hooks/pre-commit.tmpl b/manage_externals/test/repos/simple-ext.svn/hooks/pre-commit.tmpl deleted file mode 100755 index 626e72300c..0000000000 --- a/manage_externals/test/repos/simple-ext.svn/hooks/pre-commit.tmpl +++ /dev/null @@ -1,91 +0,0 @@ -#!/bin/sh - -# PRE-COMMIT HOOK -# -# The pre-commit hook is invoked before a Subversion txn is -# committed. Subversion runs this hook by invoking a program -# (script, executable, binary, etc.) named 'pre-commit' (for which -# this file is a template), with the following ordered arguments: -# -# [1] REPOS-PATH (the path to this repository) -# [2] TXN-NAME (the name of the txn about to be committed) -# -# [STDIN] LOCK-TOKENS ** the lock tokens are passed via STDIN. -# -# If STDIN contains the line "LOCK-TOKENS:\n" (the "\n" denotes a -# single newline), the lines following it are the lock tokens for -# this commit. The end of the list is marked by a line containing -# only a newline character. -# -# Each lock token line consists of a URI-escaped path, followed -# by the separator character '|', followed by the lock token string, -# followed by a newline. -# -# If the hook program exits with success, the txn is committed; but -# if it exits with failure (non-zero), the txn is aborted, no commit -# takes place, and STDERR is returned to the client. The hook -# program can use the 'svnlook' utility to help it examine the txn. -# -# *** NOTE: THE HOOK PROGRAM MUST NOT MODIFY THE TXN, EXCEPT *** -# *** FOR REVISION PROPERTIES (like svn:log or svn:author). *** -# -# This is why we recommend using the read-only 'svnlook' utility. -# In the future, Subversion may enforce the rule that pre-commit -# hooks should not modify the versioned data in txns, or else come -# up with a mechanism to make it safe to do so (by informing the -# committing client of the changes). However, right now neither -# mechanism is implemented, so hook writers just have to be careful. -# -# The default working directory for the invocation is undefined, so -# the program should set one explicitly if it cares. -# -# On a Unix system, the normal procedure is to have 'pre-commit' -# invoke other programs to do the real work, though it may do the -# work itself too. -# -# Note that 'pre-commit' must be executable by the user(s) who will -# invoke it (typically the user httpd runs as), and that user must -# have filesystem-level permission to access the repository. -# -# On a Windows system, you should name the hook program -# 'pre-commit.bat' or 'pre-commit.exe', -# but the basic idea is the same. -# -# The hook program runs in an empty environment, unless the server is -# explicitly configured otherwise. For example, a common problem is for -# the PATH environment variable to not be set to its usual value, so -# that subprograms fail to launch unless invoked via absolute path. -# If you're having unexpected problems with a hook program, the -# culprit may be unusual (or missing) environment variables. -# -# CAUTION: -# For security reasons, you MUST always properly quote arguments when -# you use them, as those arguments could contain whitespace or other -# problematic characters. Additionally, you should delimit the list -# of options with "--" before passing the arguments, so malicious -# clients cannot bootleg unexpected options to the commands your -# script aims to execute. -# For similar reasons, you should also add a trailing @ to URLs which -# are passed to SVN commands accepting URLs with peg revisions. -# -# Here is an example hook script, for a Unix /bin/sh interpreter. -# For more examples and pre-written hooks, see those in -# the Subversion repository at -# http://svn.apache.org/repos/asf/subversion/trunk/tools/hook-scripts/ and -# http://svn.apache.org/repos/asf/subversion/trunk/contrib/hook-scripts/ - - -REPOS="$1" -TXN="$2" - -# Make sure that the log message contains some text. -SVNLOOK=/opt/homebrew/Cellar/subversion/1.14.2_1/bin/svnlook -$SVNLOOK log -t "$TXN" "$REPOS" | \ - grep "[a-zA-Z0-9]" > /dev/null || exit 1 - -# Check that the author of this commit has the rights to perform -# the commit on the files and directories being modified. -commit-access-control.pl "$REPOS" "$TXN" commit-access-control.cfg || exit 1 - -# All checks passed, so allow the commit. -exit 0 diff --git a/manage_externals/test/repos/simple-ext.svn/hooks/pre-lock.tmpl b/manage_externals/test/repos/simple-ext.svn/hooks/pre-lock.tmpl deleted file mode 100755 index 148582a689..0000000000 --- a/manage_externals/test/repos/simple-ext.svn/hooks/pre-lock.tmpl +++ /dev/null @@ -1,95 +0,0 @@ -#!/bin/sh - -# PRE-LOCK HOOK -# -# The pre-lock hook is invoked before an exclusive lock is -# created. Subversion runs this hook by invoking a program -# (script, executable, binary, etc.) named 'pre-lock' (for which -# this file is a template), with the following ordered arguments: -# -# [1] REPOS-PATH (the path to this repository) -# [2] PATH (the path in the repository about to be locked) -# [3] USER (the user creating the lock) -# [4] COMMENT (the comment of the lock) -# [5] STEAL-LOCK (1 if the user is trying to steal the lock, else 0) -# -# If the hook program outputs anything on stdout, the output string will -# be used as the lock token for this lock operation. If you choose to use -# this feature, you must guarantee the tokens generated are unique across -# the repository each time. -# -# If the hook program exits with success, the lock is created; but -# if it exits with failure (non-zero), the lock action is aborted -# and STDERR is returned to the client. -# -# The default working directory for the invocation is undefined, so -# the program should set one explicitly if it cares. -# -# On a Unix system, the normal procedure is to have 'pre-lock' -# invoke other programs to do the real work, though it may do the -# work itself too. -# -# Note that 'pre-lock' must be executable by the user(s) who will -# invoke it (typically the user httpd runs as), and that user must -# have filesystem-level permission to access the repository. -# -# On a Windows system, you should name the hook program -# 'pre-lock.bat' or 'pre-lock.exe', -# but the basic idea is the same. -# -# The hook program runs in an empty environment, unless the server is -# explicitly configured otherwise. For example, a common problem is for -# the PATH environment variable to not be set to its usual value, so -# that subprograms fail to launch unless invoked via absolute path. -# If you're having unexpected problems with a hook program, the -# culprit may be unusual (or missing) environment variables. -# -# CAUTION: -# For security reasons, you MUST always properly quote arguments when -# you use them, as those arguments could contain whitespace or other -# problematic characters. Additionally, you should delimit the list -# of options with "--" before passing the arguments, so malicious -# clients cannot bootleg unexpected options to the commands your -# script aims to execute. -# For similar reasons, you should also add a trailing @ to URLs which -# are passed to SVN commands accepting URLs with peg revisions. -# -# Here is an example hook script, for a Unix /bin/sh interpreter. -# For more examples and pre-written hooks, see those in -# the Subversion repository at -# http://svn.apache.org/repos/asf/subversion/trunk/tools/hook-scripts/ and -# http://svn.apache.org/repos/asf/subversion/trunk/contrib/hook-scripts/ - - -REPOS="$1" -PATH="$2" -USER="$3" -COMMENT="$4" -STEAL="$5" - -# If a lock exists and is owned by a different person, don't allow it -# to be stolen (e.g., with 'svn lock --force ...'). - -# (Maybe this script could send email to the lock owner?) -SVNLOOK=/opt/homebrew/Cellar/subversion/1.14.2_1/bin/svnlook -GREP=/bin/grep -SED=/bin/sed - -LOCK_OWNER=`$SVNLOOK lock "$REPOS" "$PATH" | \ - $GREP '^Owner: ' | $SED 's/Owner: //'` - -# If we get no result from svnlook, there's no lock, allow the lock to -# happen: -if [ "$LOCK_OWNER" = "" ]; then - exit 0 -fi - -# If the person locking matches the lock's owner, allow the lock to -# happen: -if [ "$LOCK_OWNER" = "$USER" ]; then - exit 0 -fi - -# Otherwise, we've got an owner mismatch, so return failure: -echo "Error: $PATH already locked by ${LOCK_OWNER}." 1>&2 -exit 1 diff --git a/manage_externals/test/repos/simple-ext.svn/hooks/pre-revprop-change.tmpl b/manage_externals/test/repos/simple-ext.svn/hooks/pre-revprop-change.tmpl deleted file mode 100755 index 8b065d7c79..0000000000 --- a/manage_externals/test/repos/simple-ext.svn/hooks/pre-revprop-change.tmpl +++ /dev/null @@ -1,79 +0,0 @@ -#!/bin/sh - -# PRE-REVPROP-CHANGE HOOK -# -# The pre-revprop-change hook is invoked before a revision property -# is added, modified or deleted. Subversion runs this hook by invoking -# a program (script, executable, binary, etc.) named 'pre-revprop-change' -# (for which this file is a template), with the following ordered -# arguments: -# -# [1] REPOS-PATH (the path to this repository) -# [2] REV (the revision being tweaked) -# [3] USER (the username of the person tweaking the property) -# [4] PROPNAME (the property being set on the revision) -# [5] ACTION (the property is being 'A'dded, 'M'odified, or 'D'eleted) -# -# [STDIN] PROPVAL ** the new property value is passed via STDIN. -# -# If the hook program exits with success, the propchange happens; but -# if it exits with failure (non-zero), the propchange doesn't happen. -# The hook program can use the 'svnlook' utility to examine the -# existing value of the revision property. -# -# WARNING: unlike other hooks, this hook MUST exist for revision -# properties to be changed. If the hook does not exist, Subversion -# will behave as if the hook were present, but failed. The reason -# for this is that revision properties are UNVERSIONED, meaning that -# a successful propchange is destructive; the old value is gone -# forever. We recommend the hook back up the old value somewhere. -# -# The default working directory for the invocation is undefined, so -# the program should set one explicitly if it cares. -# -# On a Unix system, the normal procedure is to have 'pre-revprop-change' -# invoke other programs to do the real work, though it may do the -# work itself too. -# -# Note that 'pre-revprop-change' must be executable by the user(s) who will -# invoke it (typically the user httpd runs as), and that user must -# have filesystem-level permission to access the repository. -# -# On a Windows system, you should name the hook program -# 'pre-revprop-change.bat' or 'pre-revprop-change.exe', -# but the basic idea is the same. -# -# The hook program runs in an empty environment, unless the server is -# explicitly configured otherwise. For example, a common problem is for -# the PATH environment variable to not be set to its usual value, so -# that subprograms fail to launch unless invoked via absolute path. -# If you're having unexpected problems with a hook program, the -# culprit may be unusual (or missing) environment variables. -# -# CAUTION: -# For security reasons, you MUST always properly quote arguments when -# you use them, as those arguments could contain whitespace or other -# problematic characters. Additionally, you should delimit the list -# of options with "--" before passing the arguments, so malicious -# clients cannot bootleg unexpected options to the commands your -# script aims to execute. -# For similar reasons, you should also add a trailing @ to URLs which -# are passed to SVN commands accepting URLs with peg revisions. -# -# Here is an example hook script, for a Unix /bin/sh interpreter. -# For more examples and pre-written hooks, see those in -# the Subversion repository at -# http://svn.apache.org/repos/asf/subversion/trunk/tools/hook-scripts/ and -# http://svn.apache.org/repos/asf/subversion/trunk/contrib/hook-scripts/ - - -REPOS="$1" -REV="$2" -USER="$3" -PROPNAME="$4" -ACTION="$5" - -if [ "$ACTION" = "M" -a "$PROPNAME" = "svn:log" ]; then exit 0; fi - -echo "Changing revision properties other than svn:log is prohibited" >&2 -exit 1 diff --git a/manage_externals/test/repos/simple-ext.svn/hooks/pre-unlock.tmpl b/manage_externals/test/repos/simple-ext.svn/hooks/pre-unlock.tmpl deleted file mode 100755 index 9ba99d071b..0000000000 --- a/manage_externals/test/repos/simple-ext.svn/hooks/pre-unlock.tmpl +++ /dev/null @@ -1,87 +0,0 @@ -#!/bin/sh - -# PRE-UNLOCK HOOK -# -# The pre-unlock hook is invoked before an exclusive lock is -# destroyed. Subversion runs this hook by invoking a program -# (script, executable, binary, etc.) named 'pre-unlock' (for which -# this file is a template), with the following ordered arguments: -# -# [1] REPOS-PATH (the path to this repository) -# [2] PATH (the path in the repository about to be unlocked) -# [3] USER (the user destroying the lock) -# [4] TOKEN (the lock token to be destroyed) -# [5] BREAK-UNLOCK (1 if the user is breaking the lock, else 0) -# -# If the hook program exits with success, the lock is destroyed; but -# if it exits with failure (non-zero), the unlock action is aborted -# and STDERR is returned to the client. -# -# The default working directory for the invocation is undefined, so -# the program should set one explicitly if it cares. -# -# On a Unix system, the normal procedure is to have 'pre-unlock' -# invoke other programs to do the real work, though it may do the -# work itself too. -# -# Note that 'pre-unlock' must be executable by the user(s) who will -# invoke it (typically the user httpd runs as), and that user must -# have filesystem-level permission to access the repository. -# -# On a Windows system, you should name the hook program -# 'pre-unlock.bat' or 'pre-unlock.exe', -# but the basic idea is the same. -# -# The hook program runs in an empty environment, unless the server is -# explicitly configured otherwise. For example, a common problem is for -# the PATH environment variable to not be set to its usual value, so -# that subprograms fail to launch unless invoked via absolute path. -# If you're having unexpected problems with a hook program, the -# culprit may be unusual (or missing) environment variables. -# -# CAUTION: -# For security reasons, you MUST always properly quote arguments when -# you use them, as those arguments could contain whitespace or other -# problematic characters. Additionally, you should delimit the list -# of options with "--" before passing the arguments, so malicious -# clients cannot bootleg unexpected options to the commands your -# script aims to execute. -# For similar reasons, you should also add a trailing @ to URLs which -# are passed to SVN commands accepting URLs with peg revisions. -# -# Here is an example hook script, for a Unix /bin/sh interpreter. -# For more examples and pre-written hooks, see those in -# the Subversion repository at -# http://svn.apache.org/repos/asf/subversion/trunk/tools/hook-scripts/ and -# http://svn.apache.org/repos/asf/subversion/trunk/contrib/hook-scripts/ - - -REPOS="$1" -PATH="$2" -USER="$3" -TOKEN="$4" -BREAK="$5" - -# If a lock is owned by a different person, don't allow it be broken. -# (Maybe this script could send email to the lock owner?) - -SVNLOOK=/opt/homebrew/Cellar/subversion/1.14.2_1/bin/svnlook -GREP=/bin/grep -SED=/bin/sed - -LOCK_OWNER=`$SVNLOOK lock "$REPOS" "$PATH" | \ - $GREP '^Owner: ' | $SED 's/Owner: //'` - -# If we get no result from svnlook, there's no lock, return success: -if [ "$LOCK_OWNER" = "" ]; then - exit 0 -fi - -# If the person unlocking matches the lock's owner, return success: -if [ "$LOCK_OWNER" = "$USER" ]; then - exit 0 -fi - -# Otherwise, we've got an owner mismatch, so return failure: -echo "Error: $PATH locked by ${LOCK_OWNER}." 1>&2 -exit 1 diff --git a/manage_externals/test/repos/simple-ext.svn/hooks/start-commit.tmpl b/manage_externals/test/repos/simple-ext.svn/hooks/start-commit.tmpl deleted file mode 100755 index 1395e8315a..0000000000 --- a/manage_externals/test/repos/simple-ext.svn/hooks/start-commit.tmpl +++ /dev/null @@ -1,81 +0,0 @@ -#!/bin/sh - -# START-COMMIT HOOK -# -# The start-commit hook is invoked immediately after a Subversion txn is -# created and populated with initial revprops in the process of doing a -# commit. Subversion runs this hook by invoking a program (script, -# executable, binary, etc.) named 'start-commit' (for which this file -# is a template) with the following ordered arguments: -# -# [1] REPOS-PATH (the path to this repository) -# [2] USER (the authenticated user attempting to commit) -# [3] CAPABILITIES (a colon-separated list of capabilities reported -# by the client; see note below) -# [4] TXN-NAME (the name of the commit txn just created) -# -# Note: The CAPABILITIES parameter is new in Subversion 1.5, and 1.5 -# clients will typically report at least the "mergeinfo" capability. -# If there are other capabilities, then the list is colon-separated, -# e.g.: "mergeinfo:some-other-capability" (the order is undefined). -# -# The list is self-reported by the client. Therefore, you should not -# make security assumptions based on the capabilities list, nor should -# you assume that clients reliably report every capability they have. -# -# Note: The TXN-NAME parameter is new in Subversion 1.8. Prior to version -# 1.8, the start-commit hook was invoked before the commit txn was even -# created, so the ability to inspect the commit txn and its metadata from -# within the start-commit hook was not possible. -# -# If the hook program exits with success, the commit continues; but -# if it exits with failure (non-zero), the commit is stopped before -# a Subversion txn is created, and STDERR is returned to the client. -# -# The default working directory for the invocation is undefined, so -# the program should set one explicitly if it cares. -# -# On a Unix system, the normal procedure is to have 'start-commit' -# invoke other programs to do the real work, though it may do the -# work itself too. -# -# Note that 'start-commit' must be executable by the user(s) who will -# invoke it (typically the user httpd runs as), and that user must -# have filesystem-level permission to access the repository. -# -# On a Windows system, you should name the hook program -# 'start-commit.bat' or 'start-commit.exe', -# but the basic idea is the same. -# -# The hook program runs in an empty environment, unless the server is -# explicitly configured otherwise. For example, a common problem is for -# the PATH environment variable to not be set to its usual value, so -# that subprograms fail to launch unless invoked via absolute path. -# If you're having unexpected problems with a hook program, the -# culprit may be unusual (or missing) environment variables. -# -# CAUTION: -# For security reasons, you MUST always properly quote arguments when -# you use them, as those arguments could contain whitespace or other -# problematic characters. Additionally, you should delimit the list -# of options with "--" before passing the arguments, so malicious -# clients cannot bootleg unexpected options to the commands your -# script aims to execute. -# For similar reasons, you should also add a trailing @ to URLs which -# are passed to SVN commands accepting URLs with peg revisions. -# -# Here is an example hook script, for a Unix /bin/sh interpreter. -# For more examples and pre-written hooks, see those in -# the Subversion repository at -# http://svn.apache.org/repos/asf/subversion/trunk/tools/hook-scripts/ and -# http://svn.apache.org/repos/asf/subversion/trunk/contrib/hook-scripts/ - - -REPOS="$1" -USER="$2" - -commit-allower.pl --repository "$REPOS" --user "$USER" || exit 1 -special-auth-check.py --user "$USER" --auth-level 3 || exit 1 - -# All checks passed, so allow the commit. -exit 0 diff --git a/manage_externals/test/repos/simple-ext.svn/locks/db-logs.lock b/manage_externals/test/repos/simple-ext.svn/locks/db-logs.lock deleted file mode 100644 index 20dd6369be..0000000000 --- a/manage_externals/test/repos/simple-ext.svn/locks/db-logs.lock +++ /dev/null @@ -1,3 +0,0 @@ -This file is not used by Subversion 1.3.x or later. -However, its existence is required for compatibility with -Subversion 1.2.x or earlier. diff --git a/manage_externals/test/repos/simple-ext.svn/locks/db.lock b/manage_externals/test/repos/simple-ext.svn/locks/db.lock deleted file mode 100644 index 20dd6369be..0000000000 --- a/manage_externals/test/repos/simple-ext.svn/locks/db.lock +++ /dev/null @@ -1,3 +0,0 @@ -This file is not used by Subversion 1.3.x or later. -However, its existence is required for compatibility with -Subversion 1.2.x or earlier. 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 100755 index 664160dc99..0000000000 --- a/manage_externals/test/test_sys_checkout.py +++ /dev/null @@ -1,1871 +0,0 @@ -#!/usr/bin/env python3 - -"""Unit test driver for checkout_externals - -Terminology: - * 'container': a repo that has externals - * 'simple': a repo that has no externals, but is referenced as an external by another repo. - * 'mixed': a repo that both has externals and is referenced as an external by another repo. - - * 'clean': the local repo matches the version in the externals and has no local modifications. - * 'empty': the external isn't checked out at all. - -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 -# -# --------------------------------------------------------------------- - - -# Module-wide root directory for all the per-test subdirs we'll create on -# the fly (which are placed under wherever $CWD is when the test runs). -# Set by setupModule(). -module_tmp_root_dir = None -TMP_REPO_DIR_NAME = 'tmp' # subdir under $CWD - -# subdir under test/ that holds all of our checked-in repositories (which we -# will clone for these tests). -BARE_REPO_ROOT_NAME = 'repos' - -# Environment var referenced by checked-in externals file in mixed-cont-ext.git, -# which should be pointed to the fully-resolved BARE_REPO_ROOT_NAME directory. -# We explicitly clear this after every test, via tearDown(). -MIXED_CONT_EXT_ROOT_ENV_VAR = 'MANIC_TEST_BARE_REPO_ROOT' - -# Subdirs under bare repo root, each holding a repository. For more info -# on the contents of these repositories, see test/repos/README.md. In these -# tests the 'parent' repos are cloned as a starting point, whereas the 'child' -# repos are checked out when the tests run checkout_externals. -CONTAINER_REPO = 'container.git' # Parent repo -SIMPLE_REPO = 'simple-ext.git' # Child repo -SIMPLE_FORK_REPO = 'simple-ext-fork.git' # Child repo -MIXED_REPO = 'mixed-cont-ext.git' # Both parent and child -SVN_TEST_REPO = 'simple-ext.svn' # Subversion repository - -# Standard (arbitrary) external names for test configs -TAG_SECTION = 'simp_tag' -BRANCH_SECTION = 'simp_branch' -HASH_SECTION = 'simp_hash' - -# All the configs we construct check out their externals into these local paths. -EXTERNALS_PATH = 'externals' -SUB_EXTERNALS_PATH = 'src' # For mixed test repos, - -# For testing behavior with '.' instead of an explicit paths. -SIMPLE_LOCAL_ONLY_NAME = '.' - -# Externals files. -CFG_NAME = 'externals.cfg' # We construct this on a per-test basis. -CFG_SUB_NAME = 'sub-externals.cfg' # Already exists in mixed-cont-ext repo. - -# Arbitrary text file in all the test repos. -README_NAME = 'readme.txt' - -# Branch that exists in both the simple and simple-fork repos. -REMOTE_BRANCH_FEATURE2 = 'feature2' - -# 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) - - # Make available to all tests in this file. - global module_tmp_root_dir - assert module_tmp_root_dir == None, module_tmp_root_dir - module_tmp_root_dir = repo_root - - -class RepoUtils(object): - """Convenience methods for interacting with git repos.""" - @staticmethod - def create_branch(repo_base_dir, external_name, branch, with_commit=False): - """Create branch and optionally (with_commit) add a single commit. - """ - # pylint: disable=R0913 - cwd = os.getcwd() - repo_root = os.path.join(repo_base_dir, EXTERNALS_PATH, external_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(repo_base_dir, external_name): - """Make a commit to the given external. - - 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(repo_base_dir, EXTERNALS_PATH, external_name) - os.chdir(repo_root) - - 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) - - @staticmethod - def clone_test_repo(bare_root, test_id, parent_repo_name, dest_dir_in): - """Clone repo at / into dest_dir_in or local per-test-subdir. - - Returns output dir. - """ - parent_repo_dir = os.path.join(bare_root, parent_repo_name) - if dest_dir_in is None: - # create unique subdir for this test - test_dir_name = test_id - print("Test repository name: {0}".format(test_dir_name)) - dest_dir = os.path.join(module_tmp_root_dir, 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) - -class GenerateExternalsDescriptionCfgV1(object): - """Building blocks to create ExternalsDescriptionCfgV1 files. - - Basic usage: create_config() multiple create_*(), then write_config(). - Optionally after that: write_with_*(). - """ - - def __init__(self, bare_root): - self._schema_version = '1.1.0' - self._config = None - - # directory where we have test repositories (which we will clone for - # tests) - self._bare_root = bare_root - - def write_config(self, dest_dir, filename=CFG_NAME): - """Write self._config 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 url_for_repo_path(self, repo_path, repo_path_abs=None): - if repo_path_abs is not None: - return repo_path_abs - else: - return os.path.join(self._bare_root, repo_path) - - def create_section(self, repo_path, name, tag='', branch='', - ref_hash='', required=True, path=EXTERNALS_PATH, - sub_externals='', repo_path_abs=None, from_submodule=False, - sparse='', nested=False): - # pylint: disable=too-many-branches - """Create a config ExternalsDescription section with the given name. - - Autofills some items and handles some optional items. - - repo_path_abs overrides repo_path (which is relative to the bare repo) - path is a subdir under repo_path to check out to. - """ - # 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_abs 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 = '' - - repo_url = self.url_for_repo_path(repo_path, repo_path_abs) - - 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 sub_externals: - self._config.set(name, ExternalsDescription.EXTERNALS, - sub_externals) - - if sparse: - self._config.set(name, ExternalsDescription.SPARSE, sparse) - - if from_submodule: - self._config.set(name, ExternalsDescription.SUBMODULE, "True") - - def create_section_reference_to_subexternal(self, name): - """Just a reference to another externals file. - - """ - # 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(True)) - - self._config.set(name, ExternalsDescription.EXTERNALS, CFG_SUB_NAME) - - def create_svn_external(self, name, url, 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_PATH, name)) - - self._config.set(name, ExternalsDescription.PROTOCOL, - ExternalsDescription.PROTOCOL_SVN) - - self._config.set(name, ExternalsDescription.REPO_URL, url) - - 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) - - def write_with_git_branch(self, dest_dir, name, branch, new_remote_repo_path=None): - """Update fields in our config and write it to disk. - - name is the key of the ExternalsDescription in self._config to update. - """ - # pylint: disable=R0913 - self._config.set(name, ExternalsDescription.BRANCH, branch) - - if new_remote_repo_path: - if new_remote_repo_path == SIMPLE_LOCAL_ONLY_NAME: - repo_url = SIMPLE_LOCAL_ONLY_NAME - else: - repo_url = os.path.join(self._bare_root, new_remote_repo_path) - 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) - - def write_with_svn_branch(self, dest_dir, name, branch): - """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) - - def write_with_tag_and_remote_repo(self, dest_dir, name, tag, new_remote_repo_path, - remove_branch=True): - """Update a repository tag and 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 new_remote_repo_path: - repo_url = os.path.join(self._bare_root, new_remote_repo_path) - 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) - - def write_without_branch_tag(self, dest_dir, 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) - - def write_without_repo_url(self, dest_dir, 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) - - def write_with_protocol(self, dest_dir, name, protocol, repo_path=None): - """Update a repository protocol, and potentially the remote - """ - # pylint: disable=R0913 - self._config.set(name, ExternalsDescription.PROTOCOL, protocol) - - if repo_path: - repo_url = os.path.join(self._bare_root, repo_path) - self._config.set(name, ExternalsDescription.REPO_URL, repo_url) - - self.write_config(dest_dir) - - -def _execute_checkout_in_dir(dirname, args, debug_env=''): - """Execute the checkout command in the appropriate repo dir with the - specified additional args. - - args should be a list of strings. - debug_env shuld be a string of the form 'FOO=bar' or the empty string. - - 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! Note this means that environment variables are passed - to checkout_externals via os.environ; debug_env is just used to aid - manual reproducibility of a given call. - - Returns (overall_status, tree_status) - where overall_status is 0 for success, nonzero otherwise. - and tree_status is set if --status was passed in, None otherwise. - - Note this command executes the checkout command, it doesn't - necessarily do any checking out (e.g. if --status is passed in). - """ - cwd = os.getcwd() - - # Construct a command line for reproducibility; this command is not - # actually executed in the test. - os.chdir(dirname) - cmdline = ['--externals', CFG_NAME, ] - cmdline += args - manual_cmd = ('Running equivalent of:\n' - 'pushd {dirname}; ' - '{debug_env} /path/to/checkout_externals {args}'.format( - dirname=dirname, debug_env=debug_env, - 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 - -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 - - # Command-line args for checkout_externals, used in execute_checkout_in_dir() - 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 (which we will clone for - # tests) - self._bare_root = os.path.abspath( - os.path.join(root_dir, 'test', BARE_REPO_ROOT_NAME)) - - # set the input file generator - self._generator = GenerateExternalsDescriptionCfgV1(self._bare_root) - # set the input file generator for secondary externals - self._sub_generator = GenerateExternalsDescriptionCfgV1(self._bare_root) - - def tearDown(self): - """Tear down for individual tests - """ - # return to our common starting point - os.chdir(self._return_dir) - - # (in case this was set) Don't pollute environment of other tests. - os.environ.pop(MIXED_CONT_EXT_ROOT_ENV_VAR, - None) # Don't care if key wasn't set. - - def clone_test_repo(self, parent_repo_name, dest_dir_in=None): - """Clones repo under self._bare_root""" - return RepoUtils.clone_test_repo(self._bare_root, self._test_id, - parent_repo_name, dest_dir_in) - - def execute_checkout_in_dir(self, dirname, args, debug_env=''): - overall_status, tree_status = _execute_checkout_in_dir(dirname, args, - debug_env=debug_env) - self.assertEqual(overall_status, 0) - return tree_status - - def execute_checkout_with_status(self, dirname, args, debug_env=''): - """Calls checkout a second time to get status if needed.""" - tree_status = self.execute_checkout_in_dir( - dirname, args, debug_env=debug_env) - if tree_status is None: - tree_status = self.execute_checkout_in_dir(dirname, - self.status_args, - debug_env=debug_env) - self.assertNotEqual(tree_status, None) - return tree_status - - def _check_sync_clean(self, ext_status, expected_sync_state, - expected_clean_state): - self.assertEqual(ext_status.sync_state, expected_sync_state) - self.assertEqual(ext_status.clean_state, expected_clean_state) - - @staticmethod - def _external_path(section_name, base_path=EXTERNALS_PATH): - return './{0}/{1}'.format(base_path, section_name) - - 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_required_bytag(self): - """Check out a required external pointing to a git tag.""" - cloned_repo_dir = self.clone_test_repo(CONTAINER_REPO) - self._generator.create_config() - self._generator.create_section(SIMPLE_REPO, TAG_SECTION, - tag='tag1') - self._generator.write_config(cloned_repo_dir) - - # externals start out 'empty' aka not checked out. - tree = self.execute_checkout_in_dir(cloned_repo_dir, - self.status_args) - local_path_rel = self._external_path(TAG_SECTION) - self._check_sync_clean(tree[local_path_rel], - ExternalStatus.EMPTY, - ExternalStatus.DEFAULT) - local_path_abs = os.path.join(cloned_repo_dir, local_path_rel) - self.assertFalse(os.path.exists(local_path_abs)) - - # after checkout, the external is 'clean' aka at the correct version. - tree = self.execute_checkout_with_status(cloned_repo_dir, - self.checkout_args) - self._check_sync_clean(tree[local_path_rel], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - - # Actually checked out the desired repo. - self.assertEqual('origin', GitRepository._remote_name_for_url( - # Which url to look up - self._generator.url_for_repo_path(SIMPLE_REPO), - # Which directory has the local checked-out repo. - dirname=local_path_abs)) - - # Actually checked out the desired tag. - (tag_found, tag_name) = GitRepository._git_current_tag(local_path_abs) - self.assertEqual(tag_name, 'tag1') - - # Check existence of some simp_tag files - tag_path = os.path.join('externals', TAG_SECTION) - self._check_file_exists(cloned_repo_dir, - os.path.join(tag_path, README_NAME)) - # Subrepo should not exist (not referenced by configs). - self._check_file_absent(cloned_repo_dir, os.path.join(tag_path, - 'simple_subdir', - 'subdir_file.txt')) - - def test_required_bybranch(self): - """Check out a required external pointing to a git branch.""" - cloned_repo_dir = self.clone_test_repo(CONTAINER_REPO) - self._generator.create_config() - self._generator.create_section(SIMPLE_REPO, BRANCH_SECTION, - branch=REMOTE_BRANCH_FEATURE2) - self._generator.write_config(cloned_repo_dir) - - # externals start out 'empty' aka not checked out. - tree = self.execute_checkout_in_dir(cloned_repo_dir, - self.status_args) - local_path_rel = self._external_path(BRANCH_SECTION) - self._check_sync_clean(tree[local_path_rel], - ExternalStatus.EMPTY, - ExternalStatus.DEFAULT) - local_path_abs = os.path.join(cloned_repo_dir, local_path_rel) - self.assertFalse(os.path.exists(local_path_abs)) - - # after checkout, the external is 'clean' aka at the correct version. - tree = self.execute_checkout_with_status(cloned_repo_dir, - self.checkout_args) - self._check_sync_clean(tree[local_path_rel], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - self.assertTrue(os.path.exists(local_path_abs)) - - # Actually checked out the desired repo. - self.assertEqual('origin', GitRepository._remote_name_for_url( - # Which url to look up - self._generator.url_for_repo_path(SIMPLE_REPO), - # Which directory has the local checked-out repo. - dirname=local_path_abs)) - - # Actually checked out the desired branch. - (branch_found, branch_name) = GitRepository._git_current_remote_branch( - local_path_abs) - self.assertEquals(branch_name, 'origin/' + REMOTE_BRANCH_FEATURE2) - - def test_required_byhash(self): - """Check out a required external pointing to a git hash.""" - cloned_repo_dir = self.clone_test_repo(CONTAINER_REPO) - self._generator.create_config() - self._generator.create_section(SIMPLE_REPO, HASH_SECTION, - ref_hash='60b1cc1a38d63') - self._generator.write_config(cloned_repo_dir) - - # externals start out 'empty' aka not checked out. - tree = self.execute_checkout_in_dir(cloned_repo_dir, - self.status_args) - local_path_rel = self._external_path(HASH_SECTION) - self._check_sync_clean(tree[local_path_rel], - ExternalStatus.EMPTY, - ExternalStatus.DEFAULT) - local_path_abs = os.path.join(cloned_repo_dir, local_path_rel) - self.assertFalse(os.path.exists(local_path_abs)) - - # after checkout, the externals are 'clean' aka at their correct version. - tree = self.execute_checkout_with_status(cloned_repo_dir, - self.checkout_args) - self._check_sync_clean(tree[local_path_rel], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - - # Actually checked out the desired repo. - self.assertEqual('origin', GitRepository._remote_name_for_url( - # Which url to look up - self._generator.url_for_repo_path(SIMPLE_REPO), - # Which directory has the local checked-out repo. - dirname=local_path_abs)) - - # Actually checked out the desired hash. - (hash_found, hash_name) = GitRepository._git_current_hash( - local_path_abs) - self.assertTrue(hash_name.startswith('60b1cc1a38d63'), - msg=hash_name) - - def test_container_nested_required(self): - """Verify that a container with nested subrepos generates the correct initial status. - Tests over all possible permutations - """ - # Output subdirs for each of the externals, to test that one external can be - # checked out in a subdir of another. - NESTED_SUBDIR = ['./fred', './fred/wilma', './fred/wilma/barney'] - - # Assert that each type of external (e.g. tag vs branch) can be at any parent level - # (e.g. child/parent/grandparent). - 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): - dest_dir = os.path.join(module_tmp_root_dir, self._test_id, - "test"+str(n)) - cloned_repo_dir = self.clone_test_repo(CONTAINER_REPO, - dest_dir_in=dest_dir) - self._generator.create_config() - # We happen to check out each section via a different reference (tag/branch/hash) but - # those don't really matter, we just need to check out three repos into a nested set of - # directories. - self._generator.create_section( - SIMPLE_REPO, TAG_SECTION, nested=True, - tag='tag1', path=NESTED_SUBDIR[order[0]]) - self._generator.create_section( - SIMPLE_REPO, BRANCH_SECTION, nested=True, - branch=REMOTE_BRANCH_FEATURE2, path=NESTED_SUBDIR[order[1]]) - self._generator.create_section( - SIMPLE_REPO, HASH_SECTION, nested=True, - ref_hash='60b1cc1a38d63', path=NESTED_SUBDIR[order[2]]) - self._generator.write_config(cloned_repo_dir) - - # all externals start out 'empty' aka not checked out. - tree = self.execute_checkout_in_dir(cloned_repo_dir, - self.status_args) - self._check_sync_clean(tree[NESTED_SUBDIR[order[0]]], - ExternalStatus.EMPTY, - ExternalStatus.DEFAULT) - self._check_sync_clean(tree[NESTED_SUBDIR[order[1]]], - ExternalStatus.EMPTY, - ExternalStatus.DEFAULT) - self._check_sync_clean(tree[NESTED_SUBDIR[order[2]]], - ExternalStatus.EMPTY, - ExternalStatus.DEFAULT) - - # after checkout, all the repos are 'clean'. - tree = self.execute_checkout_with_status(cloned_repo_dir, - self.checkout_args) - self._check_sync_clean(tree[NESTED_SUBDIR[order[0]]], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - self._check_sync_clean(tree[NESTED_SUBDIR[order[1]]], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - self._check_sync_clean(tree[NESTED_SUBDIR[order[2]]], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - - def test_container_simple_optional(self): - """Verify that container with an optional simple subrepos generates - the correct initial status. - - """ - # create repo and externals config. - cloned_repo_dir = self.clone_test_repo(CONTAINER_REPO) - self._generator.create_config() - self._generator.create_section(SIMPLE_REPO, 'simp_req', - tag='tag1') - - self._generator.create_section(SIMPLE_REPO, 'simp_opt', - tag='tag1', required=False) - - self._generator.write_config(cloned_repo_dir) - - # all externals start out 'empty' aka not checked out. - tree = self.execute_checkout_in_dir(cloned_repo_dir, - self.status_args) - req_status = tree[self._external_path('simp_req')] - self._check_sync_clean(req_status, - ExternalStatus.EMPTY, - ExternalStatus.DEFAULT) - self.assertEqual(req_status.source_type, ExternalStatus.MANAGED) - - opt_status = tree[self._external_path('simp_opt')] - self._check_sync_clean(opt_status, - ExternalStatus.EMPTY, - ExternalStatus.DEFAULT) - self.assertEqual(opt_status.source_type, ExternalStatus.OPTIONAL) - - # after checkout, required external is clean, optional is still empty. - tree = self.execute_checkout_with_status(cloned_repo_dir, - self.checkout_args) - req_status = tree[self._external_path('simp_req')] - self._check_sync_clean(req_status, - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - self.assertEqual(req_status.source_type, ExternalStatus.MANAGED) - - opt_status = tree[self._external_path('simp_opt')] - self._check_sync_clean(opt_status, - ExternalStatus.EMPTY, - ExternalStatus.DEFAULT) - self.assertEqual(opt_status.source_type, ExternalStatus.OPTIONAL) - - # after checking out optionals, the optional external is also clean. - tree = self.execute_checkout_with_status(cloned_repo_dir, - self.optional_args) - req_status = tree[self._external_path('simp_req')] - self._check_sync_clean(req_status, - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - self.assertEqual(req_status.source_type, ExternalStatus.MANAGED) - - opt_status = tree[self._external_path('simp_opt')] - self._check_sync_clean(opt_status, - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - self.assertEqual(opt_status.source_type, ExternalStatus.OPTIONAL) - - def test_container_simple_verbose(self): - """Verify that verbose status matches non-verbose. - """ - cloned_repo_dir = self.clone_test_repo(CONTAINER_REPO) - self._generator.create_config() - self._generator.create_section(SIMPLE_REPO, TAG_SECTION, - tag='tag1') - self._generator.write_config(cloned_repo_dir) - - # after checkout, all externals should be 'clean'. - tree = self.execute_checkout_with_status(cloned_repo_dir, - self.checkout_args) - self._check_sync_clean(tree[self._external_path(TAG_SECTION)], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - - # 'Verbose' status should tell the same story. - tree = self.execute_checkout_in_dir(cloned_repo_dir, - self.verbose_args) - self._check_sync_clean(tree[self._external_path(TAG_SECTION)], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - - def test_container_simple_dirty(self): - """Verify that a container with a new tracked file is marked dirty. - """ - cloned_repo_dir = self.clone_test_repo(CONTAINER_REPO) - self._generator.create_config() - self._generator.create_section(SIMPLE_REPO, TAG_SECTION, - tag='tag1') - self._generator.write_config(cloned_repo_dir) - - # checkout, should start out clean. - tree = self.execute_checkout_with_status(cloned_repo_dir, self.checkout_args) - self._check_sync_clean(tree[self._external_path(TAG_SECTION)], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - - # add a tracked file to the simp_tag external, should be dirty. - RepoUtils.add_file_to_repo(cloned_repo_dir, - 'externals/{0}/tmp.txt'.format(TAG_SECTION), - tracked=True) - tree = self.execute_checkout_in_dir(cloned_repo_dir, self.status_args) - self._check_sync_clean(tree[self._external_path(TAG_SECTION)], - ExternalStatus.STATUS_OK, - ExternalStatus.DIRTY) - - # Re-checkout; simp_tag should still be dirty. - tree = self.execute_checkout_with_status(cloned_repo_dir, - self.checkout_args) - self._check_sync_clean(tree[self._external_path(TAG_SECTION)], - ExternalStatus.STATUS_OK, - ExternalStatus.DIRTY) - - 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. - - """ - cloned_repo_dir = self.clone_test_repo(CONTAINER_REPO) - self._generator.create_config() - self._generator.create_section(SIMPLE_REPO, TAG_SECTION, - tag='tag1') - self._generator.write_config(cloned_repo_dir) - - # checkout, should start out clean. - tree = self.execute_checkout_with_status(cloned_repo_dir, - self.checkout_args) - self._check_sync_clean(tree[self._external_path(TAG_SECTION)], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - - # add an untracked file to the simp_tag external, should stay clean. - RepoUtils.add_file_to_repo(cloned_repo_dir, - 'externals/{0}/tmp.txt'.format(TAG_SECTION), - tracked=False) - tree = self.execute_checkout_in_dir(cloned_repo_dir, self.status_args) - self._check_sync_clean(tree[self._external_path(TAG_SECTION)], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - - # After checkout, the external should still be 'clean'. - tree = self.execute_checkout_with_status(cloned_repo_dir, - self.checkout_args) - self._check_sync_clean(tree[self._external_path(TAG_SECTION)], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - - 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. - - For more info about 'detached head' state: https://www.cloudbees.com/blog/git-detached-head - """ - cloned_repo_dir = self.clone_test_repo(CONTAINER_REPO) - self._generator.create_config() - self._generator.create_section(SIMPLE_REPO, TAG_SECTION, - tag='tag1') - - self._generator.create_section(SIMPLE_REPO, BRANCH_SECTION, - branch=REMOTE_BRANCH_FEATURE2) - - self._generator.create_section(SIMPLE_REPO, 'simp_hash', - ref_hash='60b1cc1a38d63') - - self._generator.write_config(cloned_repo_dir) - - # externals start out 'empty' aka not checked out. - tree = self.execute_checkout_in_dir(cloned_repo_dir, self.status_args) - self._check_sync_clean(tree[self._external_path(TAG_SECTION)], - ExternalStatus.EMPTY, - ExternalStatus.DEFAULT) - self._check_sync_clean(tree[self._external_path(BRANCH_SECTION)], - ExternalStatus.EMPTY, - ExternalStatus.DEFAULT) - self._check_sync_clean(tree[self._external_path(HASH_SECTION)], - ExternalStatus.EMPTY, - ExternalStatus.DEFAULT) - - # checkout - self.execute_checkout_in_dir(cloned_repo_dir, self.checkout_args) - - # Commit on top of the tag and hash (creating the detached head state in those two - # externals' repos) - # The branch commit does not create the detached head state, but here for completeness. - RepoUtils.create_commit(cloned_repo_dir, TAG_SECTION) - RepoUtils.create_commit(cloned_repo_dir, HASH_SECTION) - RepoUtils.create_commit(cloned_repo_dir, BRANCH_SECTION) - - # sync status of all three should be 'modified' (uncommitted changes) - # clean status is 'ok' (matches externals version) - tree = self.execute_checkout_in_dir(cloned_repo_dir, self.status_args) - self._check_sync_clean(tree[self._external_path(TAG_SECTION)], - ExternalStatus.MODEL_MODIFIED, - ExternalStatus.STATUS_OK) - self._check_sync_clean(tree[self._external_path(BRANCH_SECTION)], - ExternalStatus.MODEL_MODIFIED, - ExternalStatus.STATUS_OK) - self._check_sync_clean(tree[self._external_path(HASH_SECTION)], - ExternalStatus.MODEL_MODIFIED, - ExternalStatus.STATUS_OK) - - # after checkout, all externals should be totally clean (no uncommitted changes, - # and matches externals version). - tree = self.execute_checkout_with_status(cloned_repo_dir, self.checkout_args) - self._check_sync_clean(tree[self._external_path(TAG_SECTION)], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - self._check_sync_clean(tree[self._external_path(BRANCH_SECTION)], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - self._check_sync_clean(tree[self._external_path(HASH_SECTION)], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - - def test_container_remote_branch(self): - """Verify that a container with remote branch change works - - """ - cloned_repo_dir = self.clone_test_repo(CONTAINER_REPO) - self._generator.create_config() - self._generator.create_section(SIMPLE_REPO, BRANCH_SECTION, - branch=REMOTE_BRANCH_FEATURE2) - self._generator.write_config(cloned_repo_dir) - - # initial checkout - self.execute_checkout_in_dir(cloned_repo_dir, self.checkout_args) - - # update the branch external to point to a different remote with the same branch, - # then simp_branch should be out of sync - self._generator.write_with_git_branch(cloned_repo_dir, - name=BRANCH_SECTION, - branch=REMOTE_BRANCH_FEATURE2, - new_remote_repo_path=SIMPLE_FORK_REPO) - tree = self.execute_checkout_in_dir(cloned_repo_dir, self.status_args) - self._check_sync_clean(tree[self._external_path(BRANCH_SECTION)], - ExternalStatus.MODEL_MODIFIED, - ExternalStatus.STATUS_OK) - - # checkout new externals, now simp_branch should be clean. - tree = self.execute_checkout_with_status(cloned_repo_dir, self.checkout_args) - self._check_sync_clean(tree[self._external_path(BRANCH_SECTION)], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - - 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. - - """ - cloned_repo_dir = self.clone_test_repo(CONTAINER_REPO) - self._generator.create_config() - self._generator.create_section(SIMPLE_REPO, BRANCH_SECTION, - branch=REMOTE_BRANCH_FEATURE2) - self._generator.write_config(cloned_repo_dir) - - # initial checkout - self.execute_checkout_in_dir(cloned_repo_dir, self.checkout_args) - - # update the config file to point to a different remote with - # the new tag replacing the old branch. Tag MUST NOT be in the original - # repo! status of simp_branch should then be out of sync - self._generator.write_with_tag_and_remote_repo(cloned_repo_dir, BRANCH_SECTION, - tag='forked-feature-v1', - new_remote_repo_path=SIMPLE_FORK_REPO) - tree = self.execute_checkout_in_dir(cloned_repo_dir, - self.status_args) - self._check_sync_clean(tree[self._external_path(BRANCH_SECTION)], - ExternalStatus.MODEL_MODIFIED, - ExternalStatus.STATUS_OK) - - # checkout new externals, then should be synced. - tree = self.execute_checkout_with_status(cloned_repo_dir, - self.checkout_args) - self._check_sync_clean(tree[self._external_path(BRANCH_SECTION)], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - - 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 fetched, - and therefore not fetched by default with 'git fetch'. It will - only be retrieved by 'git fetch --tags' - """ - cloned_repo_dir = self.clone_test_repo(CONTAINER_REPO) - self._generator.create_config() - self._generator.create_section(SIMPLE_REPO, BRANCH_SECTION, - branch=REMOTE_BRANCH_FEATURE2) - self._generator.write_config(cloned_repo_dir) - - # initial checkout - self.execute_checkout_in_dir(cloned_repo_dir, self.checkout_args) - - # update the config file to point to a different remote with - # the new tag instead of the old branch. Tag MUST NOT be in the original - # repo! status of simp_branch should then be out of sync. - self._generator.write_with_tag_and_remote_repo(cloned_repo_dir, BRANCH_SECTION, - tag='abandoned-feature', - new_remote_repo_path=SIMPLE_FORK_REPO) - tree = self.execute_checkout_in_dir(cloned_repo_dir, self.status_args) - self._check_sync_clean(tree[self._external_path(BRANCH_SECTION)], - ExternalStatus.MODEL_MODIFIED, - ExternalStatus.STATUS_OK) - - # checkout new externals, should be clean again. - tree = self.execute_checkout_with_status(cloned_repo_dir, - self.checkout_args) - self._check_sync_clean(tree[self._external_path(BRANCH_SECTION)], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - - 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. - - """ - cloned_repo_dir = self.clone_test_repo(CONTAINER_REPO) - self._generator.create_config() - self._generator.create_section(SIMPLE_REPO, BRANCH_SECTION, - branch=REMOTE_BRANCH_FEATURE2) - self._generator.write_config(cloned_repo_dir) - - # initial checkout - self.execute_checkout_in_dir(cloned_repo_dir, self.checkout_args) - - # update the config file to point to a different remote with - # the same branch. - self._generator.write_with_git_branch(cloned_repo_dir, name=BRANCH_SECTION, - branch=REMOTE_BRANCH_FEATURE2, - new_remote_repo_path=SIMPLE_FORK_REPO) - # after checkout, should be clean again. - tree = self.execute_checkout_with_status(cloned_repo_dir, self.checkout_args) - self._check_sync_clean(tree[self._external_path(BRANCH_SECTION)], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - - # update branch to point to a new branch that only exists in - # the local fork - RepoUtils.create_branch(cloned_repo_dir, external_name=BRANCH_SECTION, - branch='private-feature', with_commit=True) - self._generator.write_with_git_branch(cloned_repo_dir, name=BRANCH_SECTION, - branch='private-feature', - new_remote_repo_path=SIMPLE_LOCAL_ONLY_NAME) - # after checkout, should be clean again. - tree = self.execute_checkout_with_status(cloned_repo_dir, self.checkout_args) - self._check_sync_clean(tree[self._external_path(BRANCH_SECTION)], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - - def test_container_mixed_subrepo(self): - """Verify container with mixed subrepo. - - The mixed subrepo has a sub-externals file with different - sub-externals on different branches. - - """ - cloned_repo_dir = self.clone_test_repo(CONTAINER_REPO) - - self._generator.create_config() - self._generator.create_section(MIXED_REPO, 'mixed_req', - branch='master', sub_externals=CFG_SUB_NAME) - self._generator.write_config(cloned_repo_dir) - - # The subrepo has a repo_url that uses this environment variable. - # It'll be cleared in tearDown(). - os.environ[MIXED_CONT_EXT_ROOT_ENV_VAR] = self._bare_root - debug_env = MIXED_CONT_EXT_ROOT_ENV_VAR + '=' + self._bare_root - - # inital checkout: all requireds are clean, and optional is empty. - tree = self.execute_checkout_with_status(cloned_repo_dir, - self.checkout_args, - debug_env=debug_env) - mixed_req_path = self._external_path('mixed_req') - self._check_sync_clean(tree[mixed_req_path], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - sub_ext_base_path = "{0}/{1}/{2}".format(EXTERNALS_PATH, 'mixed_req', SUB_EXTERNALS_PATH) - # The already-checked-in subexternals file has a 'simp_branch' section - self._check_sync_clean(tree[self._external_path('simp_branch', base_path=sub_ext_base_path)], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - - # update the mixed-use external to point to different branch - # status should become out of sync for mixed_req, but sub-externals - # are still in sync - self._generator.write_with_git_branch(cloned_repo_dir, name='mixed_req', - branch='new-feature', - new_remote_repo_path=MIXED_REPO) - tree = self.execute_checkout_in_dir(cloned_repo_dir, self.status_args, - debug_env=debug_env) - self._check_sync_clean(tree[mixed_req_path], - ExternalStatus.MODEL_MODIFIED, - ExternalStatus.STATUS_OK) - self._check_sync_clean(tree[self._external_path('simp_branch', base_path=sub_ext_base_path)], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - - # run the checkout. Now the mixed use external and its sub-externals should be clean. - tree = self.execute_checkout_with_status(cloned_repo_dir, self.checkout_args, - debug_env=debug_env) - self._check_sync_clean(tree[mixed_req_path], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - self._check_sync_clean(tree[self._external_path('simp_branch', base_path=sub_ext_base_path)], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - - def test_container_component(self): - """Verify that optional component checkout works - """ - cloned_repo_dir = self.clone_test_repo(CONTAINER_REPO) - - # create the top level externals file - self._generator.create_config() - # Optional external, by tag. - self._generator.create_section(SIMPLE_REPO, 'simp_opt', - tag='tag1', required=False) - - # Required external, by branch. - self._generator.create_section(SIMPLE_REPO, BRANCH_SECTION, - branch=REMOTE_BRANCH_FEATURE2) - - # Required external, by hash. - self._generator.create_section(SIMPLE_REPO, HASH_SECTION, - ref_hash='60b1cc1a38d63') - self._generator.write_config(cloned_repo_dir) - - # inital checkout, first try a nonexistent component argument noref - checkout_args = ['simp_opt', 'noref'] - checkout_args.extend(self.checkout_args) - - with self.assertRaises(RuntimeError): - self.execute_checkout_in_dir(cloned_repo_dir, checkout_args) - - # Now explicitly check out one optional component.. - # Explicitly listed component (opt) should be present, the other two not. - checkout_args = ['simp_opt'] - checkout_args.extend(self.checkout_args) - tree = self.execute_checkout_with_status(cloned_repo_dir, - checkout_args) - self._check_sync_clean(tree[self._external_path('simp_opt')], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - self._check_sync_clean(tree[self._external_path(BRANCH_SECTION)], - ExternalStatus.EMPTY, - ExternalStatus.DEFAULT) - self._check_sync_clean(tree[self._external_path(HASH_SECTION)], - ExternalStatus.EMPTY, - ExternalStatus.DEFAULT) - - # Check out a second component, this one required. - # Explicitly listed component (branch) should be present, the still-unlisted one (tag) not. - checkout_args.append(BRANCH_SECTION) - tree = self.execute_checkout_with_status(cloned_repo_dir, - checkout_args) - self._check_sync_clean(tree[self._external_path('simp_opt')], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - self._check_sync_clean(tree[self._external_path(BRANCH_SECTION)], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - self._check_sync_clean(tree[self._external_path(HASH_SECTION)], - ExternalStatus.EMPTY, - ExternalStatus.DEFAULT) - - - def test_container_exclude_component(self): - """Verify that exclude component checkout works - """ - cloned_repo_dir = self.clone_test_repo(CONTAINER_REPO) - self._generator.create_config() - self._generator.create_section(SIMPLE_REPO, TAG_SECTION, - tag='tag1') - - self._generator.create_section(SIMPLE_REPO, BRANCH_SECTION, - branch=REMOTE_BRANCH_FEATURE2) - - self._generator.create_section(SIMPLE_REPO, 'simp_hash', - ref_hash='60b1cc1a38d63') - - self._generator.write_config(cloned_repo_dir) - - # inital checkout should result in all externals being clean except excluded TAG_SECTION. - checkout_args = ['--exclude', TAG_SECTION] - checkout_args.extend(self.checkout_args) - tree = self.execute_checkout_with_status(cloned_repo_dir, checkout_args) - self._check_sync_clean(tree[self._external_path(TAG_SECTION)], - ExternalStatus.EMPTY, - ExternalStatus.DEFAULT) - self._check_sync_clean(tree[self._external_path(BRANCH_SECTION)], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - self._check_sync_clean(tree[self._external_path(HASH_SECTION)], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - - def test_subexternal(self): - """Verify that an externals file can be brought in as a reference. - - """ - cloned_repo_dir = self.clone_test_repo(MIXED_REPO) - - self._generator.create_config() - self._generator.create_section_reference_to_subexternal('mixed_base') - self._generator.write_config(cloned_repo_dir) - - # The subrepo has a repo_url that uses this environment variable. - # It'll be cleared in tearDown(). - os.environ[MIXED_CONT_EXT_ROOT_ENV_VAR] = self._bare_root - debug_env = MIXED_CONT_EXT_ROOT_ENV_VAR + '=' + self._bare_root - - # After checkout, confirm required's are clean and the referenced - # subexternal's contents are also clean. - tree = self.execute_checkout_with_status(cloned_repo_dir, - self.checkout_args, - debug_env=debug_env) - - self._check_sync_clean( - tree[self._external_path(BRANCH_SECTION, base_path=SUB_EXTERNALS_PATH)], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - - def test_container_sparse(self): - """Verify that 'full' container with simple subrepo - can run a sparse checkout and generate the correct initial status. - - """ - cloned_repo_dir = self.clone_test_repo(CONTAINER_REPO) - - # Create a file to list filenames to checkout. - sparse_filename = 'sparse_checkout' - with open(os.path.join(cloned_repo_dir, sparse_filename), 'w') as sfile: - sfile.write(README_NAME) - - self._generator.create_config() - self._generator.create_section(SIMPLE_REPO, TAG_SECTION, - tag='tag2') - - # Same tag as above, but with a sparse file too. - sparse_relpath = '../../' + sparse_filename - self._generator.create_section(SIMPLE_REPO, 'simp_sparse', - tag='tag2', sparse=sparse_relpath) - - self._generator.write_config(cloned_repo_dir) - - # inital checkout, confirm required's are clean. - tree = self.execute_checkout_with_status(cloned_repo_dir, - self.checkout_args) - self._check_sync_clean(tree[self._external_path(TAG_SECTION)], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - self._check_sync_clean(tree[self._external_path('simp_sparse')], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - - # Check existence of some files - full set in TAG_SECTION, and sparse set - # in 'simp_sparse'. - subrepo_path = os.path.join('externals', TAG_SECTION) - self._check_file_exists(cloned_repo_dir, - os.path.join(subrepo_path, README_NAME)) - self._check_file_exists(cloned_repo_dir, os.path.join(subrepo_path, - 'simple_subdir', - 'subdir_file.txt')) - subrepo_path = os.path.join('externals', 'simp_sparse') - self._check_file_exists(cloned_repo_dir, - os.path.join(subrepo_path, README_NAME)) - self._check_file_absent(cloned_repo_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. - """ - - @staticmethod - def _svn_branch_name(): - return './{0}/svn_branch'.format(EXTERNALS_PATH) - - @staticmethod - def _svn_tag_name(): - return './{0}/svn_tag'.format(EXTERNALS_PATH) - - def _svn_test_repo_url(self): - return 'file://' + os.path.join(self._bare_root, SVN_TEST_REPO) - - def _check_tag_branch_svn_tag_clean(self, tree): - self._check_sync_clean(tree[self._external_path(TAG_SECTION)], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - self._check_sync_clean(tree[self._svn_branch_name()], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - self._check_sync_clean(tree[self._svn_tag_name()], - ExternalStatus.STATUS_OK, - ExternalStatus.STATUS_OK) - - def _have_svn_access(self): - """Check if we have svn access so we can enable tests that use svn. - - """ - have_svn = False - cmd = ['svn', 'ls', self._svn_test_repo_url(), ] - 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 - cloned_repo_dir = self.clone_test_repo(CONTAINER_REPO) - - self._generator.create_config() - # Git repo. - self._generator.create_section(SIMPLE_REPO, TAG_SECTION, tag='tag1') - - # Svn repos. - self._generator.create_svn_external('svn_branch', self._svn_test_repo_url(), branch='trunk') - self._generator.create_svn_external('svn_tag', self._svn_test_repo_url(), tag='tags/cesm2.0.beta07') - - self._generator.write_config(cloned_repo_dir) - - # checkout, make sure all sections are clean. - tree = self.execute_checkout_with_status(cloned_repo_dir, - self.checkout_args) - self._check_tag_branch_svn_tag_clean(tree) - - # update description file to make the tag into a branch and - # trigger a switch - self._generator.write_with_svn_branch(cloned_repo_dir, 'svn_tag', - 'trunk') - - # checkout, again the results should be clean. - tree = self.execute_checkout_with_status(cloned_repo_dir, - self.checkout_args) - self._check_tag_branch_svn_tag_clean(tree) - - # add an untracked file to the repo - tracked = False - RepoUtils.add_file_to_repo(cloned_repo_dir, - 'externals/svn_branch/tmp.txt', tracked) - - # run a no-op checkout. - self.execute_checkout_in_dir(cloned_repo_dir, self.checkout_args) - - # update description file to make the branch into a tag and - # trigger a modified sync status - self._generator.write_with_svn_branch(cloned_repo_dir, 'svn_tag', - 'tags/cesm2.0.beta07') - - self.execute_checkout_in_dir(cloned_repo_dir,self.checkout_args) - - # verify status is still clean and unmodified, last - # checkout modified the working dir state. - tree = self.execute_checkout_in_dir(cloned_repo_dir, - self.verbose_args) - self._check_tag_branch_svn_tag_clean(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(module_tmp_root_dir, 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.clone_test_repo(CONTAINER_REPO, - 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_REPO) - simple_repo_dir = os.path.join(self._bare_root, SIMPLE_REPO) - self._simple_ext_fork_name = os.path.splitext(SIMPLE_FORK_REPO)[0] - self._simple_ext_name = os.path.join('sourc', - os.path.splitext(SIMPLE_REPO)[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', '-c', 'protocol.file.allow=always','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', '-c', 'protocol.file.allow=always', 'submodule', 'add', '--name', SIMPLE_REPO, - 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.write_externals_config(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 write_externals_config(self, name='', dest_dir=None, - filename=CFG_NAME, - 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_REPO, - self._simple_ext_fork_name, - from_submodule=True) - self._generator.create_section(SIMPLE_REPO, - 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, sub_externals=sub_externals, - repo_path_abs=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) - self.execute_checkout_in_dir(self._my_test_dir, - self.checkout_args) - self.execute_checkout_in_dir(self._my_test_dir, - self.status_args) - 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.write_externals_config(branch_name=self._bare_branch_name) - self.execute_checkout_in_dir(self._my_test_dir, - self.checkout_args) - 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)) - - submods = git_submodule_status(checkout_dir) - print('checking status of', checkout_dir, ':', submods) - 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) - 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.write_externals_config(branch_name=self._bare_branch_name, - sub_externals="none") - self.execute_checkout_in_dir(self._my_test_dir, - self.checkout_args) - 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.write_externals_config(branch_name=self._config_branch_name, - sub_externals=self._container_extern_name) - self.execute_checkout_in_dir(self._my_test_dir, - self.checkout_args) - 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 - cloned_repo_dir = self.clone_test_repo(CONTAINER_REPO) - self._generator.create_config() - self._generator.create_section(SIMPLE_REPO, BRANCH_SECTION, - branch=REMOTE_BRANCH_FEATURE2) - self._generator.write_config(cloned_repo_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.write_with_protocol(cloned_repo_dir, BRANCH_SECTION, - 'this-protocol-does-not-exist') - - with self.assertRaises(RuntimeError): - self.execute_checkout_in_dir(cloned_repo_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 - cloned_repo_dir = self.clone_test_repo(CONTAINER_REPO) - self._generator.create_config() - self._generator.create_section(SIMPLE_REPO, BRANCH_SECTION, - branch=REMOTE_BRANCH_FEATURE2) - self._generator.write_config(cloned_repo_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.write_with_protocol(cloned_repo_dir, BRANCH_SECTION, 'svn') - with self.assertRaises(RuntimeError): - self.execute_checkout_in_dir(cloned_repo_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 - cloned_repo_dir = self.clone_test_repo(CONTAINER_REPO) - self._generator.create_config() - self._generator.create_section(SIMPLE_REPO, BRANCH_SECTION, - branch=REMOTE_BRANCH_FEATURE2) - self._generator.write_config(cloned_repo_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.write_with_tag_and_remote_repo(cloned_repo_dir, BRANCH_SECTION, - tag='this-tag-does-not-exist', - new_remote_repo_path=SIMPLE_REPO) - - with self.assertRaises(RuntimeError): - self.execute_checkout_in_dir(cloned_repo_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 - cloned_repo_dir = self.clone_test_repo(CONTAINER_REPO) - self._generator.create_config() - self._generator.create_section(SIMPLE_REPO, BRANCH_SECTION, - branch=REMOTE_BRANCH_FEATURE2) - self._generator.write_config(cloned_repo_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.write_with_tag_and_remote_repo(cloned_repo_dir, BRANCH_SECTION, - tag='this-tag-does-not-exist', - new_remote_repo_path=SIMPLE_REPO, - remove_branch=False) - - with self.assertRaises(RuntimeError): - self.execute_checkout_in_dir(cloned_repo_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 - cloned_repo_dir = self.clone_test_repo(CONTAINER_REPO) - self._generator.create_config() - self._generator.create_section(SIMPLE_REPO, BRANCH_SECTION, - branch=REMOTE_BRANCH_FEATURE2) - self._generator.write_config(cloned_repo_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.write_without_branch_tag(cloned_repo_dir, BRANCH_SECTION) - - with self.assertRaises(RuntimeError): - self.execute_checkout_in_dir(cloned_repo_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 - cloned_repo_dir = self.clone_test_repo(CONTAINER_REPO) - self._generator.create_config() - self._generator.create_section(SIMPLE_REPO, BRANCH_SECTION, - branch=REMOTE_BRANCH_FEATURE2) - self._generator.write_config(cloned_repo_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.write_without_repo_url(cloned_repo_dir, - BRANCH_SECTION) - - with self.assertRaises(RuntimeError): - self.execute_checkout_in_dir(cloned_repo_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 7e5fb5020d..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_cwd_git_repo(): - """Turn the current directory into an empty git repository""" - execute_subprocess(['git', 'init']) - - @staticmethod - def add_cwd_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_cwd_git_branch(branchname): - """Checkout a new branch in the current directory""" - execute_subprocess(['git', 'checkout', '-b', branchname]) - - @staticmethod - def make_cwd_git_tag(tagname): - """Make a lightweight tag at the current commit""" - execute_subprocess(['git', 'tag', '-m', 'making a tag', tagname]) - - @staticmethod - def checkout_cwd_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_cwd_git_repo() - self.add_cwd_git_commit() - hash_found, myhash = self._repo._git_current_hash(os.getcwd()) - 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(os.getcwd()) - 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_cwd_git_repo() - self.add_cwd_git_commit() - self.checkout_cwd_git_branch('foo') - branch_found, mybranch = self._repo._git_current_branch(os.getcwd()) - 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_cwd_git_repo() - self.add_cwd_git_commit() - self.make_cwd_git_tag('mytag') - self.checkout_cwd_ref('mytag') - branch_found, mybranch = self._repo._git_current_branch(os.getcwd()) - 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(os.getcwd()) - 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_cwd_git_repo() - self.add_cwd_git_commit() - self.make_cwd_git_tag('some_tag') - tag_found, mytag = self._repo._git_current_tag(os.getcwd()) - 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_cwd_git_repo() - self.add_cwd_git_commit() - self.make_cwd_git_tag('some_tag') - self.add_cwd_git_commit() - tag_found, mytag = self._repo._git_current_tag(os.getcwd()) - 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(os.getcwd()) - 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 1c01098acf..0000000000 --- a/manage_externals/test/test_unit_repository_git.py +++ /dev/null @@ -1,811 +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(dirname): - """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(dirname): - """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(dirname): - """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(os.getcwd()) - 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(os.getcwd()) - 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(os.getcwd()) - 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(os.getcwd()) - 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() - - # We have to override this class method rather than the self._repo - # instance method because it is called via - # GitRepository._remote_name_for_url, which is itself a @classmethod - # calls cls._git_remote_verbose(). - self._orignal_git_remote_verbose = GitRepository._git_remote_verbose - GitRepository._git_remote_verbose = self._git_remote_origin_upstream - def tearDown(self): - """Cleanup tmp stuff on the file system - """ - self._remove_tmp_git_dir() - - GitRepository._git_remote_verbose = self._orignal_git_remote_verbose - - 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(dirname): - """Return an empty string. - - Drop-in for GitRepository._current_ref - """ - return EMPTY_STR - - @staticmethod - def _git_remote_origin_upstream(dirname): - """Return an info string that is a checkout hash. - - Drop-in for GitRepository._git_remote_verbose. - """ - return GIT_REMOTE_OUTPUT_ORIGIN_UPSTREAM - - @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(dirname): - """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, dirname): - """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() - 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._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._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._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._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._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._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._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 _remote_name_for_url with a different remote - - """ - stat = ExternalStatus() - 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 _remote_name_for_url with a different remote - - """ - stat = ExternalStatus() - 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._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._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(*args, **kwargs): - return 0 - - @staticmethod - def _shell_false(*args, **kwargs): - return 1 - - @staticmethod - def _mock_revparse_commit(ref, dirname): - _ = ref - return (TestValidRef._shell_true, '97ebc0e0deadc0de') - - @staticmethod - def _mock_revparse_commit_false(ref, dirname): - _ = 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_revparse_commit_false - self._repo._tag = 'something' - remote_name = 'origin' - received, _ = self._repo._is_unique_tag(self._repo._tag, remote_name, - os.getcwd()) - 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_revparse_commit_false - self._repo._tag = 'tag1' - remote_name = 'origin' - received, _ = self._repo._is_unique_tag(self._repo._tag, remote_name, - os.getcwd()) - 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_revparse_commit - self._repo._tag = 'something' - remote_name = 'origin' - received, _ = self._repo._is_unique_tag(self._repo._tag, remote_name, - os.getcwd()) - 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_revparse_commit - self._repo._tag = 'tag1' - remote_name = 'origin' - received, _ = self._repo._is_unique_tag(self._repo._tag, remote_name, - os.getcwd()) - 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_revparse_commit - self._repo._tag = '97ebc0e0' - remote_name = 'origin' - received, _ = self._repo._is_unique_tag(self._repo._tag, remote_name, - os.getcwd()) - 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_revparse_commit - self._repo._tag = '97ebc0e0' - remote_name = 'origin' - received, _ = self._repo._is_unique_tag(self._repo._tag, remote_name, - os.getcwd()) - 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_revparse_commit_false(ref, dirname): - _ = ref - return (TestValidRef._shell_false, '') - - @staticmethod - def _mock_revparse_commit_true(ref, dirname): - _ = ref - _ = dirname - 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_revparse_commit_false - self._repo._tag = 'invalid_ref' - with self.assertRaises(RuntimeError): - self._repo._check_for_valid_ref(self._repo._tag, - remote_name=None, - dirname=os.getcwd()) - - 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_revparse_commit_true - self._repo._tag = 'tag1' - received = self._repo._check_for_valid_ref(self._repo._tag, - remote_name=None, - dirname=os.getcwd()) - 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_revparse_commit_true - self._repo._tag = 'tag1' - received = self._repo._check_for_valid_ref(self._repo._tag, - remote_name=None, - dirname=os.getcwd()) - self.assertTrue(received) - - def test_valid_hash(self): - """Verify a valid hash return true - """ - def _mock_revparse_commit_true(ref, dirname): - _ = 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_true - self._repo._hash = '56cc0b5394' - received = self._repo._check_for_valid_ref(self._repo._hash, - remote_name=None, - dirname=os.getcwd()) - 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 100755 index d9309df7f6..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 9a9b8d940c..ac705edb3c 100755 --- a/py_env_create +++ b/py_env_create @@ -122,7 +122,7 @@ if [ "$verbose" == "Yes" ]; then verbosity="--verbose" loglevel="INFO" fi -cmd="conda install --yes $verbosity --channel conda-forge --name $ctsm_python $condadir/$condafile $option" +cmd="conda install --yes $verbosity --channel conda-forge --name $ctsm_python --file $condadir/$condafile $option" echo "$cmd" $cmd if [ $? != 0 ]; then diff --git a/python/ctsm/.pylintrc b/python/ctsm/.pylintrc index db78949288..230f8acba8 100644 --- a/python/ctsm/.pylintrc +++ b/python/ctsm/.pylintrc @@ -436,6 +436,8 @@ good-names=i, ds, m, n, + ni, + nj, l1, l2, ax, diff --git a/python/ctsm/crop_calendars/check_constant_vars.py b/python/ctsm/crop_calendars/check_constant_vars.py index aa25a412fe..be7718256a 100644 --- a/python/ctsm/crop_calendars/check_constant_vars.py +++ b/python/ctsm/crop_calendars/check_constant_vars.py @@ -382,4 +382,4 @@ def check_constant_vars( raise RuntimeError("Stopping due to failed check_constant_vars().") bad_patches = np.unique(bad_patches) - return [int(p) for p in bad_patches] + return [int(p) for p in bad_patches], any_bad diff --git a/python/ctsm/crop_calendars/check_rx_obeyed.py b/python/ctsm/crop_calendars/check_rx_obeyed.py index 99b8d80bde..4d8ccd1788 100644 --- a/python/ctsm/crop_calendars/check_rx_obeyed.py +++ b/python/ctsm/crop_calendars/check_rx_obeyed.py @@ -104,6 +104,25 @@ def get_extreme_info(diff_array, rx_array, mxn, dims, gs_da, patches1d_lon, patc return round(themxn, 3), round(this_lon, 3), round(this_lat, 3), this_gs, round(this_rx) +def summarize_results(which_ds, output_var, verbose, all_ok, gdd_tolerance, diffs_eg_txt): + """ + Summarize results + """ + bad = True + if all_ok == 2: + bad = False + print(f"✅ {which_ds}: Prescribed {output_var} always obeyed") + elif all_ok == 1: + bad = False + print( + f"🟨 {which_ds}: Prescribed {output_var} *not* always obeyed, but acceptable (diffs <= " + + f"{gdd_tolerance})" + ) + elif not verbose: + print(f"❌ {which_ds}: Prescribed {output_var} *not* always obeyed. E.g., {diffs_eg_txt}") + return bad + + def check_rx_obeyed( vegtype_list, rx_ds, dates_ds, which_ds, output_var, gdd_min=None, verbose=False ): @@ -114,6 +133,7 @@ def check_rx_obeyed( dates_ds, which_ds, output_var, verbose ) + diffs_eg_txt = None for vegtype_str in vegtype_list: thisveg_patches = np.where(dates_ds.patches1d_itype_veg_str == vegtype_str)[0] if thisveg_patches.size == 0: @@ -203,14 +223,6 @@ def check_rx_obeyed( else: break - if all_ok == 2: - print(f"✅ {which_ds}: Prescribed {output_var} always obeyed") - elif all_ok == 1: - # print(f"🟨 {which_ds}: Prescribed {output_var} *not* always obeyed, but acceptable:") - # for x in diff_str_list: print(x) - print( - f"🟨 {which_ds}: Prescribed {output_var} *not* always obeyed, but acceptable (diffs <= " - + f"{gdd_tolerance})" - ) - elif not verbose: - print(f"❌ {which_ds}: Prescribed {output_var} *not* always obeyed. E.g., {diffs_eg_txt}") + bad = summarize_results(which_ds, output_var, verbose, all_ok, gdd_tolerance, diffs_eg_txt) + + return bad diff --git a/python/ctsm/crop_calendars/check_rxboth_run.py b/python/ctsm/crop_calendars/check_rxboth_run.py index ae4decde30..fa4affd220 100644 --- a/python/ctsm/crop_calendars/check_rxboth_run.py +++ b/python/ctsm/crop_calendars/check_rxboth_run.py @@ -75,6 +75,8 @@ def main(argv): "HARVEST_REASON_PERHARV", ] + any_bad = False + annual_outfiles = glob.glob(os.path.join(args.directory, "*.clm2.h1.*.nc")) # These should be constant in a Prescribed Calendars (rxboth) run, as long as the inputs were @@ -85,13 +87,19 @@ def main(argv): "rx_gdds_file": args.rx_gdds_file, } - case["ds"] = cc.import_output( + case["ds"], any_bad_import_output = cc.import_output( annual_outfiles, my_vars=my_vars, year_1=args.first_usable_year, year_n=args.last_usable_year, + throw_errors=False, + ) + any_bad = any_bad or any_bad_import_output + + _, any_bad_check_const_vars = check_constant_vars( + case["ds"], case, ignore_nan=True, verbose=True, throw_error=True ) - check_constant_vars(case["ds"], case, ignore_nan=True, verbose=True, throw_error=True) + any_bad = any_bad or any_bad_check_const_vars # Import GGCMI sowing and harvest dates, and check sims casename = "Prescribed Calendars" @@ -128,15 +136,16 @@ def main(argv): # Check if case["rx_sdates_file"]: - check_rx_obeyed( + sdate_not_obeyed = check_rx_obeyed( case["ds"].vegtype_str.values, case["rx_sdates_ds"].isel(time=0), case["ds"], casename, "SDATES", ) + any_bad = any_bad or sdate_not_obeyed if case["rx_gdds_file"]: - check_rx_obeyed( + gdds_not_obeyed = check_rx_obeyed( case["ds"].vegtype_str.values, case["rx_gdds_ds"].isel(time=0), case["ds"], @@ -144,6 +153,19 @@ def main(argv): "GDDHARV", gdd_min=gdd_min, ) + any_bad = any_bad or gdds_not_obeyed + + if any_bad: + msg = "\n ".join( + [ + "Unexpected behavior in rxboth run:", + f"any_bad_import_output: {any_bad_import_output}", + f"any_bad_check_const_vars: {any_bad_check_const_vars}", + f"sdate_not_obeyed: {sdate_not_obeyed}", + f"gdds_not_obeyed: {gdds_not_obeyed}", + ] + ) + raise RuntimeError(msg) if __name__ == "__main__": diff --git a/python/ctsm/crop_calendars/cropcal_figs_module.py b/python/ctsm/crop_calendars/cropcal_figs_module.py index d820460175..f26b5975d4 100644 --- a/python/ctsm/crop_calendars/cropcal_figs_module.py +++ b/python/ctsm/crop_calendars/cropcal_figs_module.py @@ -1,6 +1,7 @@ """ Functions for making crop calendar figures """ +# pylint: disable=abstract-class-instantiated import numpy as np diff --git a/python/ctsm/crop_calendars/cropcal_module.py b/python/ctsm/crop_calendars/cropcal_module.py index 3fe6942f94..719d352665 100644 --- a/python/ctsm/crop_calendars/cropcal_module.py +++ b/python/ctsm/crop_calendars/cropcal_module.py @@ -13,6 +13,8 @@ from ctsm.crop_calendars.cropcal_constants import DEFAULT_GDD_MIN from ctsm.crop_calendars.import_ds import import_ds +MISSING_RX_GDD_VAL = -1 + def check_and_trim_years(year_1, year_n, ds_in): """ @@ -168,8 +170,10 @@ def check_v0_le_v1(this_ds, var_list, msg_txt=" ", both_nan_ok=False, throw_erro if both_nan_ok: gdd_lt_hui = gdd_lt_hui | (np.isnan(this_ds[var0]) & np.isnan(this_ds[var1])) if np.all(gdd_lt_hui): + any_bad = False print(f"✅{msg_txt}{var0} always <= {var1}") else: + any_bad = True msg = f"❌{msg_txt}{var0} *not* always <= {var1}" gdd_lt_hui_vals = gdd_lt_hui.values patch_index = np.where(~gdd_lt_hui_vals)[0][0] @@ -185,6 +189,7 @@ def check_v0_le_v1(this_ds, var_list, msg_txt=" ", both_nan_ok=False, throw_erro print(msg) else: raise RuntimeError(msg) + return any_bad def get_gs_len_da(this_da): @@ -231,6 +236,13 @@ def import_max_gs_length(paramfile_dir, my_clm_ver, my_clm_subver): return mxmat_dict +def unexpected_negative_rx_gdd(data_array): + """ + Return True if there's a negative value not matching the designated missing value + """ + return np.any((data_array.values < 0) & (data_array.values != MISSING_RX_GDD_VAL)) + + def import_rx_dates(var_prefix, date_infile, dates_ds, set_neg1_to_nan=True): """ Import prescribed sowing/harvest dates @@ -260,19 +272,19 @@ def import_rx_dates(var_prefix, date_infile, dates_ds, set_neg1_to_nan=True): v_new = var.replace(var_prefix, "gs") this_ds = this_ds.rename({var: v_new}) - # Set -1 prescribed GDD values to NaN. Only warn the first time. + # Set GDD values matching MISSING_RX_GDD_VAL to NaN. Only warn the first time. if ( set_neg1_to_nan and var_prefix == "gdd" and v_new != var and np.any(this_ds[v_new].values < 0) ): - if np.any((this_ds[v_new].values < 0) & (this_ds[v_new].values != -1)): + if unexpected_negative_rx_gdd(this_ds[v_new]): raise RuntimeError(f"Unexpected negative value in {var}") if not did_warn: - print("Setting -1 rx GDD values to NaN") + print(f"Setting {MISSING_RX_GDD_VAL} rx GDD values to NaN") did_warn = True - this_ds[v_new] = this_ds[v_new].where(this_ds[v_new] != -1) + this_ds[v_new] = this_ds[v_new].where(this_ds[v_new] != MISSING_RX_GDD_VAL) return this_ds @@ -333,14 +345,17 @@ def import_output( my_vars, year_1=None, year_n=None, - my_vegtypes=utils.define_mgdcrop_list(), + my_vegtypes=utils.define_mgdcrop_list_withgrasses(), sdates_rx_ds=None, gdds_rx_ds=None, verbose=False, + throw_errors=True, ): """ Import CLM output """ + any_bad = False + # Import this_ds = import_ds(filename, my_vars=my_vars, my_vegtypes=my_vegtypes) @@ -410,7 +425,9 @@ def import_output( # Check that e.g., GDDACCUM <= HUI for var_list in [["GDDACCUM", "HUI"], ["SYEARS", "HYEARS"]]: if all(v in this_ds_gs for v in var_list): - check_v0_le_v1(this_ds_gs, var_list, both_nan_ok=True, throw_error=True) + any_bad = any_bad or check_v0_le_v1( + this_ds_gs, var_list, both_nan_ok=True, throw_error=throw_errors + ) # Check that prescribed calendars were obeyed if sdates_rx_ds: @@ -438,7 +455,7 @@ def import_output( raise RuntimeError("How to get NHARVEST_DISCREP for NHARVESTS > 2?") this_ds_gs["NHARVEST_DISCREP"] = (this_ds_gs["NHARVESTS"] == 2).astype(int) - return this_ds_gs + return this_ds_gs, any_bad def handle_zombie_crops(this_ds): diff --git a/python/ctsm/crop_calendars/cropcal_utils.py b/python/ctsm/crop_calendars/cropcal_utils.py index 00ed2413d2..584046edee 100644 --- a/python/ctsm/crop_calendars/cropcal_utils.py +++ b/python/ctsm/crop_calendars/cropcal_utils.py @@ -207,7 +207,24 @@ def is_each_vegtype(this_vegtypelist, this_filter, this_method): return [is_this_vegtype(x, this_filter, this_method) for x in this_vegtypelist] -def define_mgdcrop_list(): +def define_crop_list(): + """ + List (strings) of managed crops in CLM. + """ + notcrop_list = [ + "tree", + "c3_arctic_grass", + "c3_non-arctic_grass", + "c4_grass", + "shrub", + "not_vegetated", + ] + defined_pftlist = define_pftlist() + is_crop = is_each_vegtype(defined_pftlist, notcrop_list, "notok_contains") + return [defined_pftlist[i] for i, x in enumerate(is_crop) if x] + + +def define_mgdcrop_list_nograsses(): """ List (strings) of managed crops in CLM. """ @@ -217,6 +234,24 @@ def define_mgdcrop_list(): return [defined_pftlist[i] for i, x in enumerate(is_crop) if x] +def define_mgdcrop_list_withgrasses(): + """ + List (strings) of managed crops in CLM. + """ + notcrop_list = [ + "tree", + "c3_arctic_grass", + "c3_non-arctic_grass", + "c4_grass", + "shrub", + "unmanaged", + "not_vegetated", + ] + defined_pftlist = define_pftlist() + is_crop = is_each_vegtype(defined_pftlist, notcrop_list, "notok_contains") + return [defined_pftlist[i] for i, x in enumerate(is_crop) if x] + + def vegtype_str2int(vegtype_str, vegtype_mainlist=None): """ Convert list of vegtype strings to integer index equivalents. diff --git a/python/ctsm/crop_calendars/generate_gdd20_baseline.py b/python/ctsm/crop_calendars/generate_gdd20_baseline.py new file mode 100644 index 0000000000..13668fc850 --- /dev/null +++ b/python/ctsm/crop_calendars/generate_gdd20_baseline.py @@ -0,0 +1,330 @@ +""" +Generate stream_fldFileName_gdd20_baseline file from CTSM outputs +""" + +import sys +import argparse +import os +import datetime as dt +import numpy as np +import xarray as xr +import cftime + +# -- add python/ctsm to path (needed if we want to run generate_gdd20_baseline 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.crop_calendars.import_ds import import_ds +import ctsm.crop_calendars.cropcal_utils as utils +from ctsm.crop_calendars.grid_one_variable import grid_one_variable +from ctsm.crop_calendars.cropcal_module import MISSING_RX_GDD_VAL + +GRIDDING_VAR_LIST = ["patches1d_ixy", "patches1d_jxy", "lat", "lon"] +STREAM_YEAR = 2000 # The year specified for stream_yearFirst and stream_yearLast in the call of +# shr_strdata_init_from_inline() for sdat_cropcal_gdd20_baseline +MGDCROP_LIST = utils.define_crop_list() + + +def _parse_args(): + """ + Set up and parse input arguments + """ + parser = argparse.ArgumentParser( + description=( + "Given a list of CTSM history files, generate stream_fldFileName_gdd20_baseline input" + + "file from the GDD0, GDD8, and GDD10 variables." + ) + ) + + # Required + parser.add_argument( + "-i", + "--input-files", + help="Space-separated string of CTSM history files", + type=str, + required=True, + ) + parser.add_argument( + "-o", + "--output-file", + help="Path to which output file should be saved", + type=str, + required=True, + ) + parser.add_argument( + "-a", + "--author", + help=( + "String to be saved in author attribute of output files." + + "E.g., 'Author Name (authorname@ucar.edu)'" + ), + type=str, + required=True, + ) + + # Optional + parser.add_argument( + "--overwrite", + help="Overwrite existing output file, if any", + action="store_true", + ) + parser.add_argument( + "-y1", + "--first-year", + help=("First calendar year to include"), + type=int, + required=False, + ) + parser.add_argument( + "-yN", + "--last-year", + help=("Last calendar year to include"), + type=int, + required=False, + ) + parser.add_argument( + "-v", + "--variable", + help=("Which type of variable should be processed?"), + required=False, + default="GDDBX", + choices=["GDDBX", "GDDB20"], + ) + + # Get arguments + args = parser.parse_args(sys.argv[1:]) + + # Check arguments + if os.path.exists(args.output_file) and not args.overwrite: + raise FileExistsError("Output file exists but --overwrite is not specified") + + # Get and check input files + args.input_files = args.input_files.split(" ") + for filename in args.input_files: + if not os.path.exists(filename): + raise FileNotFoundError(f"Input file not found: {filename}") + + # Process time slice + # Assumes CESM behavior where data for e.g. 1987 is saved as 1988-01-01. + # It would be more robust, accounting for upcoming behavior (where timestamp for a year is the + # middle of that year), to do slice("YEAR1-01-03", "YEARN-01-02"), but that's not compatible + # with ctsm_pylib as of the version using python 3.7.9. See safer_timeslice() in cropcal_utils. + if args.first_year is not None: + date_1 = f"{args.first_year+1}-01-01" + else: + date_1 = "0000-01-01" + if args.last_year is not None: + date_n = f"{args.last_year+1}-01-01" + else: + date_n = "9999-12-31" + time_slice = slice(date_1, date_n) + + return args, time_slice + + +def _get_cft_list(crop_list): + """ + Given a list of strings, return a list of CFT names that contain any of those strings. + Will include both irrigated and rainfed! + + Args: + crop_list (list): List of crops to look for. + E.g.: ["corn", "cotton"] + + Returns: + cft_str_list: List of CFTs containing any of the crop names in crop_list. + E.g.: ["tropical_corn", "irrigated_tropical_corn", + "temperate_corn", "irrigated_temperate_corn", + "cotton", "irrigated_cotton"] + """ + + cft_str_list = [] + for crop_str in crop_list: + cft_str_list += [x for x in MGDCROP_LIST if crop_str in x] + return cft_str_list + + +def _get_gddn_for_cft(cft_str, variable): + """ + Given a CFT name, return the GDDN variable it uses. + + Args: + cft_str (str): E.g., "irrigated_temperate_corn" + + Returns: + str or None: Name of variable to use (e.g., "GDD8X"). If crop not yet handled, return None. + """ + + gddn = None + gddn_str = None + + gdd0_list_str = ["wheat", "cotton", "rice"] + if cft_str in _get_cft_list(gdd0_list_str): + gddn = 0 + + gdd8_list_str = ["corn", "sugarcane", "miscanthus", "switchgrass"] + if cft_str in _get_cft_list(gdd8_list_str): + gddn = 8 + + gdd10_list_str = ["soybean"] + if cft_str in _get_cft_list(gdd10_list_str): + gddn = 10 + + if gddn is not None: + gddn_str = variable.replace("B", str(gddn)) + + return gddn, gddn_str + + +def _get_output_varname(cft_str): + cft_int = utils.vegtype_str2int(cft_str)[0] + return f"gdd20bl_{cft_int}" + + +def _add_time_axis(da_in): + """ + Adds a size-1 time axis to a DataArray. Needed because CDEPS streams code requires a time axis, + even if the data in question is not supposed to vary over time. + + Args: + da_in (DataArray): xarray DataArray which needs a time axis added + + Returns: + DataArray: da_in with a new 1-step time axis + """ + this_date = np.array(cftime.DatetimeNoLeap(STREAM_YEAR, 1, 1, 0, 0, 0, 0, has_year_zero=True)) + this_date = np.expand_dims(this_date, axis=0) + da_time = xr.DataArray( + data=this_date, + dims={"time": this_date}, + ) + da_out = da_in.expand_dims(time=da_time) + return da_out + + +def setup_output_dataset(input_files, author, variable, year_args, ds_in): + """ + Set up output Dataset + """ + data_var_dict = {} + for gridding_var in GRIDDING_VAR_LIST: + data_var_dict[gridding_var] = ds_in[gridding_var] + ds_out = xr.Dataset( + data_vars=data_var_dict, + attrs={ + "author": author, + "created": dt.datetime.now().astimezone().isoformat(), + "input_year_range": f"{year_args[0]}-{year_args[1]}", + "input_variable": variable, + }, + ) + all_files_in_same_dir = len(np.unique([os.path.dirname(file) for file in input_files])) == 1 + if all_files_in_same_dir: + ds_out.attrs["input_files_dir"] = os.path.dirname(input_files[0]) + ds_out.attrs["input_files"] = ", ".join([os.path.basename(file) for file in input_files]) + else: + ds_out.attrs["input_files"] = ", ".join(input_files) + return ds_out + + +def generate_gdd20_baseline(input_files, output_file, author, time_slice, variable, year_args): + """ + Generate stream_fldFileName_gdd20_baseline file from CTSM outputs + """ + + # Define variables to process + if variable == "GDDBX": + suffix = "X" + elif variable == "GDDB20": + suffix = "20" + else: + raise ValueError(f"-v/--variable {variable} not recoginzed") + var_list_in = [] + for base_temp in [0, 8, 10]: + var_list_in.append(f"GDD{base_temp}{suffix}") + + # Get unique values and sort + input_files = list(set(input_files)) + input_files.sort() + + # Import history files and ensure they have lat/lon dims + ds_in = import_ds(input_files, var_list_in + GRIDDING_VAR_LIST, time_slice=time_slice) + if not all(x in ds_in.dims for x in ["lat", "lon"]): + raise RuntimeError("Input files must have lat and lon dimensions") + + # If needed, find mean over time + if "time" in ds_in.dims: + ds_in = ds_in.mean(dim="time", skipna=True) + + # Set up a dummy DataArray to use for crops without an assigned GDDN variable + dummy_da = xr.DataArray( + data=np.full_like(ds_in[var_list_in[0]].values, MISSING_RX_GDD_VAL), + dims=ds_in[var_list_in[0]].dims, + coords=ds_in[var_list_in[0]].coords, + ) + dummy_da = _add_time_axis(dummy_da) + + # Set up output Dataset + ds_out = setup_output_dataset(input_files, author, variable, year_args, ds_in) + + # Process all crops + encoding_dict = {} + for cft_str in MGDCROP_LIST: + cft_int = utils.vegtype_str2int(cft_str)[0] + print(f"{cft_str} ({cft_int})") + + # Which GDDN history variable does this crop use? E.g., GDD0, GDD10 + gddn, gddn_str = _get_gddn_for_cft(cft_str, variable) + + # Fill any missing values with MISSING_RX_GDD_VAL. This will mean that gddmaturity there + # never changes. + if gddn_str is None: + # Crop not handled yet? It's already filled with missing value + this_da = dummy_da + print(" dummy GDD20") + else: + this_da = ds_in[gddn_str] # Already did ds_in.mean(dim="time") above + this_da = _add_time_axis(this_da) + print(f" {gddn_str}") + this_da = this_da.fillna(MISSING_RX_GDD_VAL) + + # Add attributes of output file + if (gddn is None) != (gddn_str is None): + raise RuntimeError("gddn and gddn_str must either both be None or both be not None") + if gddn_str is None: + long_name = "Dummy GDD20" + else: + long_name = f"GDD{gddn}20" + this_da.attrs["long_name"] = long_name + f" baseline for {cft_str}" + this_da.attrs["units"] = "°C days" + + # Copy that to ds_out + var_out = _get_output_varname(cft_str) + print(f" Output variable {var_out}") + ds_out[var_out] = this_da + encoding_dict[var_out] = {"dtype": "float64"} + + # Grid, if needed + if any(x not in this_da.dims for x in ["lat", "lon"]): + ds_out[var_out] = grid_one_variable(ds_out, var_out) + + # Save + ds_out.to_netcdf(output_file, format="NETCDF3_CLASSIC", encoding=encoding_dict) + + print("Done!") + + +def main(): + """ + main() function for calling generate_gdd20_baseline.py from command line. + """ + args, time_slice = _parse_args() + generate_gdd20_baseline( + args.input_files, + args.output_file, + args.author, + time_slice, + args.variable, + [args.first_year, args.last_year], + ) diff --git a/python/ctsm/crop_calendars/generate_gdds.py b/python/ctsm/crop_calendars/generate_gdds.py index 156ebfb20e..49226e6f75 100644 --- a/python/ctsm/crop_calendars/generate_gdds.py +++ b/python/ctsm/crop_calendars/generate_gdds.py @@ -178,6 +178,7 @@ def main( mxmats, cc.get_gs_len_da, skip_crops, + outdir_figs, logger, ) diff --git a/python/ctsm/crop_calendars/generate_gdds_functions.py b/python/ctsm/crop_calendars/generate_gdds_functions.py index 8af2fdc049..81c71e2a51 100644 --- a/python/ctsm/crop_calendars/generate_gdds_functions.py +++ b/python/ctsm/crop_calendars/generate_gdds_functions.py @@ -1,7 +1,7 @@ """ Functions to support generate_gdds.py """ -# pylint: disable=too-many-lines,too-many-statements +# pylint: disable=too-many-lines,too-many-statements,abstract-class-instantiated import warnings import os import glob @@ -22,6 +22,7 @@ # pylint: disable=import-error from ctsm.crop_calendars.cropcal_figs_module import * from matplotlib.transforms import Bbox + import matplotlib.pyplot as plt warnings.filterwarnings( "ignore", @@ -63,7 +64,7 @@ def error(logger, string): raise RuntimeError(string) -def check_sdates(dates_ds, sdates_rx, logger, verbose=False): +def check_sdates(dates_ds, sdates_rx, outdir_figs, logger, verbose=False): """ Checking that input and output sdates match """ @@ -106,8 +107,28 @@ def check_sdates(dates_ds, sdates_rx, logger, verbose=False): log(logger, out_map_notnan[here][0:4]) log(logger, "diff:") log(logger, diff_map_notnan[here][0:4]) + first_diff = all_ok all_ok = False + if CAN_PLOT: + sdate_diffs_dir = os.path.join(outdir_figs, "sdate_diffs") + if first_diff: + log(logger, f"Saving sdate difference figures to {sdate_diffs_dir}") + if not os.path.exists(sdate_diffs_dir): + os.makedirs(sdate_diffs_dir) + in_map.where(~np.isnan(out_map)).plot() + plt.title(f"{vegtype_str} sdates in (masked)") + plt.savefig(os.path.join(sdate_diffs_dir, f"{vegtype_str}.in.png")) + plt.close() + out_map.plot() + plt.title(f"{vegtype_str} sdates out") + plt.savefig(os.path.join(sdate_diffs_dir, f"{vegtype_str}.out.png")) + plt.close() + diff_map.plot() + plt.title(f"{vegtype_str} sdates diff (out - in)") + plt.savefig(os.path.join(sdate_diffs_dir, f"{vegtype_str}.diff.png")) + plt.close() + if not any_found: error(logger, "No matching variables found in sdates_rx!") @@ -234,6 +255,7 @@ def import_and_process_1yr( mxmats, get_gs_len_da, skip_crops, + outdir_figs, logger, ): """ @@ -260,9 +282,9 @@ def import_and_process_1yr( # Get list of crops to include if skip_crops is not None: - crops_to_read = [c for c in utils.define_mgdcrop_list() if c not in skip_crops] + crops_to_read = [c for c in utils.define_mgdcrop_list_withgrasses() if c not in skip_crops] else: - crops_to_read = utils.define_mgdcrop_list() + crops_to_read = utils.define_mgdcrop_list_withgrasses() print(h1_filelist) dates_ds = import_ds( @@ -272,6 +294,8 @@ def import_and_process_1yr( time_slice=slice(f"{this_year}-01-01", f"{this_year}-12-31"), chunks=chunks, ) + for timestep in dates_ds["time"].values: + print(timestep) if dates_ds.dims["time"] > 1: if dates_ds.dims["time"] == 365: @@ -466,7 +490,7 @@ def import_and_process_1yr( # Import expected sowing dates. This will also be used as our template output file. imported_sdates = isinstance(sdates_rx, str) sdates_rx = import_rx_dates("s", sdates_rx, incl_patches1d_itype_veg, mxsowings, logger) - check_sdates(dates_incl_ds, sdates_rx, logger) + check_sdates(dates_incl_ds, sdates_rx, outdir_figs, logger) # Import hdates, if needed imported_hdates = isinstance(hdates_rx, str) @@ -575,6 +599,7 @@ def import_and_process_1yr( this_crop_gddaccum_da = this_crop_ds[clm_gdd_var] if save_figs: this_crop_gddharv_da = this_crop_ds["GDDHARV"] + check_gddharv = True if not this_crop_gddaccum_da.size: continue log(logger, f" {vegtype_str}...") @@ -625,11 +650,15 @@ def import_and_process_1yr( + "NaN after extracting GDDs accumulated at harvest", ) if save_figs and np.any(np.isnan(gddharv_atharv_p)): - log( - logger, - f" ❗ {np.sum(np.isnan(gddharv_atharv_p))}/{len(gddharv_atharv_p)} " - + "NaN after extracting GDDHARV", - ) + if np.all(np.isnan(gddharv_atharv_p)): + log(logger, " ❗ All GDDHARV are NaN; should only affect figure") + check_gddharv = False + else: + log( + logger, + f" ❗ {np.sum(np.isnan(gddharv_atharv_p))}/{len(gddharv_atharv_p)} " + + "NaN after extracting GDDHARV", + ) # Assign these to growing seasons based on whether gs crossed new year this_year_active_patch_indices = [ @@ -712,9 +741,15 @@ def import_and_process_1yr( ) else: error(logger, "Unexpected NaN for last season's GDD accumulation.") - if save_figs and np.any( - np.isnan( - gddharv_yp_list[var][year_index - 1, active_this_year_where_gs_lastyr_indices] + if ( + save_figs + and check_gddharv + and np.any( + np.isnan( + gddharv_yp_list[var][ + year_index - 1, active_this_year_where_gs_lastyr_indices + ] + ) ) ): if incorrectly_daily: @@ -1160,9 +1195,13 @@ def make_figures( else: error(logger, f"layout {layout} not recognized") - this_min = int(np.round(np.nanmin(gddharv_map_yx))) - this_max = int(np.round(np.nanmax(gddharv_map_yx))) - this_title = f"{run1_name} (range {this_min}–{this_max})" + gddharv_all_nan = np.all(np.isnan(gddharv_map_yx.values)) + if gddharv_all_nan: + this_title = f"{run1_name} (GDDHARV all NaN?)" + else: + this_min = int(np.round(np.nanmin(gddharv_map_yx))) + this_max = int(np.round(np.nanmax(gddharv_map_yx))) + this_title = f"{run1_name} (range {this_min}–{this_max})" make_gengdd_map( this_axis, gddharv_map_yx, @@ -1195,7 +1234,7 @@ def make_figures( ) # Difference - if layout == "3x2": + if not gddharv_all_nan and layout == "3x2": this_axis = fig.add_subplot(spec[2, 0], projection=ccrs.PlateCarree()) this_min = int(np.round(np.nanmin(gdd_map_yx))) this_max = int(np.round(np.nanmax(gdd_map_yx))) diff --git a/python/ctsm/crop_calendars/import_ds.py b/python/ctsm/crop_calendars/import_ds.py index 77a22b626b..486757492f 100644 --- a/python/ctsm/crop_calendars/import_ds.py +++ b/python/ctsm/crop_calendars/import_ds.py @@ -41,6 +41,28 @@ def compute_derived_vars(ds_in, var): return ds_in +def manual_mfdataset(filelist, my_vars, my_vegtypes, time_slice): + """ + Opening a list of files with Xarray's open_mfdataset requires dask. This function is a + workaround for Python environments that don't have dask. + """ + ds_out = None + for filename in filelist: + ds_in = xr.open_dataset(filename) + ds_in = mfdataset_preproc(ds_in, my_vars, my_vegtypes, time_slice) + if ds_out is None: + ds_out = ds_in + else: + ds_out = xr.concat( + [ds_out, ds_in], + data_vars="minimal", + compat="override", + coords="all", + dim="time", + ) + return ds_out + + def mfdataset_preproc(ds_in, vars_to_import, vegtypes_to_import, time_slice): """ Function to drop unwanted variables in preprocessing of open_mfdataset(). @@ -221,22 +243,20 @@ def import_ds( if isinstance(filelist, list): with warnings.catch_warnings(): warnings.filterwarnings(action="ignore", category=DeprecationWarning) - if find_spec("dask") is None: - raise ModuleNotFoundError( - "You have asked xarray to import a list of files as a single Dataset using" - " open_mfdataset(), but this requires dask, which is not available.\nFile" - f" list: {filelist}" - ) - this_ds = xr.open_mfdataset( - sorted(filelist), - data_vars="minimal", - preprocess=mfdataset_preproc_closure, - compat="override", - coords="all", - concat_dim="time", - combine="nested", - chunks=chunks, - ) + dask_unavailable = find_spec("dask") is None + if dask_unavailable: + this_ds = manual_mfdataset(filelist, my_vars, my_vegtypes, time_slice) + else: + this_ds = xr.open_mfdataset( + sorted(filelist), + data_vars="minimal", + preprocess=mfdataset_preproc_closure, + compat="override", + coords="all", + concat_dim="time", + combine="nested", + chunks=chunks, + ) elif isinstance(filelist, str): this_ds = xr.open_dataset(filelist, chunks=chunks) this_ds = mfdataset_preproc(this_ds, my_vars, my_vegtypes, time_slice) diff --git a/python/ctsm/crop_calendars/interpolate_gdds.py b/python/ctsm/crop_calendars/interpolate_gdds.py new file mode 100755 index 0000000000..123d40af38 --- /dev/null +++ b/python/ctsm/crop_calendars/interpolate_gdds.py @@ -0,0 +1,167 @@ +""" +Interpolate a maturity requirement (GDD) file +""" + +import os +import sys +import argparse +import logging +import re +import xarray as xr + +# -- 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) +sys.path.insert(1, _CTSM_PYTHON) + +from ctsm import ctsm_logging # pylint: disable=wrong-import-position +from ctsm.crop_calendars.cropcal_module import ( # pylint: disable=wrong-import-position + unexpected_negative_rx_gdd, +) + +logger = logging.getLogger(__name__) + +OUTPUT_FORMAT = "NETCDF3_CLASSIC" + + +def _file_missing(filepath, descriptor): + if not os.path.exists(filepath) and not os.path.exists(os.path.realpath(filepath)): + raise FileNotFoundError(f"{descriptor} not found: {filepath}") + return os.path.realpath(filepath) + + +def _setup_process_args(): + """Process input arguments + + Returns: + argparse.ArgumentParser: Arguments/options + """ + + # set up logging allowing user control + ctsm_logging.setup_logging_pre_config() + + parser = argparse.ArgumentParser( + description=("Interpolate a maturity requirement (GDD) file."), + ) + + # Define arguments + parser.add_argument( + "-i", + "--input-file", + help="Maturity requirement file to interpolate", + type=lambda x: _file_missing(x, "Input file"), + required=True, + ) + parser.add_argument( + "-t", + "--target-file", + help="File to whose coordinates the interpolation should take place", + type=lambda x: _file_missing(x, "Target file"), + required=True, + ) + parser.add_argument( + "-o", + "--output-file", + help="Where to save interpolated result", + type=str, + required=True, + ) + parser.add_argument( + "-p", + "--variable-prefix", + help="Interpolate variables whose names start with this string", + type=str, + required=False, + default="gdd1_", + ) + parser.add_argument( + "--overwrite", + help="If output file exists, overwrite it.", + action="store_true", + required=False, + ) + parser.add_argument( + "--dry-run", + help="Check arguments but do not run.", + action="store_true", + required=False, + ) + ctsm_logging.add_logging_args(parser) + + # Get arguments + args = parser.parse_args(sys.argv[1:]) + ctsm_logging.process_logging_args(args) + + # Process arguments + if os.path.exists(os.path.realpath(args.output_file)) and not args.overwrite: + raise FileExistsError(f"Output file exists but --overwrite not given: {args.output_file}") + args.output_file = os.path.realpath(args.output_file) + + # Make directory for output file, if needed + if not args.dry_run: + parent_dir = os.path.dirname(args.output_file) + if not os.path.exists(parent_dir): + os.makedirs(parent_dir) + + return args + + +def interpolate_gdds(args): + """ + Do the interpolation and save + """ + + # Open inputs + ds_in = xr.open_dataset(args.input_file) + ds_target = xr.open_dataset(args.target_file) + + # Interpolate + ds_out = xr.Dataset() + for var in ds_in: + + # Check variable + if "lat" not in ds_in[var].dims and "lon" not in ds_in[var].dims: + print(f"Skipping variable {var} with dimensions {ds_in[var].dims}") + continue + if not re.compile("^" + args.variable_prefix).match(var): + print(f"Unexpected variable {var} on input file. Skipping.") + continue + if args.dry_run: + continue + + # Interpolate + da_out = ds_in[var].interp_like( + ds_target, + method="nearest", + kwargs={"fill_value": "extrapolate"}, # Otherwise you get NaNs at edges + ) + + if unexpected_negative_rx_gdd(da_out): + raise RuntimeError("Unexpected negative value") + + # Add to dataset + ds_out[var] = da_out + + # Finish up + ds_out.attrs["original"] = args.input_file + ds_out.attrs["interpolation_target"] = args.target_file + ds_out.attrs["interpolation_script"] = os.path.basename(__file__) + if not args.dry_run: + ds_out.to_netcdf(args.output_file, format=OUTPUT_FORMAT) + else: + print("Dry run looks good!") + + +def main(): + """ + Description + ----------- + Calls function that interpolates a maturity requirement (GDD) file. + """ + + args = _setup_process_args() + + interpolate_gdds(args) + + +if __name__ == "__main__": + main() diff --git a/python/ctsm/lilac_make_runtime_inputs.py b/python/ctsm/lilac_make_runtime_inputs.py index 71f3c9bbe4..e751f6c931 100644 --- a/python/ctsm/lilac_make_runtime_inputs.py +++ b/python/ctsm/lilac_make_runtime_inputs.py @@ -47,6 +47,12 @@ TRUE,FALSE + + + logical + TRUE,FALSE + + """ @@ -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 a17f063a4b..16742da47e 100644 --- a/python/ctsm/machine_defaults.py +++ b/python/ctsm/machine_defaults.py @@ -77,13 +77,13 @@ create_test_queue=CREATE_TEST_QUEUE_UNSPECIFIED, job_launcher_defaults={ JOB_LAUNCHER_QSUB: QsubDefaults( - queue="main", + 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=128:mpiprocs=1 -V -r n -k oed", + required_args="-l select=1:ncpus=16:mpiprocs=1 -V -r n -k oed", ) }, ), diff --git a/python/ctsm/mesh_plotter.py b/python/ctsm/mesh_plotter.py index 7bcbae6fb4..0a2af11856 100644 --- a/python/ctsm/mesh_plotter.py +++ b/python/ctsm/mesh_plotter.py @@ -62,12 +62,26 @@ def get_parser(): parser.add_argument( "--overwrite", - help="If plots xists, overwrite them.", + 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 @@ -98,9 +112,10 @@ def process_and_check_args(args): 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(args.input)[0] + "_c" + today_string, + os.path.splitext(input_filename)[0] + "_c" + today_string, ) if not os.path.isfile(args.input): @@ -148,10 +163,15 @@ def main(): 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) + this_mesh.make_mesh_plot(plot_regional, plot_global, args) if __name__ == "__main__": diff --git a/python/ctsm/modify_input_files/fsurdat_modifier.py b/python/ctsm/modify_input_files/fsurdat_modifier.py index bd060cb9dc..1a45590872 100644 --- a/python/ctsm/modify_input_files/fsurdat_modifier.py +++ b/python/ctsm/modify_input_files/fsurdat_modifier.py @@ -254,8 +254,8 @@ def modify_optional( """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 domain file for - # MCT or the ocean mesh files for NUOPC. Here the user may specify + # 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: diff --git a/python/ctsm/run_sys_tests.py b/python/ctsm/run_sys_tests.py index de93081504..7d3ffe8444 100644 --- a/python/ctsm/run_sys_tests.py +++ b/python/ctsm/run_sys_tests.py @@ -8,6 +8,7 @@ from datetime import datetime from CIME.test_utils import get_tests_from_xml # pylint: disable=import-error +from CIME.test_utils import test_to_string # pylint: disable=import-error from CIME.cs_status_creator import create_cs_status # pylint: disable=import-error from ctsm.ctsm_logging import ( @@ -124,7 +125,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 @@ -476,11 +477,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( @@ -576,12 +577,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) @@ -736,13 +737,29 @@ def _check_py_env(test_attributes): # whether import is possible. # pylint: disable=import-error disable - # Check requirements for FSURDATMODIFYCTSM, if needed - if any("FSURDATMODIFYCTSM" in t for t in test_attributes): + # 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) @@ -764,6 +781,11 @@ def _get_compilers_for_suite(suite_name, machine_name, running_ctsm_py_tests): raise RuntimeError( "No tests found for suite {} on machine {}".format(suite_name, machine_name) ) + if logger.getEffectiveLevel() <= logging.INFO: + logger.info("Tests:") + for test in test_data: + test_string = test_to_string(test).split(" ")[1] + logger.info(" %s", test_string) 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()]) diff --git a/python/ctsm/site_and_regional/mesh_plot_type.py b/python/ctsm/site_and_regional/mesh_plot_type.py index 872c0e8101..08fd1c061c 100644 --- a/python/ctsm/site_and_regional/mesh_plot_type.py +++ b/python/ctsm/site_and_regional/mesh_plot_type.py @@ -24,7 +24,7 @@ class MeshPlotType(MeshType): Extend mesh type with some advanced plotting capability """ - def make_mesh_plot(self, plot_regional, plot_global): + def make_mesh_plot(self, plot_regional, plot_global, args): """ Create plots for the ESMF mesh file @@ -36,10 +36,10 @@ def make_mesh_plot(self, plot_regional, plot_global): The path to write the ESMF meshfile global plot """ - self.mesh_plot(plot_regional, regional=True) - self.mesh_plot(plot_global, regional=False) + self.mesh_plot(plot_regional, args, regional=True) + self.mesh_plot(plot_global, args, regional=False) - def mesh_plot(self, plot_file, regional): + 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: @@ -49,7 +49,7 @@ def mesh_plot(self, plot_file, regional): plot_type = "regional" line_width = 1 marker = "x" - marker_size = 1 + marker_size = 50 # global settings else: fig = plt.figure(num=None, figsize=(15, 10), facecolor="w", edgecolor="k") @@ -58,7 +58,9 @@ def mesh_plot(self, plot_file, regional): plot_type = "global" line_width = 0.5 marker = "o" - marker_size = None + 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") @@ -129,8 +131,9 @@ def mesh_plot(self, plot_file, regional): *[(k, mpatches.Rectangle((0, 0), 1, 1, facecolor=v)) for k, v in lc_colors.items()] ) - ax.legend(handles, labels) + if not args.no_center_coords: + ax.legend(handles, labels) - plt.savefig(plot_file, bbox_inches="tight") + 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 index be785e745d..47c0295593 100644 --- a/python/ctsm/site_and_regional/mesh_type.py +++ b/python/ctsm/site_and_regional/mesh_type.py @@ -235,8 +235,16 @@ def create_2d_coords(self): lons_size = self.center_lons.size # -- convert center points from 1d to 2d - 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)) + 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 @@ -351,7 +359,7 @@ def calculate_corners(self, unit="degrees"): ) # Longitudes should stay within 0 to 360 if np.any(self.corner_lons > 360.0): - abort("Corners have longitudes greater than 360") + 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", diff --git a/python/ctsm/site_and_regional/plumber2_usermods.py b/python/ctsm/site_and_regional/plumber2_usermods.py index 2fe183fb77..d98899771b 100644 --- a/python/ctsm/site_and_regional/plumber2_usermods.py +++ b/python/ctsm/site_and_regional/plumber2_usermods.py @@ -56,24 +56,10 @@ def write_usermods( "./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" # TODO, get working for CTSM5.1: - # remove the above line as it's redundant after PLUMBER2SITE is added - # Alternatively, we can take this out of default/user_nl_clm - # since doing it this way is works fine TODO for 5.2 - "echo \"fsurdat='/glade/u/home/wwieder/CTSM/tools/site_and_regional/subset_data_single_point/surfdata_1x1_PLUMBER2_" - + site - + "_hist_16pfts_Irrig_CMIP6_simyr2000_c231005.nc ' \" >> user_nl_clm \n" - 'echo "CLM_USRDAT.PLUMBER2:datafiles= \$DIN_LOC_ROOT/atm/datm7/CLM1PT_data/PLUMBER2/' - + site - + "/CLM1PT_data/CTSM_DATM_" - + site - + "_" - + str(start_year) - + "-" - + str(end_year) - + '.nc " >> user_nl_datm_streams \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' diff --git a/python/ctsm/site_and_regional/run_neon.py b/python/ctsm/site_and_regional/run_neon.py index 4b0df2722d..3acbf435b1 100755 --- a/python/ctsm/site_and_regional/run_neon.py +++ b/python/ctsm/site_and_regional/run_neon.py @@ -41,7 +41,7 @@ # - [ ] 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. -# - [ ] checkout_externals instead of using env varaiable +# - [ ] "./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 diff --git a/python/ctsm/site_and_regional/single_point_case.py b/python/ctsm/site_and_regional/single_point_case.py index 86dabe609d..2c2aebad52 100644 --- a/python/ctsm/site_and_regional/single_point_case.py +++ b/python/ctsm/site_and_regional/single_point_case.py @@ -14,7 +14,7 @@ # -- 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__) @@ -415,7 +415,10 @@ 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, self.cth, self.cbh) + 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 diff --git a/python/ctsm/subset_data.py b/python/ctsm/subset_data.py index bc9ce97962..d38aee1308 100644 --- a/python/ctsm/subset_data.py +++ b/python/ctsm/subset_data.py @@ -597,10 +597,6 @@ def setup_files(args, defaults, cesmroot): clmforcingindir, os.path.join(defaults.get("surfdat", "dir")), ), - "mesh_dir": os.path.join( - clmforcingindir, - os.path.join(defaults.get("surfdat", "mesh_dir")), - ), "fluse_dir": os.path.join( clmforcingindir, os.path.join(defaults.get("landuse", "dir")), @@ -608,7 +604,6 @@ def setup_files(args, defaults, cesmroot): "fsurf_in": fsurf_in, "fsurf_out": fsurf_out, "fluse_in": fluse_in, - "mesh_surf": defaults.get("surfdat", "mesh_surf"), "datm_tuple": DatmFiles( dir_input_datm, dir_output_datm, @@ -736,9 +731,6 @@ def subset_region(args, file_dict: dict): specify_fsurf_out=file_dict["fsurf_out"], ) - # if region.create_mesh: - # region.create_mesh_at_reg (file_dict["mesh_dir"], file_dict["mesh_surf"]) - # -- Create CTSM transient landuse data file if region.create_landuse: region.create_landuse_at_reg( diff --git a/python/ctsm/test/test_advanced_sys_mesh_plotter.py b/python/ctsm/test/test_advanced_sys_mesh_plotter.py index 090f7806bf..4a7c63ecf6 100755 --- a/python/ctsm/test/test_advanced_sys_mesh_plotter.py +++ b/python/ctsm/test/test_advanced_sys_mesh_plotter.py @@ -26,14 +26,27 @@ class SysTestMeshMaker(unittest.TestCase): def setUp(self): """Setup for all tests""" - testinputs_path = os.path.join(path_to_ctsm_root(), "python/ctsm/test/testinputs") + 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 = self._tempdir + "/mesh_out" + 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): """ @@ -43,15 +56,44 @@ def tearDown(self): 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, - "--output", - self.mesh_out, + "--outdir", + outdir, ] main() - plotfiles = glob.glob(self._tempdir + "/*.png") + plotfiles = glob.glob(os.path.join(outdir, "*.png")) if not plotfiles: self.fail("plot files were NOT created as they should have") diff --git a/python/ctsm/test/test_sys_gen_mksurfdata_namelist.py b/python/ctsm/test/test_sys_gen_mksurfdata_namelist.py index 29745e9d80..c9741daf5c 100755 --- a/python/ctsm/test/test_sys_gen_mksurfdata_namelist.py +++ b/python/ctsm/test/test_sys_gen_mksurfdata_namelist.py @@ -62,7 +62,7 @@ def test_simple_namelist(self): main() self.assertTrue(os.path.exists(self.outfile), "Output surface dataset file should exist") - def test_vic_nocrop_inlandwet_glc_namelist(self): + def test_nocrop_inlandwet_glc_namelist(self): """ Test a namelist with several options on """ @@ -75,7 +75,6 @@ def test_vic_nocrop_inlandwet_glc_namelist(self): "1850", "--res", "1.9x2.5", - "--vic", "--nocrop", "--inlandwet", "--glc", @@ -99,7 +98,6 @@ def test_hires_namelist(self): "mpasa15", "--glc-nec", "10", - "--hires_pft", "--hires_soitex", ] ) diff --git a/python/ctsm/test/test_unit_gen_mksurfdata_jobscript_single.py b/python/ctsm/test/test_unit_gen_mksurfdata_jobscript_single.py index 5038c6b3e1..8b8e2df32a 100755 --- a/python/ctsm/test/test_unit_gen_mksurfdata_jobscript_single.py +++ b/python/ctsm/test/test_unit_gen_mksurfdata_jobscript_single.py @@ -136,7 +136,7 @@ def test_simple_derecho_args(self): def test_derecho_mpirun(self): """ test derecho mpirun. This would've helped caught a problem we ran into - It will also be helpful when externals are updated to guide to solutions + It will also be helpful when sumodules are updated to guide to solutions to problems """ machine = "derecho" diff --git a/python/ctsm/test/test_unit_singlept_data_surfdata.py b/python/ctsm/test/test_unit_singlept_data_surfdata.py index a29fa05b33..2106799a4b 100755 --- a/python/ctsm/test/test_unit_singlept_data_surfdata.py +++ b/python/ctsm/test/test_unit_singlept_data_surfdata.py @@ -47,8 +47,8 @@ class TestSinglePointCaseSurfaceNoCrop(unittest.TestCase): 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] + cth = 0.9 + cbh = 0.1 include_nonveg = False uni_snow = True cap_saturation = True @@ -668,8 +668,8 @@ class TestSinglePointCaseSurfaceCrop(unittest.TestCase): evenly_split_cropland = False pct_pft = None num_pft = 78 - 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] + cth = 0.9 + cbh = 0.1 include_nonveg = False uni_snow = False cap_saturation = False diff --git a/python/ctsm/test/test_unit_subset_data.py b/python/ctsm/test/test_unit_subset_data.py index 143b632e8c..a918fb35f0 100755 --- a/python/ctsm/test/test_unit_subset_data.py +++ b/python/ctsm/test/test_unit_subset_data.py @@ -48,7 +48,7 @@ def test_inputdata_setup_files_basic(self): files = setup_files(self.args, self.defaults, self.cesmroot) self.assertEqual( files["fsurf_in"], - "surfdata_0.9x1.25_hist_2000_16pfts_c240216.nc", + "surfdata_0.9x1.25_hist_2000_16pfts_c240908.nc", "fsurf_in filename not whats expected", ) self.assertEqual( diff --git a/python/ctsm/test/test_unit_utils.py b/python/ctsm/test/test_unit_utils.py index 85ba2515dd..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 @@ -328,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/testinputs/default_data.cfg b/python/ctsm/test/testinputs/default_data.cfg index d736f2e933..24aa811fee 100644 --- a/python/ctsm/test/testinputs/default_data.cfg +++ b/python/ctsm/test/testinputs/default_data.cfg @@ -15,16 +15,16 @@ precname = CLMGSWP3v1.Precip tpqwname = CLMGSWP3v1.TPQW [surfdat] -dir = lnd/clm2/surfdata_esmf/ctsm5.2.0 -surfdat_16pft = surfdata_0.9x1.25_hist_2000_16pfts_c240216.nc -surfdat_78pft = surfdata_0.9x1.25_hist_2000_78pfts_c240216.nc +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.2.0 -landuse_16pft = landuse.timeseries_0.9x1.25_SSP2-4.5_1850-2100_78pfts_c240216.nc -landuse_78pft = landuse.timeseries_0.9x1.25_SSP2-4.5_1850-2100_78pfts_c240216.nc +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/toolchain/gen_mksurfdata_jobscript_multi.py b/python/ctsm/toolchain/gen_mksurfdata_jobscript_multi.py index 6deb50ebfb..5de67adb12 100755 --- a/python/ctsm/toolchain/gen_mksurfdata_jobscript_multi.py +++ b/python/ctsm/toolchain/gen_mksurfdata_jobscript_multi.py @@ -42,12 +42,14 @@ "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", @@ -197,6 +199,7 @@ def main(): "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"], @@ -204,10 +207,17 @@ def main(): "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", ], } @@ -237,11 +247,11 @@ def main(): "5x5_amazon", ), "crop-global-present": ( - "--start-year 2000 --end-year 2000 --vic --res", + "--start-year 2000 --end-year 2000 --res", "standard_res", ), "crop-global-present-low-res": ( - "--start-year 2000 --end-year 2000 --vic --res", + "--start-year 2000 --end-year 2000 --res", "low_res", ), "crop-global-present-ne16": ( @@ -261,7 +271,6 @@ def main(): "mpasa480", ), "crop-global-present-nldas": ( - # TODO slevis: --hirespft uses old data for now, so keep out "--start-year 2000 --end-year 2000 --res", "nldas_res", ), @@ -290,21 +299,25 @@ def main(): "mpasa480", ), "crop-global-hist": ( - "--start-year 1850 --end-year 2015 --nosurfdata --res", - "standard_res", + "--start-year 1850 --end-year 2023 --nosurfdata --res", + "standard_res_no_f09", ), "crop-global-hist-low-res": ( - "--start-year 1850 --end-year 2015 --nosurfdata --res", + "--start-year 1850 --end-year 2023 --nosurfdata --res", "low_res", ), "crop-global-hist-ne16": ( - "--start-year 1850 --end-year 2015 --nosurfdata --res", + "--start-year 1850 --end-year 2023 --nosurfdata --res", "ne16", ), "crop-global-hist-ne30": ( - "--start-year 1850 --end-year 2015 --nosurfdata --res", + "--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", @@ -333,6 +346,10 @@ def main(): "--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", diff --git a/python/ctsm/toolchain/gen_mksurfdata_namelist.py b/python/ctsm/toolchain/gen_mksurfdata_namelist.py index 8a953c39df..da9420871b 100755 --- a/python/ctsm/toolchain/gen_mksurfdata_namelist.py +++ b/python/ctsm/toolchain/gen_mksurfdata_namelist.py @@ -12,7 +12,7 @@ from datetime import datetime import netCDF4 -from ctsm.path_utils import path_to_ctsm_root +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__) @@ -166,16 +166,6 @@ def get_parser(): dest="input_path", default="/glade/campaign/cesm/cesmdata/inputdata/", ) - parser.add_argument( - "--vic", - help=""" - Flag for adding the fields required for the VIC model. - [default: %(default)s] - """, - action="store_true", - dest="vic_flag", - default=False, - ) parser.add_argument( "--inlandwet", help=""" @@ -196,19 +186,6 @@ def get_parser(): dest="glc_flag", default=False, ) - parser.add_argument( - "--hires_pft", - help=""" - If you want to use the high-resolution pft dataset rather - than the default lower resolution dataset. - (Low resolution is at quarter-degree, high resolution at 3-minute) - [Note: hires only available for 1850 and 2005.] - [default: %(default)s] - """, - action="store_true", - dest="hres_pft", - default=False, - ) parser.add_argument( "--hires_soitex", help=""" @@ -273,13 +250,12 @@ def main(): input_path = args.input_path nocrop_flag = args.crop_flag nosurfdata_flag = args.surfdata_flag - vic_flag = args.vic_flag inlandwet = args.inlandwet glc_flag = args.glc_flag potveg = args.potveg_flag glc_nec = args.glc_nec - hires_pft, hires_soitex = process_hires_options(args, start_year, end_year) + 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) @@ -310,7 +286,6 @@ def main(): # create attribute list for parsing xml file attribute_list = { - "hires_pft": hires_pft, "hires_soitex": hires_soitex, "pft_years": pft_years, "pft_years_ssp": pft_years_ssp, @@ -326,7 +301,7 @@ def main(): ) # determine output mesh - determine_output_mesh(res, force_model_mesh_file, input_path, rawdata_files, tool_path) + determine_output_mesh(res, force_model_mesh_file, input_path, rawdata_files) # Determine num_pft if nocrop_flag: @@ -400,7 +375,6 @@ def main(): force_model_mesh_file, force_model_mesh_nx, force_model_mesh_ny, - vic_flag, rawdata_files, landuse_fname, mksrf_ftopostats_override, @@ -413,7 +387,6 @@ def main(): # ------------------- write_nml_outdata( nosurfdata_flag, - vic_flag, inlandwet, glc_flag, hostname, @@ -436,43 +409,31 @@ def main(): print(f"Successfully created input namelist file {nlfname}") -def process_hires_options(args, start_year, end_year): +def process_hires_options(args): """ Process options related to hi-res """ - if args.hres_pft: - if (start_year == 1850 and end_year == 1850) or (start_year == 2005 and end_year == 2005): - hires_pft = "on" - else: - error_msg = ( - "ERROR: for --hires_pft you must set both start-year " - "and end-year to 1850 or to 2005" - ) - sys.exit(error_msg) - else: - hires_pft = "off" - if args.hres_soitex: hires_soitex = "on" else: hires_soitex = "off" - return hires_pft, hires_soitex + return hires_soitex def check_ssp_years(start_year, end_year): """ Check years associated with SSP period """ - if int(start_year) > 2015: + if int(start_year) > 2023: error_msg = ( - "ERROR: if start-year > 2015 must add an --ssp_rcp " + "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) > 2015: + elif int(end_year) > 2023: error_msg = ( - "ERROR: if end-year > 2015 must add an --ssp-rcp " + "ERROR: if end-year > 2023 must add an --ssp-rcp " "argument that is not none: valid opts for ssp-rcp " f"are {valid_opts}" ) @@ -537,6 +498,8 @@ def determine_pft_years(start_year, end_year, potveg): 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: @@ -545,21 +508,21 @@ def determine_pft_years(start_year, end_year, potveg): pft_years = "2005" elif int(start_year) >= 850 and int(end_year) <= 1849: pft_years = "0850-1849" - elif int(start_year) >= 1850 and int(start_year) <= 2100 and int(end_year) <= 2015: - pft_years = "1850-2015" - elif int(start_year) >= 1850 and int(start_year) <= 2100 and int(end_year) <= 2100: - pft_years = "1850-2015" - pft_years_ssp = "2016-2100" - elif int(start_year) >= 2016 and int(start_year) <= 2100 and int(end_year) <= 2100: + 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 = "2016-2100" + 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: " - "- 1850, 2000, 2005 for time-slice options " + "- 1700, 1850, 2000, 2005 for time-slice options " "- in the range from 850 to 1849 " - "- in the range from 1850 to 2100 " + "- in the range from 1700 to 2100 " "- TODO in the range from 2101 to 2300 " "- OR user must set the potveg_flag " ) @@ -571,7 +534,6 @@ def determine_pft_years(start_year, end_year, potveg): def write_nml_outdata( nosurfdata_flag, - vic_flag, inlandwet, glc_flag, hostname, @@ -602,7 +564,6 @@ def write_nml_outdata( 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(f" outnc_vic = .{str(vic_flag).lower()}. \n") nlfile.write(" outnc_large_files = .false. \n") nlfile.write(" outnc_double = .true. \n") nlfile.write(f" logname = '{logname}' \n") @@ -615,7 +576,6 @@ def write_nml_rawinput( force_model_mesh_file, force_model_mesh_nx, force_model_mesh_ny, - vic_flag, rawdata_files, landuse_fname, mksrf_ftopostats_override, @@ -641,11 +601,11 @@ def write_nml_rawinput( 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 "_fvic" not in key and "mksrf_fvegtyp" not in key and "mksrf_fgrid" not in key: + elif "mksrf_fvegtyp" not in key and "mksrf_fgrid" not in key: # write everything else nlfile.write(f" {key} = '{value}' \n") - if start_year <= 2015: + if start_year <= 2023: mksrf_fvegtyp = rawdata_files["mksrf_fvegtyp"] mksrf_fvegtyp_mesh = rawdata_files["mksrf_fvegtyp_mesh"] mksrf_fhrvtyp = rawdata_files["mksrf_fvegtyp"] @@ -690,12 +650,6 @@ def write_nml_rawinput( nlfile.write(f" mksrf_fpctlak = '{mksrf_fpctlak}' \n") nlfile.write(f" mksrf_furban = '{mksrf_furban}' \n") - if vic_flag: - mksrf_fvic = rawdata_files["mksrf_fvic"] - nlfile.write(f" mksrf_fvic = '{mksrf_fvic}' \n") - mksrf_fvic_mesh = rawdata_files["mksrf_fvic_mesh"] - nlfile.write(f" mksrf_fvic_mesh = '{mksrf_fvic_mesh}' \n") - nlfile.write(f" mksrf_fdynuse = '{landuse_fname} ' \n") return must_run_download_input_data @@ -714,7 +668,7 @@ def handle_transient_run( 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 <= 2015: + if year <= 2023: file1 = rawdata_files["mksrf_fvegtyp"] file2 = rawdata_files["mksrf_fvegtyp_urban"] file3 = rawdata_files["mksrf_fvegtyp_lake"] @@ -752,11 +706,11 @@ def handle_transient_run( return landuse_fname, must_run_download_input_data -def determine_output_mesh(res, force_model_mesh_file, input_path, rawdata_files, tool_path): +def determine_output_mesh(res, force_model_mesh_file, input_path, rawdata_files): """ determine output mesh """ - xml_path = os.path.join(tool_path, "../../ccs_config/component_grids_nuopc.xml") + xml_path = os.path.join(path_to_cime(), "../ccs_config/component_grids_nuopc.xml") tree2 = ET.parse(xml_path) root = tree2.getroot() model_mesh = "" @@ -832,16 +786,15 @@ def determine_input_rawdata(start_year, input_path, attribute_list): max_match_child = child2 if max_match_child is None: - # TODO slevis: Are these if-statements backwards? - # For years greater than 2015 - mksrf_fvegtyp_ssp must have a match - if start_year <= 2015: + # 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 2015 - mksrf_fvegtyp must have a match + # 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) diff --git a/python/ctsm/utils.py b/python/ctsm/utils.py index 8578ea860c..a5a02a5c9d 100644 --- a/python/ctsm/utils.py +++ b/python/ctsm/utils.py @@ -26,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. diff --git a/share b/share new file mode 160000 index 0000000000..4b9dc4871a --- /dev/null +++ b/share @@ -0,0 +1 @@ +Subproject commit 4b9dc4871a259f00f35bb47708d876cb7dcdf75c diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 568b53cd15..5b0f6c9b1b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -20,9 +20,11 @@ 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 the single file we need from CMEPS -set (drv_sources_needed - ${CLM_ROOT}/components/cmeps/cesm/nuopc_cap_share/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 + ) # Add CLM source directories add_subdirectory(${CLM_ROOT}/src/utils clm_utils) @@ -103,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 8d38ca4b87..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 diff --git a/src/biogeochem/CNBalanceCheckMod.F90 b/src/biogeochem/CNBalanceCheckMod.F90 index 8801efdf72..7b88422843 100644 --- a/src/biogeochem/CNBalanceCheckMod.F90 +++ b/src/biogeochem/CNBalanceCheckMod.F90 @@ -64,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 @@ -346,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 @@ -644,8 +643,8 @@ subroutine NBalanceCheck(this, bounds, num_soilc, filter_soilc, & ! 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 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/CNCStateUpdate1Mod.F90 b/src/biogeochem/CNCStateUpdate1Mod.F90 index 5e38de2676..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 @@ -147,6 +144,7 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & ! 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 @@ -188,7 +186,7 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & dt = get_step_size_real() ! Below is the input into the soil biogeochemistry model - + fc_loop: do fc = 1,num_soilc c = filter_soilc(fc) @@ -202,9 +200,7 @@ subroutine CStateUpdate1( num_soilc, filter_soilc, num_soilp, filter_soilp, & call clm_fates%UpdateCLitterfluxes(cf_soil,clump_index,c) else - do j = 1,nlevdecomp - ! ! State update without the matrix solution ! @@ -219,66 +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 + + 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 ! - else ! 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 if fates_if - - end do fc_loop - - ! 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 + ! + ! 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_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 + + cf_soil%decomp_cascade_ctransfer_vr_col(c,j,k) * dt + end if end do - end do - end if - end do + end if + end do + + end do fc_loop 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 @@ -337,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) @@ -397,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 @@ -431,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 @@ -443,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 @@ -465,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 @@ -477,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 @@ -545,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 @@ -578,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 @@ -603,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 @@ -631,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 @@ -650,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 @@ -675,7 +600,6 @@ 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 soilpatch_loop ! end of patch loop end associate diff --git a/src/biogeochem/CNCStateUpdate2Mod.F90 b/src/biogeochem/CNCStateUpdate2Mod.F90 index 6ecc4893e3..5fb7a283e9 100644 --- a/src/biogeochem/CNCStateUpdate2Mod.F90 +++ b/src/biogeochem/CNCStateUpdate2Mod.F90 @@ -97,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 @@ -237,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 @@ -327,7 +335,8 @@ end subroutine CStateUpdate2h !----------------------------------------------------------------------- subroutine CStateUpdate2g(num_soilc, filter_soilc, num_soilp, filter_soilp, & - cnveg_carbonflux_inst, cnveg_carbonstate_inst, soilbiogeochem_carbonstate_inst) + cnveg_carbonflux_inst, cnveg_carbonstate_inst, & + soilbiogeochem_carbonstate_inst, soilbiogeochem_carbonflux_inst) ! ! !DESCRIPTION: ! Update all the prognostic carbon state @@ -340,6 +349,7 @@ subroutine CStateUpdate2g(num_soilc, filter_soilc, num_soilp, filter_soilp, & 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: @@ -351,6 +361,7 @@ subroutine CStateUpdate2g(num_soilc, filter_soilc, num_soilp, filter_soilp, & associate( & cf_veg => cnveg_carbonflux_inst , & cs_veg => cnveg_carbonstate_inst , & + cf_soil => soilbiogeochem_carbonflux_inst, & cs_soil => soilbiogeochem_carbonstate_inst & ) @@ -362,15 +373,27 @@ subroutine CStateUpdate2g(num_soilc, filter_soilc, num_soilp, filter_soilp, & do fc = 1,num_soilc c = filter_soilc(fc) - ! 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 + 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 + ! 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 @@ -378,59 +401,69 @@ subroutine CStateUpdate2g(num_soilc, filter_soilc, num_soilp, filter_soilp, & do fp = 1,num_soilp p = filter_soilp(fp) - ! patch-level carbon fluxes from gross unrepresented landcover change mortality - ! 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 - ! xsmrpool - cs_veg%xsmrpool_patch(p) = cs_veg%xsmrpool_patch(p) & + cs_veg%xsmrpool_patch(p) = cs_veg%xsmrpool_patch(p) & - cf_veg%gru_xsmrpool_to_atm_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 - cs_veg%gresp_storage_patch(p) = cs_veg%gresp_storage_patch(p) & + ! 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 - - ! 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 - cs_veg%gresp_xfer_patch(p) = cs_veg%gresp_xfer_patch(p) & + ! 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 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/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 b23019eb23..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_fates_bgc, use_dynroot + 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_cn + 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 @@ -85,7 +85,7 @@ end subroutine CNDriverInit !----------------------------------------------------------------------- subroutine CNDriverNoLeaching(bounds, & - num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & + 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, & @@ -103,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: @@ -147,7 +147,6 @@ 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: @@ -564,20 +563,6 @@ subroutine CNDriverNoLeaching(bounds, call t_stopf('CNGResp') - !-------------------------------------------- - ! Dynamic Roots - !-------------------------------------------- - - if( use_dynroot ) then - call t_startf('CNRootDyn') - - call CNRootDyn(bounds, num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & - 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 @@ -609,12 +594,9 @@ subroutine CNDriverNoLeaching(bounds, 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') @@ -830,18 +812,22 @@ subroutine CNDriverNoLeaching(bounds, 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) + 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_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_cnveg_carbonflux_inst, c14_cnveg_carbonstate_inst, & + c14_soilbiogeochem_carbonstate_inst, c14_soilbiogeochem_carbonflux_inst) end if call NStateUpdate2g(num_bgc_soilc, filter_bgc_soilc, num_bgc_vegp, filter_bgc_vegp, & - cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst, soilbiogeochem_nitrogenstate_inst) + cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst, & + soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst) call t_stopf('CNUpdate2') @@ -936,7 +922,7 @@ subroutine CNDriverNoLeaching(bounds, 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, & + 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)) @@ -1040,9 +1026,11 @@ subroutine CNDriverLeaching(bounds, & use SoilBiogeochemNLeachingMod, only: SoilBiogeochemNLeaching use CNNStateUpdate3Mod , only: NStateUpdate3 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 + use SoilBiogeochemDecompCascadeConType, only: use_soil_matrixcn ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds @@ -1088,10 +1076,6 @@ subroutine CNDriverLeaching(bounds, & soilbiogeochem_nitrogenflux_inst, soilbiogeochem_nitrogenstate_inst) call t_stopf('SoilBiogeochemNLeaching') - - - - ! Nitrogen state variable update, mortality fluxes. if(num_bgc_vegp>0)then call t_startf('NUpdate3') @@ -1108,14 +1092,23 @@ 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 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/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 aa53317fb3..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,18 +89,21 @@ 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 @@ -141,12 +167,47 @@ subroutine CNGapMortality (bounds, num_soilp, filter_soilp, & 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 @@ -178,9 +239,11 @@ subroutine CNGapMortality (bounds, num_soilp, filter_soilp, & 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) @@ -195,9 +258,23 @@ subroutine CNGapMortality (bounds, num_soilp, filter_soilp, & 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 @@ -216,11 +293,23 @@ subroutine CNGapMortality (bounds, num_soilp, filter_soilp, & 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 !------------------------------------------------------ @@ -234,8 +323,10 @@ subroutine CNGapMortality (bounds, num_soilp, filter_soilp, & 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 @@ -243,16 +334,18 @@ subroutine CNGapMortality (bounds, num_soilp, filter_soilp, & 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 @@ -260,8 +353,7 @@ subroutine CNGapMortality (bounds, num_soilp, filter_soilp, & 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 @@ -282,10 +374,21 @@ subroutine CNGapMortality (bounds, num_soilp, filter_soilp, & 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 diff --git a/src/biogeochem/CNNStateUpdate1Mod.F90 b/src/biogeochem/CNNStateUpdate1Mod.F90 index 833a65cbc3..21b5d335b7 100644 --- a/src/biogeochem/CNNStateUpdate1Mod.F90 +++ b/src/biogeochem/CNNStateUpdate1Mod.F90 @@ -182,6 +182,8 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & 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 @@ -286,6 +288,14 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & (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 @@ -298,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 678bdf05d3..4b6174195e 100644 --- a/src/biogeochem/CNNStateUpdate2Mod.F90 +++ b/src/biogeochem/CNNStateUpdate2Mod.F90 @@ -96,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 @@ -235,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 @@ -313,7 +321,8 @@ end subroutine NStateUpdate2h !----------------------------------------------------------------------- subroutine NStateUpdate2g(num_soilc, filter_soilc, num_soilp, filter_soilp, & - cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst, soilbiogeochem_nitrogenstate_inst) + cnveg_nitrogenflux_inst, cnveg_nitrogenstate_inst, & + soilbiogeochem_nitrogenstate_inst, soilbiogeochem_nitrogenflux_inst) ! ! !DESCRIPTION: ! Update all the prognostic nitrogen state @@ -329,6 +338,7 @@ subroutine NStateUpdate2g(num_soilc, filter_soilc, num_soilp, filter_soilp, & 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 @@ -339,6 +349,7 @@ subroutine NStateUpdate2g(num_soilc, filter_soilc, num_soilp, filter_soilp, & associate( & nf_veg => cnveg_nitrogenflux_inst , & ns_veg => cnveg_nitrogenstate_inst , & + nf_soil => soilbiogeochem_nitrogenflux_inst, & ns_soil => soilbiogeochem_nitrogenstate_inst & ) @@ -350,14 +361,29 @@ subroutine NStateUpdate2g(num_soilc, filter_soilc, num_soilp, filter_soilp, & do j = 1,nlevdecomp do fc = 1,num_soilc c = filter_soilc(fc) - 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 + ! + ! 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 @@ -366,51 +392,59 @@ subroutine NStateUpdate2g(num_soilc, filter_soilc, num_soilp, filter_soilp, & do fp = 1,num_soilp p = filter_soilp(fp) - ! 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 + ! + ! 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 diff --git a/src/biogeochem/CNNStateUpdate3Mod.F90 b/src/biogeochem/CNNStateUpdate3Mod.F90 index 26902cef22..fb8f57b38f 100644 --- a/src/biogeochem/CNNStateUpdate3Mod.F90 +++ b/src/biogeochem/CNNStateUpdate3Mod.F90 @@ -146,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 fffb19bc46..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 @@ -86,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 @@ -105,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 @@ -132,10 +138,8 @@ 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 @@ -143,6 +147,9 @@ module CNPhenologyMod 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 @@ -270,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 @@ -304,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) @@ -465,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 @@ -674,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() @@ -697,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 @@ -728,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 @@ -805,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) (:) ] @@ -880,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 @@ -900,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 @@ -993,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. @@ -1002,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 @@ -1264,7 +1401,10 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & stress_decid => 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) @@ -1340,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() @@ -1358,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 @@ -1499,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. @@ -1508,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 @@ -1631,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 @@ -1647,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 @@ -1808,7 +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, use_cropcal_rx_cultivar_gdds, use_cropcal_streams + use clm_varctl , only : use_cropcal_rx_swindows ! ! !ARGUMENTS: integer , intent(in) :: num_pcropp ! number of prog crop patches in filter @@ -1973,7 +2194,7 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & 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 = -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 @@ -2242,7 +2463,7 @@ subroutine CropPhenology(num_pcropp, filter_pcropp , & do_harvest = .true. fake_harvest = .true. harvest_reason = HARVEST_REASON_SOWNBADDEC31 - else if (use_cropcal_streams .and. do_plant .and. .not. did_plant) then + 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 @@ -2559,7 +2780,7 @@ subroutine PlantCrop(p, leafcn_in, jday, kyr, do_plant_normal, & ! !USES: use clm_varctl , only : use_c13, use_c14 - use clm_varctl , only : use_cropcal_rx_cultivar_gdds, use_cropcal_streams + 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 @@ -2590,6 +2811,7 @@ subroutine PlantCrop(p, leafcn_in, jday, kyr, do_plant_normal, & ! 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? @@ -2668,42 +2890,71 @@ subroutine PlantCrop(p, leafcn_in, jday, kyr, do_plant_normal, & 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) 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_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(gdd820(p)*0.85_r8, hybgdd(ivt(p)))) + 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 - 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))) + else + write(iulog, *) 'ERROR: PlantCrop(): unrecognized ivt for GDD target: ',ivt(p) + call endrun(msg="Stopping") end if endif - if (use_cropcal_streams .and. gddmaturity(p) < min_gddmaturity) 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,')' - endif - gddmaturity(p) = min_gddmaturity - 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 @@ -2961,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 @@ -2980,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 @@ -3006,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 @@ -3021,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 @@ -3143,8 +3468,51 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & 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 @@ -3159,14 +3527,18 @@ 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) - - ! 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 @@ -3269,8 +3641,55 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & ! as well as leaf C:N ratio (unaffected by biofuel harvest). It thus does not ! need to be updated here. - ! Matrix for grain, livestem to litter and biofuel + ! 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 @@ -3281,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 @@ -3292,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 @@ -3325,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 @@ -3350,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 @@ -3359,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 @@ -3375,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 @@ -3395,12 +3850,10 @@ 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 @@ -3470,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 @@ -3483,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) @@ -3502,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 @@ -3527,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 @@ -3546,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 @@ -3565,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 @@ -3624,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 ) @@ -3642,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 @@ -3653,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 @@ -3672,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 @@ -3691,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 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 8210bafc97..b4c581c081 100644 --- a/src/biogeochem/CNVegCarbonFluxType.F90 +++ b/src/biogeochem/CNVegCarbonFluxType.F90 @@ -9,10 +9,17 @@ 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 @@ -402,11 +409,112 @@ 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 @@ -463,7 +571,233 @@ 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 !------------------------------------------------------------------------ @@ -839,6 +1173,58 @@ subroutine InitAllocate(this, bounds, carbon_type, alloc_full_veg) 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 & @@ -3574,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 @@ -3588,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 @@ -4194,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 @@ -4208,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 diff --git a/src/biogeochem/CNVegCarbonStateType.F90 b/src/biogeochem/CNVegCarbonStateType.F90 index c7e21da1d6..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,33 +36,50 @@ 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 @@ -74,6 +91,28 @@ module CNVegCarbonStateType 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 @@ -90,7 +129,83 @@ module CNVegCarbonStateType 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) real(r8), pointer :: totc_p2c_col (:) ! (gC/m2) totc_patch averaged to col - + +! 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 @@ -242,23 +357,53 @@ subroutine InitAllocate(this, bounds, alloc_full_veg) 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 @@ -272,7 +417,127 @@ subroutine InitAllocate(this, bounds, alloc_full_veg) 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 @@ -287,11 +552,6 @@ subroutine InitAllocate(this, bounds, alloc_full_veg) allocate(this%totc_p2c_col (begc:endc)) ; this%totc_p2c_col (:) = nan - ! Matrix solution variables - if(use_matrixcn)then - ! Initisl pool size for matrix solution - end if - end subroutine InitAllocate !------------------------------------------------------------------------ @@ -375,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', & @@ -400,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', & @@ -415,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', & @@ -430,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', & @@ -445,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', & @@ -460,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', & @@ -515,9 +877,6 @@ subroutine InitHistory(this, bounds, carbon_type) avgflag='A', long_name='fuel load', & ptr_col=this%fuelc_col) - ! Matrix solution history variables - if ( use_matrixcn )then - end if end if !------------------------------- @@ -541,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', & @@ -561,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', & @@ -576,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', & @@ -591,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', & @@ -606,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', & @@ -621,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', & @@ -695,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 @@ -727,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', & @@ -742,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', & @@ -757,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', & @@ -772,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', & @@ -787,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', & @@ -802,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', & @@ -875,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 @@ -890,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 ! @@ -957,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 @@ -967,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 @@ -1045,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 @@ -1056,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 @@ -1107,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 @@ -1186,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) @@ -1206,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) @@ -1218,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) @@ -1230,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) @@ -1242,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) @@ -1254,37 +2222,125 @@ 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) - 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) + 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='gresp_xfer', xtype=ncd_double, & - dim1name='pft', long_name='', units='', & - interpinic_flag='interp', readvar=readvar, data=this%gresp_xfer_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='cpool', xtype=ncd_double, & - dim1name='pft', long_name='', units='', & - interpinic_flag='interp', readvar=readvar, data=this%cpool_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='xsmrpool', xtype=ncd_double, & - dim1name='pft', long_name='', units='', & - interpinic_flag='interp', readvar=readvar, data=this%xsmrpool_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) - ! Restart variables for matrix solution - if ( use_matrixcn )then - end if + 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) - if (use_crop) then - call restartvar(ncid=ncid, flag=flag, varname='xsmrpool_loss', xtype=ncd_double, & + 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) + + call restartvar(ncid=ncid, flag=flag, varname='gresp_xfer', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%gresp_xfer_patch) + + call restartvar(ncid=ncid, flag=flag, varname='cpool', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%cpool_patch) + + call restartvar(ncid=ncid, flag=flag, varname='xsmrpool', xtype=ncd_double, & + dim1name='pft', long_name='', units='', & + interpinic_flag='interp', readvar=readvar, data=this%xsmrpool_patch) + + if (use_crop) then + call restartvar(ncid=ncid, flag=flag, varname='xsmrpool_loss', xtype=ncd_double, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%xsmrpool_loss_patch) 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, & @@ -1372,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 @@ -1382,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 @@ -1418,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 @@ -1441,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 @@ -1460,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 @@ -1633,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) @@ -1675,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) @@ -1717,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) @@ -1759,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) @@ -1801,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) @@ -1843,6 +3204,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_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, & dim1name='pft', long_name='', units='', & interpinic_flag='interp', readvar=readvar, data=this%gresp_storage_patch) @@ -1930,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 !-------------------------------- @@ -1997,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) @@ -2036,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) @@ -2072,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) @@ -2108,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) @@ -2144,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) @@ -2180,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) @@ -2252,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 !-------------------------------- @@ -2537,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 @@ -2547,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 @@ -2569,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 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 3806de9838..788be23137 100644 --- a/src/biogeochem/CNVegNitrogenFluxType.F90 +++ b/src/biogeochem/CNVegNitrogenFluxType.F90 @@ -5,7 +5,14 @@ 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 @@ -277,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 @@ -289,7 +415,7 @@ module CNVegNitrogenFluxType procedure , public :: ZeroGRU procedure , public :: Summary => Summary_nitrogenflux procedure , private :: InitAllocate - procedure , private :: InitTransfer + procedure , private :: InitTransfer procedure , private :: InitHistory procedure , private :: InitCold @@ -317,20 +443,337 @@ subroutine Init(this, bounds, alloc_full_veg) 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, alloc_full_veg) @@ -612,10 +1055,57 @@ subroutine InitAllocate(this, bounds, alloc_full_veg) 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 @@ -1248,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 @@ -1676,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='', & @@ -1792,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) ! @@ -1802,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 @@ -2042,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 diff --git a/src/biogeochem/CNVegNitrogenStateType.F90 b/src/biogeochem/CNVegNitrogenStateType.F90 index 42bc47e102..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,9 +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 - - - ! 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 @@ -142,14 +276,29 @@ subroutine InitAllocate(this, bounds, alloc_full_veg) 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 @@ -162,6 +311,20 @@ subroutine InitAllocate(this, bounds, alloc_full_veg) 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 @@ -176,8 +339,125 @@ subroutine InitAllocate(this, bounds, alloc_full_veg) allocate(this%totn_p2c_col (begc:endc)) ; this%totn_p2c_col (:) = 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 @@ -246,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 @@ -277,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', & @@ -292,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', & @@ -307,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', & @@ -322,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', & @@ -337,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', & @@ -450,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 @@ -490,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 @@ -518,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 @@ -537,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 @@ -544,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 @@ -635,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) @@ -648,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, & @@ -662,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='', & @@ -710,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='', & @@ -748,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, & @@ -825,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 @@ -860,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 @@ -885,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 @@ -991,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 diff --git a/src/biogeochem/CNVegStateType.F90 b/src/biogeochem/CNVegStateType.F90 index c286c0344f..d63752c5b7 100644 --- a/src/biogeochem/CNVegStateType.F90 +++ b/src/biogeochem/CNVegStateType.F90 @@ -519,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 diff --git a/src/biogeochem/CNVegetationFacade.F90 b/src/biogeochem/CNVegetationFacade.F90 index 61e2e9cf91..706d52da27 100644 --- a/src/biogeochem/CNVegetationFacade.F90 +++ b/src/biogeochem/CNVegetationFacade.F90 @@ -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 @@ -469,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 @@ -545,6 +547,14 @@ subroutine Restart(this, bounds, ncid, flag) template_multiplier = c14ratio) 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 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 760aa21b76..0f650a4a9f 100644 --- a/src/biogeochem/CropType.F90 +++ b/src/biogeochem/CropType.F90 @@ -52,6 +52,9 @@ module CropType 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] @@ -235,6 +238,9 @@ subroutine InitAllocate(this, bounds) 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 @@ -358,6 +364,19 @@ subroutine InitHistory(this, bounds) 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 subroutine InitCold(this, bounds) @@ -772,7 +791,7 @@ 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, nlevmaxurbgrnd @@ -848,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) @@ -872,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) diff --git a/src/biogeochem/DUSTMod.F90 b/src/biogeochem/DustEmisBase.F90 similarity index 54% rename from src/biogeochem/DUSTMod.F90 rename to src/biogeochem/DustEmisBase.F90 index ffa2bfe6f0..84467c701d 100644 --- a/src/biogeochem/DUSTMod.F90 +++ b/src/biogeochem/DustEmisBase.F90 @@ -1,21 +1,23 @@ -module DUSTMod +module DustEmisBase +#include "shr_assert.h" - !----------------------------------------------------------------------- - ! !DESCRIPTION: + !----------------------------------------------------------------------- + ! !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 + ! 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 + ! 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_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_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 @@ -24,83 +26,150 @@ module DUSTMod 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 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 - use ZenderSoilErodStreamType, only : soil_erod_stream_type - use clm_varctl , only : dust_emis_method - ! + ! ! !PUBLIC TYPES implicit none private ! - ! !PUBLIC MEMBER FUNCTIONS: - ! - public DustEmission ! Dust mobilization - public DustDryDep ! Turbulent dry deposition for dust + ! !PRIVATE DATA: ! - ! !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 + real(r8), parameter :: dns_aer = 2.5e+3_r8 ![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) + 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) - type(soil_erod_stream_type), private :: soil_erod_stream ! Zender soil erodibility stream data - real(r8), pointer, private :: mbl_bsn_fct_col (:) ! [dimensionless] basin factor, or soil erodibility, time-constant contains - procedure , public :: Init - procedure , private :: InitAllocate - procedure , private :: InitHistory - procedure , private :: InitCold - procedure , private :: InitDustVars ! Initialize variables used in subroutine Dust + 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 + !------------------------------------------------------------------------ - end type dust_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 Init(this, bounds, NLFilename) + subroutine InitBase(this, bounds, NLFilename) - class(dust_type) :: this - type(bounds_type), intent(in) :: bounds + ! 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%soil_erod_stream%Init( bounds, NLFilename ) - call this%InitAllocate (bounds) - call this%InitHistory (bounds) - call this%InitCold (bounds) + call this%InitAllocateBase (bounds) + call this%InitHistoryBase (bounds) call this%InitDustVars (bounds) - end subroutine Init + end subroutine InitBase !------------------------------------------------------------------------ - subroutine InitAllocate(this, bounds) + 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_type) :: this - type(bounds_type), intent(in) :: bounds + class (dust_emis_base_type) :: this + type(bounds_type), intent(in) :: bounds ! ! !LOCAL VARIABLES: integer :: begp,endp @@ -114,23 +183,26 @@ subroutine InitAllocate(this, bounds) 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_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 + 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 InitHistory(this, bounds) + subroutine InitHistoryBase(this, bounds) ! ! !USES: use histFileMod, only : hist_addfld1d ! ! ! !ARGUMENTS: - class (dust_type) :: this - type(bounds_type), intent(in) :: bounds + class (dust_emis_base_type) :: this + type(bounds_type), intent(in) :: bounds ! ! !LOCAL VARIABLES: integer :: begp,endp @@ -165,348 +237,140 @@ subroutine InitHistory(this, bounds) avgflag='A', long_name='turbulent deposition velocity 4', & ptr_patch=this%vlc_trb_4_patch, default='inactive') - if (dust_emis_method == 'Zender_2003') then - 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 if - - 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 - - if (dust_emis_method == 'Leung_2023') then - !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 - call endrun( msg="Leung_2023 dust_emis_method is currently not available"//errMsg(sourcefile, __LINE__)) - else if (dust_emis_method == 'Zender_2003') then - 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 - else - write(iulog,*) 'dust_emis_method not recognized = ', trim(dust_emis_method) - call endrun( msg="dust_emis_method namelist item is not valid "//errMsg(sourcefile, __LINE__)) - end if - - end subroutine InitCold + end subroutine InitHistoryBase !------------------------------------------------------------------------ - 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 + 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 - 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 + call endrun(msg="SetDragPartition is NOT allowed for this dust emission class type") - ! 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 + end subroutine SetDragPartitionBase - 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 + 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 - 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 + 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 - end if ! lnd_frc_mbl > 0.0 + !----------------------------------------------------------------------- - end do + 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 - ! 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 + !------------------------------------------------------------------------ + 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 - 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 + subroutine GetConstVars(this, SaltationFactor ) + ! + ! !DESCRIPTION: + ! Get important constant variables + ! !ARGUMENTS: + class(dust_emis_base_type) , intent(in) :: this + real(r8) , intent(out) :: SaltationFactor - end associate + SaltationFactor = this%saltation_factor + end subroutine GetConstVars - end subroutine DustEmission + !------------------------------------------------------------------------ - !------------------------------------------------------------------------ - subroutine DustDryDep (bounds, & - atm2lnd_inst, frictionvel_inst, dust_inst) + subroutine DustDryDep (this, bounds, & + atm2lnd_inst, frictionvel_inst) ! - ! !DESCRIPTION: + ! !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 + ! 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 @@ -520,10 +384,10 @@ subroutine DustDryDep (bounds, & use shr_const_mod, only : SHR_CONST_PI, SHR_CONST_RDAIR, SHR_CONST_BOLTZ ! ! !ARGUMENTS: - type(bounds_type) , intent(in) :: bounds + 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 - type(dust_type) , intent(inout) :: dust_inst ! ! !LOCAL VARIABLES integer :: p,c,g,m,n ! indices @@ -538,23 +402,23 @@ subroutine DustDryDep (bounds, & 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) :: 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 + 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 @@ -577,11 +441,11 @@ subroutine DustDryDep (bounds, & 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 * & + (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) * stk_crc(m) ![m s-1] Correction to Stokes settling velocity + 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 @@ -594,7 +458,7 @@ subroutine DustDryDep (bounds, & 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 + (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] @@ -603,7 +467,7 @@ subroutine DustDryDep (bounds, & ! 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 # + ! [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 @@ -635,14 +499,15 @@ subroutine DustDryDep (bounds, & end subroutine DustDryDep - !------------------------------------------------------------------------ - subroutine InitDustVars(this, bounds) + !------------------------------------------------------------------------ + + subroutine InitDustVars(this, bounds) ! - ! !DESCRIPTION: + ! !DESCRIPTION: ! ! Compute source efficiency factor from topography ! Initialize other variables used in subroutine Dust: - ! ovr_src_snk_mss(m,n) and tmp1. + ! 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) @@ -655,8 +520,8 @@ subroutine InitDustVars(this, bounds) use decompMod , only : get_proc_bounds ! ! !ARGUMENTS: - class(dust_type) :: this - type(bounds_type), intent(in) :: bounds + class(dust_emis_base_type) :: this + type(bounds_type), intent(in) :: bounds ! ! !LOCAL VARIABLES integer :: fc,c,l,m,n ! indices @@ -678,7 +543,7 @@ subroutine InitDustVars(this, bounds) 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) :: 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 @@ -698,7 +563,7 @@ subroutine InitDustVars(this, bounds) 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 @@ -710,19 +575,16 @@ subroutine InitDustVars(this, bounds) real(r8), parameter :: dns_slt = 2650.0_r8 ! [kg m-3] Density of optimal saltation particles !------------------------------------------------------------------------ - ! allocate module variable - allocate (ovr_src_snk_mss(dst_src_nbr,ndst)) - allocate (dmt_vwr(ndst)) - allocate (stk_crc(ndst)) - + 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)) + 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 /) + 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 @@ -738,12 +600,12 @@ subroutine InitDustVars(this, bounds) 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) + 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 tmp1 needs to be defined just once + ! 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 @@ -760,7 +622,7 @@ subroutine InitDustVars(this, bounds) 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) + 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, @@ -794,7 +656,6 @@ subroutine InitDustVars(this, bounds) 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 @@ -829,7 +690,7 @@ subroutine InitDustVars(this, bounds) 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 + 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 @@ -839,7 +700,7 @@ subroutine InitDustVars(this, bounds) 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) * & + 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) + & @@ -848,7 +709,7 @@ subroutine InitDustVars(this, bounds) end do - dmt_vwr(n) = dmt_vwr(n) / vlm_rsl(n) ![m] Mass weighted diameter resolved + this%dmt_vwr(n) = this%dmt_vwr(n) / vlm_rsl(n) ![m] Mass weighted diameter resolved end do @@ -867,9 +728,9 @@ subroutine InitDustVars(this, bounds) 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 * & + (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 @@ -894,7 +755,7 @@ subroutine InitDustVars(this, bounds) ! 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 + 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 @@ -918,8 +779,8 @@ subroutine InitDustVars(this, bounds) ! 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)) + 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 @@ -942,9 +803,11 @@ subroutine InitDustVars(this, bounds) ! actual settling velocities do m = 1, ndst - stk_crc(m) = vlc_grv(m) / vlc_stk(m) + this%stk_crc(m) = vlc_grv(m) / vlc_stk(m) end do end subroutine InitDustVars -end module DUSTMod + !============================================================================== + +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/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/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 6f8632658d..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,16 +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 - 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 @@ -1386,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 @@ -1478,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 a4bd9dc4d2..533c7d892e 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 @@ -378,7 +379,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 @@ -422,6 +423,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 @@ -476,14 +478,7 @@ 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_downscaled_col, & ! Input: [real(r8) (:,:) ] direct beam radiation (visible only) forc_solai => atm2lnd_inst%forc_solai_grc , & ! Input: [real(r8) (:,:) ] diffuse radiation (visible only) @@ -569,10 +564,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 @@ -599,7 +592,7 @@ subroutine VOCEmission (bounds, num_soilp, filter_soilp, & ! 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, patch%itype(p)) ! Activity factor for Leaf Age gamma_a = get_gamma_A(patch%itype(p), elai240(p),elai(p),class_num) @@ -818,90 +811,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 +873,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 +885,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/test/CMakeLists.txt b/src/biogeochem/test/CMakeLists.txt index 81fe9bbaf0..e22a720523 100644 --- a/src/biogeochem/test/CMakeLists.txt +++ b/src/biogeochem/test/CMakeLists.txt @@ -2,3 +2,4 @@ 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/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/biogeophys/CMakeLists.txt b/src/biogeophys/CMakeLists.txt index 2ffc346670..07b88b07bf 100644 --- a/src/biogeophys/CMakeLists.txt +++ b/src/biogeophys/CMakeLists.txt @@ -7,6 +7,7 @@ list(APPEND clm_sources BalanceCheckMod.F90 CanopyStateType.F90 EnergyFluxType.F90 + FrictionVelocityMod.F90 GlacierSurfaceMassBalanceMod.F90 HillslopeHydrologyUtilsMod.F90 HumanIndexMod.F90 @@ -24,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 58334a70c0..0c5431728d 100644 --- a/src/biogeophys/CanopyFluxesMod.F90 +++ b/src/biogeophys/CanopyFluxesMod.F90 @@ -753,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 @@ -1624,7 +1625,8 @@ subroutine CanopyFluxes(bounds, num_exposedvegp, filter_exposedvegp, ! 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)) + snocan_baseline(begp:endp), snocan(begp:endp), & + custom_rel_epsilon=1.e-10_r8) if ( use_fates ) then 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 313f7a83f3..4bfc08fc80 100644 --- a/src/biogeophys/CanopyStateType.F90 +++ b/src/biogeophys/CanopyStateType.F90 @@ -72,6 +72,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 = & @@ -442,6 +444,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 2e709596a1..6a31293fa3 100644 --- a/src/biogeophys/EnergyFluxType.F90 +++ b/src/biogeophys/EnergyFluxType.F90 @@ -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') @@ -988,7 +988,7 @@ subroutine UpdateAccVars (this, bounds) ! ! USES 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 7cea2a22f9..44e1bf6294 100644 --- a/src/biogeophys/FrictionVelocityMod.F90 +++ b/src/biogeophys/FrictionVelocityMod.F90 @@ -89,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 @@ -122,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) ! @@ -244,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 ', & @@ -437,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', & diff --git a/src/biogeophys/HillslopeHydrologyMod.F90 b/src/biogeophys/HillslopeHydrologyMod.F90 index b2866df679..8fccd762f0 100644 --- a/src/biogeophys/HillslopeHydrologyMod.F90 +++ b/src/biogeophys/HillslopeHydrologyMod.F90 @@ -168,7 +168,7 @@ end subroutine check_aquifer_layer !----------------------------------------------------------------------- - subroutine InitHillslope(bounds,fsurdat) + subroutine InitHillslope(bounds, hillslope_file) ! ! !DESCRIPTION: ! Initialize hillslope geomorphology from input dataset @@ -187,7 +187,7 @@ subroutine InitHillslope(bounds,fsurdat) ! ! !ARGUMENTS: type(bounds_type), intent(in) :: bounds - character(len=*) , intent(in) :: fsurdat ! surface data file name + 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 @@ -224,9 +224,9 @@ subroutine InitHillslope(bounds,fsurdat) ! consistency check call check_aquifer_layer() - ! Open surface dataset to read in data below + ! Open hillslope dataset to read in data below - call getfil (fsurdat, locfn, 0) + call getfil (hillslope_file, locfn, 0) call ncd_pio_openfile (ncid, locfn, 0) allocate( & @@ -248,7 +248,7 @@ subroutine InitHillslope(bounds,fsurdat) 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 surface data set.'//errmsg(sourcefile, __LINE__) ) + 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) @@ -266,7 +266,7 @@ subroutine InitHillslope(bounds,fsurdat) 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 surface data set.'//errmsg(sourcefile, __LINE__) ) + 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) @@ -278,7 +278,7 @@ subroutine InitHillslope(bounds,fsurdat) 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 surface data set.'//errmsg(sourcefile, __LINE__) ) + 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) @@ -287,7 +287,7 @@ subroutine InitHillslope(bounds,fsurdat) 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 surface data set.'//errmsg(sourcefile, __LINE__) ) + 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) @@ -296,7 +296,7 @@ subroutine InitHillslope(bounds,fsurdat) 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 surface data set.'//errmsg(sourcefile, __LINE__) ) + 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) @@ -307,7 +307,7 @@ subroutine InitHillslope(bounds,fsurdat) 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 surface data set.'//errmsg(sourcefile, __LINE__) ) + call endrun( 'ERROR:: hillslope_slope not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) end if do l = bounds%begl,bounds%endl @@ -317,7 +317,7 @@ subroutine InitHillslope(bounds,fsurdat) 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 surface data set.'//errmsg(sourcefile, __LINE__) ) + call endrun( 'ERROR:: hillslope_aspect not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) end if do l = bounds%begl,bounds%endl @@ -327,7 +327,7 @@ subroutine InitHillslope(bounds,fsurdat) 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 surface data set.'//errmsg(sourcefile, __LINE__) ) + 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) @@ -335,7 +335,7 @@ subroutine InitHillslope(bounds,fsurdat) 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_length not found on surface data set.'//errmsg(sourcefile, __LINE__) ) + call endrun( 'ERROR:: hillslope_distance not found on hillslope data set.'//errmsg(sourcefile, __LINE__) ) end if do l = bounds%begl,bounds%endl @@ -345,7 +345,7 @@ subroutine InitHillslope(bounds,fsurdat) 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 surface data set.'//errmsg(sourcefile, __LINE__) ) + 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) @@ -354,7 +354,7 @@ subroutine InitHillslope(bounds,fsurdat) 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_height not found on surface data set.'//errmsg(sourcefile, __LINE__) ) + 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) @@ -380,7 +380,7 @@ subroutine InitHillslope(bounds,fsurdat) 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 surface data set.'//errmsg(sourcefile, __LINE__) ) + 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) @@ -389,7 +389,7 @@ subroutine InitHillslope(bounds,fsurdat) 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 surface data set.'//errmsg(sourcefile, __LINE__) ) + 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) @@ -398,7 +398,7 @@ subroutine InitHillslope(bounds,fsurdat) 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 surface data set.'//errmsg(sourcefile, __LINE__) ) + 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) @@ -504,11 +504,11 @@ subroutine InitHillslope(bounds,fsurdat) enddo end if - ! if missing hillslope information on surface dataset, + ! 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 surface data for gridcell at (lon/lat): ', grc%londeg(g),grc%latdeg(g) + 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 @@ -559,7 +559,7 @@ end subroutine InitHillslope !----------------------------------------------------------------------- - subroutine SetHillslopeSoilThickness(bounds,fsurdat,soil_depth_lowland_in,soil_depth_upland_in) + subroutine SetHillslopeSoilThickness(bounds, hillslope_file, soil_depth_lowland_in, soil_depth_upland_in) ! ! !DESCRIPTION: ! Set hillslope column nbedrock values @@ -578,7 +578,7 @@ subroutine SetHillslopeSoilThickness(bounds,fsurdat,soil_depth_lowland_in,soil_d ! ! !ARGUMENTS: type(bounds_type), intent(in) :: bounds - character(len=*) , intent(in) :: fsurdat ! surface data file name + 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 @@ -599,14 +599,14 @@ subroutine SetHillslopeSoilThickness(bounds,fsurdat,soil_depth_lowland_in,soil_d if (soil_profile_method==soil_profile_from_file) then - ! Open surface dataset to read in data below - call getfil (fsurdat, locfn, 0) + ! 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 surface data set.'//errmsg(sourcefile, __LINE__) ) + 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) @@ -896,7 +896,7 @@ end subroutine HillslopeDominantLowlandPft subroutine HillslopePftFromFile(bounds,col_pftndx) ! ! !DESCRIPTION: - ! Reassign patch type using indices from surface data file + ! 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. 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/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/SaturatedExcessRunoffMod.F90 b/src/biogeophys/SaturatedExcessRunoffMod.F90 index 5643a95394..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 @@ -266,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 ! diff --git a/src/biogeophys/SnowHydrologyMod.F90 b/src/biogeophys/SnowHydrologyMod.F90 index 9fb1a52dbc..578769d9ea 100644 --- a/src/biogeophys/SnowHydrologyMod.F90 +++ b/src/biogeophys/SnowHydrologyMod.F90 @@ -87,6 +87,7 @@ module SnowHydrologyMod 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 @@ -151,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) ! ------------------------------------------------------------------------ @@ -211,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 @@ -246,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) @@ -333,6 +331,8 @@ subroutine readParams( ncid ) 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 @@ -1972,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 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 0dc8876d24..d6c9660b96 100644 --- a/src/biogeophys/SoilTemperatureMod.F90 +++ b/src/biogeophys/SoilTemperatureMod.F90 @@ -671,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] diff --git a/src/biogeophys/SurfaceAlbedoType.F90 b/src/biogeophys/SurfaceAlbedoType.F90 index ddb57d88f7..10819a47b6 100644 --- a/src/biogeophys/SurfaceAlbedoType.F90 +++ b/src/biogeophys/SurfaceAlbedoType.F90 @@ -226,7 +226,7 @@ subroutine InitHistory(this, bounds) this%azsun_grc(begg:endg) = spval call hist_addfld1d (fname='AZSUN', units='radians', & - avgflag='A', long_name='cosine of solar zenith angle', & + avgflag='A', long_name='azimuth angle of the sun', & ptr_lnd=this%azsun_grc, default='inactive') this%coszen_grc(begg:endg) = spval @@ -242,12 +242,12 @@ subroutine InitHistory(this, bounds) 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') + ptr_col=this%albgrd_col, default='active') this%albgri_col(begc:endc,:) = spval call hist_addfld2d (fname='ALBGRI', units='proportion', type2d='numrad', & avgflag='A', long_name='ground albedo (indirect)', & - ptr_col=this%albgri_col, default='inactive') + ptr_col=this%albgri_col, default='active') if (use_SSRE) then this%albdSF_patch(begp:endp,:) = spval diff --git a/src/biogeophys/TemperatureType.F90 b/src/biogeophys/TemperatureType.F90 index ab310650c8..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 + 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_excess_ice + 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__) @@ -742,8 +777,23 @@ subroutine InitCold(this, bounds, & end if else this%t_soisno_col(c,1:nlevgrnd) = 272._r8 - if (use_excess_ice .and. (lun%itype(l) == istsoil .or. lun%itype(l) == istcrop)) then - this%t_soisno_col(c,1:nlevgrnd) = SHR_CONST_TKFRZ - 5.0_r8 !needs to be below freezing to properly initiate excess ice + 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 @@ -895,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, & @@ -1357,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 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, accumResetVal + 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 @@ -1392,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 @@ -1535,69 +1698,25 @@ 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 - end if - end do - call update_accum_field ('GDD10', rbufslp, nstep) - call extract_accum_field ('GDD10', this%gdd10_patch, nstep) + 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 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) @@ -1634,4 +1753,67 @@ subroutine Clean(this) 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/UrbBuildTempOleson2015Mod.F90 b/src/biogeophys/UrbBuildTempOleson2015Mod.F90 index 4c985f0ab3..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) @@ -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 2e854a0497..3e84f73176 100644 --- a/src/biogeophys/UrbanAlbedoMod.F90 +++ b/src/biogeophys/UrbanAlbedoMod.F90 @@ -78,9 +78,14 @@ subroutine UrbanAlbedo (bounds, num_urbanl, filter_urbanl, & type(surfalb_type) , intent(inout) :: surfalb_inst ! ! !LOCAL VARIABLES: - integer :: fl,fp,fc,g,l,p,c,ib ! indices + integer :: fl,fp,fc,g,l,p,c,ib,f,fn ! indices and counters integer :: ic ! 0=unit incoming direct; 1=unit incoming diffuse - integer :: num_solar ! counter + integer, allocatable :: filter_urbanl_coszen_gt0(:) ! filter for urban landunits with coszen > 0 + integer :: num_urbanl_coszen_gt0 ! number of urban landunits with coszen > 0 + integer, allocatable :: filter_nourbanl_coszen_gt0(:) ! filter for urban landunits with coszen <= 0 + integer :: num_nourbanl_coszen_gt0 ! number of urban landunits with coszen <= 0 + integer, allocatable :: filter_urbanc_coszen_gt0(:) ! filter for urban columns with coszen > 0 + integer :: num_urbanc_coszen_gt0 ! number of urban columns with coszen > 0 real(r8) :: coszen (bounds%begl:bounds%endl) ! cosine solar zenith angle for next time step (landunit) real(r8) :: zen (bounds%begl:bounds%endl) ! solar zenith angle (radians) real(r8) :: sdir (bounds%begl:bounds%endl, numrad) ! direct beam solar radiation on horizontal surface @@ -165,9 +170,16 @@ subroutine UrbanAlbedo (bounds, num_urbanl, filter_urbanl, & 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 - endl => bounds%endl & + endl => bounds%endl , & + begc => bounds%begc , & + endc => bounds%endc & ) + ! Allocate urbanl and urbanc coszen filters + allocate(filter_urbanl_coszen_gt0(bounds%endl-bounds%begl+1)) + allocate(filter_nourbanl_coszen_gt0(bounds%endl-bounds%begl+1)) + allocate(filter_urbanc_coszen_gt0(bounds%endc-bounds%begc+1)) + ! ---------------------------------------------------------------------------- ! Solar declination and cosine solar zenith angle and zenith angle for ! next time step @@ -228,15 +240,36 @@ subroutine UrbanAlbedo (bounds, num_urbanl, filter_urbanl, & end do end do - ! ---------------------------------------------------------------------------- - ! Urban Code - ! ---------------------------------------------------------------------------- - - num_solar = 0 + ! Populate urbanl and urbanc coszen filters + f = 0 + fn = 0 do fl = 1,num_urbanl l = filter_urbanl(fl) - if (coszen(l) > 0._r8) num_solar = num_solar + 1 + if (coszen(l) > 0._r8) then + f = f + 1 + filter_urbanl_coszen_gt0(f) = l + else + fn = fn + 1 + filter_nourbanl_coszen_gt0(fn) = l + end if + end do + num_urbanl_coszen_gt0 = f + num_nourbanl_coszen_gt0 = fn + + f = 0 + do fc = 1,num_urbanc + c = filter_urbanc(fc) + l = col%landunit(c) + if (coszen(l) > 0._r8) then + f = f + 1 + filter_urbanc_coszen_gt0(f) = c + end if end do + num_urbanc_coszen_gt0 = f + + ! ---------------------------------------------------------------------------- + ! Urban Code + ! ---------------------------------------------------------------------------- do ib = 1,numrad do fl = 1,num_urbanl @@ -267,184 +300,183 @@ subroutine UrbanAlbedo (bounds, num_urbanl, filter_urbanl, & end do ! ---------------------------------------------------------------------------- - ! Only do the rest if all coszen are positive + ! Use the urban coszen filters to only calculate quantities when coszen > 0 ! ---------------------------------------------------------------------------- - if (num_solar > 0)then - ! Set constants - solar fluxes are per unit incoming flux + ! Set constants - solar fluxes are per unit incoming flux - do ib = 1,numrad - do fl = 1,num_urbanl - l = filter_urbanl(fl) - sdir(l,ib) = 1._r8 - sdif(l,ib) = 1._r8 - end do + do ib = 1,numrad + do fl = 1,num_urbanl_coszen_gt0 + l = filter_urbanl_coszen_gt0(fl) + sdir(l,ib) = 1._r8 + sdif(l,ib) = 1._r8 end do + end do - ! Incident direct beam radiation for - ! (a) roof and (b) road and both walls in urban canyon - - if (num_urbanl > 0) then - call incident_direct (bounds, & - num_urbanl, filter_urbanl, & - canyon_hwr(begl:endl), & - coszen(begl:endl), & - zen(begl:endl), & - sdir(begl:endl, :), & - sdir_road(begl:endl, :), & - sdir_sunwall(begl:endl, :), & - sdir_shadewall(begl:endl, :)) - end if + ! Incident direct beam radiation for + ! (a) roof and (b) road and both walls in urban canyon + + if (num_urbanl > 0) then + call incident_direct (bounds, & + num_urbanl_coszen_gt0, & + filter_urbanl_coszen_gt0, & + num_nourbanl_coszen_gt0, & + filter_nourbanl_coszen_gt0, & + canyon_hwr(begl:endl), & + zen(begl:endl), & + sdir(begl:endl, :), & + sdir_road(begl:endl, :), & + sdir_sunwall(begl:endl, :), & + sdir_shadewall(begl:endl, :)) + end if - ! Incident diffuse radiation for - ! (a) roof and (b) road and both walls in urban canyon. - - if (num_urbanl > 0) then - call incident_diffuse (bounds, & - num_urbanl, filter_urbanl, & - canyon_hwr(begl:endl), & - sdif(begl:endl, :), & - sdif_road(begl:endl, :), & - sdif_sunwall(begl:endl, :), & - sdif_shadewall(begl:endl, :), & - urbanparams_inst) - end if + ! Incident diffuse radiation for + ! (a) roof and (b) road and both walls in urban canyon. + + if (num_urbanl_coszen_gt0 > 0) then + call incident_diffuse (bounds, & + num_urbanl_coszen_gt0, & + filter_urbanl_coszen_gt0, & + canyon_hwr(begl:endl), & + sdif(begl:endl, :), & + sdif_road(begl:endl, :), & + sdif_sunwall(begl:endl, :), & + sdif_shadewall(begl:endl, :), & + urbanparams_inst) + end if - ! Get snow albedos for roof and impervious and pervious road - if (num_urbanl > 0) then - ic = 0 - call SnowAlbedo(bounds, & - num_urbanc, filter_urbanc, & - coszen(begl:endl), & - ic, & - albsnd_roof(begl:endl, :), & - albsnd_improad(begl:endl, :), & - albsnd_perroad(begl:endl, :), & - waterstatebulk_inst) - - ic = 1 - call SnowAlbedo(bounds, & - num_urbanc, filter_urbanc, & - coszen(begl:endl), & - ic, & - albsni_roof(begl:endl, :), & - albsni_improad(begl:endl, :), & - albsni_perroad(begl:endl, :), & - waterstatebulk_inst) - end if + ! Get snow albedos for roof and impervious and pervious road + if (num_urbanl > 0) then + ic = 0 + call SnowAlbedo(bounds, & + num_urbanc, filter_urbanc, & + num_urbanc_coszen_gt0, & + filter_urbanc_coszen_gt0, & + ic, & + albsnd_roof(begl:endl, :), & + albsnd_improad(begl:endl, :), & + albsnd_perroad(begl:endl, :), & + waterstatebulk_inst) + + ic = 1 + call SnowAlbedo(bounds, & + num_urbanc, filter_urbanc, & + num_urbanc_coszen_gt0, & + filter_urbanc_coszen_gt0, & + ic, & + albsni_roof(begl:endl, :), & + albsni_improad(begl:endl, :), & + albsni_perroad(begl:endl, :), & + waterstatebulk_inst) + end if - ! Combine snow-free and snow albedos - do ib = 1,numrad - do fc = 1,num_urbanc - c = filter_urbanc(fc) - l = col%landunit(c) - if (ctype(c) == icol_roof) then - alb_roof_dir_s(l,ib) = alb_roof_dir(l,ib)*(1._r8-frac_sno(c)) & - + albsnd_roof(l,ib)*frac_sno(c) - alb_roof_dif_s(l,ib) = alb_roof_dif(l,ib)*(1._r8-frac_sno(c)) & - + albsni_roof(l,ib)*frac_sno(c) - else if (ctype(c) == icol_road_imperv) then - alb_improad_dir_s(l,ib) = alb_improad_dir(l,ib)*(1._r8-frac_sno(c)) & - + albsnd_improad(l,ib)*frac_sno(c) - alb_improad_dif_s(l,ib) = alb_improad_dif(l,ib)*(1._r8-frac_sno(c)) & - + albsni_improad(l,ib)*frac_sno(c) - else if (ctype(c) == icol_road_perv) then - alb_perroad_dir_s(l,ib) = alb_perroad_dir(l,ib)*(1._r8-frac_sno(c)) & - + albsnd_perroad(l,ib)*frac_sno(c) - alb_perroad_dif_s(l,ib) = alb_perroad_dif(l,ib)*(1._r8-frac_sno(c)) & - + albsni_perroad(l,ib)*frac_sno(c) - end if - end do + ! Combine snow-free and snow albedos + do ib = 1,numrad + do fc = 1,num_urbanc_coszen_gt0 + c = filter_urbanc_coszen_gt0(fc) + l = col%landunit(c) + if (ctype(c) == icol_roof) then + alb_roof_dir_s(l,ib) = alb_roof_dir(l,ib)*(1._r8-frac_sno(c)) & + + albsnd_roof(l,ib)*frac_sno(c) + alb_roof_dif_s(l,ib) = alb_roof_dif(l,ib)*(1._r8-frac_sno(c)) & + + albsni_roof(l,ib)*frac_sno(c) + else if (ctype(c) == icol_road_imperv) then + alb_improad_dir_s(l,ib) = alb_improad_dir(l,ib)*(1._r8-frac_sno(c)) & + + albsnd_improad(l,ib)*frac_sno(c) + alb_improad_dif_s(l,ib) = alb_improad_dif(l,ib)*(1._r8-frac_sno(c)) & + + albsni_improad(l,ib)*frac_sno(c) + else if (ctype(c) == icol_road_perv) then + alb_perroad_dir_s(l,ib) = alb_perroad_dir(l,ib)*(1._r8-frac_sno(c)) & + + albsnd_perroad(l,ib)*frac_sno(c) + alb_perroad_dif_s(l,ib) = alb_perroad_dif(l,ib)*(1._r8-frac_sno(c)) & + + albsni_perroad(l,ib)*frac_sno(c) + end if end do + end do - ! Reflected and absorbed solar radiation per unit incident radiation - ! for road and both walls in urban canyon allowing for multiple reflection - ! Reflected and absorbed solar radiation per unit incident radiation for roof + ! Reflected and absorbed solar radiation per unit incident radiation + ! for road and both walls in urban canyon allowing for multiple reflection + ! Reflected and absorbed solar radiation per unit incident radiation for roof + + if (num_urbanl_coszen_gt0 > 0) then + call net_solar (bounds, & + num_urbanl_coszen_gt0, & + filter_urbanl_coszen_gt0, & + canyon_hwr (begl:endl), & + wtroad_perv (begl:endl), & + sdir (begl:endl, :), & + sdif (begl:endl, :), & + alb_improad_dir_s (begl:endl, :), & + alb_perroad_dir_s (begl:endl, :), & + alb_wall_dir (begl:endl, :), & + alb_roof_dir_s (begl:endl, :), & + alb_improad_dif_s (begl:endl, :), & + alb_perroad_dif_s (begl:endl, :), & + alb_wall_dif (begl:endl, :), & + alb_roof_dif_s (begl:endl, :), & + sdir_road (begl:endl, :), & + sdir_sunwall (begl:endl, :), & + sdir_shadewall (begl:endl, :), & + sdif_road (begl:endl, :), & + sdif_sunwall (begl:endl, :), & + sdif_shadewall (begl:endl, :), & + sref_improad_dir (begl:endl, :), & + sref_perroad_dir (begl:endl, :), & + sref_sunwall_dir (begl:endl, :), & + sref_shadewall_dir (begl:endl, :), & + sref_roof_dir (begl:endl, :), & + sref_improad_dif (begl:endl, :), & + sref_perroad_dif (begl:endl, :), & + sref_sunwall_dif (begl:endl, :), & + sref_shadewall_dif (begl:endl, :), & + sref_roof_dif (begl:endl, :), & + urbanparams_inst, solarabs_inst) + end if - if (num_urbanl > 0) then - call net_solar (bounds, & - num_urbanl, filter_urbanl, & - coszen (begl:endl), & - canyon_hwr (begl:endl), & - wtroad_perv (begl:endl), & - sdir (begl:endl, :), & - sdif (begl:endl, :), & - alb_improad_dir_s (begl:endl, :), & - alb_perroad_dir_s (begl:endl, :), & - alb_wall_dir (begl:endl, :), & - alb_roof_dir_s (begl:endl, :), & - alb_improad_dif_s (begl:endl, :), & - alb_perroad_dif_s (begl:endl, :), & - alb_wall_dif (begl:endl, :), & - alb_roof_dif_s (begl:endl, :), & - sdir_road (begl:endl, :), & - sdir_sunwall (begl:endl, :), & - sdir_shadewall (begl:endl, :), & - sdif_road (begl:endl, :), & - sdif_sunwall (begl:endl, :), & - sdif_shadewall (begl:endl, :), & - sref_improad_dir (begl:endl, :), & - sref_perroad_dir (begl:endl, :), & - sref_sunwall_dir (begl:endl, :), & - sref_shadewall_dir (begl:endl, :), & - sref_roof_dir (begl:endl, :), & - sref_improad_dif (begl:endl, :), & - sref_perroad_dif (begl:endl, :), & - sref_sunwall_dif (begl:endl, :), & - sref_shadewall_dif (begl:endl, :), & - sref_roof_dif (begl:endl, :), & - urbanparams_inst, solarabs_inst) - end if + ! ---------------------------------------------------------------------------- + ! Map urban output to surfalb_inst components + ! ---------------------------------------------------------------------------- - ! ---------------------------------------------------------------------------- - ! Map urban output to surfalb_inst components - ! ---------------------------------------------------------------------------- - - ! Set albgrd and albgri (ground albedos) and albd and albi (surface albedos) - - do ib = 1,numrad - do fc = 1,num_urbanc - c = filter_urbanc(fc) - l = col%landunit(c) - if (ctype(c) == icol_roof) then - albgrd(c,ib) = sref_roof_dir(l,ib) - albgri(c,ib) = sref_roof_dif(l,ib) - else if (ctype(c) == icol_sunwall) then - albgrd(c,ib) = sref_sunwall_dir(l,ib) - albgri(c,ib) = sref_sunwall_dif(l,ib) - else if (ctype(c) == icol_shadewall) then - albgrd(c,ib) = sref_shadewall_dir(l,ib) - albgri(c,ib) = sref_shadewall_dif(l,ib) - else if (ctype(c) == icol_road_perv) then - albgrd(c,ib) = sref_perroad_dir(l,ib) - albgri(c,ib) = sref_perroad_dif(l,ib) - else if (ctype(c) == icol_road_imperv) then - 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 + ! Set albgrd and albgri (ground albedos) and albd and albi (surface albedos) + + do ib = 1,numrad + do fc = 1,num_urbanc + c = filter_urbanc(fc) + l = col%landunit(c) + if (ctype(c) == icol_roof) then + albgrd(c,ib) = sref_roof_dir(l,ib) + albgri(c,ib) = sref_roof_dif(l,ib) + else if (ctype(c) == icol_sunwall) then + albgrd(c,ib) = sref_sunwall_dir(l,ib) + albgri(c,ib) = sref_sunwall_dif(l,ib) + else if (ctype(c) == icol_shadewall) then + albgrd(c,ib) = sref_shadewall_dir(l,ib) + albgri(c,ib) = sref_shadewall_dif(l,ib) + else if (ctype(c) == icol_road_perv) then + albgrd(c,ib) = sref_perroad_dir(l,ib) + albgri(c,ib) = sref_perroad_dif(l,ib) + else if (ctype(c) == icol_road_imperv) then + albgrd(c,ib) = sref_improad_dir(l,ib) + albgri(c,ib) = sref_improad_dif(l,ib) + endif + if (coszen(l) > 0._r8) then + albgrd_hst(c,ib) = albgrd(c,ib) + albgri_hst(c,ib) = albgri(c,ib) + end if end do - end if + 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) + if (coszen(l) > 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 @@ -452,7 +484,7 @@ end subroutine UrbanAlbedo !----------------------------------------------------------------------- subroutine SnowAlbedo (bounds , & - num_urbanc, filter_urbanc, coszen, ind , & + num_urbanc, filter_urbanc, num_urbanc_coszen_gt0, filter_urbanc_coszen_gt0, ind , & albsn_roof, albsn_improad, albsn_perroad, & waterstatebulk_inst) ! @@ -466,8 +498,9 @@ subroutine SnowAlbedo (bounds , & type(bounds_type), intent(in) :: bounds integer , intent(in) :: num_urbanc ! number of urban columns in clump integer , intent(in) :: filter_urbanc(:) ! urban column filter + integer , intent(in) :: num_urbanc_coszen_gt0 ! number of urban columns with coszen > 0 + integer , intent(in) :: filter_urbanc_coszen_gt0(:) ! filter for urban columns with coszen > 0 integer , intent(in) :: ind ! 0=direct beam, 1=diffuse radiation - real(r8), intent(in) :: coszen ( bounds%begl: ) ! cosine solar zenith angle [landunit] real(r8), intent(out):: albsn_roof ( bounds%begl: , 1: ) ! roof snow albedo by waveband [landunit, numrad] real(r8), intent(out):: albsn_improad ( bounds%begl: , 1: ) ! impervious road snow albedo by waveband [landunit, numrad] real(r8), intent(out):: albsn_perroad ( bounds%begl: , 1: ) ! pervious road snow albedo by waveband [landunit, numrad] @@ -488,7 +521,6 @@ subroutine SnowAlbedo (bounds , & SHR_ASSERT_ALL_FL(numrad == 2, sourcefile, __LINE__) ! Enforce expected array sizes - SHR_ASSERT_ALL_FL((ubound(coszen) == (/bounds%endl/)), sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(albsn_roof) == (/bounds%endl, numrad/)), sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(albsn_improad) == (/bounds%endl, numrad/)), sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(albsn_perroad) == (/bounds%endl, numrad/)), sourcefile, __LINE__) @@ -497,10 +529,10 @@ subroutine SnowAlbedo (bounds , & caller = 'UrbanAlbedoMod:SnowAlbedo', & h2osno_total = h2osno_total(bounds%begc:bounds%endc)) - do fc = 1,num_urbanc - c = filter_urbanc(fc) + do fc = 1,num_urbanc_coszen_gt0 + c = filter_urbanc_coszen_gt0(fc) l = col%landunit(c) - if (coszen(l) > 0._r8 .and. h2osno_total(c) > 0._r8) then + if (h2osno_total(c) > 0._r8) then if (col%itype(c) == icol_roof) then albsn_roof(l,1) = snal0 albsn_roof(l,2) = snal1 @@ -528,8 +560,9 @@ subroutine SnowAlbedo (bounds , & end subroutine SnowAlbedo !----------------------------------------------------------------------- - subroutine incident_direct (bounds , & - num_urbanl, filter_urbanl, canyon_hwr, coszen, zen , & + subroutine incident_direct (bounds, & + num_urbanl_coszen_gt0, filter_urbanl_coszen_gt0, & + num_nourbanl_coszen_gt0, filter_nourbanl_coszen_gt0, canyon_hwr, zen, & sdir, sdir_road, sdir_sunwall, sdir_shadewall) ! ! !DESCRIPTION: @@ -567,10 +600,11 @@ subroutine incident_direct (bounds , & ! ! !ARGUMENTS: type(bounds_type), intent(in) :: bounds - integer , intent(in) :: num_urbanl ! number of urban landunits - integer , intent(in) :: filter_urbanl(:) ! urban landunit filter + integer , intent(in) :: num_urbanl_coszen_gt0 ! number of urban landunits with coszen > 0 + integer , intent(in) :: filter_urbanl_coszen_gt0(:) ! filter for urban landunits with coszen > 0 + integer , intent(in) :: num_nourbanl_coszen_gt0 ! number of urban landunits with coszen <= 0 + integer , intent(in) :: filter_nourbanl_coszen_gt0(:) ! filter for urban landunits with coszen <= 0 real(r8), intent(in) :: canyon_hwr( bounds%begl: ) ! ratio of building height to street width [landunit] - real(r8), intent(in) :: coszen( bounds%begl: ) ! cosine solar zenith angle [landunit] real(r8), intent(in) :: zen( bounds%begl: ) ! solar zenith angle (radians) [landunit] real(r8), intent(in) :: sdir( bounds%begl: , 1: ) ! direct beam solar radiation incident on horizontal surface [landunit, numrad] real(r8), intent(out) :: sdir_road( bounds%begl: , 1: ) ! direct beam solar radiation incident on road per unit incident flux [landunit, numrad] @@ -595,54 +629,49 @@ subroutine incident_direct (bounds , & ! Enforce expected array sizes SHR_ASSERT_ALL_FL((ubound(canyon_hwr) == (/bounds%endl/)), sourcefile, __LINE__) - SHR_ASSERT_ALL_FL((ubound(coszen) == (/bounds%endl/)), sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(zen) == (/bounds%endl/)), sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(sdir) == (/bounds%endl, numrad/)), sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(sdir_road) == (/bounds%endl, numrad/)), sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(sdir_sunwall) == (/bounds%endl, numrad/)), sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(sdir_shadewall) == (/bounds%endl, numrad/)), sourcefile, __LINE__) - do fl = 1,num_urbanl - l = filter_urbanl(fl) - if (coszen(l) > 0._r8) then - theta0(l) = asin(min( (1._r8/(canyon_hwr(l)*tan(max(zen(l),0.000001_r8)))), 1._r8 )) - tanzen(l) = tan(zen(l)) - end if + do fl = 1,num_urbanl_coszen_gt0 + l = filter_urbanl_coszen_gt0(fl) + theta0(l) = asin(min( (1._r8/(canyon_hwr(l)*tan(max(zen(l),0.000001_r8)))), 1._r8 )) + tanzen(l) = tan(zen(l)) end do do ib = 1,numrad - do fl = 1,num_urbanl - l = filter_urbanl(fl) - if (coszen(l) > 0._r8) then - sdir_shadewall(l,ib) = 0._r8 + do fl = 1,num_urbanl_coszen_gt0 + l = filter_urbanl_coszen_gt0(fl) + sdir_shadewall(l,ib) = 0._r8 - ! incident solar radiation on wall and road integrated over all canyon orientations (0 <= theta <= pi/2) + ! incident solar radiation on wall and road integrated over all canyon orientations (0 <= theta <= pi/2) - sdir_road(l,ib) = sdir(l,ib) * & - (2._r8*theta0(l)/rpi - 2./rpi*canyon_hwr(l)*tanzen(l)*(1._r8-cos(theta0(l)))) - sdir_sunwall(l,ib) = 2._r8 * sdir(l,ib) * ((1._r8/canyon_hwr(l))* & - (0.5_r8-theta0(l)/rpi) + (1._r8/rpi)*tanzen(l)*(1._r8-cos(theta0(l)))) + sdir_road(l,ib) = sdir(l,ib) * & + (2._r8*theta0(l)/rpi - 2./rpi*canyon_hwr(l)*tanzen(l)*(1._r8-cos(theta0(l)))) + sdir_sunwall(l,ib) = 2._r8 * sdir(l,ib) * ((1._r8/canyon_hwr(l))* & + (0.5_r8-theta0(l)/rpi) + (1._r8/rpi)*tanzen(l)*(1._r8-cos(theta0(l)))) - ! conservation check for road and wall. need to use wall fluxes converted to ground area + ! conservation check for road and wall. need to use wall fluxes converted to ground area - swall_projected = (sdir_shadewall(l,ib) + sdir_sunwall(l,ib)) * canyon_hwr(l) - err1(l) = sdir(l,ib) - (sdir_road(l,ib) + swall_projected) - else - sdir_road(l,ib) = 0._r8 - sdir_sunwall(l,ib) = 0._r8 - sdir_shadewall(l,ib) = 0._r8 - endif + swall_projected = (sdir_shadewall(l,ib) + sdir_sunwall(l,ib)) * canyon_hwr(l) + err1(l) = sdir(l,ib) - (sdir_road(l,ib) + swall_projected) + end do + do fl = 1,num_nourbanl_coszen_gt0 + l = filter_nourbanl_coszen_gt0(fl) + sdir_road(l,ib) = 0._r8 + sdir_sunwall(l,ib) = 0._r8 + sdir_shadewall(l,ib) = 0._r8 end do - do fl = 1,num_urbanl - l = filter_urbanl(fl) - if (coszen(l) > 0._r8) then - if (abs(err1(l)) > 0.001_r8) then - write (iulog,*) 'urban direct beam solar radiation balance error',err1(l) - write (iulog,*) 'clm model is stopping' - call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit, msg=errmsg(sourcefile, __LINE__)) - endif + do fl = 1,num_urbanl_coszen_gt0 + l = filter_urbanl_coszen_gt0(fl) + if (abs(err1(l)) > 0.001_r8) then + write (iulog,*) 'urban direct beam solar radiation balance error',err1(l) + write (iulog,*) 'clm model is stopping' + call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit, msg=errmsg(sourcefile, __LINE__)) endif end do @@ -650,41 +679,37 @@ subroutine incident_direct (bounds , & ! sum sroad and swall over all canyon orientations (0 <= theta <= pi/2) if (numchk) then - do fl = 1,num_urbanl - l = filter_urbanl(fl) - if (coszen(l) > 0._r8) then - sumr = 0._r8 - sumw = 0._r8 - num = 0._r8 - do i = 1, 9000 - theta = i/100._r8 * rpi/180._r8 - zen0 = atan(1._r8/(canyon_hwr(l)*sin(theta))) - if (zen(l) >= zen0) then - sumr = sumr + 0._r8 - sumw = sumw + sdir(l,ib) / canyon_hwr(l) - else - sumr = sumr + sdir(l,ib) * (1._r8-canyon_hwr(l)*sin(theta)*tanzen(l)) - sumw = sumw + sdir(l,ib) * sin(theta)*tanzen(l) - end if - num = num + 1._r8 - end do - err2(l) = sumr/num - sdir_road(l,ib) - err3(l) = sumw/num - sdir_sunwall(l,ib) - endif - end do - do fl = 1,num_urbanl - l = filter_urbanl(fl) - if (coszen(l) > 0._r8) then - if (abs(err2(l)) > 0.0006_r8 ) then - write (iulog,*) 'urban road incident direct beam solar radiation error',err2(l) - write (iulog,*) 'clm model is stopping' - call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit, msg=errmsg(sourcefile, __LINE__)) - endif - if (abs(err3(l)) > 0.0006_r8 ) then - write (iulog,*) 'urban wall incident direct beam solar radiation error',err3(l) - write (iulog,*) 'clm model is stopping' - call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit, msg=errmsg(sourcefile, __LINE__)) + do fl = 1,num_urbanl_coszen_gt0 + l = filter_urbanl_coszen_gt0(fl) + sumr = 0._r8 + sumw = 0._r8 + num = 0._r8 + do i = 1, 9000 + theta = i/100._r8 * rpi/180._r8 + zen0 = atan(1._r8/(canyon_hwr(l)*sin(theta))) + if (zen(l) >= zen0) then + sumr = sumr + 0._r8 + sumw = sumw + sdir(l,ib) / canyon_hwr(l) + else + sumr = sumr + sdir(l,ib) * (1._r8-canyon_hwr(l)*sin(theta)*tanzen(l)) + sumw = sumw + sdir(l,ib) * sin(theta)*tanzen(l) end if + num = num + 1._r8 + end do + err2(l) = sumr/num - sdir_road(l,ib) + err3(l) = sumw/num - sdir_sunwall(l,ib) + end do + do fl = 1,num_urbanl_coszen_gt0 + l = filter_urbanl_coszen_gt0(fl) + if (abs(err2(l)) > 0.0006_r8 ) then + write (iulog,*) 'urban road incident direct beam solar radiation error',err2(l) + write (iulog,*) 'clm model is stopping' + call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit, msg=errmsg(sourcefile, __LINE__)) + endif + if (abs(err3(l)) > 0.0006_r8 ) then + write (iulog,*) 'urban wall incident direct beam solar radiation error',err3(l) + write (iulog,*) 'clm model is stopping' + call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit, msg=errmsg(sourcefile, __LINE__)) end if end do end if @@ -695,7 +720,7 @@ end subroutine incident_direct !----------------------------------------------------------------------- subroutine incident_diffuse (bounds, & - num_urbanl, filter_urbanl, canyon_hwr, & + num_urbanl_coszen_gt0, filter_urbanl_coszen_gt0, canyon_hwr, & sdif, sdif_road, sdif_sunwall, sdif_shadewall, & urbanparams_inst) ! @@ -707,8 +732,8 @@ subroutine incident_diffuse (bounds, & ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds - integer , intent(in) :: num_urbanl ! number of urban landunits - integer , intent(in) :: filter_urbanl(:) ! urban landunit filter + integer , intent(in) :: num_urbanl_coszen_gt0 ! number of urban landunits with coszen > 0 + integer , intent(in) :: filter_urbanl_coszen_gt0(:) ! filter for urban landunits with coszen > 0 real(r8) , intent(in) :: canyon_hwr ( bounds%begl: ) ! ratio of building height to street width [landunit] real(r8) , intent(in) :: sdif ( bounds%begl: , 1: ) ! diffuse solar radiation incident on horizontal surface [landunit, numrad] real(r8) , intent(out) :: sdif_road ( bounds%begl: , 1: ) ! diffuse solar radiation incident on road [landunit, numrad] @@ -738,8 +763,8 @@ subroutine incident_diffuse (bounds, & ! diffuse solar and conservation check. need to convert wall fluxes to ground area - do fl = 1,num_urbanl - l = filter_urbanl(fl) + do fl = 1,num_urbanl_coszen_gt0 + l = filter_urbanl_coszen_gt0(fl) sdif_road(l,ib) = sdif(l,ib) * vf_sr(l) sdif_sunwall(l,ib) = sdif(l,ib) * vf_sw(l) sdif_shadewall(l,ib) = sdif(l,ib) * vf_sw(l) @@ -750,8 +775,8 @@ subroutine incident_diffuse (bounds, & ! error check - do fl = 1, num_urbanl - l = filter_urbanl(fl) + do fl = 1, num_urbanl_coszen_gt0 + l = filter_urbanl_coszen_gt0(fl) if (abs(err(l)) > 0.001_r8) then write (iulog,*) 'urban diffuse solar radiation balance error',err(l) write (iulog,*) 'clm model is stopping' @@ -767,11 +792,11 @@ end subroutine incident_diffuse !----------------------------------------------------------------------- subroutine net_solar (bounds , & - num_urbanl, filter_urbanl, coszen, canyon_hwr, wtroad_perv, sdir, sdif , & + num_urbanl_coszen_gt0, filter_urbanl_coszen_gt0, canyon_hwr, wtroad_perv, sdir, sdif , & alb_improad_dir, alb_perroad_dir, alb_wall_dir, alb_roof_dir , & alb_improad_dif, alb_perroad_dif, alb_wall_dif, alb_roof_dif , & - sdir_road, sdir_sunwall, sdir_shadewall, & - sdif_road, sdif_sunwall, sdif_shadewall, & + sdir_road, sdir_sunwall, sdir_shadewall , & + sdif_road, sdif_sunwall, sdif_shadewall , & sref_improad_dir, sref_perroad_dir, sref_sunwall_dir, sref_shadewall_dir, sref_roof_dir , & sref_improad_dif, sref_perroad_dif, sref_sunwall_dif, sref_shadewall_dif, sref_roof_dif , & urbanparams_inst, solarabs_inst) @@ -782,9 +807,8 @@ subroutine net_solar (bounds ! ! !ARGUMENTS: type (bounds_type), intent(in) :: bounds - integer , intent(in) :: num_urbanl ! number of urban landunits - integer , intent(in) :: filter_urbanl(:) ! urban landunit filter - real(r8), intent(in) :: coszen ( bounds%begl: ) ! cosine solar zenith angle [landunit] + integer, intent(in) :: num_urbanl_coszen_gt0 ! number of urban landunits with coszen > 0 + integer, intent(in) :: filter_urbanl_coszen_gt0(:) ! filter for urban landunits with coszen > 0 real(r8), intent(in) :: canyon_hwr ( bounds%begl: ) ! ratio of building height to street width [landunit] real(r8), intent(in) :: wtroad_perv ( bounds%begl: ) ! weight of pervious road wrt total road [landunit] real(r8), intent(in) :: sdir ( bounds%begl: , 1: ) ! direct beam solar radiation incident on horizontal surface [landunit, numrad] @@ -897,7 +921,6 @@ subroutine net_solar (bounds !----------------------------------------------------------------------- ! Enforce expected array sizes - SHR_ASSERT_ALL_FL((ubound(coszen) == (/bounds%endl/)), sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(canyon_hwr) == (/bounds%endl/)), sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(wtroad_perv) == (/bounds%endl/)), sourcefile, __LINE__) SHR_ASSERT_ALL_FL((ubound(sdir) == (/bounds%endl, numrad/)), sourcefile, __LINE__) @@ -948,351 +971,345 @@ subroutine net_solar (bounds ! Calculate impervious road - do fl = 1,num_urbanl - l = filter_urbanl(fl) + do fl = 1,num_urbanl_coszen_gt0 + l = filter_urbanl_coszen_gt0(fl) wtroad_imperv(l) = 1._r8 - wtroad_perv(l) end do do ib = 1,numrad - do fl = 1,num_urbanl - l = filter_urbanl(fl) - if (coszen(l) > 0._r8) then + do fl = 1,num_urbanl_coszen_gt0 + l = filter_urbanl_coszen_gt0(fl) + + ! initial absorption and reflection for road and both walls. + ! distribute reflected radiation to sky, road, and walls + ! according to appropriate view factor. radiation reflected to + ! road and walls will undergo multiple reflections within the canyon. + ! do separately for direct beam and diffuse radiation. + + ! direct beam + + road_a_dir(l) = 0.0_r8 + road_r_dir(l) = 0.0_r8 + improad_a_dir(l) = (1._r8-alb_improad_dir(l,ib)) * sdir_road(l,ib) + improad_r_dir(l) = alb_improad_dir(l,ib) * sdir_road(l,ib) + improad_r_sky_dir(l) = improad_r_dir(l) * vf_sr(l) + improad_r_sunwall_dir(l) = improad_r_dir(l) * vf_wr(l) + improad_r_shadewall_dir(l) = improad_r_dir(l) * vf_wr(l) + road_a_dir(l) = road_a_dir(l) + improad_a_dir(l)*wtroad_imperv(l) + road_r_dir(l) = road_r_dir(l) + improad_r_dir(l)*wtroad_imperv(l) + + perroad_a_dir(l) = (1._r8-alb_perroad_dir(l,ib)) * sdir_road(l,ib) + perroad_r_dir(l) = alb_perroad_dir(l,ib) * sdir_road(l,ib) + perroad_r_sky_dir(l) = perroad_r_dir(l) * vf_sr(l) + perroad_r_sunwall_dir(l) = perroad_r_dir(l) * vf_wr(l) + perroad_r_shadewall_dir(l) = perroad_r_dir(l) * vf_wr(l) + road_a_dir(l) = road_a_dir(l) + perroad_a_dir(l)*wtroad_perv(l) + road_r_dir(l) = road_r_dir(l) + perroad_r_dir(l)*wtroad_perv(l) + + road_r_sky_dir(l) = road_r_dir(l) * vf_sr(l) + road_r_sunwall_dir(l) = road_r_dir(l) * vf_wr(l) + road_r_shadewall_dir(l) = road_r_dir(l) * vf_wr(l) + + sunwall_a_dir(l) = (1._r8-alb_wall_dir(l,ib)) * sdir_sunwall(l,ib) + sunwall_r_dir(l) = alb_wall_dir(l,ib) * sdir_sunwall(l,ib) + sunwall_r_sky_dir(l) = sunwall_r_dir(l) * vf_sw(l) + sunwall_r_road_dir(l) = sunwall_r_dir(l) * vf_rw(l) + sunwall_r_shadewall_dir(l) = sunwall_r_dir(l) * vf_ww(l) + + shadewall_a_dir(l) = (1._r8-alb_wall_dir(l,ib)) * sdir_shadewall(l,ib) + shadewall_r_dir(l) = alb_wall_dir(l,ib) * sdir_shadewall(l,ib) + shadewall_r_sky_dir(l) = shadewall_r_dir(l) * vf_sw(l) + shadewall_r_road_dir(l) = shadewall_r_dir(l) * vf_rw(l) + shadewall_r_sunwall_dir(l) = shadewall_r_dir(l) * vf_ww(l) + + ! diffuse + + road_a_dif(l) = 0.0_r8 + road_r_dif(l) = 0.0_r8 + improad_a_dif(l) = (1._r8-alb_improad_dif(l,ib)) * sdif_road(l,ib) + improad_r_dif(l) = alb_improad_dif(l,ib) * sdif_road(l,ib) + improad_r_sky_dif(l) = improad_r_dif(l) * vf_sr(l) + improad_r_sunwall_dif(l) = improad_r_dif(l) * vf_wr(l) + improad_r_shadewall_dif(l) = improad_r_dif(l) * vf_wr(l) + road_a_dif(l) = road_a_dif(l) + improad_a_dif(l)*wtroad_imperv(l) + road_r_dif(l) = road_r_dif(l) + improad_r_dif(l)*wtroad_imperv(l) + + perroad_a_dif(l) = (1._r8-alb_perroad_dif(l,ib)) * sdif_road(l,ib) + perroad_r_dif(l) = alb_perroad_dif(l,ib) * sdif_road(l,ib) + perroad_r_sky_dif(l) = perroad_r_dif(l) * vf_sr(l) + perroad_r_sunwall_dif(l) = perroad_r_dif(l) * vf_wr(l) + perroad_r_shadewall_dif(l) = perroad_r_dif(l) * vf_wr(l) + road_a_dif(l) = road_a_dif(l) + perroad_a_dif(l)*wtroad_perv(l) + road_r_dif(l) = road_r_dif(l) + perroad_r_dif(l)*wtroad_perv(l) + + road_r_sky_dif(l) = road_r_dif(l) * vf_sr(l) + road_r_sunwall_dif(l) = road_r_dif(l) * vf_wr(l) + road_r_shadewall_dif(l) = road_r_dif(l) * vf_wr(l) + + sunwall_a_dif(l) = (1._r8-alb_wall_dif(l,ib)) * sdif_sunwall(l,ib) + sunwall_r_dif(l) = alb_wall_dif(l,ib) * sdif_sunwall(l,ib) + sunwall_r_sky_dif(l) = sunwall_r_dif(l) * vf_sw(l) + sunwall_r_road_dif(l) = sunwall_r_dif(l) * vf_rw(l) + sunwall_r_shadewall_dif(l) = sunwall_r_dif(l) * vf_ww(l) + + shadewall_a_dif(l) = (1._r8-alb_wall_dif(l,ib)) * sdif_shadewall(l,ib) + shadewall_r_dif(l) = alb_wall_dif(l,ib) * sdif_shadewall(l,ib) + shadewall_r_sky_dif(l) = shadewall_r_dif(l) * vf_sw(l) + shadewall_r_road_dif(l) = shadewall_r_dif(l) * vf_rw(l) + shadewall_r_sunwall_dif(l) = shadewall_r_dif(l) * vf_ww(l) + + ! initialize sum of direct and diffuse solar absorption and reflection for road and both walls + + sabs_improad_dir(l,ib) = improad_a_dir(l) + sabs_perroad_dir(l,ib) = perroad_a_dir(l) + sabs_sunwall_dir(l,ib) = sunwall_a_dir(l) + sabs_shadewall_dir(l,ib) = shadewall_a_dir(l) + + sabs_improad_dif(l,ib) = improad_a_dif(l) + sabs_perroad_dif(l,ib) = perroad_a_dif(l) + sabs_sunwall_dif(l,ib) = sunwall_a_dif(l) + sabs_shadewall_dif(l,ib) = shadewall_a_dif(l) + + sref_improad_dir(l,ib) = improad_r_sky_dir(l) + sref_perroad_dir(l,ib) = perroad_r_sky_dir(l) + sref_sunwall_dir(l,ib) = sunwall_r_sky_dir(l) + sref_shadewall_dir(l,ib) = shadewall_r_sky_dir(l) + + sref_improad_dif(l,ib) = improad_r_sky_dif(l) + sref_perroad_dif(l,ib) = perroad_r_sky_dif(l) + sref_sunwall_dif(l,ib) = sunwall_r_sky_dif(l) + sref_shadewall_dif(l,ib) = shadewall_r_sky_dif(l) + + end do + + ! absorption and reflection for walls and road with multiple reflections + ! (i.e., absorb and reflect initial reflection in canyon and allow for + ! subsequent scattering) + ! + ! (1) absorption and reflection of scattered solar radiation + ! road: reflected fluxes from walls need to be projected to ground area + ! wall: reflected flux from road needs to be projected to wall area + ! + ! (2) add absorbed radiation for ith reflection to total absorbed + ! + ! (3) distribute reflected radiation to sky, road, and walls according to view factors + ! + ! (4) add solar reflection to sky for ith reflection to total reflection + ! + ! (5) stop iteration when absorption for ith reflection is less than some nominal amount. + ! small convergence criteria is required to ensure solar radiation is conserved + ! + ! do separately for direct beam and diffuse + + do fl = 1,num_urbanl_coszen_gt0 + l = filter_urbanl_coszen_gt0(fl) + + ! reflected direct beam + + do iter_dir = 1, n + ! step (1) + + stot(l) = (sunwall_r_road_dir(l) + shadewall_r_road_dir(l))*canyon_hwr(l) + + road_a_dir(l) = 0.0_r8 + road_r_dir(l) = 0.0_r8 + improad_a_dir(l) = (1._r8-alb_improad_dir(l,ib)) * stot(l) + improad_r_dir(l) = alb_improad_dir(l,ib) * stot(l) + road_a_dir(l) = road_a_dir(l) + improad_a_dir(l)*wtroad_imperv(l) + road_r_dir(l) = road_r_dir(l) + improad_r_dir(l)*wtroad_imperv(l) + perroad_a_dir(l) = (1._r8-alb_perroad_dir(l,ib)) * stot(l) + perroad_r_dir(l) = alb_perroad_dir(l,ib) * stot(l) + road_a_dir(l) = road_a_dir(l) + perroad_a_dir(l)*wtroad_perv(l) + road_r_dir(l) = road_r_dir(l) + perroad_r_dir(l)*wtroad_perv(l) + + stot(l) = road_r_sunwall_dir(l)/canyon_hwr(l) + shadewall_r_sunwall_dir(l) + sunwall_a_dir(l) = (1._r8-alb_wall_dir(l,ib)) * stot(l) + sunwall_r_dir(l) = alb_wall_dir(l,ib) * stot(l) + + stot(l) = road_r_shadewall_dir(l)/canyon_hwr(l) + sunwall_r_shadewall_dir(l) + shadewall_a_dir(l) = (1._r8-alb_wall_dir(l,ib)) * stot(l) + shadewall_r_dir(l) = alb_wall_dir(l,ib) * stot(l) - ! initial absorption and reflection for road and both walls. - ! distribute reflected radiation to sky, road, and walls - ! according to appropriate view factor. radiation reflected to - ! road and walls will undergo multiple reflections within the canyon. - ! do separately for direct beam and diffuse radiation. + ! step (2) - ! direct beam + sabs_improad_dir(l,ib) = sabs_improad_dir(l,ib) + improad_a_dir(l) + sabs_perroad_dir(l,ib) = sabs_perroad_dir(l,ib) + perroad_a_dir(l) + sabs_sunwall_dir(l,ib) = sabs_sunwall_dir(l,ib) + sunwall_a_dir(l) + sabs_shadewall_dir(l,ib) = sabs_shadewall_dir(l,ib) + shadewall_a_dir(l) + + ! step (3) - road_a_dir(l) = 0.0_r8 - road_r_dir(l) = 0.0_r8 - improad_a_dir(l) = (1._r8-alb_improad_dir(l,ib)) * sdir_road(l,ib) - improad_r_dir(l) = alb_improad_dir(l,ib) * sdir_road(l,ib) improad_r_sky_dir(l) = improad_r_dir(l) * vf_sr(l) improad_r_sunwall_dir(l) = improad_r_dir(l) * vf_wr(l) improad_r_shadewall_dir(l) = improad_r_dir(l) * vf_wr(l) - road_a_dir(l) = road_a_dir(l) + improad_a_dir(l)*wtroad_imperv(l) - road_r_dir(l) = road_r_dir(l) + improad_r_dir(l)*wtroad_imperv(l) - perroad_a_dir(l) = (1._r8-alb_perroad_dir(l,ib)) * sdir_road(l,ib) - perroad_r_dir(l) = alb_perroad_dir(l,ib) * sdir_road(l,ib) perroad_r_sky_dir(l) = perroad_r_dir(l) * vf_sr(l) perroad_r_sunwall_dir(l) = perroad_r_dir(l) * vf_wr(l) perroad_r_shadewall_dir(l) = perroad_r_dir(l) * vf_wr(l) - road_a_dir(l) = road_a_dir(l) + perroad_a_dir(l)*wtroad_perv(l) - road_r_dir(l) = road_r_dir(l) + perroad_r_dir(l)*wtroad_perv(l) road_r_sky_dir(l) = road_r_dir(l) * vf_sr(l) road_r_sunwall_dir(l) = road_r_dir(l) * vf_wr(l) road_r_shadewall_dir(l) = road_r_dir(l) * vf_wr(l) - sunwall_a_dir(l) = (1._r8-alb_wall_dir(l,ib)) * sdir_sunwall(l,ib) - sunwall_r_dir(l) = alb_wall_dir(l,ib) * sdir_sunwall(l,ib) sunwall_r_sky_dir(l) = sunwall_r_dir(l) * vf_sw(l) sunwall_r_road_dir(l) = sunwall_r_dir(l) * vf_rw(l) sunwall_r_shadewall_dir(l) = sunwall_r_dir(l) * vf_ww(l) - shadewall_a_dir(l) = (1._r8-alb_wall_dir(l,ib)) * sdir_shadewall(l,ib) - shadewall_r_dir(l) = alb_wall_dir(l,ib) * sdir_shadewall(l,ib) shadewall_r_sky_dir(l) = shadewall_r_dir(l) * vf_sw(l) shadewall_r_road_dir(l) = shadewall_r_dir(l) * vf_rw(l) shadewall_r_sunwall_dir(l) = shadewall_r_dir(l) * vf_ww(l) - ! diffuse + ! step (4) + + sref_improad_dir(l,ib) = sref_improad_dir(l,ib) + improad_r_sky_dir(l) + sref_perroad_dir(l,ib) = sref_perroad_dir(l,ib) + perroad_r_sky_dir(l) + sref_sunwall_dir(l,ib) = sref_sunwall_dir(l,ib) + sunwall_r_sky_dir(l) + sref_shadewall_dir(l,ib) = sref_shadewall_dir(l,ib) + shadewall_r_sky_dir(l) + + ! step (5) + + crit = max(road_a_dir(l), sunwall_a_dir(l), shadewall_a_dir(l)) + if (crit < errcrit) exit + end do + if (iter_dir >= n) then + write (iulog,*) 'urban net solar radiation error: no convergence, direct beam' + write (iulog,*) 'clm model is stopping' + call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit, msg=errmsg(sourcefile, __LINE__)) + endif + + ! reflected diffuse + + do iter_dif = 1, n + ! step (1) + + stot(l) = (sunwall_r_road_dif(l) + shadewall_r_road_dif(l))*canyon_hwr(l) + road_a_dif(l) = 0.0_r8 + road_r_dif(l) = 0.0_r8 + improad_a_dif(l) = (1._r8-alb_improad_dif(l,ib)) * stot(l) + improad_r_dif(l) = alb_improad_dif(l,ib) * stot(l) + road_a_dif(l) = road_a_dif(l) + improad_a_dif(l)*wtroad_imperv(l) + road_r_dif(l) = road_r_dif(l) + improad_r_dif(l)*wtroad_imperv(l) + perroad_a_dif(l) = (1._r8-alb_perroad_dif(l,ib)) * stot(l) + perroad_r_dif(l) = alb_perroad_dif(l,ib) * stot(l) + road_a_dif(l) = road_a_dif(l) + perroad_a_dif(l)*wtroad_perv(l) + road_r_dif(l) = road_r_dif(l) + perroad_r_dif(l)*wtroad_perv(l) + + stot(l) = road_r_sunwall_dif(l)/canyon_hwr(l) + shadewall_r_sunwall_dif(l) + sunwall_a_dif(l) = (1._r8-alb_wall_dif(l,ib)) * stot(l) + sunwall_r_dif(l) = alb_wall_dif(l,ib) * stot(l) + + stot(l) = road_r_shadewall_dif(l)/canyon_hwr(l) + sunwall_r_shadewall_dif(l) + shadewall_a_dif(l) = (1._r8-alb_wall_dif(l,ib)) * stot(l) + shadewall_r_dif(l) = alb_wall_dif(l,ib) * stot(l) + + ! step (2) + + sabs_improad_dif(l,ib) = sabs_improad_dif(l,ib) + improad_a_dif(l) + sabs_perroad_dif(l,ib) = sabs_perroad_dif(l,ib) + perroad_a_dif(l) + sabs_sunwall_dif(l,ib) = sabs_sunwall_dif(l,ib) + sunwall_a_dif(l) + sabs_shadewall_dif(l,ib) = sabs_shadewall_dif(l,ib) + shadewall_a_dif(l) + + ! step (3) - road_a_dif(l) = 0.0_r8 - road_r_dif(l) = 0.0_r8 - improad_a_dif(l) = (1._r8-alb_improad_dif(l,ib)) * sdif_road(l,ib) - improad_r_dif(l) = alb_improad_dif(l,ib) * sdif_road(l,ib) improad_r_sky_dif(l) = improad_r_dif(l) * vf_sr(l) improad_r_sunwall_dif(l) = improad_r_dif(l) * vf_wr(l) improad_r_shadewall_dif(l) = improad_r_dif(l) * vf_wr(l) - road_a_dif(l) = road_a_dif(l) + improad_a_dif(l)*wtroad_imperv(l) - road_r_dif(l) = road_r_dif(l) + improad_r_dif(l)*wtroad_imperv(l) - perroad_a_dif(l) = (1._r8-alb_perroad_dif(l,ib)) * sdif_road(l,ib) - perroad_r_dif(l) = alb_perroad_dif(l,ib) * sdif_road(l,ib) perroad_r_sky_dif(l) = perroad_r_dif(l) * vf_sr(l) perroad_r_sunwall_dif(l) = perroad_r_dif(l) * vf_wr(l) perroad_r_shadewall_dif(l) = perroad_r_dif(l) * vf_wr(l) - road_a_dif(l) = road_a_dif(l) + perroad_a_dif(l)*wtroad_perv(l) - road_r_dif(l) = road_r_dif(l) + perroad_r_dif(l)*wtroad_perv(l) road_r_sky_dif(l) = road_r_dif(l) * vf_sr(l) road_r_sunwall_dif(l) = road_r_dif(l) * vf_wr(l) road_r_shadewall_dif(l) = road_r_dif(l) * vf_wr(l) - sunwall_a_dif(l) = (1._r8-alb_wall_dif(l,ib)) * sdif_sunwall(l,ib) - sunwall_r_dif(l) = alb_wall_dif(l,ib) * sdif_sunwall(l,ib) sunwall_r_sky_dif(l) = sunwall_r_dif(l) * vf_sw(l) sunwall_r_road_dif(l) = sunwall_r_dif(l) * vf_rw(l) sunwall_r_shadewall_dif(l) = sunwall_r_dif(l) * vf_ww(l) - shadewall_a_dif(l) = (1._r8-alb_wall_dif(l,ib)) * sdif_shadewall(l,ib) - shadewall_r_dif(l) = alb_wall_dif(l,ib) * sdif_shadewall(l,ib) shadewall_r_sky_dif(l) = shadewall_r_dif(l) * vf_sw(l) - shadewall_r_road_dif(l) = shadewall_r_dif(l) * vf_rw(l) - shadewall_r_sunwall_dif(l) = shadewall_r_dif(l) * vf_ww(l) - - ! initialize sum of direct and diffuse solar absorption and reflection for road and both walls - - sabs_improad_dir(l,ib) = improad_a_dir(l) - sabs_perroad_dir(l,ib) = perroad_a_dir(l) - sabs_sunwall_dir(l,ib) = sunwall_a_dir(l) - sabs_shadewall_dir(l,ib) = shadewall_a_dir(l) - - sabs_improad_dif(l,ib) = improad_a_dif(l) - sabs_perroad_dif(l,ib) = perroad_a_dif(l) - sabs_sunwall_dif(l,ib) = sunwall_a_dif(l) - sabs_shadewall_dif(l,ib) = shadewall_a_dif(l) - - sref_improad_dir(l,ib) = improad_r_sky_dir(l) - sref_perroad_dir(l,ib) = perroad_r_sky_dir(l) - sref_sunwall_dir(l,ib) = sunwall_r_sky_dir(l) - sref_shadewall_dir(l,ib) = shadewall_r_sky_dir(l) - - sref_improad_dif(l,ib) = improad_r_sky_dif(l) - sref_perroad_dif(l,ib) = perroad_r_sky_dif(l) - sref_sunwall_dif(l,ib) = sunwall_r_sky_dif(l) - sref_shadewall_dif(l,ib) = shadewall_r_sky_dif(l) - endif - - end do + shadewall_r_road_dif(l) = shadewall_r_dif(l) * vf_rw(l) + shadewall_r_sunwall_dif(l) = shadewall_r_dif(l) * vf_ww(l) - ! absorption and reflection for walls and road with multiple reflections - ! (i.e., absorb and reflect initial reflection in canyon and allow for - ! subsequent scattering) - ! - ! (1) absorption and reflection of scattered solar radiation - ! road: reflected fluxes from walls need to be projected to ground area - ! wall: reflected flux from road needs to be projected to wall area - ! - ! (2) add absorbed radiation for ith reflection to total absorbed - ! - ! (3) distribute reflected radiation to sky, road, and walls according to view factors - ! - ! (4) add solar reflection to sky for ith reflection to total reflection - ! - ! (5) stop iteration when absorption for ith reflection is less than some nominal amount. - ! small convergence criteria is required to ensure solar radiation is conserved - ! - ! do separately for direct beam and diffuse + ! step (4) - do fl = 1,num_urbanl - l = filter_urbanl(fl) - if (coszen(l) > 0._r8) then - - ! reflected direct beam - - do iter_dir = 1, n - ! step (1) - - stot(l) = (sunwall_r_road_dir(l) + shadewall_r_road_dir(l))*canyon_hwr(l) - - road_a_dir(l) = 0.0_r8 - road_r_dir(l) = 0.0_r8 - improad_a_dir(l) = (1._r8-alb_improad_dir(l,ib)) * stot(l) - improad_r_dir(l) = alb_improad_dir(l,ib) * stot(l) - road_a_dir(l) = road_a_dir(l) + improad_a_dir(l)*wtroad_imperv(l) - road_r_dir(l) = road_r_dir(l) + improad_r_dir(l)*wtroad_imperv(l) - perroad_a_dir(l) = (1._r8-alb_perroad_dir(l,ib)) * stot(l) - perroad_r_dir(l) = alb_perroad_dir(l,ib) * stot(l) - road_a_dir(l) = road_a_dir(l) + perroad_a_dir(l)*wtroad_perv(l) - road_r_dir(l) = road_r_dir(l) + perroad_r_dir(l)*wtroad_perv(l) + sref_improad_dif(l,ib) = sref_improad_dif(l,ib) + improad_r_sky_dif(l) + sref_perroad_dif(l,ib) = sref_perroad_dif(l,ib) + perroad_r_sky_dif(l) + sref_sunwall_dif(l,ib) = sref_sunwall_dif(l,ib) + sunwall_r_sky_dif(l) + sref_shadewall_dif(l,ib) = sref_shadewall_dif(l,ib) + shadewall_r_sky_dif(l) - stot(l) = road_r_sunwall_dir(l)/canyon_hwr(l) + shadewall_r_sunwall_dir(l) - sunwall_a_dir(l) = (1._r8-alb_wall_dir(l,ib)) * stot(l) - sunwall_r_dir(l) = alb_wall_dir(l,ib) * stot(l) + ! step (5) - stot(l) = road_r_shadewall_dir(l)/canyon_hwr(l) + sunwall_r_shadewall_dir(l) - shadewall_a_dir(l) = (1._r8-alb_wall_dir(l,ib)) * stot(l) - shadewall_r_dir(l) = alb_wall_dir(l,ib) * stot(l) - - ! step (2) - - sabs_improad_dir(l,ib) = sabs_improad_dir(l,ib) + improad_a_dir(l) - sabs_perroad_dir(l,ib) = sabs_perroad_dir(l,ib) + perroad_a_dir(l) - sabs_sunwall_dir(l,ib) = sabs_sunwall_dir(l,ib) + sunwall_a_dir(l) - sabs_shadewall_dir(l,ib) = sabs_shadewall_dir(l,ib) + shadewall_a_dir(l) + crit = max(road_a_dif(l), sunwall_a_dif(l), shadewall_a_dif(l)) + if (crit < errcrit) exit + end do + if (iter_dif >= n) then + write (iulog,*) 'urban net solar radiation error: no convergence, diffuse' + write (iulog,*) 'clm model is stopping' + call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit, msg=errmsg(sourcefile, __LINE__)) + endif - ! step (3) + ! total reflected by canyon - sum of solar reflection to sky from canyon. + ! project wall fluxes to horizontal surface + + sref_canyon_dir(l) = 0.0_r8 + sref_canyon_dif(l) = 0.0_r8 + sref_canyon_dir(l) = sref_canyon_dir(l) + sref_improad_dir(l,ib)*wtroad_imperv(l) + sref_canyon_dif(l) = sref_canyon_dif(l) + sref_improad_dif(l,ib)*wtroad_imperv(l) + sref_canyon_dir(l) = sref_canyon_dir(l) + sref_perroad_dir(l,ib)*wtroad_perv(l) + sref_canyon_dif(l) = sref_canyon_dif(l) + sref_perroad_dif(l,ib)*wtroad_perv(l) + sref_canyon_dir(l) = sref_canyon_dir(l) + (sref_sunwall_dir(l,ib) + sref_shadewall_dir(l,ib))*canyon_hwr(l) + sref_canyon_dif(l) = sref_canyon_dif(l) + (sref_sunwall_dif(l,ib) + sref_shadewall_dif(l,ib))*canyon_hwr(l) + + ! total absorbed by canyon. project wall fluxes to horizontal surface + + sabs_canyon_dir(l) = 0.0_r8 + sabs_canyon_dif(l) = 0.0_r8 + sabs_canyon_dir(l) = sabs_canyon_dir(l) + sabs_improad_dir(l,ib)*wtroad_imperv(l) + sabs_canyon_dif(l) = sabs_canyon_dif(l) + sabs_improad_dif(l,ib)*wtroad_imperv(l) + sabs_canyon_dir(l) = sabs_canyon_dir(l) + sabs_perroad_dir(l,ib)*wtroad_perv(l) + sabs_canyon_dif(l) = sabs_canyon_dif(l) + sabs_perroad_dif(l,ib)*wtroad_perv(l) + sabs_canyon_dir(l) = sabs_canyon_dir(l) + (sabs_sunwall_dir(l,ib) + sabs_shadewall_dir(l,ib))*canyon_hwr(l) + sabs_canyon_dif(l) = sabs_canyon_dif(l) + (sabs_sunwall_dif(l,ib) + sabs_shadewall_dif(l,ib))*canyon_hwr(l) + + ! conservation check. note: previous conservation checks confirm partioning of total direct + ! beam and diffuse radiation from atmosphere to road and walls is conserved as + ! sdir (from atmosphere) = sdir_road + (sdir_sunwall + sdir_shadewall)*canyon_hwr + ! sdif (from atmosphere) = sdif_road + (sdif_sunwall + sdif_shadewall)*canyon_hwr + + stot_dir(l) = sdir_road(l,ib) + (sdir_sunwall(l,ib) + sdir_shadewall(l,ib))*canyon_hwr(l) + stot_dif(l) = sdif_road(l,ib) + (sdif_sunwall(l,ib) + sdif_shadewall(l,ib))*canyon_hwr(l) + + err = stot_dir(l) + stot_dif(l) & + - (sabs_canyon_dir(l) + sabs_canyon_dif(l) + sref_canyon_dir(l) + sref_canyon_dif(l)) + if (abs(err) > 0.001_r8 ) then + write(iulog,*)'urban net solar radiation balance error for ib=',ib,' err= ',err + write(iulog,*)' l= ',l,' ib= ',ib + write(iulog,*)' stot_dir = ',stot_dir(l) + write(iulog,*)' stot_dif = ',stot_dif(l) + write(iulog,*)' sabs_canyon_dir = ',sabs_canyon_dir(l) + write(iulog,*)' sabs_canyon_dif = ',sabs_canyon_dif(l) + write(iulog,*)' sref_canyon_dir = ',sref_canyon_dir(l) + write(iulog,*)' sref_canyon_dif = ',sref_canyon_dir(l) + write(iulog,*) 'clm model is stopping' + call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit, msg=errmsg(sourcefile, __LINE__)) + endif - improad_r_sky_dir(l) = improad_r_dir(l) * vf_sr(l) - improad_r_sunwall_dir(l) = improad_r_dir(l) * vf_wr(l) - improad_r_shadewall_dir(l) = improad_r_dir(l) * vf_wr(l) + ! canyon albedo - perroad_r_sky_dir(l) = perroad_r_dir(l) * vf_sr(l) - perroad_r_sunwall_dir(l) = perroad_r_dir(l) * vf_wr(l) - perroad_r_shadewall_dir(l) = perroad_r_dir(l) * vf_wr(l) - - road_r_sky_dir(l) = road_r_dir(l) * vf_sr(l) - road_r_sunwall_dir(l) = road_r_dir(l) * vf_wr(l) - road_r_shadewall_dir(l) = road_r_dir(l) * vf_wr(l) - - sunwall_r_sky_dir(l) = sunwall_r_dir(l) * vf_sw(l) - sunwall_r_road_dir(l) = sunwall_r_dir(l) * vf_rw(l) - sunwall_r_shadewall_dir(l) = sunwall_r_dir(l) * vf_ww(l) - - shadewall_r_sky_dir(l) = shadewall_r_dir(l) * vf_sw(l) - shadewall_r_road_dir(l) = shadewall_r_dir(l) * vf_rw(l) - shadewall_r_sunwall_dir(l) = shadewall_r_dir(l) * vf_ww(l) - - ! step (4) - - sref_improad_dir(l,ib) = sref_improad_dir(l,ib) + improad_r_sky_dir(l) - sref_perroad_dir(l,ib) = sref_perroad_dir(l,ib) + perroad_r_sky_dir(l) - sref_sunwall_dir(l,ib) = sref_sunwall_dir(l,ib) + sunwall_r_sky_dir(l) - sref_shadewall_dir(l,ib) = sref_shadewall_dir(l,ib) + shadewall_r_sky_dir(l) - - ! step (5) - - crit = max(road_a_dir(l), sunwall_a_dir(l), shadewall_a_dir(l)) - if (crit < errcrit) exit - end do - if (iter_dir >= n) then - write (iulog,*) 'urban net solar radiation error: no convergence, direct beam' - write (iulog,*) 'clm model is stopping' - call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit, msg=errmsg(sourcefile, __LINE__)) - endif - - ! reflected diffuse - - do iter_dif = 1, n - ! step (1) - - stot(l) = (sunwall_r_road_dif(l) + shadewall_r_road_dif(l))*canyon_hwr(l) - road_a_dif(l) = 0.0_r8 - road_r_dif(l) = 0.0_r8 - improad_a_dif(l) = (1._r8-alb_improad_dif(l,ib)) * stot(l) - improad_r_dif(l) = alb_improad_dif(l,ib) * stot(l) - road_a_dif(l) = road_a_dif(l) + improad_a_dif(l)*wtroad_imperv(l) - road_r_dif(l) = road_r_dif(l) + improad_r_dif(l)*wtroad_imperv(l) - perroad_a_dif(l) = (1._r8-alb_perroad_dif(l,ib)) * stot(l) - perroad_r_dif(l) = alb_perroad_dif(l,ib) * stot(l) - road_a_dif(l) = road_a_dif(l) + perroad_a_dif(l)*wtroad_perv(l) - road_r_dif(l) = road_r_dif(l) + perroad_r_dif(l)*wtroad_perv(l) - - stot(l) = road_r_sunwall_dif(l)/canyon_hwr(l) + shadewall_r_sunwall_dif(l) - sunwall_a_dif(l) = (1._r8-alb_wall_dif(l,ib)) * stot(l) - sunwall_r_dif(l) = alb_wall_dif(l,ib) * stot(l) - - stot(l) = road_r_shadewall_dif(l)/canyon_hwr(l) + sunwall_r_shadewall_dif(l) - shadewall_a_dif(l) = (1._r8-alb_wall_dif(l,ib)) * stot(l) - shadewall_r_dif(l) = alb_wall_dif(l,ib) * stot(l) - - ! step (2) - - sabs_improad_dif(l,ib) = sabs_improad_dif(l,ib) + improad_a_dif(l) - sabs_perroad_dif(l,ib) = sabs_perroad_dif(l,ib) + perroad_a_dif(l) - sabs_sunwall_dif(l,ib) = sabs_sunwall_dif(l,ib) + sunwall_a_dif(l) - sabs_shadewall_dif(l,ib) = sabs_shadewall_dif(l,ib) + shadewall_a_dif(l) - - ! step (3) - - improad_r_sky_dif(l) = improad_r_dif(l) * vf_sr(l) - improad_r_sunwall_dif(l) = improad_r_dif(l) * vf_wr(l) - improad_r_shadewall_dif(l) = improad_r_dif(l) * vf_wr(l) - - perroad_r_sky_dif(l) = perroad_r_dif(l) * vf_sr(l) - perroad_r_sunwall_dif(l) = perroad_r_dif(l) * vf_wr(l) - perroad_r_shadewall_dif(l) = perroad_r_dif(l) * vf_wr(l) - - road_r_sky_dif(l) = road_r_dif(l) * vf_sr(l) - road_r_sunwall_dif(l) = road_r_dif(l) * vf_wr(l) - road_r_shadewall_dif(l) = road_r_dif(l) * vf_wr(l) - - sunwall_r_sky_dif(l) = sunwall_r_dif(l) * vf_sw(l) - sunwall_r_road_dif(l) = sunwall_r_dif(l) * vf_rw(l) - sunwall_r_shadewall_dif(l) = sunwall_r_dif(l) * vf_ww(l) - - shadewall_r_sky_dif(l) = shadewall_r_dif(l) * vf_sw(l) - shadewall_r_road_dif(l) = shadewall_r_dif(l) * vf_rw(l) - shadewall_r_sunwall_dif(l) = shadewall_r_dif(l) * vf_ww(l) - - ! step (4) - - sref_improad_dif(l,ib) = sref_improad_dif(l,ib) + improad_r_sky_dif(l) - sref_perroad_dif(l,ib) = sref_perroad_dif(l,ib) + perroad_r_sky_dif(l) - sref_sunwall_dif(l,ib) = sref_sunwall_dif(l,ib) + sunwall_r_sky_dif(l) - sref_shadewall_dif(l,ib) = sref_shadewall_dif(l,ib) + shadewall_r_sky_dif(l) - - ! step (5) - - crit = max(road_a_dif(l), sunwall_a_dif(l), shadewall_a_dif(l)) - if (crit < errcrit) exit - end do - if (iter_dif >= n) then - write (iulog,*) 'urban net solar radiation error: no convergence, diffuse' - write (iulog,*) 'clm model is stopping' - call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit, msg=errmsg(sourcefile, __LINE__)) - endif - - ! total reflected by canyon - sum of solar reflection to sky from canyon. - ! project wall fluxes to horizontal surface - - sref_canyon_dir(l) = 0.0_r8 - sref_canyon_dif(l) = 0.0_r8 - sref_canyon_dir(l) = sref_canyon_dir(l) + sref_improad_dir(l,ib)*wtroad_imperv(l) - sref_canyon_dif(l) = sref_canyon_dif(l) + sref_improad_dif(l,ib)*wtroad_imperv(l) - sref_canyon_dir(l) = sref_canyon_dir(l) + sref_perroad_dir(l,ib)*wtroad_perv(l) - sref_canyon_dif(l) = sref_canyon_dif(l) + sref_perroad_dif(l,ib)*wtroad_perv(l) - sref_canyon_dir(l) = sref_canyon_dir(l) + (sref_sunwall_dir(l,ib) + sref_shadewall_dir(l,ib))*canyon_hwr(l) - sref_canyon_dif(l) = sref_canyon_dif(l) + (sref_sunwall_dif(l,ib) + sref_shadewall_dif(l,ib))*canyon_hwr(l) - - ! total absorbed by canyon. project wall fluxes to horizontal surface - - sabs_canyon_dir(l) = 0.0_r8 - sabs_canyon_dif(l) = 0.0_r8 - sabs_canyon_dir(l) = sabs_canyon_dir(l) + sabs_improad_dir(l,ib)*wtroad_imperv(l) - sabs_canyon_dif(l) = sabs_canyon_dif(l) + sabs_improad_dif(l,ib)*wtroad_imperv(l) - sabs_canyon_dir(l) = sabs_canyon_dir(l) + sabs_perroad_dir(l,ib)*wtroad_perv(l) - sabs_canyon_dif(l) = sabs_canyon_dif(l) + sabs_perroad_dif(l,ib)*wtroad_perv(l) - sabs_canyon_dir(l) = sabs_canyon_dir(l) + (sabs_sunwall_dir(l,ib) + sabs_shadewall_dir(l,ib))*canyon_hwr(l) - sabs_canyon_dif(l) = sabs_canyon_dif(l) + (sabs_sunwall_dif(l,ib) + sabs_shadewall_dif(l,ib))*canyon_hwr(l) - - ! conservation check. note: previous conservation checks confirm partioning of total direct - ! beam and diffuse radiation from atmosphere to road and walls is conserved as - ! sdir (from atmosphere) = sdir_road + (sdir_sunwall + sdir_shadewall)*canyon_hwr - ! sdif (from atmosphere) = sdif_road + (sdif_sunwall + sdif_shadewall)*canyon_hwr - - stot_dir(l) = sdir_road(l,ib) + (sdir_sunwall(l,ib) + sdir_shadewall(l,ib))*canyon_hwr(l) - stot_dif(l) = sdif_road(l,ib) + (sdif_sunwall(l,ib) + sdif_shadewall(l,ib))*canyon_hwr(l) - - err = stot_dir(l) + stot_dif(l) & - - (sabs_canyon_dir(l) + sabs_canyon_dif(l) + sref_canyon_dir(l) + sref_canyon_dif(l)) - if (abs(err) > 0.001_r8 ) then - write(iulog,*)'urban net solar radiation balance error for ib=',ib,' err= ',err - write(iulog,*)' l= ',l,' ib= ',ib - write(iulog,*)' stot_dir = ',stot_dir(l) - write(iulog,*)' stot_dif = ',stot_dif(l) - write(iulog,*)' sabs_canyon_dir = ',sabs_canyon_dir(l) - write(iulog,*)' sabs_canyon_dif = ',sabs_canyon_dif(l) - write(iulog,*)' sref_canyon_dir = ',sref_canyon_dir(l) - write(iulog,*)' sref_canyon_dif = ',sref_canyon_dir(l) - write(iulog,*) 'clm model is stopping' - call endrun(subgrid_index=l, subgrid_level=subgrid_level_landunit, msg=errmsg(sourcefile, __LINE__)) - endif - - ! canyon albedo - - canyon_alb_dif(l) = sref_canyon_dif(l) / max(stot_dif(l), 1.e-06_r8) - canyon_alb_dir(l) = sref_canyon_dir(l) / max(stot_dir(l), 1.e-06_r8) - end if + canyon_alb_dif(l) = sref_canyon_dif(l) / max(stot_dif(l), 1.e-06_r8) + canyon_alb_dir(l) = sref_canyon_dir(l) / max(stot_dir(l), 1.e-06_r8) end do ! end of landunit loop - ! Refected and absorbed solar radiation per unit incident radiation for roof + ! Reflected and absorbed solar radiation per unit incident radiation for roof - do fl = 1,num_urbanl - l = filter_urbanl(fl) - if (coszen(l) > 0._r8) then - sref_roof_dir(l,ib) = alb_roof_dir(l,ib) * sdir(l,ib) - sref_roof_dif(l,ib) = alb_roof_dif(l,ib) * sdif(l,ib) - sabs_roof_dir(l,ib) = sdir(l,ib) - sref_roof_dir(l,ib) - sabs_roof_dif(l,ib) = sdif(l,ib) - sref_roof_dif(l,ib) - end if + do fl = 1,num_urbanl_coszen_gt0 + l = filter_urbanl_coszen_gt0(fl) + sref_roof_dir(l,ib) = alb_roof_dir(l,ib) * sdir(l,ib) + sref_roof_dif(l,ib) = alb_roof_dif(l,ib) * sdif(l,ib) + sabs_roof_dir(l,ib) = sdir(l,ib) - sref_roof_dir(l,ib) + sabs_roof_dif(l,ib) = sdif(l,ib) - sref_roof_dif(l,ib) end do end do ! end of radiation band loop 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/WaterDiagnosticBulkType.F90 b/src/biogeophys/WaterDiagnosticBulkType.F90 index dd556a2df6..f91aaca761 100644 --- a/src/biogeophys/WaterDiagnosticBulkType.F90 +++ b/src/biogeophys/WaterDiagnosticBulkType.F90 @@ -346,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 diff --git a/src/biogeophys/WaterStateBulkType.F90 b/src/biogeophys/WaterStateBulkType.F90 index ba3f0513c5..4cd425c976 100644 --- a/src/biogeophys/WaterStateBulkType.F90 +++ b/src/biogeophys/WaterStateBulkType.F90 @@ -47,7 +47,7 @@ module WaterStateBulkType !------------------------------------------------------------------------ subroutine InitBulk(this, bounds, info, vars, & - h2osno_input_col, watsat_col, t_soisno_col, use_aquifer_layer, NLFilename) + 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 @@ -57,7 +57,8 @@ subroutine InitBulk(this, bounds, info, vars, & 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 - character(len=*) , intent(in) :: NLFilename ! Namelist filename + 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, & @@ -66,7 +67,7 @@ subroutine InitBulk(this, bounds, info, vars, & watsat_col = watsat_col, & t_soisno_col = t_soisno_col, & use_aquifer_layer = use_aquifer_layer, & - NLFilename = NLFilename) + exice_coldstart_depth = exice_coldstart_depth, exice_init_conc_col = exice_init_conc_col(bounds%begc:bounds%endc)) call this%InitBulkAllocate(bounds) diff --git a/src/biogeophys/WaterStateType.F90 b/src/biogeophys/WaterStateType.F90 index 390e9e8691..35441d65d9 100644 --- a/src/biogeophys/WaterStateType.F90 +++ b/src/biogeophys/WaterStateType.F90 @@ -56,8 +56,6 @@ module WaterStateType 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) - type(excessicestream_type), private :: exicestream ! stream type for excess ice initialization NUOPC only - ! Hillslope stream variables real(r8), pointer :: stream_water_volume_lun(:) ! landunit volume of water in the streams (m3) @@ -82,7 +80,7 @@ module WaterStateType !------------------------------------------------------------------------ subroutine Init(this, bounds, info, tracer_vars, & - h2osno_input_col, watsat_col, t_soisno_col, use_aquifer_layer, NLFilename) + 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 @@ -91,8 +89,9 @@ 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 - character(len=*) , intent(in) :: NLFilename ! Namelist filename + 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 @@ -104,7 +103,7 @@ subroutine Init(this, bounds, info, tracer_vars, & watsat_col = watsat_col, & t_soisno_col = t_soisno_col, & use_aquifer_layer = use_aquifer_layer, & - NLFilename = NLFilename) + exice_coldstart_depth = exice_coldstart_depth , exice_init_conc_col = exice_init_conc_col) end subroutine Init @@ -323,7 +322,7 @@ end subroutine InitHistory !----------------------------------------------------------------------- subroutine InitCold(this, bounds, & - h2osno_input_col, watsat_col, t_soisno_col, use_aquifer_layer, NLFilename) + 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 @@ -343,11 +342,12 @@ subroutine InitCold(this, bounds, & 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 - character(len=*) , intent(in) :: NLFilename ! Namelist filename + 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,g - integer :: nbedrock, n05m ! layer containing 0.5 m + integer :: nbedrock, nexice ! layer containing 0.5 m real(r8) :: ratio !----------------------------------------------------------------------- @@ -550,52 +550,40 @@ subroutine InitCold(this, bounds, & this%dynbal_baseline_ice_col(bounds%begc:bounds%endc) = 0._r8 !Initialize excess ice - if (use_excess_ice .and. NLFilename /= '') then - ! enforce initialization with 0 for everything - this%excess_ice_col(bounds%begc:bounds%endc,-nlevsno+1:nlevmaxurbgrnd)=0.0_r8 - this%exice_bulk_init(bounds%begc:bounds%endc)=0.0_r8 - call this%exicestream%Init(bounds, NLFilename) ! get initial fraction of excess ice per column - ! - ! If excess ice is being read from streams, use the streams to - ! initialize - ! - if ( UseExcessIceStreams() )then - call this%exicestream%CalcExcessIce(bounds, this%exice_bulk_init) - 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) >= 0.5_r8) then - call find_soil_layer_containing_depth(0.5_r8,n05m) - else - n05m=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 (n05m= n05m .and. j= 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 - else ! just in case zeros for lakes and other columns - this%excess_ice_col(c,-nlevsno+1:nlevmaxurbgrnd) = 0.0_r8 + do j = 2, nlevmaxurbgrnd ! ignore first layer + if (nexice= nexice .and. j 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/cpl/lilac/lnd_comp_esmf.F90 b/src/cpl/lilac/lnd_comp_esmf.F90 index 298aa730c0..6c8bb2a491 100644 --- a/src/cpl/lilac/lnd_comp_esmf.F90 +++ b/src/cpl/lilac/lnd_comp_esmf.F90 @@ -114,6 +114,8 @@ subroutine lnd_init(comp, import_state, export_state, clock, rc) 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 type(ESMF_State) :: import_state ! CLM import state @@ -270,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 !---------------------- diff --git a/src/cpl/mct/ExcessIceStreamType.F90 b/src/cpl/mct/ExcessIceStreamType.F90 deleted file mode 100644 index 5c5394233c..0000000000 --- a/src/cpl/mct/ExcessIceStreamType.F90 +++ /dev/null @@ -1,144 +0,0 @@ -module ExcessIceStreamType - - !----------------------------------------------------------------------- - ! !DESCRIPTION: - ! Stub for ExcessIceStreams for the MCT driver. So that MCT can be used - ! without 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 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 - contains - - ! !PUBLIC MEMBER FUNCTIONS: - procedure, public :: Init ! Initialize and read data in - procedure, public :: CalcExcessIce ! Calculate excess ice ammount - - ! !PRIVATE MEMBER FUNCTIONS: - procedure, private :: ReadNML ! Read in namelist - - end type excessicestream_type - ! ! PRIVATE DATA: - - 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 - - ! - ! local variables - - call this%ReadNML( bounds, NLFileName ) - 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: - - end subroutine CalcExcessIce - - logical function UseExcessIceStreams() - ! - ! !DESCRIPTION: - ! Return true if - ! - ! !USES: - ! - ! !ARGUMENTS: - implicit none - ! - ! !LOCAL VARIABLES: - UseExcessIceStreams = .false. -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(excessicestream_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_mapalgo_exice = 'none' - 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, 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) - - if (masterproc) then - if ( use_excess_ice_streams ) then - call endrun(msg=' ERROR excess ice streams can NOT be on for the MCT driver'//errMsg(sourcefile, __LINE__)) - end if - if ( trim(stream_fldFileName_exice) /= '' ) then - call endrun(msg=' ERROR stream_fldFileName_exice can NOT be set for the MCT driver'//errMsg(sourcefile, __LINE__)) - end if - if ( trim(stream_mapalgo_exice) /= 'none' ) then - call endrun(msg=' ERROR stream_mapalgo_exice can only be none for the MCT driver'//errMsg(sourcefile, __LINE__)) - end if - endif - -end subroutine ReadNML - -end module ExcessIceStreamType 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 537abd49d9..0000000000 --- a/src/cpl/mct/lnd_import_export.F90 +++ /dev/null @@ -1,354 +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 - use GridcellType , only : grc - ! - 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_not_downscaled_grc(g,2) = x2l(index_x2l_Faxa_swndr,i) ! forc_sollxy Atm flux W/m^2 - atm2lnd_inst%forc_solad_not_downscaled_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, "x2l") - - 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, "l2x") - - 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 3852a1bf1b..7fe93454ac 100644 --- a/src/cpl/nuopc/lnd_comp_nuopc.F90 +++ b/src/cpl/nuopc/lnd_comp_nuopc.F90 @@ -29,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 @@ -66,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 !-------------------------------------------------------------------------- @@ -333,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 @@ -497,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 @@ -683,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 @@ -774,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 @@ -864,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 @@ -964,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) @@ -1289,14 +1288,14 @@ subroutine CheckImport(gcomp, rc) 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 @@ -1320,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 @@ -1328,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) @@ -1354,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_import_export.F90 b/src/cpl/nuopc/lnd_import_export.F90 index 11cc807640..624590b9a6 100644 --- a/src/cpl/nuopc/lnd_import_export.F90 +++ b/src/cpl/nuopc/lnd_import_export.F90 @@ -160,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 @@ -237,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) @@ -248,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 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/UrbanTimeVarType.F90 b/src/cpl/share_esmf/UrbanTimeVarType.F90 index 088ec9eeae..926a2c0557 100644 --- a/src/cpl/share_esmf/UrbanTimeVarType.F90 +++ b/src/cpl/share_esmf/UrbanTimeVarType.F90 @@ -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,18 +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 ! 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 - ! Since we are within an urban land unit, we know that - ! lun%itype is within [pisturb_MIN, isturb_MAX] - this%t_building_max(l) = dataptr2d(ig, lun%itype(l)) + 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,11 +310,17 @@ subroutine urbantv_interp(this, bounds) do g = bounds%begg,bounds%endg 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 @@ -285,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 index 194e022132..32e776063b 100644 --- a/src/cpl/share_esmf/ZenderSoilErodStreamType.F90 +++ b/src/cpl/share_esmf/ZenderSoilErodStreamType.F90 @@ -42,7 +42,6 @@ module ZenderSoilErodStreamType ! ! PRIVATE DATA: type, private :: streamcontrol_type - character(len=CL) :: zender_soil_erod_source ! if calculed in lnd or atm character(len=CL) :: stream_fldFileName_zendersoilerod ! data Filename character(len=CL) :: stream_meshfile_zendersoilerod ! mesh Filename character(len=CL) :: zendersoilerod_mapalgo ! map algo @@ -179,7 +178,7 @@ logical function UseStreams(this) ! file is being used with it ! ! !USES: - use clm_varctl, only : dust_emis_method + use shr_dust_emis_mod, only : is_dust_emis_zender, is_zender_soil_erod_from_land ! ! !ARGUMENTS: implicit none @@ -189,7 +188,7 @@ logical function UseStreams(this) if ( .not. control%namelist_set )then call endrun(msg=' ERROR namelist NOT set before being used'//errMsg(sourcefile, __LINE__)) end if - if ( (trim(dust_emis_method) == 'Zender_2003') .and. (control%zender_soil_erod_source == "lnd") )then + if ( is_dust_emis_zender() .and. is_zender_soil_erod_from_land() )then UseStreams = .true. else UseStreams = .false. @@ -289,6 +288,7 @@ subroutine ReadNML(this, bounds, NLFilename) 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 @@ -304,14 +304,13 @@ subroutine ReadNML(this, bounds, NLFilename) character(len=CL) :: stream_meshfile_zendersoilerod = ' ' character(len=CL) :: zendersoilerod_mapalgo = ' ' character(len=CL) :: tmp_file_array(3) - character(len=3) :: zender_soil_erod_source = 'atm' 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, zender_soil_erod_source + stream_meshfile_zendersoilerod ! Default values for namelist @@ -330,12 +329,11 @@ subroutine ReadNML(this, bounds, NLFilename) close(nu_nml) endif - call shr_mpi_bcast(zender_soil_erod_source , mpicom) 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. (zender_soil_erod_source == "lnd") ) then + 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 @@ -343,13 +341,10 @@ subroutine ReadNML(this, bounds, NLFilename) write(iulog,*) ' zendersoilerod_mapalgo = ',zendersoilerod_mapalgo endif - if ( (trim(zender_soil_erod_source) /= 'atm') .and. (trim(zender_soil_erod_source) /= 'lnd') )then - call endrun(msg=' ERROR zender_soil_erod_source must be either lnd or atm and is NOT'//errMsg(sourcefile, __LINE__)) - end if tmp_file_array(1) = stream_fldFileName_zendersoilerod tmp_file_array(2) = stream_meshfile_zendersoilerod tmp_file_array(3) = zendersoilerod_mapalgo - if ( trim(zender_soil_erod_source) == 'lnd' )then + 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__)) @@ -365,7 +360,6 @@ subroutine ReadNML(this, bounds, NLFilename) this%stream_fldFileName_zendersoilerod = stream_fldFileName_zendersoilerod this%stream_meshfile_zendersoilerod = stream_meshfile_zendersoilerod this%zendersoilerod_mapalgo = zendersoilerod_mapalgo - this%zender_soil_erod_source = zender_soil_erod_source this%namelist_set = .true. diff --git a/src/cpl/share_esmf/cropcalStreamMod.F90 b/src/cpl/share_esmf/cropcalStreamMod.F90 index 0ea63f2c6d..5587641c21 100644 --- a/src/cpl/share_esmf/cropcalStreamMod.F90 +++ b/src/cpl/share_esmf/cropcalStreamMod.F90 @@ -14,7 +14,9 @@ module cropcalStreamMod 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 @@ -35,14 +37,26 @@ module cropcalStreamMod 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 ! sdate 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__ @@ -67,9 +81,12 @@ subroutine cropcal_init(bounds) ! ! !LOCAL VARIABLES: integer :: i,n,ivt ! index - integer :: stream_year_first_cropcal ! first year in crop calendar streams to use - integer :: stream_year_last_cropcal ! last year in crop calendar streams to use - integer :: model_year_align_cropcal ! align stream_year_first_cropcal with + 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 @@ -83,32 +100,54 @@ subroutine cropcal_init(bounds) ! deal with namelist variables here in init ! namelist /cropcal_streams/ & - stream_year_first_cropcal, & - stream_year_last_cropcal, & - model_year_align_cropcal, & + 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_meshfile_cropcal + 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 = 1 ! first year in stream to use - stream_year_last_cropcal = 1 ! last year in stream to use - model_year_align_cropcal = 1 ! align stream_year_first_cropcal with this model year + 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 @@ -125,29 +164,47 @@ subroutine cropcal_init(bounds) end if close(nu_nml) endif - call shr_mpi_bcast(stream_year_first_cropcal , mpicom) - call shr_mpi_bcast(stream_year_last_cropcal , mpicom) - call shr_mpi_bcast(model_year_align_cropcal , mpicom) + 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 = ',stream_year_first_cropcal - write(iulog,'(a,i8)') ' stream_year_last_cropcal = ',stream_year_last_cropcal - write(iulog,'(a,i8)') ' model_year_align_cropcal = ',model_year_align_cropcal + 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 @@ -155,9 +212,12 @@ subroutine cropcal_init(bounds) ! 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 /= '' - use_cropcal_streams = use_cropcal_rx_swindows .or. use_cropcal_rx_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, & @@ -172,9 +232,9 @@ subroutine cropcal_init(bounds) stream_filenames = (/trim(stream_fldFileName_swindow_start)/), & stream_fldlistFile = stream_varnames_sdate, & stream_fldListModel = stream_varnames_sdate, & - stream_yearFirst = stream_year_first_cropcal, & - stream_yearLast = stream_year_last_cropcal, & - stream_yearAlign = model_year_align_cropcal, & + 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, & @@ -199,9 +259,9 @@ subroutine cropcal_init(bounds) stream_filenames = (/trim(stream_fldFileName_swindow_end)/), & stream_fldlistFile = stream_varnames_sdate, & stream_fldListModel = stream_varnames_sdate, & - stream_yearFirst = stream_year_first_cropcal, & - stream_yearLast = stream_year_last_cropcal, & - stream_yearAlign = model_year_align_cropcal, & + 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, & @@ -216,6 +276,7 @@ subroutine cropcal_init(bounds) ! 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, & @@ -228,9 +289,9 @@ subroutine cropcal_init(bounds) 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, & - stream_yearLast = stream_year_last_cropcal, & - stream_yearAlign = model_year_align_cropcal, & + 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, & @@ -242,6 +303,109 @@ subroutine cropcal_init(bounds) 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 !================================================================ @@ -258,6 +422,7 @@ subroutine cropcal_advance( 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 @@ -266,6 +431,9 @@ subroutine cropcal_advance( bounds ) 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 @@ -285,10 +453,31 @@ subroutine cropcal_advance( bounds ) 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(bounds%begg:bounds%endg) ) + allocate (g_to_ig(begg:endg) ) ig = 0 - do g = bounds%begg,bounds%endg + do g = begg,endg ig = ig+1 g_to_ig(g) = ig end do @@ -298,7 +487,7 @@ end subroutine cropcal_advance !================================================================ - subroutine cropcal_interp(bounds, num_pcropp, filter_pcropp, crop_inst) + subroutine cropcal_interp(bounds, num_pcropp, filter_pcropp, init, crop_inst) ! ! Interpolate data stream information for crop calendars. ! @@ -314,6 +503,7 @@ subroutine cropcal_interp(bounds, num_pcropp, filter_pcropp, crop_inst) 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: @@ -321,39 +511,48 @@ subroutine cropcal_interp(bounds, num_pcropp, filter_pcropp, crop_inst) integer :: nc, fp integer :: dayspyr integer :: n, g - integer :: lsize 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( & - starts => crop_inst%rx_swindow_starts_thisyr_patch, & - ends => crop_inst%rx_swindow_ends_thisyr_patch & + 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 & ) - SHR_ASSERT_FL( (lbound(g_to_ig,1) <= bounds%begg ), sourcefile, __LINE__) - SHR_ASSERT_FL( (ubound(g_to_ig,1) >= bounds%endg ), sourcefile, __LINE__) + 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 - lsize = bounds%endg - bounds%begg + 1 begp = bounds%begp - endp= bounds%endp + endp = bounds%endp dayspyr = get_curr_days_per_year() ! Read prescribed sowing window start dates from input files - allocate(dataptr2d_swindow_start(lsize, ncft)) - dataptr2d_swindow_start(:,:) = -1._r8 - allocate(dataptr2d_swindow_end (lsize, ncft)) - dataptr2d_swindow_end(:,:) = -1._r8 + 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 @@ -369,7 +568,7 @@ subroutine cropcal_interp(bounds, num_pcropp, filter_pcropp, crop_inst) 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 = 1,lsize + 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 & @@ -392,8 +591,8 @@ subroutine cropcal_interp(bounds, num_pcropp, filter_pcropp, crop_inst) n = ivt - npcropmin + 1 ! vegetated pft ig = g_to_ig(patch%gridcell(p)) - starts(p,1) = dataptr2d_swindow_start(ig,n) - ends(p,1) = dataptr2d_swindow_end (ig,n) + 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) @@ -402,23 +601,23 @@ subroutine cropcal_interp(bounds, num_pcropp, filter_pcropp, crop_inst) ! 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(ends(begp:endp,2:mxsowings) <= ends(begp:endp,1:mxsowings-1) .and. & - ends(begp:endp,2: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(starts(begp:endp,:) < 1 .or. ends(begp:endp,:) < 1)) then + 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(starts(begp:endp,:) < 1, dim=2) .and. patch%wtgcell > 0._r8 .and. patch%itype >= npcropmin)) then + 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(starts(p,:) < 1)) then + 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 @@ -427,7 +626,7 @@ subroutine cropcal_interp(bounds, num_pcropp, filter_pcropp, crop_inst) 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((starts(begp:endp,:) >= 1 .and. ends(begp:endp,:) < 1) .or. (starts(begp:endp,:) < 1 .and. ends(begp:endp,:) >= 1))) then + 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 @@ -437,7 +636,7 @@ subroutine cropcal_interp(bounds, num_pcropp, filter_pcropp, crop_inst) deallocate(dataptr2d_swindow_start) deallocate(dataptr2d_swindow_end) - allocate(dataptr2d_cultivar_gdds(lsize, ncft)) + 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 @@ -450,7 +649,7 @@ subroutine cropcal_interp(bounds, num_pcropp, filter_pcropp, crop_inst) ! 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 = 1,lsize + 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 @@ -478,8 +677,8 @@ subroutine cropcal_interp(bounds, num_pcropp, filter_pcropp, crop_inst) ! vegetated pft ig = g_to_ig(patch%gridcell(p)) - if (ig > lsize) then - write(iulog,'(a,i0,a,i0,a)') 'ig (',ig,') > lsize (',lsize,')' + 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 @@ -490,11 +689,147 @@ subroutine cropcal_interp(bounds, num_pcropp, filter_pcropp, crop_inst) call ESMF_Finalize(endflag=ESMF_END_ABORT) endif end do - write(iulog,*) 'cropcal_interp(): Reading cultivar_gdds file DONE' 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 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 index 45f4340d6a..1bc6ab929e 100644 --- a/src/dyn_subgrid/dynFATESLandUseChangeMod.F90 +++ b/src/dyn_subgrid/dynFATESLandUseChangeMod.F90 @@ -26,13 +26,40 @@ module dynFATESLandUseChangeMod ! 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', & @@ -64,8 +91,9 @@ module dynFATESLandUseChangeMod '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 landuse variable - type(dyn_var_time_uninterp_type) :: landuse_state_vars(num_landuse_state_vars) ! value of each landuse variable + 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 @@ -79,14 +107,15 @@ subroutine dynFatesLandUseInit(bounds, landuse_filename) ! Initialize data structures for land use information. ! !USES: - use clm_varctl , only : use_cn, use_fates_luh + 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 land use information + character(len=*) , intent(in) :: landuse_filename ! name of file containing landuse timeseries information (fates luh2) ! !LOCAL VARIABLES integer :: varnum, i ! counter for harvest variables @@ -111,37 +140,69 @@ subroutine dynFatesLandUseInit(bounds, landuse_filename) 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 - - if (use_fates_luh) then - - ! Generate the dyn_file_type object. Note that the land use data being read in is for the - ! transitions occuring within the current year - dynFatesLandUse_file = dyn_file_type(landuse_filename, YEAR_POSITION_END_OF_TIMESTEP) - - ! Get initial land use data - 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 + 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 - ! Since fates needs state data during initialization, make sure to call - ! the interpolation routine at the start - call dynFatesLandUseInterp(bounds,init_state=.true.) - end subroutine dynFatesLandUseInit @@ -159,7 +220,7 @@ subroutine dynFatesLandUseInterp(bounds, init_state) ! !USES: use dynTimeInfoMod , only : time_info_type - use clm_varctl , only : use_cn + use clm_varctl , only : use_cn, fates_harvest_mode ! !ARGUMENTS: type(bounds_type), intent(in) :: bounds ! proc-level bounds @@ -181,13 +242,14 @@ subroutine dynFatesLandUseInterp(bounds, init_state) init_flag = init_state end if - ! Get the current year + ! 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. @@ -200,6 +262,13 @@ subroutine dynFatesLandUseInterp(bounds, init_state) 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 diff --git a/src/dyn_subgrid/dynGrossUnrepMod.F90 b/src/dyn_subgrid/dynGrossUnrepMod.F90 index 8d0e7ee004..7ad860f0ce 100644 --- a/src/dyn_subgrid/dynGrossUnrepMod.F90 +++ b/src/dyn_subgrid/dynGrossUnrepMod.F90 @@ -24,6 +24,7 @@ module dynGrossUnrepMod 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 @@ -157,6 +158,7 @@ subroutine CNGrossUnrep (num_soilp, filter_soilp, & 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 @@ -266,7 +268,44 @@ subroutine CNGrossUnrep (num_soilp, filter_soilp, & 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) (:)] + 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() @@ -294,61 +333,157 @@ subroutine CNGrossUnrep (num_soilp, filter_soilp, & m = 0._r8 end if - ! 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 + 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 diff --git a/src/dyn_subgrid/dynHarvestMod.F90 b/src/dyn_subgrid/dynHarvestMod.F90 index d5a72aa547..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 @@ -245,6 +245,7 @@ subroutine CNHarvest (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_soilp ! number of soil patches in filter @@ -351,7 +352,44 @@ subroutine CNHarvest (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() @@ -389,9 +427,9 @@ subroutine CNHarvest (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 @@ -447,8 +485,96 @@ subroutine CNHarvest (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 diff --git a/src/dyn_subgrid/dynSubgridDriverMod.F90 b/src/dyn_subgrid/dynSubgridDriverMod.F90 index e5ca3f002e..ea1210521d 100644 --- a/src/dyn_subgrid/dynSubgridDriverMod.F90 +++ b/src/dyn_subgrid/dynSubgridDriverMod.F90 @@ -89,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 @@ -123,7 +128,7 @@ 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 @@ -201,7 +206,7 @@ subroutine dynSubgrid_driver(bounds_proc, ! OUTSIDE any loops over clumps in the driver. ! ! !USES: - use clm_varctl , only : use_cn, use_fates, use_fates_luh + 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 @@ -290,7 +295,7 @@ subroutine dynSubgrid_driver(bounds_proc, call dynurban_interp(bounds_proc) end if - if (use_fates_luh) then + if (use_fates_luh .and. .not. use_fates_potentialveg) then call dynFatesLandUseInterp(bounds_proc) end if diff --git a/src/fates b/src/fates new file mode 160000 index 0000000000..e3e7d2cd86 --- /dev/null +++ b/src/fates @@ -0,0 +1 @@ +Subproject commit e3e7d2cd86a66f8ca0e8f6dc4a823246a2bdb95b 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/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/clm_driver.F90 b/src/main/clm_driver.F90 index 00a98e61b4..454ff87463 100644 --- a/src/main/clm_driver.F90 +++ b/src/main/clm_driver.F90 @@ -62,7 +62,6 @@ module clm_driver 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 @@ -476,7 +475,7 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro ! When crop calendar streams are being used ! NOTE: This call needs to happen outside loops over nclumps (as streams are not threadsafe) - if (use_cropcal_streams .and. is_beg_curr_year()) then + if (use_crop .and. use_cropcal_streams .and. is_beg_curr_year()) then call cropcal_advance( bounds_proc ) end if @@ -806,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') @@ -1074,11 +1073,12 @@ subroutine clm_drv(doalb, nextsw_cday, declinp1, declin, rstwr, nlend, rdate, ro frictionvel_inst, photosyns_inst, drydepvel_inst) call t_stopf('depvel') - if (use_cropcal_streams .and. is_beg_curr_year()) then + 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, crop_inst) + call cropcal_interp(bounds_clump, filter_inactive_and_active(nc)%num_pcropp, & + filter_inactive_and_active(nc)%pcropp, .false., crop_inst) end if ! ============================================================================ @@ -1308,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) @@ -1373,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) diff --git a/src/main/clm_initializeMod.F90 b/src/main/clm_initializeMod.F90 index 9bf0cc59a2..e3d9eeda06 100644 --- a/src/main/clm_initializeMod.F90 +++ b/src/main/clm_initializeMod.F90 @@ -58,7 +58,7 @@ 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, surfrd_get_nlevurb + 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 @@ -100,6 +100,7 @@ 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) @@ -135,8 +136,8 @@ 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 : 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 clm_varctl , only : use_crop, ndep_from_cpl, fates_spitfire_mode use clm_varctl , only : use_hillslope @@ -174,7 +175,7 @@ subroutine initialize2(ni,nj) 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 @@ -253,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 @@ -304,7 +305,7 @@ subroutine initialize2(ni,nj) if (use_hillslope) then ! Initialize hillslope properties - call InitHillslope(bounds_proc, fsurdat) + call InitHillslope(bounds_proc, hillslope_file) endif ! Set filters @@ -520,17 +521,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) @@ -659,19 +650,21 @@ subroutine initialize2(ni,nj) end if ! Initialize crop calendars - 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, crop_inst) - end do - !$OMP END PARALLEL DO + 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 - call t_stopf('init_cropcal') ! Initialize active history fields. ! This is only done if not a restart run. If a restart run, then this diff --git a/src/main/clm_instMod.F90 b/src/main/clm_instMod.F90 index b9d74c418a..210cff2c2e 100644 --- a/src/main/clm_instMod.F90 +++ b/src/main/clm_instMod.F90 @@ -11,6 +11,7 @@ module clm_instMod 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,9 +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 @@ -218,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 !---------------------------------------------------------------------- @@ -273,7 +280,7 @@ subroutine clm_instInit(bounds) ! Set hillslope column bedrock values if (use_hillslope) then - call SetHillslopeSoilThickness(bounds,fsurdat, & + call SetHillslopeSoilThickness(bounds, hillslope_file, & soil_depth_lowland_in=8.5_r8,& soil_depth_upland_in =2.0_r8) call setSoilLayerClass(bounds) @@ -295,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) @@ -314,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) @@ -350,7 +370,7 @@ subroutine clm_instInit(bounds) call surfrad_inst%Init(bounds) - call dust_inst%Init(bounds, NLFilename) + allocate(dust_emis_inst, source = create_dust_emissions(bounds, NLFilename)) allocate(scf_method, source = CreateAndInitSnowCoverFraction( & snow_cover_fraction_method = snow_cover_fraction_method, & @@ -447,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 diff --git a/src/main/clm_varctl.F90 b/src/main/clm_varctl.F90 index 7d0b2b55ad..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 @@ -276,17 +277,25 @@ module clm_varctl ! option to activate OC in snow in SNICAR logical, public :: do_sno_oc = .false. ! control to include organic carbon (OC) in snow - !---------------------------------------------------------- - ! DUST emission method - !---------------------------------------------------------- - character(len=25), public :: dust_emis_method = 'Zender_2003' ! Dust emisison method to use: Zender_2003 or Leung_2023 - !---------------------------------------------------------- ! 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 @@ -321,7 +330,7 @@ module clm_varctl ! > 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 + 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 @@ -344,7 +353,10 @@ module clm_varctl 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 @@ -391,6 +403,8 @@ module clm_varctl 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 @@ -414,9 +428,11 @@ module clm_varctl 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 + ! excess ice physics switch and params !---------------------------------------------------------- logical, public :: use_excess_ice = .false. ! true. => use excess ice physics @@ -426,12 +442,6 @@ module clm_varctl logical, public :: use_hydrstress = .false. ! true => use plant hydraulic stress calculation - !---------------------------------------------------------- - ! dynamic root switch - !---------------------------------------------------------- - - logical, public :: use_dynroot = .false. ! true => use dynamic root module - !---------------------------------------------------------- ! glacier_mec control variables: default values (may be overwritten by namelist) !---------------------------------------------------------- diff --git a/src/main/clm_varpar.F90 b/src/main/clm_varpar.F90 index 4ddacc38e4..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 @@ -285,9 +328,29 @@ subroutine clm_varpar_init(actual_maxsoil_patches, surf_numpft, surf_numcft, act ! 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/controlMod.F90 b/src/main/controlMod.F90 index 46d9e9958a..3f5c58ac0e 100644 --- a/src/main/controlMod.F90 +++ b/src/main/controlMod.F90 @@ -39,8 +39,9 @@ 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 @@ -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 @@ -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 @@ -207,12 +213,6 @@ subroutine control_init(dtime) for_testing_no_crop_seed_replenishment, & z0param_method, use_z0m_snowmelt - ! NOTE: EBK 02/26/2024: dust_emis_method is here in CTSM temporarily until it's moved to CMEPS - ! See: https://github.com/ESCOMP/CMEPS/pull/429 - ! Normally this should also need error checking and a broadcast, but since - ! there is only one hardcoded option right now that is unneeded. - namelist /clm_inparm/ dust_emis_method - ! vertical soil mixing variables namelist /clm_inparm/ & som_adv_flux, max_depth_cryoturb @@ -228,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, & @@ -237,7 +237,10 @@ subroutine control_init(dtime) 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, & fates_seeddisp_cadence, & @@ -256,7 +259,8 @@ subroutine control_init(dtime) namelist /clm_inparm/ use_soil_moisture_streams - namelist /clm_inparm/ use_excess_ice + ! excess ice flag + namelist /clm_inparm/ use_excess_ice namelist /clm_inparm/ use_lai_streams @@ -270,9 +274,9 @@ subroutine control_init(dtime) namelist /clm_inparm/ use_hillslope_routing - namelist /clm_inparm/ use_hydrstress + namelist /clm_inparm/ hillslope_fsat_equals_zero - namelist /clm_inparm/ use_dynroot + namelist /clm_inparm/ use_hydrstress namelist /clm_inparm/ & use_c14_bombspike, atm_c14_filename, use_c13_timeseries, atm_c13_filename @@ -302,7 +306,7 @@ subroutine control_init(dtime) use_lch4, use_nitrif_denitrif, use_extralakelayers, & use_vichydro, use_cn, use_cndv, use_crop, use_fertilizer, & use_grainproduct, use_snicar_frc, use_vancouver, use_mexicocity, use_noio, & - use_nguardrail, crop_residue_removal_frac + use_nguardrail, crop_residue_removal_frac, flush_gdd20 ! SNICAR namelist /clm_inparm/ & @@ -324,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) @@ -571,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 @@ -598,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 @@ -613,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'//& @@ -711,6 +717,7 @@ 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) @@ -727,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) @@ -790,7 +798,7 @@ subroutine control_spmd() call mpi_bcast (for_testing_allow_interp_non_ciso_to_ciso, 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) @@ -801,10 +809,14 @@ subroutine control_spmd() 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) @@ -840,9 +852,16 @@ subroutine control_spmd() call mpi_bcast (use_hillslope_routing, 1, MPI_LOGICAL, 0, mpicom, ier) - call mpi_bcast (use_hydrstress, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (hillslope_fsat_equals_zero, 1, MPI_LOGICAL, 0, mpicom, ier) - call mpi_bcast (use_dynroot, 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 @@ -983,6 +1002,7 @@ subroutine control_print () 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 @@ -1000,6 +1020,11 @@ 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 @@ -1124,13 +1149,13 @@ subroutine control_print () 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,*) ' 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.' @@ -1174,7 +1199,7 @@ subroutine control_print () 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 @@ -1187,7 +1212,10 @@ subroutine control_print () write(iulog, *) ' use_fates_nocomp = ', use_fates_nocomp write(iulog, *) ' use_fates_sp = ', use_fates_sp 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) @@ -1195,6 +1223,38 @@ subroutine control_print () 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) ! @@ -1245,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/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 8ae4ace7e3..381e1f1170 100644 --- a/src/main/histFileMod.F90 +++ b/src/main/histFileMod.F90 @@ -28,7 +28,7 @@ module histFileMod use FatesInterfaceTypesMod , only : nlevheight use FatesInterfaceTypesMod , only : nlevdamage use FatesConstantsMod , only : n_landuse_cats - use FatesLitterMod , only : nfsc + use FatesFuelClassesMod , only : num_fuel_classes use FatesLitterMod , only : ncwd use PRTGenericMod , only : num_elements_fates => num_elements use FatesInterfaceTypesMod , only : numpft_fates => numpft @@ -91,6 +91,7 @@ module histFileMod character(len=max_namlen+2), public :: & 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 include in history tape 2 character(len=max_namlen+2), public :: & @@ -116,6 +117,7 @@ module histFileMod character(len=max_namlen+2), public :: & 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 exclude from history tape 2 character(len=max_namlen+2), public :: & @@ -2328,6 +2330,7 @@ subroutine htape_create (t, histrest) 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 @@ -2428,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 @@ -2501,7 +2506,7 @@ subroutine htape_create (t, histrest) call ncd_defdim(lnfid, 'fates_levpft', numpft_fates, dimid) call ncd_defdim(lnfid, 'fates_levage', nlevage, dimid) call ncd_defdim(lnfid, 'fates_levheight', nlevheight, dimid) - call ncd_defdim(lnfid, 'fates_levfuel', nfsc, dimid) + call ncd_defdim(lnfid, 'fates_levfuel', num_fuel_classes, dimid) call ncd_defdim(lnfid, 'fates_levcwdsc', ncwd, dimid) call ncd_defdim(lnfid, 'fates_levscpf', nlevsclass*numpft_fates, dimid) call ncd_defdim(lnfid, 'fates_levcapf', nlevcoage*numpft_fates, dimid) @@ -2516,7 +2521,7 @@ subroutine htape_create (t, histrest) call ncd_defdim(lnfid, 'fates_levelpft', num_elements_fates * numpft_fates, dimid) 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_levagefuel', nlevage * num_fuel_classes, 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) @@ -5592,7 +5597,7 @@ subroutine hist_addfld2d (fname, type2d, units, avgflag, long_name, type1d_out, case ('fates_levheight') num2d = nlevheight case ('fates_levfuel') - num2d = nfsc + num2d = num_fuel_classes case ('fates_levcwdsc') num2d = ncwd case ('fates_levscpf') @@ -5632,7 +5637,7 @@ subroutine hist_addfld2d (fname, type2d, units, avgflag, long_name, type1d_out, case ('fates_levelage') num2d = num_elements_fates*nlevage case ('fates_levagefuel') - num2d = nlevage*nfsc + num2d = nlevage*num_fuel_classes case('fates_levclscpf') num2d = nclmax * nclmax * numpft_fates case ('fates_levlanduse') diff --git a/src/main/initVerticalMod.F90 b/src/main/initVerticalMod.F90 index b91c3439aa..64383e7a7c 100644 --- a/src/main/initVerticalMod.F90 +++ b/src/main/initVerticalMod.F90 @@ -47,6 +47,8 @@ module initVerticalMod 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 ! @@ -79,6 +81,9 @@ 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 !------------------------------------------------------------------------ @@ -447,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 diff --git a/src/main/lnd2atmMod.F90 b/src/main/lnd2atmMod.F90 index 1cda0cff91..503f4b9585 100644 --- a/src/main/lnd2atmMod.F90 +++ b/src/main/lnd2atmMod.F90 @@ -20,7 +20,7 @@ module lnd2atmMod 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) ! @@ -173,7 +173,7 @@ 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 @@ -332,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') diff --git a/src/main/lnd2glcMod.F90 b/src/main/lnd2glcMod.F90 index 27fa7639d7..26359ff261 100644 --- a/src/main/lnd2glcMod.F90 +++ b/src/main/lnd2glcMod.F90 @@ -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 diff --git a/src/main/pftconMod.F90 b/src/main/pftconMod.F90 index e5379100e0..b987879c03 100644 --- a/src/main/pftconMod.F90 +++ b/src/main/pftconMod.F90 @@ -162,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 @@ -280,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 @@ -494,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) ) @@ -506,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 @@ -520,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, z0param_method + 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 @@ -847,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__)) @@ -1105,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) @@ -1583,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) @@ -1595,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/restFileMod.F90 b/src/main/restFileMod.F90 index 6a574406fd..c7dbf0da72 100644 --- a/src/main/restFileMod.F90 +++ b/src/main/restFileMod.F90 @@ -503,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 @@ -569,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') diff --git a/src/main/surfrdMod.F90 b/src/main/surfrdMod.F90 index 12212e2160..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 @@ -27,6 +27,7 @@ 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 @@ -45,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_get_data (begg, endg, ldomain, lfsurdat, actual_numcft) + 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, lhillslope_file, actual_numcft) ! ! !DESCRIPTION: ! Read the surface dataset and create subgrid weights. @@ -73,9 +215,10 @@ subroutine surfrd_get_data (begg, endg, ldomain, lfsurdat, actual_numcft) 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 @@ -87,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 !----------------------------------------------------------------------- @@ -110,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 @@ -119,71 +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) - - ! 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) @@ -766,7 +860,7 @@ 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 @@ -783,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: @@ -869,7 +964,7 @@ subroutine surfrd_veg_all(begg, endg, ncid, ns, actual_numcft) ! Obtain hillslope hydrology information and modify pft weights if (use_hillslope) then - call surfrd_hillslope(begg, endg, ncid, ns) + call surfrd_hillslope(begg, endg, ncid_hillslope, ns) endif ! Convert from percent to fraction diff --git a/src/main/surfrdUtilsMod.F90 b/src/main/surfrdUtilsMod.F90 index 007770b3c3..b79f97e0b4 100644 --- a/src/main/surfrdUtilsMod.F90 +++ b/src/main/surfrdUtilsMod.F90 @@ -317,8 +317,8 @@ subroutine collapse_to_dominant(weight, lower_bound, upper_bound, begg, endg, n_ ! original sum of all the weights wt_sum(g) = sum(weight(g,:)) - if (present(do_not_collapse) .and. do_not_collapse(g)) then - cycle + if (present(do_not_collapse)) then + if (do_not_collapse(g)) cycle end if max_indices = 0 ! initialize diff --git a/src/main/test/accumul_test/test_accumul.pf b/src/main/test/accumul_test/test_accumul.pf index 15d2e7403e..423a0aea18 100644 --- a/src/main/test/accumul_test/test_accumul.pf +++ b/src/main/test/accumul_test/test_accumul.pf @@ -5,7 +5,7 @@ module test_accumul 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/glcBehavior_test/test_glcBehavior.pf b/src/main/test/glcBehavior_test/test_glcBehavior.pf index ff104458b1..37271d2f98 100644 --- a/src/main/test/glcBehavior_test/test_glcBehavior.pf +++ b/src/main/test/glcBehavior_test/test_glcBehavior.pf @@ -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/topo_test/test_topo.pf b/src/main/test/topo_test/test_topo.pf index 196ce34763..82c3b2cb90 100644 --- a/src/main/test/topo_test/test_topo.pf +++ b/src/main/test/topo_test/test_topo.pf @@ -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/soilbiogeochem/CNSoilMatrixMod.F90 b/src/soilbiogeochem/CNSoilMatrixMod.F90 new file mode 100644 index 0000000000..56c1f11b5c --- /dev/null +++ b/src/soilbiogeochem/CNSoilMatrixMod.F90 @@ -0,0 +1,940 @@ +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 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 ( 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 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 2cb28f04e9..23f24e44d5 100644 --- a/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCarbonFluxType.F90 @@ -3,8 +3,8 @@ 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 @@ -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 @@ -61,8 +62,25 @@ module SoilBiogeochemCarbonFluxType 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 procedure , public :: Init @@ -168,6 +186,25 @@ subroutine InitAllocate(this, bounds) 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 allocate(this%litr_lig_c_to_n_col(begc:endc)) @@ -724,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 diff --git a/src/soilbiogeochem/SoilBiogeochemCarbonStateType.F90 b/src/soilbiogeochem/SoilBiogeochemCarbonStateType.F90 index de269a4c78..768811925d 100644 --- a/src/soilbiogeochem/SoilBiogeochemCarbonStateType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemCarbonStateType.F90 @@ -27,6 +27,8 @@ 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 @@ -54,6 +56,17 @@ module SoilBiogeochemCarbonStateType ! 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 @@ -113,17 +126,41 @@ subroutine InitAllocate(this, bounds) 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 @@ -217,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 @@ -317,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 @@ -420,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 @@ -502,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 @@ -514,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 @@ -528,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 @@ -536,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 @@ -544,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 @@ -553,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 @@ -562,11 +644,28 @@ 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 @@ -669,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 @@ -699,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' & @@ -709,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 @@ -716,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 @@ -741,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: '//& @@ -751,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 @@ -758,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 @@ -895,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 @@ -905,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 @@ -915,17 +1377,28 @@ 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 @@ -963,6 +1436,7 @@ subroutine Summary(this, bounds, num_allc, filter_allc, num_bgc_soilc, filter_bg 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 @@ -974,6 +1448,9 @@ subroutine Summary(this, bounds, num_allc, filter_allc, num_bgc_soilc, filter_bg 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 diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 index f4785fc4d8..49fc95d6f5 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompCascadeBGCMod.F90 @@ -588,7 +588,8 @@ subroutine decomp_rate_constants_bgc(bounds, num_bgc_soilc, filter_bgc_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 @@ -910,9 +911,16 @@ subroutine decomp_rate_constants_bgc(bounds, num_bgc_soilc, filter_bgc_soilc, & ! 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 diff --git a/src/soilbiogeochem/SoilBiogeochemDecompCascadeConType.F90 b/src/soilbiogeochem/SoilBiogeochemDecompCascadeConType.F90 index 0474ab9a63..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 !------------------------------------------------------------------------ @@ -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 65091755f5..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 @@ -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) @@ -763,7 +765,7 @@ subroutine decomp_rates_mimics(bounds, num_bgc_soilc, filter_bgc_soilc, & ! 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 @@ -822,6 +824,7 @@ subroutine decomp_rates_mimics(bounds, num_bgc_soilc, filter_bgc_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 @@ -882,6 +885,7 @@ subroutine decomp_rates_mimics(bounds, num_bgc_soilc, filter_bgc_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 ) @@ -892,6 +896,7 @@ subroutine decomp_rates_mimics(bounds, num_bgc_soilc, filter_bgc_soilc, & 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 @@ -1311,6 +1316,23 @@ subroutine decomp_rates_mimics(bounds, num_bgc_soilc, filter_bgc_soilc, & 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 9bd8b13008..6be924bcf5 100644 --- a/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemDecompMod.F90 @@ -131,7 +131,8 @@ subroutine SoilBiogeochemDecomp (bounds, num_bgc_soilc, filter_bgc_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 @@ -177,6 +178,8 @@ subroutine SoilBiogeochemDecomp (bounds, num_bgc_soilc, filter_bgc_soilc, 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 diff --git a/src/soilbiogeochem/SoilBiogeochemLittVertTranspMod.F90 b/src/soilbiogeochem/SoilBiogeochemLittVertTranspMod.F90 index e58e2f22d6..889fda5bdb 100644 --- a/src/soilbiogeochem/SoilBiogeochemLittVertTranspMod.F90 +++ b/src/soilbiogeochem/SoilBiogeochemLittVertTranspMod.F90 @@ -149,9 +149,8 @@ subroutine SoilBiogeochemLittVertTransp(bounds, num_bgc_soilc, filter_bgc_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_bgc_soilc, filter_bgc_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 @@ -237,16 +237,17 @@ subroutine SoilBiogeochemLittVertTransp(bounds, num_bgc_soilc, filter_bgc_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 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 @@ -399,6 +400,8 @@ subroutine SoilBiogeochemLittVertTransp(bounds, num_bgc_soilc, filter_bgc_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 @@ -409,12 +412,17 @@ subroutine SoilBiogeochemLittVertTransp(bounds, num_bgc_soilc, filter_bgc_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 @@ -463,11 +471,11 @@ subroutine SoilBiogeochemLittVertTransp(bounds, num_bgc_soilc, filter_bgc_soilc, 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_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 @@ -479,7 +487,7 @@ subroutine SoilBiogeochemLittVertTransp(bounds, num_bgc_soilc, filter_bgc_soilc, 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) diff --git a/src/soilbiogeochem/SoilBiogeochemNStateUpdate1Mod.F90 b/src/soilbiogeochem/SoilBiogeochemNStateUpdate1Mod.F90 index 4b70459aca..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 ! @@ -118,49 +119,48 @@ subroutine SoilBiogeochemNStateUpdate1(num_bgc_soilc, filter_bgc_soilc, & end if ! decomposition fluxes - if (.not. use_soil_matrixcn) then - do k = 1, ndecomp_cascade_transitions + ! 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 + 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_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 + 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_ntransfer_vr_col(c,j,k) * dt + nf%decomp_cascade_sminn_flux_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_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 - 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 do - end if - end do - else - ! Matrix solution equvalent to above is in CNSoilMatrixMod.F90? (TODO check on this) - end if ! + end if + end do + end if ! if (.not. use_nitrif_denitrif) then diff --git a/src/soilbiogeochem/SoilBiogeochemNitrogenFluxType.F90 b/src/soilbiogeochem/SoilBiogeochemNitrogenFluxType.F90 index 90213b8123..94d5b4324f 100644 --- a/src/soilbiogeochem/SoilBiogeochemNitrogenFluxType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemNitrogenFluxType.F90 @@ -3,8 +3,8 @@ 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_fates @@ -12,7 +12,7 @@ module SoilBiogeochemNitrogenFluxType 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: @@ -132,7 +132,16 @@ module SoilBiogeochemNitrogenFluxType ! 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 @@ -173,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 @@ -282,8 +291,20 @@ subroutine InitAllocate(this, bounds) allocate(this%fates_litter_flux(0:0)); this%fates_litter_flux(:) = nan end if - ! Allocate soil Matrix setug + ! 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 @@ -1005,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 diff --git a/src/soilbiogeochem/SoilBiogeochemNitrogenStateType.F90 b/src/soilbiogeochem/SoilBiogeochemNitrogenStateType.F90 index ee889503d0..d3042b02e8 100644 --- a/src/soilbiogeochem/SoilBiogeochemNitrogenStateType.F90 +++ b/src/soilbiogeochem/SoilBiogeochemNitrogenStateType.F90 @@ -12,10 +12,10 @@ module SoilBiogeochemNitrogenStateType use clm_varpar , only : nlevdecomp_full, nlevdecomp, nlevsoi use clm_varcon , only : spval, dzsoi_decomp, zisoi use clm_varctl , only : use_nitrif_denitrif, use_fates_bgc - use SoilBiogeochemDecompCascadeConType , only : mimics_decomp, century_decomp, decomp_method, use_soil_matrixcn 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 @@ -30,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 @@ -66,6 +68,17 @@ module SoilBiogeochemNitrogenStateType 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 @@ -140,11 +153,36 @@ 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 @@ -195,10 +233,12 @@ 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 @@ -209,6 +249,12 @@ subroutine InitHistory(this, bounds) 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 @@ -220,6 +266,12 @@ subroutine InitHistory(this, bounds) 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 @@ -382,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 @@ -393,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 @@ -403,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 @@ -410,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 @@ -422,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 @@ -539,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 @@ -775,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 @@ -786,6 +979,8 @@ 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 @@ -799,6 +994,32 @@ subroutine SetValues ( this, num_column, filter_column, value_column ) ! 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 @@ -857,6 +1078,7 @@ subroutine Summary(this, bounds, num_allc, filter_allc, num_bgc_soilc, filter_bg 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 @@ -866,6 +1088,9 @@ subroutine Summary(this, bounds, num_allc, filter_allc, num_bgc_soilc, filter_bg 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 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/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 f5f417f9ce..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,12 +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, & - NLFilename = ' ') + 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/share_esmf/CMakeLists.txt b/src/unit_test_stubs/share_esmf/CMakeLists.txt index 5eb2d42415..1d767543ea 100644 --- a/src/unit_test_stubs/share_esmf/CMakeLists.txt +++ b/src/unit_test_stubs/share_esmf/CMakeLists.txt @@ -1,5 +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/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/utils/clmfates_interfaceMod.F90 b/src/utils/clmfates_interfaceMod.F90 index fcd5cb5230..269189d1b7 100644 --- a/src/utils/clmfates_interfaceMod.F90 +++ b/src/utils/clmfates_interfaceMod.F90 @@ -54,12 +54,15 @@ 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 @@ -134,7 +137,6 @@ module CLMFatesInterfaceMod use FatesParametersInterface, only : fates_parameters_type use FatesInterfaceMod , only : DetermineGridCellNeighbors - use FatesIOVariableKindMod, only : group_dyna_simple, group_dyna_complx use FatesHistoryInterfaceMod, only : fates_hist use FatesRestartInterfaceMod, only : fates_restart_interface_type @@ -167,7 +169,6 @@ 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 @@ -180,7 +181,14 @@ module CLMFatesInterfaceMod 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 : dynFatesLandUseInterp + 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 @@ -273,6 +281,8 @@ module CLMFatesInterfaceMod character(len=*), parameter, private :: sourcefile = & __FILE__ + integer, parameter :: num_landuse_pft_vars = 4 + public :: CLMFatesGlobals1 public :: CLMFatesGlobals2 public :: CrossRefHistoryFields @@ -386,6 +396,7 @@ subroutine CLMFatesGlobals2() 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 @@ -483,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 @@ -511,26 +515,30 @@ 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 @@ -540,10 +548,18 @@ subroutine CLMFatesGlobals2() 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 @@ -675,7 +691,7 @@ end subroutine CLMFatesTimesteps ! ==================================================================================== - subroutine init(this, bounds_proc ) + subroutine init(this, bounds_proc, flandusepftdat) ! --------------------------------------------------------------------------------- ! This initializes the hlm_fates_interface_type @@ -704,6 +720,7 @@ subroutine init(this, bounds_proc ) ! 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 @@ -721,6 +738,9 @@ subroutine init(this, bounds_proc ) 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 ! 1) allocate the vectors @@ -753,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. @@ -857,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) > 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 + 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 @@ -910,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 @@ -1026,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) @@ -1152,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 @@ -1170,6 +1212,12 @@ subroutine dynamics_driv(this, nc, bounds_clump, & write(iulog,*) harvest_units 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 @@ -1192,14 +1240,6 @@ subroutine dynamics_driv(this, nc, bounds_clump, & call this%WrapUpdateFatesSeedInOut(bounds_clump) end if - ! --------------------------------------------------------------------------------- - ! Flush arrays to values defined by %flushval (see registry entry in - ! subroutine define_history_vars() - ! --------------------------------------------------------------------------------- - call fates_hist%flush_hvars(nc,upfreq_in=group_dyna_simple) - - call fates_hist%flush_hvars(nc,upfreq_in=group_dyna_complx) - ! --------------------------------------------------------------------------------- ! Part II: Call the FATES model now that input boundary conditions have been ! provided. @@ -1970,23 +2010,16 @@ 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. ! ------------------------------------------------------------------------ - if(fates_history_dimlevel(2)>0) then - call fates_hist%flush_hvars(nc,upfreq_in=group_dyna_simple) - do s = 1,this%fates(nc)%nsites - call fates_hist%zero_site_hvars(this%fates(nc)%sites(s), & - upfreq_in=group_dyna_simple) - end do - if(fates_history_dimlevel(2)>1) then - call fates_hist%flush_hvars(nc,upfreq_in=group_dyna_complx) - do s = 1,this%fates(nc)%nsites - call fates_hist%zero_site_hvars(this%fates(nc)%sites(s), & - upfreq_in=group_dyna_complx) - end do - end if - end if + + call fates_hist%flush_all_hvars(nc) + call fates_hist%update_history_dyn( nc, & this%fates(nc)%nsites, & this%fates(nc)%sites, & @@ -2132,6 +2165,13 @@ subroutine init_coldstart(this, waterstatebulk_inst, waterdiagnosticbulk_inst, & 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 @@ -2164,22 +2204,15 @@ 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. ! ------------------------------------------------------------------------ - if(fates_history_dimlevel(2)>0) then - call fates_hist%flush_hvars(nc,upfreq_in=group_dyna_simple) - do s = 1,this%fates(nc)%nsites - call fates_hist%zero_site_hvars(this%fates(nc)%sites(s), & - upfreq_in=group_dyna_simple) - end do - if(fates_history_dimlevel(2)>1) then - call fates_hist%flush_hvars(nc,upfreq_in=group_dyna_complx) - do s = 1,this%fates(nc)%nsites - call fates_hist%zero_site_hvars(this%fates(nc)%sites(s), & - upfreq_in=group_dyna_complx) - end do - end if - end if + + call fates_hist%flush_all_hvars(nc) + call fates_hist%update_history_dyn( nc, & this%fates(nc)%nsites, & this%fates(nc)%sites, & @@ -3570,9 +3603,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, & @@ -3592,7 +3622,7 @@ subroutine hlm_bounds_to_fates_bounds(hlm, fates) use FatesInterfaceTypesMod, only : nlevsclass, nlevage, nlevcoage use FatesInterfaceTypesMod, only : nlevheight use FatesInterfaceTypesMod, only : nlevdamage - use FatesLitterMod, only : nfsc + use FatesFuelClassesMod, only : num_fuel_classes use FatesLitterMod, only : ncwd use EDParamsMod, only : nlevleaf, nclmax use FatesInterfaceTypesMod, only : numpft_fates => numpft @@ -3644,7 +3674,7 @@ subroutine hlm_bounds_to_fates_bounds(hlm, fates) fates%sizeagepft_class_end = nlevsclass * nlevage * numpft_fates fates%fuel_begin = 1 - fates%fuel_end = nfsc + fates%fuel_end = num_fuel_classes fates%cwdsc_begin = 1 fates%cwdsc_end = ncwd @@ -3671,7 +3701,7 @@ subroutine hlm_bounds_to_fates_bounds(hlm, fates) fates%elage_end = num_elements * nlevage fates%agefuel_begin = 1 - fates%agefuel_end = nlevage * nfsc + fates%agefuel_end = nlevage * num_fuel_classes fates%cdpf_begin = 1 fates%cdpf_end = nlevdamage * numpft_fates * nlevsclass @@ -3755,6 +3785,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/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 c545f625b8..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 Derecho - -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 Derecho, Casper (DAV) and izumi. - -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 74dbe8e5f3..0000000000 --- a/test/tools/README.testnames +++ /dev/null @@ -1,69 +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 -- mesh_maker -0 -- run_neon -a -- modify_data -b -- subset_data -c -- mkprocdata_map -d -- mkmapgrids -e -- unused -f -- unused -g -- unused -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 -c -- NEON OSBS -d -- SouthAmerica -e -- 1850PanTropics -f -- PanBoreal -g -- AlaskaTananaValley -h -- single point from the 0.9x1.25 grid (Township SD) -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/CFGtools__ds b/test/tools/config_files/CFGtools__ds deleted file mode 100644 index e69de29bb2..0000000000 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 '' >> $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 7da8c19803..0000000000 --- a/test/tools/input_tests_master +++ /dev/null @@ -1,32 +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 - -sm0c1 TSMscript_tools.sh site_and_regional run_neon.py run_neon_OSBS -bl0c1 TBLscript_tools.sh site_and_regional run_neon.py run_neon_OSBS -sm0a1 TSMscript_tools.sh site_and_regional run_neon.py run_neon_YELL_PRISM -bl0a1 TBLscript_tools.sh site_and_regional run_neon.py run_neon_YELL_PRISM - -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 -smbh1 TSMscript_tools.sh site_and_regional subset_data subset_data_f09_1x1pt_townshipSD -blbh1 TBLscript_tools.sh site_and_regional subset_data subset_data_f09_1x1pt_townshipSD -smbd1 TSMscript_tools.sh site_and_regional subset_data subset_data_f09_58x45pt_SouthAmerica -blbd1 TBLscript_tools.sh site_and_regional subset_data subset_data_f09_58x45pt_SouthAmerica -smbe1 TSMscript_tools.sh site_and_regional subset_data subset_data_f09_90x288pt_1850PanTropics -blbe1 TBLscript_tools.sh site_and_regional subset_data subset_data_f09_90x288pt_1850PanTropics -smbf1 TSMscript_tools.sh site_and_regional subset_data subset_data_f09_37x288pt_PanBoreal -blbf1 TBLscript_tools.sh site_and_regional subset_data subset_data_f09_37x288pt_PanBoreal -smbg1 TSMscript_tools.sh site_and_regional subset_data subset_data_f09_4x9pt_AlaskaTananaValley -blbg1 TBLscript_tools.sh site_and_regional subset_data subset_data_f09_4x9pt_AlaskaTananaValley - -sm901 TSMscript_tools.sh site_and_regional mesh_maker mesh_maker_fv09 -bl901 TBLscript_tools.sh site_and_regional mesh_maker mesh_maker_fv09 - -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 diff --git a/test/tools/nl_files/mesh_maker_fv09 b/test/tools/nl_files/mesh_maker_fv09 deleted file mode 100644 index 7de951fee1..0000000000 --- a/test/tools/nl_files/mesh_maker_fv09 +++ /dev/null @@ -1 +0,0 @@ - --input CSMDATA/atm/datm7/domain.lnd.fv0.9x1.25_gx1v6.090309.nc --lat yc --lon xc --overwrite --mask mask --area area --verbose 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/modify_data_YELL b/test/tools/nl_files/modify_data_YELL deleted file mode 100644 index 0d180e8bf6..0000000000 --- a/test/tools/nl_files/modify_data_YELL +++ /dev/null @@ -1 +0,0 @@ ---neon_site YELL --surf_dir CSMDATA/lnd/clm2/surfdata_esmf/NEON --out_dir EXEDIR --inputdata-dir CSMDATA diff --git a/test/tools/nl_files/run_neon_OSBS b/test/tools/nl_files/run_neon_OSBS deleted file mode 100644 index 0c274b13ad..0000000000 --- a/test/tools/nl_files/run_neon_OSBS +++ /dev/null @@ -1 +0,0 @@ ---verbose --run-type ad --setup-only --neon-site OSBS diff --git a/test/tools/nl_files/run_neon_YELL_PRISM b/test/tools/nl_files/run_neon_YELL_PRISM deleted file mode 100644 index f5ebdf9fdf..0000000000 --- a/test/tools/nl_files/run_neon_YELL_PRISM +++ /dev/null @@ -1 +0,0 @@ ---verbose --run-type transient --setup-only --neon-site YELL --prism --neon-version v2 --experiment toolstest diff --git a/test/tools/nl_files/subset_data_KONA b/test/tools/nl_files/subset_data_KONA deleted file mode 100644 index 0df59b1b17..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-surface --outdir EXEDIR/KONA_user-mod_and_data --user-mods-dir EXEDIR/KONA_user-mod_and_data --verbose --inputdata-dir CSMDATA 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 935b0dc99d..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 --inputdata-dir CSMDATA diff --git a/test/tools/nl_files/subset_data_YELL b/test/tools/nl_files/subset_data_YELL deleted file mode 100644 index 0d6960e7f5..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 --uniform-snowpack --cap-saturation --create-surface --outdir EXEDIR/YELL_user-mod_and_data --user-mods-dir EXEDIR/YELL_user-mod_and_data --silent --inputdata-dir CSMDATA diff --git a/test/tools/nl_files/subset_data_f09_1x1pt_townshipSD b/test/tools/nl_files/subset_data_f09_1x1pt_townshipSD deleted file mode 100644 index aa25c07d1e..0000000000 --- a/test/tools/nl_files/subset_data_f09_1x1pt_townshipSD +++ /dev/null @@ -1 +0,0 @@ -point --lon 257.5 --lat 43.822 --site f09_1x1pt_townshipSD --include-nonveg --crop --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 --inputdata-dir CSMDATA diff --git a/test/tools/nl_files/subset_data_f09_37x288pt_PanBoreal b/test/tools/nl_files/subset_data_f09_37x288pt_PanBoreal deleted file mode 100644 index 448b5052d6..0000000000 --- a/test/tools/nl_files/subset_data_f09_37x288pt_PanBoreal +++ /dev/null @@ -1 +0,0 @@ -region --lat1 55 --lat2 89.1 --lon1 0 --lon2 360 --create-mesh --create-surface --create-domain --create-user-mods --verbose --overwrite --reg f09_37x288pt_PanBoreal --inputdata-dir CSMDATA diff --git a/test/tools/nl_files/subset_data_f09_4x9pt_AlaskaTananaValley b/test/tools/nl_files/subset_data_f09_4x9pt_AlaskaTananaValley deleted file mode 100644 index 9928d78429..0000000000 --- a/test/tools/nl_files/subset_data_f09_4x9pt_AlaskaTananaValley +++ /dev/null @@ -1 +0,0 @@ -region --lat1 62 --lat2 66 --lon1 -152 --lon2 -141 --create-mesh --create-domain --create-surface --create-user-mods --verbose --overwrite --reg f09_4x9pt_AlaskaTananaValley --inputdata-dir CSMDATA diff --git a/test/tools/nl_files/subset_data_f09_58x45pt_SouthAmerica b/test/tools/nl_files/subset_data_f09_58x45pt_SouthAmerica deleted file mode 100644 index 201dd2c76c..0000000000 --- a/test/tools/nl_files/subset_data_f09_58x45pt_SouthAmerica +++ /dev/null @@ -1 +0,0 @@ -region --lat1 -40 --lat2 15 --lon1 275 --lon2 330 --create-mesh --create-surface --create-user-mods --create-domain --create-landuse --verbose --overwrite --reg f09_58x45_SouthAmerica --inputdata-dir CSMDATA diff --git a/test/tools/nl_files/subset_data_f09_90x288pt_1850PanTropics b/test/tools/nl_files/subset_data_f09_90x288pt_1850PanTropics deleted file mode 100644 index 1c9d5eace9..0000000000 --- a/test/tools/nl_files/subset_data_f09_90x288pt_1850PanTropics +++ /dev/null @@ -1 +0,0 @@ -region --lat1 -55 --lat2 30 --lon1 0 --lon2 360 --crop --create-surface --create-domain --create-mesh --overwrite --reg f09_90x288pt_1850PanTropics --inputdata-dir CSMDATA --cfg-file CTSM_ROOT/tools/mksurfdata_map/default_data_1850.cfg --verbose 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 f93301a530..0000000000 --- a/test/tools/test_driver.sh +++ /dev/null @@ -1,722 +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 - - ##Derecho - derecho* | dec*) - submit_script="test_driver_derecho${cur_time}.sh" - -##vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv writing to batch script vvvvvvvvvvvvvvvvvvv -cat > ./${submit_script} << EOF -#!/bin/sh -# - -interactive="YES" -input_file="tests_pretag_derecho_nompi" -c_threads=128 - -export INITMODULES="/glade/u/apps/derecho/23.06/spack/opt/spack/lmod/8.7.20/gcc/7.5.0/pdxb/lmod/lmod/init/sh" -. \$INITMODULES - -module --force purge -module load ncarenv -module load craype -module load intel -module load mkl -module load ncarcompilers -module load netcdf -module load nco -module load ncl - -#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="derecho" -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=\$SCRATCH -export CPRNC_EXE="$CESMDATAROOT/cprnc/cprnc" -dataroot="$CESMDATAROOT/inputdata" -export TOOLSLIBS="" -export REGRID_PROC=1 -export TOOLS_CONF_STRING="--mpilib mpi-serial" - - -echo_arg="" - -EOF -#^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ writing to batch script ^^^^^^^^^^^^^^^^^^^ - ;; - - ##cheyenne - cheyenne* | r*i*n*) - submit_script="test_driver_cheyenne${cur_time}.sh" - -#vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv writing to batch script vvvvvvvvvvvvvvvvvvv -at > ./${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 - - -##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 - - -##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 - -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 - -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: derecho, 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 - -# Setup conda environment -conda activate ctsm_pylib -if [ \$? -ne 0 ]; then - echo "ERROR: Trouble activating the ctsm_pylib conda environment, be sure it's setup with \$CLM_ROOT/py_env_create, then rerun" - exit 4 -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 derecho, 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_hobart_nompi b/test/tools/tests_posttag_hobart_nompi deleted file mode 100644 index c185428868..0000000000 --- a/test/tools/tests_posttag_hobart_nompi +++ /dev/null @@ -1 +0,0 @@ -smc#4 blc#4 diff --git a/test/tools/tests_posttag_nompi_regression b/test/tools/tests_posttag_nompi_regression deleted file mode 100644 index c185428868..0000000000 --- a/test/tools/tests_posttag_nompi_regression +++ /dev/null @@ -1 +0,0 @@ -smc#4 blc#4 diff --git a/test/tools/tests_pretag_cheyenne_nompi b/test/tools/tests_pretag_cheyenne_nompi deleted file mode 100644 index e92ffaaaad..0000000000 --- a/test/tools/tests_pretag_cheyenne_nompi +++ /dev/null @@ -1,3 +0,0 @@ -smc#4 blc#4 -smba1 blba1 -smbd1 blbd1 diff --git a/test/tools/tests_pretag_derecho_nompi b/test/tools/tests_pretag_derecho_nompi deleted file mode 100644 index 5fdaf335ae..0000000000 --- a/test/tools/tests_pretag_derecho_nompi +++ /dev/null @@ -1,9 +0,0 @@ -smba1 blba1 -smbd1 blbd1 -sm0a1 bl0a1 -sm0c1 bl0c1 -smaa2 blaa2 -smba1 blba1 -smb81 blb81 -smbc1 blbc1 -smbd1 blbd1 diff --git a/test/tools/tests_pretag_nompi_neon b/test/tools/tests_pretag_nompi_neon deleted file mode 100644 index e5fa27e6c4..0000000000 --- a/test/tools/tests_pretag_nompi_neon +++ /dev/null @@ -1,8 +0,0 @@ -sm0a1 bl0a1 -sm0c1 bl0c1 -smaa2 blaa2 -smba1 blba1 -smbb1 blbb1 -smb81 blb81 -smbc1 blbc1 -smbd1 blbd1 diff --git a/tools/README b/tools/README index 568dc1239b..693e793370 100644 --- a/tools/README +++ b/tools/README @@ -11,8 +11,6 @@ I. General directory structure: crop_calendars --- Regrid and process GGCMI sowing and harvest date files for use in CTSM. mkmapgrids ------- Create regular lat/lon SCRIP grid files - mkprocdata_map --- Convert output unstructured grids into a 2D format that - can be plotted easily site_and_regional Scripts for handling input datasets for site and regional cases. These scripts both help with creation of datasets using the @@ -33,49 +31,6 @@ I. General directory structure: II. Notes on building/running for each of the above tools: - mkprocdata_map has the following files to facilitate building the FORTRAN code: - - 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 - - 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 - - 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 - mksurfdata_esmf has a cime configure and CMake based build using the following files: gen_mksurfdata_build ---- Build mksurfdata_esmf 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/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 e4dd2519ff..7e9dbbc426 100755 --- a/tools/contrib/run_clmtowers +++ b/tools/contrib/run_clmtowers @@ -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/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/mkprocdata_map/README b/tools/mkprocdata_map/README deleted file mode 100644 index 92ffb4856c..0000000000 --- a/tools/mkprocdata_map/README +++ /dev/null @@ -1,151 +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. - -(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 42f797b3c2..0000000000 --- a/tools/mkprocdata_map/src/Makefile +++ /dev/null @@ -1,10 +0,0 @@ -# Makefile for mkprocdata_map - -EXENAME = ../mkprocdata_map - -# Set optimization on by default -ifeq ($(OPT),$(null)) - OPT := TRUE -endif - -include Makefile.common 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