diff --git a/.github/workflows/e3sm-gh-ci-cime-tests.yml b/.github/workflows/e3sm-gh-ci-cime-tests.yml index 366fef018f20..6c9ee1ab114c 100644 --- a/.github/workflows/e3sm-gh-ci-cime-tests.yml +++ b/.github/workflows/e3sm-gh-ci-cime-tests.yml @@ -5,14 +5,18 @@ on: branches: [ master ] paths: # first, yes to these + - '.github/workflows/e3sm-gh-ci-cime-tests.yml' - 'cime_config/**' - 'components/eam/**' + - 'components/eamxx/**' - 'components/elm/**' - 'driver-moab/**' - 'driver-mct/**' # second, no to these - '!components/eam/docs/**' - '!components/eam/mkdocs.yml' + - '!components/eamxx/docs/**' + - '!components/eamxx/mkdocs.yml' - '!components/elm/docs/**' - '!components/elm/mkdocs.yml' @@ -26,17 +30,13 @@ jobs: strategy: fail-fast: false matrix: - test: - - SMS_D_P4.ne4pg2_oQU480.F2010.singularity_gnu - - SMS_P4.ne4pg2_oQU480.F2010.singularity_gnu - - REP_P4.ne4pg2_oQU480.F2010.singularity_gnu - - ERS_P4.ne4pg2_oQU480.F2010.singularity_gnu - - ERS_P4.ne4pg2_oQU480.F2010.singularity_gnu.eam-wcprod_F2010 - - ERP_P4.ne4pg2_oQU480.F2010.singularity_gnu - - PET_P4.ne4pg2_oQU480.F2010.singularity_gnu - - PEM_P4.ne4pg2_oQU480.F2010.singularity_gnu + test: + - SMS_D_Ln5_P4.ne4pg2_oQU480.F2010.ghci-oci_gnu + - ERS_Ld5_P4.ne4pg2_oQU480.F2010.ghci-oci_gnu.eam-wcprod_F2010 + - SMS_D_Ln5_P4.ne4pg2_oQU480.F2010-SCREAMv1-MPASSI.ghci-oci_gnu + - ERS_Ld5_P4.ne4pg2_oQU480.F2010-SCREAMv1-MPASSI.ghci-oci_gnu.eamxx-prod container: - image: ghcr.io/mahf708/e3sm-imgs:v0.0.6 + image: ghcr.io/e3sm-project/containers-ghci:ghci-0.1.0 steps: - @@ -49,10 +49,6 @@ jobs: name: CIME working-directory: cime/scripts run: | - mkdir -p $HOME/projects/e3sm/cesm-inputdata/atm/cam/physprops/ - wget https://web.lcrc.anl.gov/public/e3sm/inputdata/atm/cam/physprops/p3_lookup_table_1.dat-v4.1.2 - mv p3_lookup_table_1.dat-v4.1.2 $HOME/projects/e3sm/cesm-inputdata/atm/cam/physprops/ - export USER=test ./create_test ${{ matrix.test }} --wait --debug - name: Artifacts @@ -61,7 +57,7 @@ jobs: with: name: ${{ matrix.test }} path: | - ~/projects/e3sm/scratch/${{ matrix.test }}*/TestStatus.log - ~/projects/e3sm/scratch/${{ matrix.test }}*/bld/*.bldlog.* - ~/projects/e3sm/scratch/${{ matrix.test }}*/run/*.log.* - ~/projects/e3sm/scratch/${{ matrix.test }}*/run/*.cprnc.out + /projects/e3sm/scratch/${{ matrix.test }}*/TestStatus.log + /projects/e3sm/scratch/${{ matrix.test }}*/bld/*.bldlog.* + /projects/e3sm/scratch/${{ matrix.test }}*/run/*.log.* + /projects/e3sm/scratch/${{ matrix.test }}*/run/*.cprnc.out diff --git a/.github/workflows/e3sm-gh-ci-w-cime-tests.yml b/.github/workflows/e3sm-gh-ci-w-cime-tests.yml index 595518c326d7..48c367c8f625 100644 --- a/.github/workflows/e3sm-gh-ci-w-cime-tests.yml +++ b/.github/workflows/e3sm-gh-ci-w-cime-tests.yml @@ -14,21 +14,16 @@ on: jobs: ci-w: + if: ${{ github.event.repository.name == 'e3sm' }} runs-on: ubuntu-latest strategy: fail-fast: false matrix: - test: - - SMS_D_P8.ne4pg2_oQU480.WCYCL2010NS.singularity_gnu - - SMS_P8.ne4pg2_oQU480.WCYCL2010NS.singularity_gnu - - REP_P8.ne4pg2_oQU480.WCYCL2010NS.singularity_gnu - - ERS_P8.ne4pg2_oQU480.WCYCL2010NS.singularity_gnu - - ERS_P8.ne4pg2_oQU480.WCYCL2010NS.singularity_gnu.allactive-wcprod_1850 - - ERP_P8.ne4pg2_oQU480.WCYCL2010NS.singularity_gnu - - PET_P8.ne4pg2_oQU480.WCYCL2010NS.singularity_gnu - - PEM_P8.ne4pg2_oQU480.WCYCL2010NS.singularity_gnu + test: + - SMS_D_Ld1_P8.ne4pg2_oQU480.WCYCL2010NS.ghci-oci_gnu + - ERS_Ld3_P8.ne4pg2_oQU480.WCYCL2010NS.ghci-oci_gnu.allactive-wcprod_1850 container: - image: ghcr.io/mahf708/e3sm-imgs:v0.0.6 + image: ghcr.io/e3sm-project/containers-ghci:ghci-0.1.0 steps: - @@ -41,10 +36,6 @@ jobs: name: CIME working-directory: cime/scripts run: | - mkdir -p $HOME/projects/e3sm/cesm-inputdata/atm/cam/physprops/ - wget https://web.lcrc.anl.gov/public/e3sm/inputdata/atm/cam/physprops/p3_lookup_table_1.dat-v4.1.2 - mv p3_lookup_table_1.dat-v4.1.2 $HOME/projects/e3sm/cesm-inputdata/atm/cam/physprops/ - export USER=test ./create_test ${{ matrix.test }} --wait --debug - name: Artifacts @@ -53,7 +44,7 @@ jobs: with: name: ${{ matrix.test }} path: | - ~/projects/e3sm/scratch/${{ matrix.test }}*/TestStatus.log - ~/projects/e3sm/scratch/${{ matrix.test }}*/bld/*.bldlog.* - ~/projects/e3sm/scratch/${{ matrix.test }}*/run/*.log.* - ~/projects/e3sm/scratch/${{ matrix.test }}*/run/*.cprnc.out + /projects/e3sm/scratch/${{ matrix.test }}*/TestStatus.log + /projects/e3sm/scratch/${{ matrix.test }}*/bld/*.bldlog.* + /projects/e3sm/scratch/${{ matrix.test }}*/run/*.log.* + /projects/e3sm/scratch/${{ matrix.test }}*/run/*.cprnc.out diff --git a/.github/workflows/e3sm-gh-md-linter.yml b/.github/workflows/e3sm-gh-md-linter.yml index 8ee8b7a7f13c..424a871637b6 100644 --- a/.github/workflows/e3sm-gh-md-linter.yml +++ b/.github/workflows/e3sm-gh-md-linter.yml @@ -17,12 +17,12 @@ jobs: - uses: actions/checkout@v4 with: fetch-depth: 0 - - uses: tj-actions/changed-files@v44 + - uses: tj-actions/changed-files@v45 id: changed-files with: files: '**/*.md' separator: "," - - uses: DavidAnson/markdownlint-cli2-action@v16 + - uses: DavidAnson/markdownlint-cli2-action@v17 if: steps.changed-files.outputs.any_changed == 'true' with: config: 'docs/.markdownlint.json' diff --git a/.github/workflows/e3sm-gh-pages.yml b/.github/workflows/e3sm-gh-pages.yml index ccca0c479f26..ebd2ac9c1e97 100644 --- a/.github/workflows/e3sm-gh-pages.yml +++ b/.github/workflows/e3sm-gh-pages.yml @@ -30,10 +30,10 @@ jobs: submodules: true - name: Show action trigger run: echo "= The job was automatically triggered by a ${{github.event_name}} event on repo ${{github.event.repository.name}}." - - name: Set up Python 3.10 - uses: actions/setup-python@v5.1.0 + - name: Set up Python 3.11 + uses: actions/setup-python@v5 with: - python-version: "3.10" + python-version: "3.11" - name: Install python deps run: python3 -m pip install mkdocs-material pymdown-extensions mkdocs-monorepo-plugin mdutils mkdocs-bibtex # build every time (PR or push to master) diff --git a/.github/workflows/e3sm-gh-tools-mkatmsrffile-test.yml b/.github/workflows/e3sm-gh-tools-mkatmsrffile-test.yml new file mode 100644 index 000000000000..8fe212886d9f --- /dev/null +++ b/.github/workflows/e3sm-gh-tools-mkatmsrffile-test.yml @@ -0,0 +1,86 @@ +name: mkatmsrffile + +on: + push: + branches: [ master ] + pull_request: + branches: [ master ] + paths: + - 'components/eam/tools/mkatmsrffile/mkatmsrffile.py' + schedule: + - cron: '00 15 * * 2' + workflow_dispatch: + +jobs: + mkatmsrffile-test: + runs-on: ubuntu-latest + defaults: + run: + shell: bash -l {0} + outputs: + event_name: ${{ github.event_name }} + steps: + - + name: Repository checkout + uses: actions/checkout@v4 + with: + show-progress: false + submodules: false + - + name: Conda setup + uses: conda-incubator/setup-miniconda@v3 + with: + activate-environment: "envmkatmsrffile" + miniforge-variant: Mambaforge + miniforge-version: latest + use-mamba: true + mamba-version: "*" + channel-priority: strict + auto-update-conda: true + python-version: 3.11 + - + name: Install dependencies + run: | + echo $CONDA_PREFIX + mamba install -y nco xarray numba numpy netcdf4 + - + name: Run tests + working-directory: components/eam/tools/mkatmsrffile + run: | + echo $CONDA_PREFIX + wget https://web.lcrc.anl.gov/public/e3sm/inputdata/atm/cam/chem/trop_mozart/dvel/clim_soilw.nc + wget https://web.lcrc.anl.gov/public/e3sm/inputdata/atm/cam/chem/trop_mozart/dvel/regrid_vegetation.nc + wget https://web.lcrc.anl.gov/public/e3sm/inputdata/atm/cam/chem/trop_mozart/dvel/map_1x1_to_ne30pg2_traave_c20240903.nc + python mkatmsrffile.py --map_file=map_1x1_to_ne30pg2_traave_c20240903.nc --vegetation_file=regrid_vegetation.nc --soil_water_file=clim_soilw.nc --dst_grid=ne30pg2 + + mkatmsrffile-notify: + needs: mkatmsrffile-test + if: ${{ failure() && needs.mkatmsrffile-test.outputs.event_name != 'pull_request' }} + runs-on: ubuntu-latest + steps: + - name: Create issue + run: | + previous_issue_number=$(gh issue list \ + --label "$LABELS" \ + --json number \ + --jq '.[0].number') + if [[ -n $previous_issue_number ]]; then + gh issue comment "$previous_issue_number" \ + --body "$BODY" + else + gh issue create \ + --title "$TITLE" \ + --assignee "$ASSIGNEES" \ + --label "$LABELS" \ + --body "$BODY" + fi + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GH_REPO: ${{ github.repository }} + TITLE: mkatmsrffile test failure + ASSIGNEES: whannah1 + LABELS: bug,notify-mkatmsrffile-gh-action + BODY: | + Workflow failed! There's likely an issue in the mkatmsrffile tool! For more information, please see: + - Workflow URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} (number ${{ github.run_number }}, attempt ${{ github.run_attempt }}) + - Workflow SHA: ${{ github.sha }} diff --git a/.github/workflows/eamxx-gh-pages.yml b/.github/workflows/eamxx-gh-pages.yml index abd8b92e4f6c..2ce70d97843c 100644 --- a/.github/workflows/eamxx-gh-pages.yml +++ b/.github/workflows/eamxx-gh-pages.yml @@ -54,7 +54,7 @@ jobs: echo "= The job was automatically triggered by a ${{github.event_name}} event." - name: Set up Python 3.11 - uses: actions/setup-python@v5.1.0 + uses: actions/setup-python@v5 with: python-version: "3.11" diff --git a/.github/workflows/eamxx_default_files.yml b/.github/workflows/eamxx_default_files.yml index 5ecdf6dec00c..950f335700ee 100644 --- a/.github/workflows/eamxx_default_files.yml +++ b/.github/workflows/eamxx_default_files.yml @@ -5,6 +5,8 @@ on: branches: [ master ] pull_request: branches: [ master ] + paths: + - 'components/eamxx/cime_config/namelist_defaults_scream.xml' schedule: - cron: '00 00 * * *' workflow_dispatch: @@ -21,7 +23,7 @@ jobs: show-progress: false submodules: false - name: Set up Python 3.11 - uses: actions/setup-python@v5.1.0 + uses: actions/setup-python@v5 with: python-version: "3.11" - name: Run unit tests diff --git a/cime b/cime index f903115718eb..0cdd4b1c5c5e 160000 --- a/cime +++ b/cime @@ -1 +1 @@ -Subproject commit f903115718ebc30669ce557f511abaef231a1d88 +Subproject commit 0cdd4b1c5c5eb2e29c6ec64667724af434847bcf diff --git a/cime_config/allactive/config_compsets.xml b/cime_config/allactive/config_compsets.xml index 6ecf2fbf29c6..d5a52a8bac38 100755 --- a/cime_config/allactive/config_compsets.xml +++ b/cime_config/allactive/config_compsets.xml @@ -86,23 +86,65 @@ 20TRSOI_EAM%CMIP6_ELM%CNPRDCTCBCTOP_MPASSI_MPASO_MOSART_SGLC_SWAV + + + + WCYCL20TR-GHG + 20TRSOI_EAM%CMIP6-GHG_ELM%CNPRDCTCBCTOP_MPASSI_MPASO_MOSART_SGLC_SWAV + + + + WCYCL20TR-aer + 20TRSOI_EAM%CMIP6-AER_ELM%CNPRDCTCBCTOP_MPASSI_MPASO_MOSART_SGLC_SWAV + + + + WCYCL20TR-xGHG-xaer + 20TRSOI_EAM%CMIP6-xGHG-xAER_ELM%CNPRDCTCBCTOP_MPASSI_MPASO_MOSART_SGLC_SWAV + + + + WCYCL20TR-nat + 20TRSOI_EAM%CMIP6-NAT_ELM%CNPRDCTCBCTOP_MPASSI_MPASO_MOSART_SGLC_SWAV + + + + WCYCL20TR-ozone + 20TRSOI_EAM%CMIP6-OZONE_ELM%CNPRDCTCBCTOP_MPASSI_MPASO_MOSART_SGLC_SWAV + + + + WCYCL20TR-lulc + 20TRSOI_EAM%CMIP6-LULC_ELM%CNPRDCTCBCTOP_MPASSI_MPASO_MOSART_SGLC_SWAV + + + + WCYCL20TR-volc + 20TRSOI_EAM%CMIP6-VOLC_ELM%CNPRDCTCBCTOP_MPASSI_MPASO_MOSART_SGLC_SWAV + + + + WCYCL20TR-xaer + 20TRSOI_EAM%CMIP6-xAER_ELM%CNPRDCTCBCTOP_MPASSI_MPASO_MOSART_SGLC_SWAV + + WCYCL1950-MMF1 - 1950SOI_EAM%CMIP6-MMF1_ELM%SPBC_MPASSI_MPASO_MOSART_SGLC_SWAV + 1950SOI_EAM%MMF1_ELM%SPBC_MPASSI_MPASO_MOSART_SGLC_SWAV WCYCL20TR-MMF1 - 20TRSOI_EAM%CMIP6-MMF1_ELM%SP_MPASSI_MPASO_MOSART_SGLC_SWAV + 20TRSOI_EAM%MMF1_ELM%SP_MPASSI_MPASO_MOSART_SGLC_SWAV WCYCL20TRNS-MMF1 - 20TR_EAM%CMIP6-MMF1_ELM%SP_MPASSI_MPASO_MOSART_SGLC_SWAV + 20TR_EAM%MMF1_ELM%SP_MPASSI_MPASO_MOSART_SGLC_SWAV @@ -341,42 +383,52 @@ CRYO1850 - 1850SOI_EAM%CMIP6_ELM%SPBC_MPASSI%DIB_MPASO%IBPISMF_MOSART_SGLC_SWAV + 1850SOI_EAM%CMIP6_ELM%CNPRDCTCBCTOP_MPASSI%DIB_MPASO%IBPISMF_MOSART_SGLC_SWAV CRYO1850-4xCO2 - 1850SOI_EAM%CMIP6-4xCO2_ELM%SPBC_MPASSI%DIB_MPASO%IBPISMF_MOSART_SGLC_SWAV + 1850SOI_EAM%CMIP6-4xCO2_ELM%CNPRDCTCBCTOP_MPASSI%DIB_MPASO%IBPISMF_MOSART_SGLC_SWAV + + + + CRYO1850-1pctCO2 + 1850SOI_EAM%CMIP6-1pctCO2_ELM%CNPRDCTCBCTOP_MPASSI%DIB_MPASO%IBPISMF_MOSART_SGLC_SWAV CRYO1950 - 1950SOI_EAM%CMIP6_ELM%SPBC_MPASSI%DIB_MPASO%IBPISMF_MOSART_SGLC_SWAV + 1950SOI_EAM%CMIP6_ELM%CNPRDCTCBCTOP_MPASSI%DIB_MPASO%IBPISMF_MOSART_SGLC_SWAV CRYO1850-DISMF - 1850SOI_EAM%CMIP6_ELM%SPBC_MPASSI%DIB_MPASO%IBDISMF_MOSART_SGLC_SWAV + 1850SOI_EAM%CMIP6_ELM%CNPRDCTCBCTOP_MPASSI%DIB_MPASO%IBDISMF_MOSART_SGLC_SWAV CRYO1950-DISMF - 1950SOI_EAM%CMIP6_ELM%SPBC_MPASSI%DIB_MPASO%IBDISMF_MOSART_SGLC_SWAV + 1950SOI_EAM%CMIP6_ELM%CNPRDCTCBCTOP_MPASSI%DIB_MPASO%IBDISMF_MOSART_SGLC_SWAV CRYO20TR - 20TRSOI_EAM%CMIP6_ELM%SPBC_MPASSI%DIB_MPASO%IBPISMF_MOSART_SGLC_SWAV + 20TRSOI_EAM%CMIP6_ELM%CNPRDCTCBCTOP_MPASSI%DIB_MPASO%IBPISMF_MOSART_SGLC_SWAV + + + + CRYOSSP245 + SSP245SOI_EAM%CMIP6_ELM%CNPRDCTCBCTOP_MPASSI%DIB_MPASO%IBPISMF_MOSART_SGLC_SWAV CRYOSSP585 - SSP585SOI_EAM%CMIP6_ELM%SPBC_MPASSI%DIB_MPASO%IBPISMF_MOSART_SGLC_SWAV + SSP585SOI_EAM%CMIP6_ELM%CNPRDCTCBCTOP_MPASSI%DIB_MPASO%IBPISMF_MOSART_SGLC_SWAV CRYOSSP370 - SSP370SOI_EAM%CMIP6_ELM%SPBC_MPASSI%DIB_MPASO%IBPISMF_MOSART_SGLC_SWAV + SSP370SOI_EAM%CMIP6_ELM%CNPRDCTCBCTOP_MPASSI%DIB_MPASO%IBPISMF_MOSART_SGLC_SWAV @@ -421,6 +473,11 @@ 2000_DATM%JRA-1p5_SLND_MPASSI_MPASO%DATMFORCED_DROF%JRA-1p5_MALI%SIA_SWAV + + MPAS_FOLISIO_JRA1p5 + 2000_DATM%JRA-1p5_SLND_MPASSI_MPASO%DATMFORCED_DROF%JRA-1p5_MALI_SWAV + + E1850C5ELM diff --git a/cime_config/allactive/config_pesall.xml b/cime_config/allactive/config_pesall.xml index 2457b287ec5b..3392ad71ca10 100644 --- a/cime_config/allactive/config_pesall.xml +++ b/cime_config/allactive/config_pesall.xml @@ -1322,6 +1322,65 @@ + + + --compset WCYCL* --res ne30pg2_r05_IcoswISC30E3r5 on 25 nodes pure-MPI, ~2.9 sypd + + 675 + 324 + 324 + 360 + 216 + 684 + + + 0 + 360 + 360 + 0 + 684 + 0 + + + + --compset WCYCL* --res ne30pg2_r05_IcoswISC30E3r5 on 50 nodes pure-MPI, ~5.6 sypd + + 1350 + 648 + 648 + 720 + 432 + 1368 + + + 0 + 720 + 720 + 0 + 1368 + 0 + + + + --compset WCYCL* --res ne30pg2_r05_IcoswISC30E3r5 on 100 nodes pure-MPI, ~8.8 sypd + + 2700 + 1260 + 1260 + 1440 + 900 + 2700 + + + 0 + 1440 + 1440 + 0 + 2700 + 0 + + + gcp12 --compset WCYCL* --res ne30pg2_r05_IcoswISC30E3r5 on 4 nodes @@ -1413,6 +1472,21 @@ + + + sunspot|aurora: --compset BGC* --res ne30pg2_r05_IcoswISC30E3r5 on 2 nodes pure-MPI + + -2 + -2 + -2 + -2 + -2 + -2 + -2 + -2 + + + @@ -1685,6 +1759,21 @@ + + + allactive+sunspot|aurora: default, 96 mpi x 1 omp @ root 0 + + 96 + 96 + 96 + 96 + 96 + 96 + 96 + 96 + + + diff --git a/cime_config/config_archive.xml b/cime_config/config_archive.xml index f343fce81ba0..8cb7a5305386 100644 --- a/cime_config/config_archive.xml +++ b/cime_config/config_archive.xml @@ -29,7 +29,7 @@ r\.(INSTANT|AVERAGE|MAX|MIN)\.n(step|sec|min|hour|day|month|year)s_x\d* rhist\.(INSTANT|AVERAGE|MAX|MIN)\.n(step|sec|min|hour|day|month|year)s_x\d* - hi\.(INSTANT|AVERAGE|MAX|MIN)\.n(step|sec|min|hour|day|month|year)s_x\d*\.\d{4}-\d{2}-\d{2}-\d{5}\.nc$ + .*\.h\.(?!rhist\.).*\.nc$ diff --git a/cime_config/config_files.xml b/cime_config/config_files.xml index 281291798dbd..e88a9d68f62a 100644 --- a/cime_config/config_files.xml +++ b/cime_config/config_files.xml @@ -348,6 +348,7 @@ $COMP_ROOT_DIR_ICE/cime_config/testdefs/testmods_dirs $COMP_ROOT_DIR_ROF/cime_config/testdefs/testmods_dirs $COMP_ROOT_DIR_ATM/cime_config/testdefs/testmods_dirs + $COMP_ROOT_DIR_ATM/cime_config/testdefs/testmods_dirs $COMP_ROOT_DIR_OCN/cime_config/testdefs/testmods_dirs $COMP_ROOT_DIR_ICE/cime_config/testdefs/testmods_dirs $COMP_ROOT_DIR_WAV/cime_config/testdefs/testmods_dirs diff --git a/cime_config/config_grids.xml b/cime_config/config_grids.xml index 3fb5ef619d73..0f1c3512ec8a 100755 --- a/cime_config/config_grids.xml +++ b/cime_config/config_grids.xml @@ -626,6 +626,16 @@ IcoswISC30E3r5 + + TL319 + r05 + IcoswISC30E3r5 + r05 + null + null + IcoswISC30E3r5 + + TL319 TL319 @@ -1835,6 +1845,8 @@ + + ne30np4 ne30np4 @@ -1855,6 +1867,8 @@ oEC60to30v3wLI + + ne30np4 ne30np4 @@ -1985,6 +1999,8 @@ gx1v6 + + 0.9x1.25 0.9x1.25 @@ -2005,6 +2021,56 @@ oQU240wLI + + TL319 + TL319 + oQU240wLI + JRA025 + mpas.ais8to30km + null + oQU240wLI + + + + ne30np4.pg2 + r05 + IcoswISC30E3r5 + r05 + mpas.ais8to30km + null + IcoswISC30E3r5 + + + + TL319 + TL319 + IcoswISC30E3r5 + JRA025 + mpas.ais8to30km + null + IcoswISC30E3r5 + + + + ne30np4.pg2 + r05 + IcoswISC30E3r5 + r05 + mpas.ais4to20km + null + IcoswISC30E3r5 + + + + TL319 + TL319 + IcoswISC30E3r5 + JRA025 + mpas.ais4to20km + null + IcoswISC30E3r5 + + @@ -3279,6 +3345,18 @@ mpas.ais20km is a uniform-resolution 20km MALI grid of the Antarctic Ice Sheet. It is primarily intended for testing. + + 98341 + 1 + mpas.ais8to30km is a variable resolution MALI mesh of the Antarctic Ice Sheet with resolution varying from 8 km in fast flowing regions and near the ice-sheet margins to 30 km in the ice-sheet interior. It behaves reasonably well for most of the ice sheet but results in Thwaites Glacier retreating too rapidly due to insufficient resolution there. It is meant as a cheaper alternative to mpas.ais4to20km for testing realistic conditions. + + + + 385379 + 1 + mpas.ais4to20km is a variable resolution MALI mesh of the Antarctic Ice Sheet with resolution varying from 4 km in fast flowing regions and near the ice-sheet margins to 20 km in the ice-sheet interior. It was the primary mesh and initial condition used for ISMIP6-Antarctica-2300 and is the primary Antarctic mesh to use for E3SM v3 simulation and development with an active Antarctic Ice Sheet component. + + @@ -5622,6 +5700,76 @@ cpl/gridmaps/mpas.ais20km/map_ais20km_to_oQU240wLI_esmfnearestdtos.20240509.nc + + + + + + cpl/gridmaps/r05/map_r05_to_ais8to30_traave.20240701.nc + cpl/gridmaps/r05/map_r05_to_ais8to30_trbilin.20240701.nc + cpl/gridmaps/mpas.ais8to30km/map_ais8to30_to_r05_traave.20240701.nc + cpl/gridmaps/mpas.ais8to30km/map_ais8to30_to_r05_traave.20240701.nc + + + + cpl/gridmaps/TL319/map_TL319_to_ais8to30_traave.20240701.nc + cpl/gridmaps/TL319/map_TL319_to_ais8to30_trbilin.20240701.nc + cpl/gridmaps/mpas.ais8to30km/map_ais8to30_to_TL319_traave.20240701.nc + cpl/gridmaps/mpas.ais8to30km/map_ais8to30_to_TL319_traave.20240701.nc + + + + cpl/gridmaps/oQU240wLI/map_oQU240wLI-nomask_to_ais8to30_esmfaave.20240701.nc + cpl/gridmaps/oQU240wLI/map_oQU240wLI-nomask_to_ais8to30_esmfbilin.20240701.nc + cpl/gridmaps/mpas.ais8to30km/map_ais8to30_to_oQU240wLI-nomask_esmfaave.20240701.nc + cpl/gridmaps/mpas.ais8to30km/map_ais8to30_to_oQU240wLI-nomask_esmfbilin.20240701.nc + cpl/gridmaps/mpas.ais8to30km/map_ais8to30_to_oQU240wLI-nomask_esmfaave.20240701.nc + cpl/gridmaps/mpas.ais8to30km/map_ais8to30_to_oQU240wLI-nomask_esmfbilin.20240701.nc + cpl/gridmaps/mpas.ais8to30km/map_ais8to30_to_oQU240wLI-nomask_esmfnearestdtos.20240701.nc + cpl/gridmaps/mpas.ais8to30km/map_ais8to30_to_oQU240wLI_esmfnearestdtos.20240701.nc + + + + cpl/gridmaps/IcoswISC30E3r5/map_IcoswISC30E3r5-nomask_to_ais8to30_esmfaave.20240701.nc + cpl/gridmaps/IcoswISC30E3r5/map_IcoswISC30E3r5-nomask_to_ais8to30_esmfbilin.20240701.nc + cpl/gridmaps/mpas.ais8to30km/map_ais8to30_to_IcoswISC30E3r5-nomask_esmfaave.20240701.nc + cpl/gridmaps/mpas.ais8to30km/map_ais8to30_to_IcoswISC30E3r5-nomask_esmfbilin.20240701.nc + cpl/gridmaps/mpas.ais8to30km/map_ais8to30_to_IcoswISC30E3r5-nomask_esmfaave.20240701.nc + cpl/gridmaps/mpas.ais8to30km/map_ais8to30_to_IcoswISC30E3r5-nomask_esmfbilin.20240701.nc + cpl/gridmaps/mpas.ais8to30km/map_ais8to30_to_IcoswISC30E3r5-nomask_esmfnearestdtos.20240701.nc + cpl/gridmaps/mpas.ais8to30km/map_ais8to30_to_IcoswISC30E3r5_esmfnearestdtos.20240701.nc + + + + + + + + cpl/gridmaps/r05/map_r05_to_ais4to20_traave.20240701.nc + cpl/gridmaps/r05/map_r05_to_ais4to20_trbilin.20240701.nc + cpl/gridmaps/mpas.ais4to20km/map_ais4to20_to_r05_traave.20240701.nc + cpl/gridmaps/mpas.ais4to20km/map_ais4to20_to_r05_traave.20240701.nc + + + + cpl/gridmaps/TL319/map_TL319_to_ais4to20_traave.20240701.nc + cpl/gridmaps/TL319/map_TL319_to_ais4to20_trbilin.20240701.nc + cpl/gridmaps/mpas.ais4to20km/map_ais4to20_to_TL319_traave.20240701.nc + cpl/gridmaps/mpas.ais4to20km/map_ais4to20_to_TL319_traave.20240701.nc + + + + cpl/gridmaps/IcoswISC30E3r5/map_IcoswISC30E3r5-nomask_to_ais4to20_esmfaave.20240701.nc + cpl/gridmaps/IcoswISC30E3r5/map_IcoswISC30E3r5-nomask_to_ais4to20_esmfbilin.20240701.nc + cpl/gridmaps/mpas.ais4to20km/map_ais4to20_to_IcoswISC30E3r5-nomask_esmfaave.20240701.nc + cpl/gridmaps/mpas.ais4to20km/map_ais4to20_to_IcoswISC30E3r5-nomask_esmfbilin.20240701.nc + cpl/gridmaps/mpas.ais4to20km/map_ais4to20_to_IcoswISC30E3r5-nomask_esmfaave.20240701.nc + cpl/gridmaps/mpas.ais4to20km/map_ais4to20_to_IcoswISC30E3r5-nomask_esmfbilin.20240701.nc + cpl/gridmaps/mpas.ais4to20km/map_ais4to20_to_IcoswISC30E3r5-nomask_esmfnearestdtos.20240701.nc + cpl/gridmaps/mpas.ais4to20km/map_ais4to20_to_IcoswISC30E3r5_esmfnearestdtos.20240701.nc + + + diff --git a/cime_config/customize/case_post_run_io.py b/cime_config/customize/case_post_run_io.py index 83419aa81348..4451040db848 100755 --- a/cime_config/customize/case_post_run_io.py +++ b/cime_config/customize/case_post_run_io.py @@ -3,7 +3,11 @@ """ import os from CIME.XML.standard_module_setup import * -from CIME.utils import new_lid, run_and_log_case_status +try: + from CIME.utils import new_lid, run_and_log_case_status +except ImportError: + from CIME.utils import new_lid + from CIME.status import run_and_log_case_status logger = logging.getLogger(__name__) diff --git a/cime_config/machines/Depends.muller-cpu.gnu.cmake b/cime_config/machines/Depends.muller-cpu.gnu.cmake index 9ebd88ff8762..5c7331f979a9 100644 --- a/cime_config/machines/Depends.muller-cpu.gnu.cmake +++ b/cime_config/machines/Depends.muller-cpu.gnu.cmake @@ -8,6 +8,22 @@ if (NOT DEBUG) endforeach() endif() +# On pm-cpu (and muller-cpu), with gcc-native/12.3, we see hang with DEBUG runs of certain tests. +# https://github.com/E3SM-Project/E3SM/issues/6516 +# Currently, we have pm-cpu using gcc/12.2.0 which does not have this issue, but using muller-cpu to test 12.3 +# Turning off -O0 for these 2 files (by adding -O) at least avoids hang and will produce FPE in HOMME code +if (CMAKE_Fortran_COMPILER_VERSION VERSION_GREATER_EQUAL 12.3) + if (DEBUG) + set(ADJUST + eam/src/dynamics/se/inidat.F90 + eam/src/dynamics/se/dyn_comp.F90 + ) + foreach(ITEM IN LISTS ADJUST) + e3sm_add_flags("${ITEM}" "-O") + #e3sm_add_flags("${ITEM}" "-DNDEBUG -O") + endforeach() + endif() +endif() diff --git a/cime_config/machines/Depends.oneapi-ifxgpu.cmake b/cime_config/machines/Depends.oneapi-ifxgpu.cmake index 0dd35e56bcc9..5a958df26eba 100644 --- a/cime_config/machines/Depends.oneapi-ifxgpu.cmake +++ b/cime_config/machines/Depends.oneapi-ifxgpu.cmake @@ -1,14 +1,5 @@ -set(CPPDEFS "${CPPDEFS} -DMPAS_OPENMP_OFFLOAD") -list(APPEND MPAS_ADD_ACC_FLAGS - ${CMAKE_BINARY_DIR}/core_seaice/shared/mpas_seaice_mesh_pool.f90 - ${CMAKE_BINARY_DIR}/core_seaice/shared/mpas_seaice_velocity_solver_variational.f90 - ${CMAKE_BINARY_DIR}/core_seaice/shared/mpas_seaice_velocity_solver.f90 -) - -foreach(ITEM IN LISTS MPAS_ADD_ACC_FLAGS) - e3sm_add_flags("${ITEM}" "-fiopenmp -fopenmp-targets=spir64") -endforeach() - # compile mpas_seaice_core_interface.f90 with ifort, not ifx -e3sm_add_flags("${CMAKE_BINARY_DIR}/core_seaice/model_forward/mpas_seaice_core_interface.f90" "-fc=ifort") +if (NOT MPILIB STREQUAL "openmpi") + e3sm_add_flags("${CMAKE_BINARY_DIR}/core_seaice/model_forward/mpas_seaice_core_interface.f90" "-fc=ifort") +endif() diff --git a/cime_config/machines/cmake_macros/amdclang_frontier.cmake b/cime_config/machines/cmake_macros/amdclang_frontier.cmake index 2df5074d11f3..3727164933dc 100644 --- a/cime_config/machines/cmake_macros/amdclang_frontier.cmake +++ b/cime_config/machines/cmake_macros/amdclang_frontier.cmake @@ -9,4 +9,7 @@ string(APPEND CPPDEFS " -DLINUX") if (COMP_NAME STREQUAL gptl) string(APPEND CPPDEFS " -DHAVE_NANOTIME -DBIT64 -DHAVE_SLASHPROC -DHAVE_COMM_F2C -DHAVE_TIMES -DHAVE_GETTIMEOFDAY") endif() -string(APPEND CMAKE_EXE_LINKER_FLAGS " -L$ENV{CRAY_LIBSCI_PREFIX_DIR}/lib -lsci_amd") +string(APPEND CMAKE_EXE_LINKER_FLAGS " -L/opt/cray/pe/gcc/12.2.0/snos/lib64 -lgfortran -lstdc++") + +# to support Fortran specific compiler intrinsic functions +set(E3SM_LINK_WITH_FORTRAN "TRUE") diff --git a/cime_config/machines/cmake_macros/amdclanggpu_frontier.cmake b/cime_config/machines/cmake_macros/amdclanggpu_frontier.cmake index 6f3c0074798e..4412ea0de7b3 100644 --- a/cime_config/machines/cmake_macros/amdclanggpu_frontier.cmake +++ b/cime_config/machines/cmake_macros/amdclanggpu_frontier.cmake @@ -1,8 +1,8 @@ set(MPICC "cc") -set(MPICXX "CC") +set(MPICXX "mpicxx") set(MPIFC "ftn") set(SCC "cc") -set(SCXX "CC") +set(SCXX "hipcc") set(SFC "ftn") string(APPEND CPPDEFS " -DLINUX") @@ -14,13 +14,12 @@ string(APPEND CMAKE_CXX_FLAGS_RELEASE " -O2") string(APPEND CMAKE_Fortran_FLAGS_RELEASE " -O2") string(APPEND SPIO_CMAKE_OPTS " -DPIO_ENABLE_TOOLS:BOOL=OFF") -string(APPEND CMAKE_EXE_LINKER_FLAGS " -L$ENV{CRAY_LIBSCI_PREFIX_DIR}/lib -lsci_amd") -set(MPICXX "hipcc") -set(SCXX "hipcc") -string(APPEND CMAKE_CXX_FLAGS " -I$ENV{MPICH_DIR}/include --offload-arch=gfx90a") -string(APPEND CMAKE_EXE_LINKER_FLAGS " -L$ENV{MPICH_DIR}/lib -lmpi -L$ENV{CRAY_MPICH_ROOTDIR}/gtl/lib -lmpi_gtl_hsa") +string(APPEND CMAKE_CXX_FLAGS " --offload-arch=gfx90a") +string(APPEND CMAKE_EXE_LINKER_FLAGS " -L$ENV{CRAY_MPICH_ROOTDIR}/gtl/lib -lmpi_gtl_hsa") +string(APPEND CMAKE_EXE_LINKER_FLAGS " -L/opt/cray/pe/gcc/12.2.0/snos/lib64 -lgfortran -lstdc++") string(APPEND KOKKOS_OPTIONS " -DKokkos_ENABLE_HIP=On -DKokkos_ARCH_ZEN3=On -DKokkos_ARCH_VEGA90A=On") set(USE_HIP "TRUE") string(APPEND CMAKE_HIP_FLAGS "${CXXFLAGS} -munsafe-fp-atomics -x hip") +set(E3SM_LINK_WITH_FORTRAN "TRUE") diff --git a/cime_config/machines/cmake_macros/crayclang_frontier.cmake b/cime_config/machines/cmake_macros/crayclang_frontier.cmake index 6c8d4164cb28..76ec41bdbe72 100644 --- a/cime_config/machines/cmake_macros/crayclang_frontier.cmake +++ b/cime_config/machines/cmake_macros/crayclang_frontier.cmake @@ -16,5 +16,7 @@ string(APPEND CMAKE_Fortran_FLAGS " -hipa0 -hzero") # Scorpio installs string(APPEND CMAKE_Fortran_FLAGS " -em -ef") +string(APPEND CMAKE_EXE_LINKER_FLAGS " -L/opt/cray/pe/gcc/12.2.0/snos/lib64 -lgfortran -lstdc++") + # to support Fortran specific compiler intrinsic functions set(E3SM_LINK_WITH_FORTRAN "TRUE") diff --git a/cime_config/machines/cmake_macros/crayclanggpu_frontier.cmake b/cime_config/machines/cmake_macros/crayclanggpu_frontier.cmake index 32f125947b5c..a37ccde439e5 100644 --- a/cime_config/machines/cmake_macros/crayclanggpu_frontier.cmake +++ b/cime_config/machines/cmake_macros/crayclanggpu_frontier.cmake @@ -1,5 +1,6 @@ set(MPICC "cc") -set(MPICXX "hipcc") +set(MPICXX "mpicxx") +#set(MPICXX "CC") set(MPIFC "ftn") set(SCC "cc") set(SCXX "hipcc") @@ -33,7 +34,7 @@ set(HAS_F2008_CONTIGUOUS "TRUE") # -Wl,--allow-shlib-undefined was added to address rocm 5.4.3 Fortran linker issue: # /opt/rocm-5.4.3/lib/libhsa-runtime64.so.1: undefined reference to `std::condition_variable::wait(std::unique_lock&)@GLIBCXX_3.4.30' # AMD started building with GCC 12.2.0, which brings in a GLIBCXX symbol that isn't in CCE's default GCC toolchain. -string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,--allow-multiple-definition -Wl,--allow-shlib-undefined") +#string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,--allow-multiple-definition -Wl,--allow-shlib-undefined") # Switching to O3 for performance benchmarking # Will revisit any failing tests @@ -53,11 +54,13 @@ string(APPEND CMAKE_Fortran_FLAGS " -hipa0 -hzero -em -ef -hnoacc") string(APPEND SPIO_CMAKE_OPTS " -DPIO_ENABLE_TOOLS:BOOL=OFF") -string(APPEND CMAKE_CXX_FLAGS " -I$ENV{MPICH_DIR}/include --offload-arch=gfx90a") -string(APPEND CMAKE_EXE_LINKER_FLAGS " -L$ENV{MPICH_DIR}/lib -lmpi -L$ENV{CRAY_MPICH_ROOTDIR}/gtl/lib -lmpi_gtl_hsa") +string(APPEND CMAKE_CXX_FLAGS " --offload-arch=gfx90a") +string(APPEND CMAKE_EXE_LINKER_FLAGS " -L$ENV{CRAY_MPICH_ROOTDIR}/gtl/lib -lmpi_gtl_hsa") string(APPEND CMAKE_EXE_LINKER_FLAGS " -L$ENV{ROCM_PATH}/lib -lamdhip64") +string(APPEND CMAKE_EXE_LINKER_FLAGS " -L/opt/cray/pe/gcc/12.2.0/snos/lib64 -lgfortran -lstdc++") string(APPEND KOKKOS_OPTIONS " -DKokkos_ENABLE_HIP=On -DKokkos_ARCH_ZEN3=On -DKokkos_ARCH_VEGA90A=On") set(USE_HIP "TRUE") string(APPEND CMAKE_HIP_FLAGS "${CXXFLAGS} -munsafe-fp-atomics -x hip") +set(E3SM_LINK_WITH_FORTRAN "TRUE") diff --git a/cime_config/machines/cmake_macros/gnu_frontier.cmake b/cime_config/machines/cmake_macros/gnu_frontier.cmake index 9b242243989b..ee44a2ca08f5 100644 --- a/cime_config/machines/cmake_macros/gnu_frontier.cmake +++ b/cime_config/machines/cmake_macros/gnu_frontier.cmake @@ -13,3 +13,8 @@ string(APPEND CMAKE_Fortran_FLAGS " -Wno-implicit-interface") string(APPEND CMAKE_Fortran_FLAGS_RELEASE " -O2") string(APPEND CMAKE_C_FLAGS_RELEASE " -O2") + +string(APPEND CMAKE_EXE_LINKER_FLAGS " -L/opt/cray/pe/gcc/12.2.0/snos/lib64 -lgfortran -lstdc++") + +# to support Fortran specific compiler intrinsic functions +set(E3SM_LINK_WITH_FORTRAN "TRUE") diff --git a/cime_config/machines/cmake_macros/gnugpu_frontier.cmake b/cime_config/machines/cmake_macros/gnugpu_frontier.cmake index 174f8207d0d0..6ca4b83d9c2f 100644 --- a/cime_config/machines/cmake_macros/gnugpu_frontier.cmake +++ b/cime_config/machines/cmake_macros/gnugpu_frontier.cmake @@ -1,6 +1,6 @@ set(MPICC "cc") -set(MPICXX "hipcc") # Needs MPICH_CXX to use hipcc -set(MPIFC "ftn") # Linker needs to be the Cray wrapper ftn, not mpif90 +set(MPICXX "mpicxx") +set(MPIFC "ftn") set(SCC "cc") set(SCXX "hipcc") set(SFC "ftn") @@ -16,11 +16,17 @@ string(APPEND CMAKE_CXX_FLAGS_RELEASE " -O2") string(APPEND CMAKE_Fortran_FLAGS_RELEASE " -O2") string(APPEND SPIO_CMAKE_OPTS " -DPIO_ENABLE_TOOLS:BOOL=OFF") -set(E3SM_LINK_WITH_FORTRAN "TRUE") -string(APPEND CMAKE_CXX_FLAGS " -I$ENV{MPICH_DIR}/include --offload-arch=gfx90a") -string(APPEND CMAKE_EXE_LINKER_FLAGS " -L/opt/cray/pe/gcc/11.2.0/snos/lib64/ -lgfortran -L/opt/rocm-5.4.0/lib -lhsa-runtime64 -L$ENV{MPICH_DIR}/lib -lmpi -L$ENV{CRAY_MPICH_ROOTDIR}/gtl/lib -lmpi_gtl_hsa ") +string(APPEND CMAKE_CXX_FLAGS " --offload-arch=gfx90a") +string(APPEND CMAKE_EXE_LINKER_FLAGS " -L$ENV{CRAY_MPICH_ROOTDIR}/gtl/lib -lmpi_gtl_hsa") +string(APPEND CMAKE_EXE_LINKER_FLAGS " -L$ENV{ROCM_PATH}/lib -lamdhip64") +string(APPEND CMAKE_EXE_LINKER_FLAGS " -L/opt/cray/pe/gcc/12.2.0/snos/lib64 -lgfortran -lstdc++") +# +#string(APPEND CMAKE_EXE_LINKER_FLAGS " -L/opt/rocm-5.4.0/lib -lhsa-runtime64 -L$ENV{CRAY_MPICH_ROOTDIR}/gtl/lib -lmpi_gtl_hsa ") string(APPEND KOKKOS_OPTIONS " -DKokkos_ENABLE_HIP=On -DKokkos_ARCH_ZEN3=On -DKokkos_ARCH_VEGA90A=On -DKokkos_ENABLE_OPENMP=Off") set(USE_HIP "TRUE") string(APPEND CMAKE_HIP_FLAGS "${CXXFLAGS} -munsafe-fp-atomics -x hip") + + +set(E3SM_LINK_WITH_FORTRAN "TRUE") diff --git a/cime_config/machines/cmake_macros/intel_dane.cmake b/cime_config/machines/cmake_macros/intel_dane.cmake new file mode 100644 index 000000000000..ef25a97b300e --- /dev/null +++ b/cime_config/machines/cmake_macros/intel_dane.cmake @@ -0,0 +1,10 @@ +string(APPEND CPPDEFS " -DNO_SHR_VMATH -DCNL") +string(APPEND CMAKE_Fortran_FLAGS_DEBUG " -check all -ftrapuv") +string(APPEND CMAKE_EXE_LINKER_FLAGS " -L/usr/tce/packages/gcc/gcc-10.3.1-magic/lib/gcc/x86_64-redhat-linux/10/") + +list(APPEND CMAKE_BUILD_RPATH "/usr/workspace/e3sm/spack/libs/linux-rhel8-sapphirerapids/intel-2021.6.0/hdf5-1.10.7-766kapalbrdntu2pcgdgbhg2ch26gsuv/lib") +list(APPEND CMAKE_BUILD_RPATH "/usr/workspace/e3sm/spack/libs/linux-rhel8-sapphirerapids/intel-2021.6.0/netcdf-c-4.4.1.1-2uznnlwgiezxute6iyqzqjrpolokeaib/lib") +list(APPEND CMAKE_BUILD_RPATH "/usr/workspace/e3sm/spack/libs/linux-rhel8-sapphirerapids/intel-2021.6.0/netcdf-fortran-4.4.4-itpstyordbern7vlulmlnt47eeeokzfp/lib") +list(APPEND CMAKE_BUILD_RPATH "/usr/workspace/e3sm/spack/libs/linux-rhel8-sapphirerapids/intel-2021.6.0/parallel-netcdf-1.11.0-26sxm4mormsglmhi24poix7sugbigkck/lib") + +set(KOKKOS_OPTIONS "--with-serial --ldflags='-L/usr/tce/packages/gcc/gcc-10.3.1-magic/lib/gcc/x86_64-redhat-linux/10/'") diff --git a/cime_config/machines/cmake_macros/intel_quartz.cmake b/cime_config/machines/cmake_macros/intel_quartz.cmake deleted file mode 100644 index 8091325c6cec..000000000000 --- a/cime_config/machines/cmake_macros/intel_quartz.cmake +++ /dev/null @@ -1,4 +0,0 @@ -string(APPEND CPPDEFS " -DNO_SHR_VMATH -DCNL") -string(APPEND CMAKE_Fortran_FLAGS_DEBUG " -check all -ftrapuv") -string(APPEND CMAKE_EXE_LINKER_FLAGS " -L/usr/tce/packages/gcc/gcc-10.3.1-magic/lib/gcc/x86_64-redhat-linux/10/") -set(KOKKOS_OPTIONS "--with-serial --ldflags='-L/usr/tce/packages/gcc/gcc-10.3.1-magic/lib/gcc/x86_64-redhat-linux/10/'") diff --git a/cime_config/machines/cmake_macros/intel_ruby.cmake b/cime_config/machines/cmake_macros/intel_ruby.cmake index 8091325c6cec..e874bfb7eaf6 100644 --- a/cime_config/machines/cmake_macros/intel_ruby.cmake +++ b/cime_config/machines/cmake_macros/intel_ruby.cmake @@ -1,4 +1,10 @@ string(APPEND CPPDEFS " -DNO_SHR_VMATH -DCNL") string(APPEND CMAKE_Fortran_FLAGS_DEBUG " -check all -ftrapuv") string(APPEND CMAKE_EXE_LINKER_FLAGS " -L/usr/tce/packages/gcc/gcc-10.3.1-magic/lib/gcc/x86_64-redhat-linux/10/") + +list(APPEND CMAKE_BUILD_RPATH "/usr/workspace/e3sm/spack/libs/linux-rhel8-cascadelake/intel-2021.6.0/hdf5-1.10.7-ewjpbjdhjgjzrzjcvwyjyuulaesbsjhg/lib") +list(APPEND CMAKE_BUILD_RPATH "/usr/workspace/e3sm/spack/libs/linux-rhel8-cascadelake/intel-2021.6.0/netcdf-c-4.4.1.1-vaxofekwvnvngh7wptmzkwdb7tkzvesn/lib") +list(APPEND CMAKE_BUILD_RPATH "/usr/workspace/e3sm/spack/libs/linux-rhel8-cascadelake/intel-2021.6.0/netcdf-fortran-4.4.4-3pzbx2unddhladhubaahhhysjmprzqi2/lib") +list(APPEND CMAKE_BUILD_RPATH "/usr/workspace/e3sm/spack/libs/linux-rhel8-cascadelake/intel-2021.6.0/parallel-netcdf-1.11.0-tzgdalakmem7tod6cruhqyeackeix5q5/lib") + set(KOKKOS_OPTIONS "--with-serial --ldflags='-L/usr/tce/packages/gcc/gcc-10.3.1-magic/lib/gcc/x86_64-redhat-linux/10/'") diff --git a/cime_config/machines/cmake_macros/oneapi-ifx.cmake b/cime_config/machines/cmake_macros/oneapi-ifx.cmake index e98a65d32a67..9ab0cdda7d51 100644 --- a/cime_config/machines/cmake_macros/oneapi-ifx.cmake +++ b/cime_config/machines/cmake_macros/oneapi-ifx.cmake @@ -7,7 +7,7 @@ endif() string(APPEND CMAKE_C_FLAGS_RELEASE " -O2") string(APPEND CMAKE_Fortran_FLAGS_RELEASE " -O2") string(APPEND CMAKE_CXX_FLAGS_RELEASE " -O2") -string(APPEND CMAKE_Fortran_FLAGS_DEBUG " -O0 -g -check uninit -check bounds -check pointers -fpe0 -check noarg_temp_created") +string(APPEND CMAKE_Fortran_FLAGS_DEBUG " -O0 -g -fpe0") string(APPEND CMAKE_C_FLAGS_DEBUG " -O0 -g") string(APPEND CMAKE_CXX_FLAGS_DEBUG " -O0 -g") string(APPEND CMAKE_C_FLAGS " -fp-model precise -std=gnu99") diff --git a/cime_config/machines/cmake_macros/oneapi-ifxgpu.cmake b/cime_config/machines/cmake_macros/oneapi-ifxgpu.cmake index 9d08ca6c6302..d7dfae002192 100644 --- a/cime_config/machines/cmake_macros/oneapi-ifxgpu.cmake +++ b/cime_config/machines/cmake_macros/oneapi-ifxgpu.cmake @@ -7,7 +7,7 @@ endif() string(APPEND CMAKE_C_FLAGS_RELEASE " -O2") string(APPEND CMAKE_Fortran_FLAGS_RELEASE " -O2") string(APPEND CMAKE_CXX_FLAGS_RELEASE " -O2") -string(APPEND CMAKE_Fortran_FLAGS_DEBUG " -O0 -g -check uninit -check bounds -check pointers -fpe0 -check noarg_temp_created") +string(APPEND CMAKE_Fortran_FLAGS_DEBUG " -O0 -g -fpe0") string(APPEND CMAKE_C_FLAGS_DEBUG " -O0 -g") string(APPEND CMAKE_CXX_FLAGS_DEBUG " -O0 -g") string(APPEND CMAKE_C_FLAGS " -fp-model precise -std=gnu99") diff --git a/cime_config/machines/cmake_macros/oneapi-ifxgpu_aurora.cmake b/cime_config/machines/cmake_macros/oneapi-ifxgpu_aurora.cmake index 47d513408c2c..6835515164f0 100644 --- a/cime_config/machines/cmake_macros/oneapi-ifxgpu_aurora.cmake +++ b/cime_config/machines/cmake_macros/oneapi-ifxgpu_aurora.cmake @@ -3,5 +3,5 @@ string(APPEND CMAKE_EXE_LINKER_FLAGS " -lmkl_intel_lp64 -lmkl_sequential -lmkl_c if (compile_threaded) string(APPEND CMAKE_EXE_LINKER_FLAGS " -fiopenmp -fopenmp-targets=spir64") endif() -string(APPEND KOKKOS_OPTIONS " -DCMAKE_CXX_STANDARD=17 -DKokkos_ENABLE_SERIAL=On -DKokkos_ARCH_INTEL_PVC=On -DKokkos_ENABLE_SYCL=On -DKokkos_ENABLE_EXPLICIT_INSTANTIATION=Off") string(APPEND SYCL_FLAGS " -\-intel -fsycl -fsycl-targets=spir64_gen -mlong-double-64 -Xsycl-target-backend \"-device 12.60.7\"") +string(APPEND CMAKE_CXX_FLAGS " -Xclang -fsycl-allow-virtual-functions") diff --git a/cime_config/machines/cmake_macros/oneapi-ifxgpu_sunspot.cmake b/cime_config/machines/cmake_macros/oneapi-ifxgpu_sunspot.cmake new file mode 100644 index 000000000000..6835515164f0 --- /dev/null +++ b/cime_config/machines/cmake_macros/oneapi-ifxgpu_sunspot.cmake @@ -0,0 +1,7 @@ + +string(APPEND CMAKE_EXE_LINKER_FLAGS " -lmkl_intel_lp64 -lmkl_sequential -lmkl_core") +if (compile_threaded) + string(APPEND CMAKE_EXE_LINKER_FLAGS " -fiopenmp -fopenmp-targets=spir64") +endif() +string(APPEND SYCL_FLAGS " -\-intel -fsycl -fsycl-targets=spir64_gen -mlong-double-64 -Xsycl-target-backend \"-device 12.60.7\"") +string(APPEND CMAKE_CXX_FLAGS " -Xclang -fsycl-allow-virtual-functions") diff --git a/cime_config/machines/config_batch.xml b/cime_config/machines/config_batch.xml index 6e4f483361de..3cdb1ce6347a 100644 --- a/cime_config/machines/config_batch.xml +++ b/cime_config/machines/config_batch.xml @@ -237,33 +237,17 @@ - - squeue - sbatch - scancel - #SBATCH - (\d+)$ - --dependency=afterok:jobid - --dependency=afterany:jobid - : - %H:%M:%S - --mail-user - --mail-type - none, all, begin, end, fail - - --export=ALL - -p {{ job_queue }} - -J {{ job_id }} - -N {{ num_nodes }} - -n {{ total_tasks }} - -t {{ job_wallclock_time }} - -o {{ job_id }}.out - -e {{ job_id }}.err - -A {{ project }} - + + + pbatch + pdebug + + + + - pbatch - pdebug + pbatch + pdebug @@ -562,7 +546,7 @@ - /lus/gecko/projects/CSC249ADSE15_CNDA/tools/qsub/throttle + /lus/flare/projects/CSC249ADSE15_CNDA/tools/qsub/throttle EarlyAppAccess workq-route diff --git a/cime_config/machines/config_machines.xml b/cime_config/machines/config_machines.xml index 7ee75879bb4a..b976a00905b4 100644 --- a/cime_config/machines/config_machines.xml +++ b/cime_config/machines/config_machines.xml @@ -200,12 +200,14 @@ PrgEnv-nvidia PrgEnv-cray PrgEnv-aocc + gcc-native intel intel-oneapi nvidia aocc cudatoolkit climate-utils + cray-libsci matlab craype-accel-nvidia80 craype-accel-host @@ -215,14 +217,14 @@ - PrgEnv-gnu/8.3.3 - gcc/11.2.0 + PrgEnv-gnu/8.5.0 + gcc/12.2.0 cray-libsci/23.02.1.1 - PrgEnv-intel/8.3.3 - intel/2023.1.0 + PrgEnv-intel/8.5.0 + intel/2023.2.0 @@ -237,13 +239,25 @@ cray-libsci/23.02.1.1 - + + craype-accel-host + craype/2.7.30 + cray-mpich/8.1.28 + cray-hdf5-parallel/1.12.2.9 + cray-netcdf-hdf5parallel/4.9.0.9 + cray-parallel-netcdf/1.12.3.9 + + + craype-accel-host craype/2.7.20 cray-mpich/8.1.25 cray-hdf5-parallel/1.12.2.3 cray-netcdf-hdf5parallel/4.9.0.3 cray-parallel-netcdf/1.12.3.3 + + + cmake/3.24.3 evp-patch @@ -275,15 +289,15 @@ $SHELL{if [ -z "$ADIOS2_ROOT" ]; then echo /global/cfs/cdirs/e3sm/3rdparty/adios2/2.9.1/cray-mpich-8.1.25/gcc-11.2.0; else echo "$ADIOS2_ROOT"; fi} Generic - $SHELL{if [ -z "$Albany_ROOT" ]; then echo /global/common/software/e3sm/mali_tpls/albany-e3sm-serial-release-gcc-cmake-fix; else echo "$Albany_ROOT"; fi} - $SHELL{if [ -z "$Trilinos_ROOT" ]; then echo /global/common/software/e3sm/mali_tpls/trilinos-e3sm-serial-release-gcc; else echo "$Trilinos_ROOT"; fi} + $SHELL{if [ -z "$Albany_ROOT" ]; then echo /global/common/software/e3sm/albany/2024.03.26/gcc/11.2.0; else echo "$Albany_ROOT"; fi} + $SHELL{if [ -z "$Trilinos_ROOT" ]; then echo /global/common/software/e3sm/trilinos/15.1.1/gcc/11.2.0; else echo "$Trilinos_ROOT"; fi} $SHELL{if [ -z "$ADIOS2_ROOT" ]; then echo /global/cfs/cdirs/e3sm/3rdparty/adios2/2.9.1/cray-mpich-8.1.25/nvidia-22.7; else echo "$ADIOS2_ROOT"; fi} - $SHELL{if [ -z "$BLAS_ROOT" ]; then echo /opt/nvidia/hpc_sdk/Linux_x86_64/22.7/compilers; else echo "$BLAS_ROOT"; fi} - $SHELL{if [ -z "$LAPACK_ROOT" ]; then echo /opt/nvidia/hpc_sdk/Linux_x86_64/22.7/compilers; else echo "$LAPACK_ROOT"; fi} + $SHELL{if [ -z "$BLAS_ROOT" ]; then echo $NVIDIA_PATH/compilers; else echo "$BLAS_ROOT"; fi} + $SHELL{if [ -z "$LAPACK_ROOT" ]; then echo $NVIDIA_PATH/compilers; else echo "$LAPACK_ROOT"; fi} NVHPC @@ -508,12 +522,14 @@ PrgEnv-nvidia PrgEnv-cray PrgEnv-aocc + gcc-native intel intel-oneapi nvidia aocc cudatoolkit climate-utils + cray-libsci matlab craype-accel-nvidia80 craype-accel-host @@ -523,24 +539,19 @@ - PrgEnv-gnu/8.5.0 gcc-native/12.3 cray-libsci/23.12.5 - PrgEnv-intel/8.5.0 - intel/2023.2.0 + intel/2024.1.0 PrgEnv-nvidia - nvidia/23.9 + nvidia/24.5 cray-libsci/23.12.5 @@ -554,9 +565,6 @@ craype-accel-host craype/2.7.30 cray-mpich/8.1.28 - cray-hdf5-parallel/1.12.2.9 cray-netcdf-hdf5parallel/4.9.0.9 cray-parallel-netcdf/1.12.3.9 @@ -596,8 +604,8 @@ $SHELL{if [ -z "$ADIOS2_ROOT" ]; then echo /global/cfs/cdirs/e3sm/3rdparty/adios2/2.9.1/cray-mpich-8.1.25/nvidia-22.7; else echo "$ADIOS2_ROOT"; fi} - $SHELL{if [ -z "$BLAS_ROOT" ]; then echo /opt/nvidia/hpc_sdk/Linux_x86_64/22.7/compilers; else echo "$BLAS_ROOT"; fi} - $SHELL{if [ -z "$LAPACK_ROOT" ]; then echo /opt/nvidia/hpc_sdk/Linux_x86_64/22.7/compilers; else echo "$LAPACK_ROOT"; fi} + $SHELL{if [ -z "$BLAS_ROOT" ]; then echo $NVIDIA_PATH/compilers; else echo "$BLAS_ROOT"; fi} + $SHELL{if [ -z "$LAPACK_ROOT" ]; then echo $NVIDIA_PATH/compilers; else echo "$LAPACK_ROOT"; fi} NVHPC @@ -825,12 +833,14 @@ PrgEnv-nvidia PrgEnv-cray PrgEnv-aocc + gcc-native intel intel-oneapi nvidia aocc cudatoolkit climate-utils + cray-libsci matlab craype-accel-nvidia80 craype-accel-host @@ -841,7 +851,7 @@ PrgEnv-gnu - gcc + gcc-native cray-libsci @@ -852,24 +862,24 @@ PrgEnv-nvidia - nvidia/22.7 + nvidia/24.5 cray-libsci PrgEnv-aocc - aocc/4.0.0 + aocc/4.0.1 cray-libsci craype-accel-host cray-libsci - craype/2.7.21 - cray-mpich/8.1.26 - cray-hdf5-parallel/1.12.2.3 - cray-netcdf-hdf5parallel/4.9.0.3 - cray-parallel-netcdf/1.12.3.3 + craype/2.7.30 + cray-mpich/8.1.28 + cray-hdf5-parallel/1.12.2.9 + cray-netcdf-hdf5parallel/4.9.0.9 + cray-parallel-netcdf/1.12.3.9 cmake/3.24.3 @@ -982,7 +992,7 @@ Frontier exascale supercomputer at ORNL. 9408 nodes, Node: 4 AMD MI250X GPUs (2 GCDs) ~ 8 GPUs, 512 GB HDB2E, AMD EPYC 64 cores, 512GB DDR4 .*frontier.* Linux - crayclang,gnu,amdclang,gnugpu,crayclanggpu,amdclanggpu + gnu,amdclang,crayclang,gnugpu,amdclanggpu,crayclanggpu mpich cli115 /lustre/orion/cli115/world-shared/frontier @@ -1044,8 +1054,7 @@ PrgEnv-cray PrgEnv-gnu/8.3.3 - - gcc gcc/11.2.0 + gcc gcc/12.2.0 craype-accel-amd-gfx90a @@ -1053,6 +1062,7 @@ cray-python/3.9.13.1 + cray-libsci subversion/1.14.1 git/2.36.1 cmake/3.21.3 @@ -1068,14 +1078,12 @@ 0.25 0 + $ENV{CRAY_LIBSCI_PREFIX_DIR}/lib/pkgconfig:$ENV{PKG_CONFIG_PATH} $ENV{NETCDF_DIR} $ENV{PNETCDF_DIR} - - $ENV{CRAY_LIBSCI_DIR}/amd/4.0/x86_64/lib:$ENV{LD_LIBRARY_PATH} - --ntasks-per-gpu=$SHELL{echo "`./xmlquery --value MAX_MPITASKS_PER_NODE`/8"|bc} --gpu-bind=closest @@ -1092,6 +1100,9 @@ spread threads + @@ -1714,6 +1726,51 @@ + + OCI-based container + ghci-oci + LINUX + gnu + mpich + /projects/e3sm/scratch + /projects/e3sm/inputdata + /projects/e3sm/ptclm-data + /projects/e3sm/scratch/archive/$CASE + /projects/e3sm/baselines/$COMPILER + /usr/local/packages/bin/cprnc + make + 4 + e3sm_developer + none + e3sm-team + 16 + 16 + + mpirun + + -launcher fork -hosts localhost -np {{ total_tasks }} + + + + /projects/e3sm/scratch/$CASE/run + /projects/e3sm/scratch/$CASE/bld + + $SRCROOT + + + /usr/local/packages + /usr/local/packages/bin:$ENV{PATH} + /usr/local/packages/lib + + + /usr/local/packages + /usr/local/packages + /usr/local/packages + /usr/local/packages/bin:$ENV{PATH} + /usr/local/packages/lib + + + Linux workstation for Jenkins testing (melvin|watson|s999964|climate|penn|sems) @@ -1816,31 +1873,33 @@ - /projects/sems/install/rhel7-x86_64/sems/v2/lmod/lmod/8.3/gcc/10.1.0/zbzzu7k/lmod/lmod/init/env_modules_python.py - /projects/sems/install/rhel7-x86_64/sems/v2/lmod/lmod/8.3/gcc/10.1.0/zbzzu7k/lmod/lmod/init/perl - /projects/sems/install/rhel7-x86_64/sems/v2/lmod/lmod/8.3/gcc/10.1.0/zbzzu7k/lmod/lmod/init/sh - /projects/sems/install/rhel7-x86_64/sems/v2/lmod/lmod/8.3/gcc/10.1.0/zbzzu7k/lmod/lmod/init/csh - /projects/sems/install/rhel7-x86_64/sems/v2/lmod/lmod/8.3/gcc/10.1.0/zbzzu7k/lmod/lmod/libexec/lmod python - /projects/sems/install/rhel7-x86_64/sems/v2/lmod/lmod/8.3/gcc/10.1.0/zbzzu7k/lmod/lmod/libexec/lmod perl + /projects/sems/install/rhel9-x86_64/sems/lmod/lmod/8.7.24/gcc/11.4.1/base/lnirq74/lmod/lmod/init/env_modules_python.py + /projects/sems/install/rhel9-x86_64/sems/lmod/lmod/8.7.24/gcc/11.4.1/base/lnirq74/lmod/lmod/init/perl + /projects/sems/install/rhel9-x86_64/sems/lmod/lmod/8.7.24/gcc/11.4.1/base/lnirq74/lmod/lmod/init/sh + /projects/sems/install/rhel9-x86_64/sems/lmod/lmod/8.7.24/gcc/11.4.1/base/lnirq74/lmod/lmod/init/csh + /projects/sems/install/rhel9-x86_64/sems/lmod/lmod/8.7.24/gcc/11.4.1/base/lnirq74/lmod/lmod/libexec/lmod python + /projects/sems/install/rhel9-x86_64/sems/lmod/lmod/8.7.24/gcc/11.4.1/base/lnirq74/lmod/lmod/libexec/lmod perl module module - sems-archive-env - acme-env - sems-archive-git - acme-cmake/3.26.3 + sems-git/2.42.0 + sems-cmake/3.27.9 - acme-gcc/11.2.0 + sems-gcc/11.4.0 + sems-openblas - acme-netcdf/4.4.1/exo_acme - acme-pfunit/3.2.8/base + sems-netcdf-c-serial/4.9.2 + sems-netcdf-fortran-serial/4.6.1 - acme-openmpi/4.1.4 - acme-netcdf/4.7.4/acme + sems-openmpi-no-cuda/4.1.6 + sems-netcdf-c/4.9.2 + sems-netcdf-cxx/4.2 + sems-netcdf-fortran/4.6.1 + sems-parallel-netcdf/1.12.3 $CIME_OUTPUT_ROOT/$CASE/run @@ -1849,13 +1908,18 @@ 0 - $ENV{SEMS_NETCDF_ROOT} + $ENV{NETCDF_C_ROOT} + $ENV{NETCDF_FORTRAN_ROOT} + $ENV{OPENBLAS_ROOT} 64M spread threads - Generic + OpenBLAS 4000MB + + $ENV{PARALLEL_NETCDF_ROOT} + @@ -2731,13 +2795,13 @@ $SHELL{if [ -z "$MOAB_ROOT" ]; then echo /lcrc/soft/climate/moab/chrysalis/intel; else echo "$MOAB_ROOT"; fi} + $SHELL{if [ -z "$Albany_ROOT" ]; then echo /lcrc/group/e3sm/soft/albany/2024.03.26/intel/20.0.4; else echo "$Albany_ROOT"; fi} + $SHELL{if [ -z "$Trilinos_ROOT" ]; then echo /lcrc/group/e3sm/soft/trilinos/15.1.1/intel/20.0.4; else echo "$Trilinos_ROOT"; fi} $SHELL{if [ -z "$MOAB_ROOT" ]; then echo /lcrc/soft/climate/moab/chrysalis/gnu; else echo "$MOAB_ROOT"; fi} - - - $SHELL{if [ -z "$Albany_ROOT" ]; then echo /lcrc/group/e3sm/ac.jwatkins/LandIce/AlbanyBuilds/build-gcc-sfad12-e3sm/install; else echo "$Albany_ROOT"; fi} - $SHELL{if [ -z "$Trilinos_ROOT" ]; then echo /lcrc/group/e3sm/ac.jwatkins/LandIce/TrilinosBuilds/build-gcc-e3sm/install; else echo "$Trilinos_ROOT"; fi} + $SHELL{if [ -z "$Albany_ROOT" ]; then echo /lcrc/group/e3sm/soft/albany/2024.03.26/gcc/9.2.0; else echo "$Albany_ROOT"; fi} + $SHELL{if [ -z "$Trilinos_ROOT" ]; then echo /lcrc/group/e3sm/soft/trilinos/15.1.1/gcc/9.2.0; else echo "$Trilinos_ROOT"; fi} @@ -3042,7 +3106,7 @@ module module - + cmake/3.27.4 @@ -3059,6 +3123,7 @@ /lcrc/group/e3sm/soft/improv/pnetcdf/1.12.3/gcc-12.3.0/openmpi-4.1.6 /lcrc/group/e3sm/soft/improv/pnetcdf/1.12.3/gcc-12.3.0/openmpi-4.1.6/bin:/lcrc/group/e3sm/soft/improv/netcdf-fortran/4.6.1b/gcc-12.3.0/openmpi-4.1.6/bin:/lcrc/group/e3sm/soft/improv/netcdf-c/4.9.2b/gcc-12.3.0/openmpi-4.1.6/bin:/lcrc/group/e3sm/soft/improv/openmpi/4.1.6/gcc-12.3.0/bin:/lcrc/group/e3sm/soft/perl/improv/bin:$ENV{PATH} $SHELL{lp=/lcrc/group/e3sm/soft/improv/netlib-lapack/3.12.0/gcc-12.3.0:/lcrc/group/e3sm/soft/improv/pnetcdf/1.12.3/gcc-12.3.0/openmpi-4.1.6/lib:/lcrc/group/e3sm/soft/improv/netcdf-fortran/4.6.1b/gcc-12.3.0/openmpi-4.1.6/lib:/lcrc/group/e3sm/soft/improv/netcdf-c/4.9.2b/gcc-12.3.0/openmpi-4.1.6/lib:/opt/pbs/lib:/lcrc/group/e3sm/soft/improv/openmpi/4.1.6/gcc-12.3.0/lib; if [ -z "$LD_LIBRARY_PATH" ]; then echo $lp; else echo "$lp:$LD_LIBRARY_PATH"; fi} + ^lockedfile 128M @@ -3075,14 +3140,14 @@ mpich cbronze /p/lustre2/$USER/e3sm_scratch/ruby - /usr/gdata/e3sm/ccsm3data/inputdata - /usr/gdata/e3sm/ccsm3data/inputdata/atm/datm7 + /usr/workspace/e3sm/ccsm3data/inputdata + /usr/workspace/e3sm/ccsm3data/inputdata/atm/datm7 /p/lustre2/$USER/archive/$CASE /p/lustre2/$USER/ccsm_baselines/$COMPILER - /usr/gdata/e3sm/tools/cprnc + /usr/workspace/e3sm/apps/cprnc 8 - lc_slurm - donahue5 -at- llnl.gov + slurm + boutte3 -at- llnl.gov 56 56 @@ -3090,8 +3155,16 @@ srun + + --mpi=pmi2 + --export=ALL + -n {{ total_tasks }} -N {{ num_nodes }} + -c 1 + --cpu_bind=cores + -m plane={{ tasks_per_node }} + - + /usr/share/lmod/lmod/init/env_modules_python.py /usr/share/lmod/lmod/init/perl /usr/share/lmod/lmod/init/sh @@ -3103,51 +3176,62 @@ python/3.9.12 git + subversion + cmake/3.19.2 mkl/2022.1.0 intel-classic/2021.6.0-magic - mvapich2/2.3.7 - cmake/3.19.2 - /usr/gdata/e3sm/install/quartz/modulefiles - hdf5/1.12.2 - netcdf-c/4.9.0 - netcdf-fortran/4.6.0 - parallel-netcdf/1.12.3 - screamML-venv/0.0.1 - subversion + /usr/workspace/e3sm/spack/modules/ruby/linux-rhel8-x86_64/Core + mvapich2/2.3.7-ll7cmqm + hdf5/1.10.7-ewjpbjd + netcdf-c/4.4.1.1-vaxofek + netcdf-fortran/4.4.4-3pzbx2u + parallel-netcdf/1.11.0-tzgdala $CIME_OUTPUT_ROOT/$CASE/run $CIME_OUTPUT_ROOT/$CASE/bld - /usr/gdata/e3sm/install/quartz/netcdf-fortran/ - /usr/tce/packages/parallel-netcdf/parallel-netcdf-1.12.3-mvapich2-2.3.7-intel-classic-2021.6.0 + 128M + FALSE + /usr/workspace/e3sm/spack/libs/linux-rhel8-cascadelake/intel-2021.6.0/hdf5-1.10.7-ewjpbjdhjgjzrzjcvwyjyuulaesbsjhg + /usr/workspace/e3sm/spack/libs/linux-rhel8-cascadelake/intel-2021.6.0/netcdf-c-4.4.1.1-vaxofekwvnvngh7wptmzkwdb7tkzvesn + /usr/workspace/e3sm/spack/libs/linux-rhel8-cascadelake/intel-2021.6.0/netcdf-fortran-4.4.4-3pzbx2unddhladhubaahhhysjmprzqi2 + /usr/workspace/e3sm/spack/libs/linux-rhel8-cascadelake/intel-2021.6.0/parallel-netcdf-1.11.0-tzgdalakmem7tod6cruhqyeackeix5q5 - - LLNL Linux Cluster, Linux (pgi), 36 pes/node, batch system is Slurm + + LLNL Linux Cluster, 112 pes/node, batch system is Slurm LINUX intel mpich cbronze - /p/lustre2/$USER/e3sm_scratch/quartz - /usr/gdata/e3sm/ccsm3data/inputdata - /usr/gdata/e3sm/ccsm3data/inputdata/atm/datm7 + /p/lustre2/$USER/e3sm_scratch/dane + /usr/workspace/e3sm/ccsm3data/inputdata + /usr/workspace/e3sm/ccsm3data/inputdata/atm/datm7 /p/lustre2/$USER/archive/$CASE /p/lustre2/$USER/ccsm_baselines/$COMPILER - /usr/gdata/e3sm/tools/cprnc + /usr/workspace/e3sm/apps/cprnc 8 - lc_slurm - donahue5 -at- llnl.gov - 72 - 36 + slurm + boutte3 -at- llnl.gov + 224 + 112 srun + + --mpi=pmi2 + --export=ALL + -n {{ total_tasks }} -N {{ num_nodes }} + -c 1 + --cpu_bind=cores + -m plane={{ tasks_per_node }} + - + /usr/share/lmod/lmod/init/env_modules_python.py /usr/share/lmod/lmod/init/perl /usr/share/lmod/lmod/init/sh @@ -3159,24 +3243,27 @@ python/3.9.12 git + subversion mkl/2022.1.0 intel-classic/2021.6.0-magic - mvapich2/2.3.7 cmake/3.19.2 - /usr/gdata/e3sm/install/quartz/modulefiles - hdf5/1.12.2 - netcdf-c/4.9.0 - netcdf-fortran/4.6.0 - parallel-netcdf/1.12.3 - screamML-venv/0.0.1 - subversion + /usr/workspace/e3sm/spack/modules/dane/linux-rhel8-x86_64/Core + mvapich2/2.3.7-27jao34 + hdf5/1.10.7-766kapa + netcdf-c/4.4.1.1-2uznnlw + netcdf-fortran/4.4.4-itpstyo + parallel-netcdf/1.11.0-26sxm4m $CIME_OUTPUT_ROOT/$CASE/run $CIME_OUTPUT_ROOT/$CASE/bld - /usr/gdata/e3sm/install/quartz/netcdf-fortran/ - /usr/tce/packages/parallel-netcdf/parallel-netcdf-1.12.3-mvapich2-2.3.7-intel-classic-2021.6.0 + 128M + FALSE + /usr/workspace/e3sm/spack/libs/linux-rhel8-sapphirerapids/intel-2021.6.0/hdf5-1.10.7-766kapalbrdntu2pcgdgbhg2ch26gsuv + /usr/workspace/e3sm/spack/libs/linux-rhel8-sapphirerapids/intel-2021.6.0/netcdf-c-4.4.1.1-2uznnlwgiezxute6iyqzqjrpolokeaib + /usr/workspace/e3sm/spack/libs/linux-rhel8-sapphirerapids/intel-2021.6.0/netcdf-fortran-4.4.4-itpstyordbern7vlulmlnt47eeeokzfp + /usr/workspace/e3sm/spack/libs/linux-rhel8-sapphirerapids/intel-2021.6.0/parallel-netcdf-1.11.0-26sxm4mormsglmhi24poix7sugbigkck @@ -3400,7 +3487,7 @@ uan-.* LINUX oneapi-ifx,oneapi-ifxgpu,gnu - mpich,impi,openmpi + mpich CSC249ADSE15_CNDA /gila/CSC249ADSE15_CNDA/performance_archive .* @@ -3420,7 +3507,7 @@ 104 104 104 - 12 + 48 FALSE mpiexec @@ -3433,13 +3520,6 @@ $ENV{GPU_TILE_COMPACT} - - mpirun - - --tag-output -n {{ total_tasks }} - --map-by ppr:{{ tasks_per_numa }}:socket:PE=$ENV{OMP_NUM_THREADS} --bind-to hwthread - - /soft/packaging/lmod/lmod/init/sh /soft/packaging/lmod/lmod/init/csh @@ -3448,14 +3528,13 @@ module /soft/packaging/lmod/lmod/libexec/lmod python - - /soft/modulefiles - spack cmake/3.26.3-gcc-11.2.0-vnn7ncx - prepend-deps/default + cmake - gcc - oneapi/eng-compiler/2023.05.15.007 + oneapi/eng-compiler/2024.04.15.002 + + + kokkos/git.7ff87a5-omp-sycl spack cmake @@ -3473,12 +3552,6 @@ 1 - - 10 - omp - spread - unit - level_zero:gpu NO_GPU @@ -3491,6 +3564,9 @@ /soft/tools/mpi_wrapper_utils/gpu_tile_compact.sh 131072 20 + $ENV{KOKKOS_ROOT} + 1 + 0:4,1:4,2:4,3:4:4:4,5:4,6:4,7:4 0 @@ -3520,14 +3596,14 @@ oneapi-ifx,oneapi-ifxgpu,gnu mpich CSC249ADSE15_CNDA - /lus/gecko/projects/CSC249ADSE15_CNDA/performance_archive + /lus/flare/projects/CSC249ADSE15_CNDA/performance_archive .* - /lus/gecko/projects/CSC249ADSE15_CNDA/$USER/scratch - /lus/gecko/projects/CSC249ADSE15_CNDA/inputdata - /lus/gecko/projects/CSC249ADSE15_CNDA/inputdata/atm/datm7 + /lus/flare/projects/CSC249ADSE15_CNDA/$USER/scratch + /lus/flare/projects/CSC249ADSE15_CNDA/inputdata + /lus/flare/projects/CSC249ADSE15_CNDA/inputdata/atm/datm7 $CIME_OUTPUT_ROOT/archive/$CASE - /lus/gecko/projects/CSC249ADSE15_CNDA/baselines/$COMPILER - /lus/gecko/projects/CSC249ADSE15_CNDA/tools/cprnc/cprnc + /lus/flare/projects/CSC249ADSE15_CNDA/baselines/$COMPILER + /lus/flare/projects/CSC249ADSE15_CNDA/tools/cprnc/cprnc 16 e3sm_developer 4 @@ -3536,54 +3612,48 @@ 208 104 104 - 12 - FALSE + 48 + FALSE mpiexec -np {{ total_tasks }} --label -ppn {{ tasks_per_node }} - --cpu-bind $ENV{RANKS_BIND} -envall + -envall -d $ENV{OMP_NUM_THREADS} $ENV{GPU_TILE_COMPACT} - /lus/gecko/projects/CSC249ADSE15_CNDA/modules/lmod.sh + /lus/flare/projects/CSC249ADSE15_CNDA/modules/lmod.sh /soft/sunspot_migrate/soft/packaging/lmod/lmod/init/csh /soft/sunspot_migrate/soft/packaging/lmod/lmod/init/env_modules_python.py module module /soft/sunspot_migrate/soft/packaging/lmod/lmod/libexec/lmod python - - /soft/modulefiles - /soft/restricted/CNDA/updates/modulefiles - spack-pe-gcc cmake + cmake - oneapi/eng-compiler/2023.05.15.007 + oneapi/eng-compiler/2024.04.15.002 + + + kokkos/git.7ff87a5-omp-sycl spack-pe-gcc cmake gcc/10.3.0 - - cray-pals - libfabric/1.15.2.0 - cray-libpals/1.3.2 - $CIME_OUTPUT_ROOT/$CASE/run $CIME_OUTPUT_ROOT/$CASE/bld - /lus/gecko/projects/CSC249ADSE15_CNDA/software/netcdf-c/4.9.2/oneapi.eng.2023.05.15.007 - /lus/gecko/projects/CSC249ADSE15_CNDA/software/netcdf-fortran/4.6.1/oneapi.eng.2023.05.15.007 - /lus/gecko/projects/CSC249ADSE15_CNDA/software/pnetcdf/1.12.3/oneapi.eng.2023.05.15.007 - /lus/gecko/projects/CSC249ADSE15_CNDA/software/pnetcdf/1.12.3/oneapi.eng.2023.05.15.007/lib:/lus/gecko/projects/CSC249ADSE15_CNDA/software/netcdf-fortran/4.6.1/oneapi.eng.2023.05.15.007/lib:/lus/gecko/projects/CSC249ADSE15_CNDA/software/netcdf-c/4.9.2/oneapi.eng.2023.05.15.007/lib:$ENV{LD_LIBRARY_PATH} - /lus/gecko/projects/CSC249ADSE15_CNDA/software/pnetcdf/1.12.3/oneapi.eng.2023.05.15.007/bin:/lus/gecko/projects/CSC249ADSE15_CNDA/software/netcdf-fortran/4.6.1/oneapi.eng.2023.05.15.007/bin:/lus/gecko/projects/CSC249ADSE15_CNDA/software/netcdf-c/4.9.2/oneapi.eng.2023.05.15.007/bin:$ENV{PATH} - list:0-7,104-111:8-15,112-119:16-23,120-127:24-31,128-135:32-39,136-143:40-47,144-151:52-59,156-163:60-67,164-171:68-75,172-179:76-83,180-187:84-91,188-195:92-99,196-203 + /lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-c/4.9.2/oneapi.eng.2024.04.15.002 + /lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-fortran/4.6.1/oneapi.eng.2024.04.15.002 + /lus/flare/projects/CSC249ADSE15_CNDA/software/pnetcdf/1.12.3/oneapi.eng.2024.04.15.002 + /lus/flare/projects/CSC249ADSE15_CNDA/software/pnetcdf/1.12.3/oneapi.eng.2024.04.15.002/lib:/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-fortran/4.6.1/oneapi.eng.2024.04.15.002/lib:/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-c/4.9.2/oneapi.eng.2024.04.15.002/lib:$ENV{LD_LIBRARY_PATH} + /lus/flare/projects/CSC249ADSE15_CNDA/software/pnetcdf/1.12.3/oneapi.eng.2024.04.15.002/bin:/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-fortran/4.6.1/oneapi.eng.2024.04.15.002/bin:/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-c/4.9.2/oneapi.eng.2024.04.15.002/bin:$ENV{PATH} 1 @@ -3600,6 +3670,9 @@ /soft/tools/mpi_wrapper_utils/gpu_tile_compact.sh 131072 20 + $ENV{KOKKOS_ROOT} + 1 + 0:4,1:4,2:4,3:4:4:4,5:4,6:4,7:4 0 @@ -3912,7 +3985,7 @@ /compyfs/inputdata/atm/datm7 /compyfs/$USER/e3sm_scratch/archive/$CASE /compyfs/e3sm_baselines/$COMPILER - /compyfs/e3sm_baselines/cprnc/cprnc + /compyfs/e3sm_baselines/cprnc/cprnc.intel.v20.0.04/cprnc 8 e3sm_integration 4 @@ -3959,7 +4032,7 @@ gcc/8.1.0 - intel/19.0.5 + intel/20.0.0 pgi/19.10 @@ -3968,7 +4041,7 @@ mvapich2/2.3.1 - intelmpi/2019u4 + intelmpi/2020 intelmpi/2019u3 @@ -4333,7 +4406,7 @@ - Chicoma GPU nodes at LANL IC. Each GPU node has single + Chicoma GPU nodes at LANL IC. Each GPU node has single AMD EPYC 7713 64-Core (Milan) (256GB) and 4 nvidia A100' ch-fe* Linux diff --git a/cime_config/testmods_dirs/allactive/wcprod/user_nl_elm b/cime_config/testmods_dirs/allactive/wcprod/user_nl_elm index cd1adab77404..9224c77e0f0a 100644 --- a/cime_config/testmods_dirs/allactive/wcprod/user_nl_elm +++ b/cime_config/testmods_dirs/allactive/wcprod/user_nl_elm @@ -33,7 +33,7 @@ hist_fexcl1 = 'AGWDNPP','ALTMAX_LASTYEAR','AVAIL_RETRANSP','AVAILC','BAF_CROP', 'SOIL4N_vr','SOIL4P_TNDNCY_VERT_TRANS','SOIL4P_TO_SMINP','SOIL4P_vr','SOLUTIONP_vr', 'TCS_MONTH_BEGIN','TCS_MONTH_END','TOTCOLCH4','water_scalar','WF', 'wlim_m','WOODC_LOSS','WTGQ' -hist_fincl1 = 'SNOWDP','COL_FIRE_CLOSS','NPOOL','PPOOL','TOTPRODC' +hist_fincl1 = 'SNOWDP','COL_FIRE_CLOSS','NPOOL','PPOOL','TOTPRODC','LND_FRC_DUST_MBL' hist_fincl2 = 'H2OSNO', 'FSNO', 'QRUNOFF', 'QSNOMELT', 'FSNO_EFF', 'SNORDSL', 'SNOW', 'FSDS', 'FSR', 'FLDS', 'FIRE', 'FIRA' hist_mfilt = 1,365 hist_nhtfrq = -24,-24 diff --git a/cime_config/testmods_dirs/allactive/wcprod_1850/user_nl_elm b/cime_config/testmods_dirs/allactive/wcprod_1850/user_nl_elm index cd1adab77404..9224c77e0f0a 100644 --- a/cime_config/testmods_dirs/allactive/wcprod_1850/user_nl_elm +++ b/cime_config/testmods_dirs/allactive/wcprod_1850/user_nl_elm @@ -33,7 +33,7 @@ hist_fexcl1 = 'AGWDNPP','ALTMAX_LASTYEAR','AVAIL_RETRANSP','AVAILC','BAF_CROP', 'SOIL4N_vr','SOIL4P_TNDNCY_VERT_TRANS','SOIL4P_TO_SMINP','SOIL4P_vr','SOLUTIONP_vr', 'TCS_MONTH_BEGIN','TCS_MONTH_END','TOTCOLCH4','water_scalar','WF', 'wlim_m','WOODC_LOSS','WTGQ' -hist_fincl1 = 'SNOWDP','COL_FIRE_CLOSS','NPOOL','PPOOL','TOTPRODC' +hist_fincl1 = 'SNOWDP','COL_FIRE_CLOSS','NPOOL','PPOOL','TOTPRODC','LND_FRC_DUST_MBL' hist_fincl2 = 'H2OSNO', 'FSNO', 'QRUNOFF', 'QSNOMELT', 'FSNO_EFF', 'SNORDSL', 'SNOW', 'FSDS', 'FSR', 'FLDS', 'FIRE', 'FIRA' hist_mfilt = 1,365 hist_nhtfrq = -24,-24 diff --git a/cime_config/testmods_dirs/allactive/wcprod_1850_1pctCO2/user_nl_elm b/cime_config/testmods_dirs/allactive/wcprod_1850_1pctCO2/user_nl_elm index cd1adab77404..9224c77e0f0a 100644 --- a/cime_config/testmods_dirs/allactive/wcprod_1850_1pctCO2/user_nl_elm +++ b/cime_config/testmods_dirs/allactive/wcprod_1850_1pctCO2/user_nl_elm @@ -33,7 +33,7 @@ hist_fexcl1 = 'AGWDNPP','ALTMAX_LASTYEAR','AVAIL_RETRANSP','AVAILC','BAF_CROP', 'SOIL4N_vr','SOIL4P_TNDNCY_VERT_TRANS','SOIL4P_TO_SMINP','SOIL4P_vr','SOLUTIONP_vr', 'TCS_MONTH_BEGIN','TCS_MONTH_END','TOTCOLCH4','water_scalar','WF', 'wlim_m','WOODC_LOSS','WTGQ' -hist_fincl1 = 'SNOWDP','COL_FIRE_CLOSS','NPOOL','PPOOL','TOTPRODC' +hist_fincl1 = 'SNOWDP','COL_FIRE_CLOSS','NPOOL','PPOOL','TOTPRODC','LND_FRC_DUST_MBL' hist_fincl2 = 'H2OSNO', 'FSNO', 'QRUNOFF', 'QSNOMELT', 'FSNO_EFF', 'SNORDSL', 'SNOW', 'FSDS', 'FSR', 'FLDS', 'FIRE', 'FIRA' hist_mfilt = 1,365 hist_nhtfrq = -24,-24 diff --git a/cime_config/testmods_dirs/allactive/wcprod_1850_4xCO2/user_nl_elm b/cime_config/testmods_dirs/allactive/wcprod_1850_4xCO2/user_nl_elm index cd1adab77404..9224c77e0f0a 100644 --- a/cime_config/testmods_dirs/allactive/wcprod_1850_4xCO2/user_nl_elm +++ b/cime_config/testmods_dirs/allactive/wcprod_1850_4xCO2/user_nl_elm @@ -33,7 +33,7 @@ hist_fexcl1 = 'AGWDNPP','ALTMAX_LASTYEAR','AVAIL_RETRANSP','AVAILC','BAF_CROP', 'SOIL4N_vr','SOIL4P_TNDNCY_VERT_TRANS','SOIL4P_TO_SMINP','SOIL4P_vr','SOLUTIONP_vr', 'TCS_MONTH_BEGIN','TCS_MONTH_END','TOTCOLCH4','water_scalar','WF', 'wlim_m','WOODC_LOSS','WTGQ' -hist_fincl1 = 'SNOWDP','COL_FIRE_CLOSS','NPOOL','PPOOL','TOTPRODC' +hist_fincl1 = 'SNOWDP','COL_FIRE_CLOSS','NPOOL','PPOOL','TOTPRODC','LND_FRC_DUST_MBL' hist_fincl2 = 'H2OSNO', 'FSNO', 'QRUNOFF', 'QSNOMELT', 'FSNO_EFF', 'SNORDSL', 'SNOW', 'FSDS', 'FSR', 'FLDS', 'FIRE', 'FIRA' hist_mfilt = 1,365 hist_nhtfrq = -24,-24 diff --git a/cime_config/testmods_dirs/allactive/wcprodrrm/user_nl_elm b/cime_config/testmods_dirs/allactive/wcprodrrm/user_nl_elm index cd1adab77404..9224c77e0f0a 100644 --- a/cime_config/testmods_dirs/allactive/wcprodrrm/user_nl_elm +++ b/cime_config/testmods_dirs/allactive/wcprodrrm/user_nl_elm @@ -33,7 +33,7 @@ hist_fexcl1 = 'AGWDNPP','ALTMAX_LASTYEAR','AVAIL_RETRANSP','AVAILC','BAF_CROP', 'SOIL4N_vr','SOIL4P_TNDNCY_VERT_TRANS','SOIL4P_TO_SMINP','SOIL4P_vr','SOLUTIONP_vr', 'TCS_MONTH_BEGIN','TCS_MONTH_END','TOTCOLCH4','water_scalar','WF', 'wlim_m','WOODC_LOSS','WTGQ' -hist_fincl1 = 'SNOWDP','COL_FIRE_CLOSS','NPOOL','PPOOL','TOTPRODC' +hist_fincl1 = 'SNOWDP','COL_FIRE_CLOSS','NPOOL','PPOOL','TOTPRODC','LND_FRC_DUST_MBL' hist_fincl2 = 'H2OSNO', 'FSNO', 'QRUNOFF', 'QSNOMELT', 'FSNO_EFF', 'SNORDSL', 'SNOW', 'FSDS', 'FSR', 'FLDS', 'FIRE', 'FIRA' hist_mfilt = 1,365 hist_nhtfrq = -24,-24 diff --git a/cime_config/testmods_dirs/allactive/wcprodrrm_1850/user_nl_elm b/cime_config/testmods_dirs/allactive/wcprodrrm_1850/user_nl_elm index cd1adab77404..9224c77e0f0a 100644 --- a/cime_config/testmods_dirs/allactive/wcprodrrm_1850/user_nl_elm +++ b/cime_config/testmods_dirs/allactive/wcprodrrm_1850/user_nl_elm @@ -33,7 +33,7 @@ hist_fexcl1 = 'AGWDNPP','ALTMAX_LASTYEAR','AVAIL_RETRANSP','AVAILC','BAF_CROP', 'SOIL4N_vr','SOIL4P_TNDNCY_VERT_TRANS','SOIL4P_TO_SMINP','SOIL4P_vr','SOLUTIONP_vr', 'TCS_MONTH_BEGIN','TCS_MONTH_END','TOTCOLCH4','water_scalar','WF', 'wlim_m','WOODC_LOSS','WTGQ' -hist_fincl1 = 'SNOWDP','COL_FIRE_CLOSS','NPOOL','PPOOL','TOTPRODC' +hist_fincl1 = 'SNOWDP','COL_FIRE_CLOSS','NPOOL','PPOOL','TOTPRODC','LND_FRC_DUST_MBL' hist_fincl2 = 'H2OSNO', 'FSNO', 'QRUNOFF', 'QSNOMELT', 'FSNO_EFF', 'SNORDSL', 'SNOW', 'FSDS', 'FSR', 'FLDS', 'FIRE', 'FIRA' hist_mfilt = 1,365 hist_nhtfrq = -24,-24 diff --git a/cime_config/testmods_dirs/allactive/wcprodssp/user_nl_elm b/cime_config/testmods_dirs/allactive/wcprodssp/user_nl_elm index 7bfdbac5c84b..e2ac4d5d1ab7 100644 --- a/cime_config/testmods_dirs/allactive/wcprodssp/user_nl_elm +++ b/cime_config/testmods_dirs/allactive/wcprodssp/user_nl_elm @@ -38,7 +38,7 @@ 'SOIL4N_vr','SOIL4P_TNDNCY_VERT_TRANS','SOIL4P_TO_SMINP','SOIL4P_vr','SOLUTIONP_vr', 'TCS_MONTH_BEGIN','TCS_MONTH_END','TOTCOLCH4','water_scalar','WF', 'wlim_m','WOODC_LOSS','WTGQ' - hist_fincl1 = 'SNOWDP','COL_FIRE_CLOSS','NPOOL','PPOOL','TOTPRODC' + hist_fincl1 = 'SNOWDP','COL_FIRE_CLOSS','NPOOL','PPOOL','TOTPRODC','LND_FRC_DUST_MBL' hist_fincl2 = 'H2OSNO', 'FSNO', 'QRUNOFF', 'QSNOMELT', 'FSNO_EFF', 'SNORDSL', 'SNOW', 'FSDS', 'FSR', 'FLDS', 'FIRE', 'FIRA' hist_mfilt = 1,365 hist_nhtfrq = -24,-24 diff --git a/cime_config/testmods_dirs/bench/gmpas_noio/user_nl_mpaso b/cime_config/testmods_dirs/bench/gmpas_noio/user_nl_mpaso index 18d93c003d90..e0e9bc591fb6 100644 --- a/cime_config/testmods_dirs/bench/gmpas_noio/user_nl_mpaso +++ b/cime_config/testmods_dirs/bench/gmpas_noio/user_nl_mpaso @@ -1,2 +1,3 @@ config_am_highfrequencyoutput_enable=false config_am_globalstats_enable=false +config_am_conservationcheck_enable=false diff --git a/cime_config/testmods_dirs/bench/wcycl/hires/shell_commands b/cime_config/testmods_dirs/bench/wcycl/hires/shell_commands index a90a9cc89765..615b8f21ffcd 100644 --- a/cime_config/testmods_dirs/bench/wcycl/hires/shell_commands +++ b/cime_config/testmods_dirs/bench/wcycl/hires/shell_commands @@ -3,3 +3,8 @@ # save benchmark timing info for provenance ./xmlchange SAVE_TIMING=TRUE + +# increase mem-tolerance on pm-cpu to 30% +if [ `./xmlquery --value MACH` == pm-cpu ]; then + ./xmlchange TEST_MEMLEAK_TOLERANCE=0.3 +fi diff --git a/cime_config/testmods_dirs/bench/wcycl/lores/user_nl_eam b/cime_config/testmods_dirs/bench/wcycl/lores/user_nl_eam index eeac1d647b1d..095c6946f5de 100644 --- a/cime_config/testmods_dirs/bench/wcycl/lores/user_nl_eam +++ b/cime_config/testmods_dirs/bench/wcycl/lores/user_nl_eam @@ -1,11 +1,59 @@ - nhtfrq = -24,-24,-6,-6,-3,-24,-24 - mfilt = 1,30,120,120,240,30,1 - avgflag_pertape = 'A','A','I','A','A','A','I' - fexcl1 = 'CFAD_SR532_CAL', 'LINOZ_DO3', 'LINOZ_DO3_PSC', 'LINOZ_O3CLIM', 'LINOZ_O3COL', 'LINOZ_SSO3', 'hstobie_linoz' - fincl1 = 'extinct_sw_inp','extinct_lw_bnd7','extinct_lw_inp','CLD_CAL', 'TREFMNAV', 'TREFMXAV' - fincl2 = 'FLUT','PRECT','U200','V200','U850','V850','Z500','OMEGA500','UBOT','VBOT','TREFHT','TREFHTMN:M','TREFHTMX:X','QREFHT','TS','PS','TMQ','TUQ','TVQ','TOZ', 'FLDS', 'FLNS', 'FSDS', 'FSNS', 'SHFLX', 'LHFLX', 'TGCLDCWP', 'TGCLDIWP', 'TGCLDLWP', 'CLDTOT', 'T250', 'T200', 'T150', 'T100', 'T050', 'T025', 'T010', 'T005', 'T002', 'T001', 'TTOP', 'U250', 'U150', 'U100', 'U050', 'U025', 'U010', 'U005', 'U002', 'U001', 'UTOP', 'FSNT', 'FLNT' - fincl3 = 'PSL','T200','T500','U850','V850','UBOT','VBOT','TREFHT', 'Z700', 'TBOT:M' - fincl4 = 'FLUT','U200','U850','PRECT','OMEGA500' - fincl5 = 'PRECT','PRECC','TUQ','TVQ','QFLX','SHFLX','U90M','V90M' - fincl6 = 'CLDTOT_ISCCP','MEANCLDALB_ISCCP','MEANTAU_ISCCP','MEANPTOP_ISCCP','MEANTB_ISCCP','CLDTOT_CAL','CLDTOT_CAL_LIQ','CLDTOT_CAL_ICE','CLDTOT_CAL_UN','CLDHGH_CAL','CLDHGH_CAL_LIQ','CLDHGH_CAL_ICE','CLDHGH_CAL_UN','CLDMED_CAL','CLDMED_CAL_LIQ','CLDMED_CAL_ICE','CLDMED_CAL_UN','CLDLOW_CAL','CLDLOW_CAL_LIQ','CLDLOW_CAL_ICE','CLDLOW_CAL_UN' - fincl7 = 'O3', 'PS', 'TROP_P' +cosp_lite = .true. + +empty_htapes = .true. + +avgflag_pertape = 'A','A','A','A','I','I' +nhtfrq = -24,-24,-6,-3,-1,-24 +mfilt = 1,30,120,240,720,1 + +fincl1 = 'AODALL','AODBC','AODDUST','AODPOM','AODSO4','AODSOA','AODSS','AODVIS', + 'CLDLOW','CLDMED','CLDHGH','CLDTOT', + 'CLDHGH_CAL','CLDLOW_CAL','CLDMED_CAL','CLD_MISR','CLDTOT_CAL', + 'CLMODIS','FISCCP1_COSP','FLDS','FLNS','FLNSC','FLNT','FLUT', + 'FLUTC','FSDS','FSDSC','FSNS','FSNSC','FSNT','FSNTOA','FSNTOAC','FSNTC', + 'ICEFRAC','LANDFRAC','LWCF','OCNFRAC','OMEGA','PRECC','PRECL','PRECSC','PRECSL','PS','PSL','Q', + 'QFLX','QREFHT','RELHUM','SCO','SHFLX','SOLIN','SWCF','T','TAUX','TAUY','TCO', + 'TGCLDLWP','TMQ','TREFHT','TREFMNAV','TREFMXAV','TS','U','U10','V','Z3', + 'dst_a1DDF','dst_a3DDF','dst_c1DDF','dst_c3DDF','dst_a1SFWET','dst_a3SFWET','dst_c1SFWET','dst_c3SFWET', + 'O3','LHFLX', + 'O3_2DTDA_trop','O3_2DTDB_trop','O3_2DTDD_trop','O3_2DTDE_trop','O3_2DTDI_trop','O3_2DTDL_trop', + 'O3_2DTDN_trop','O3_2DTDO_trop','O3_2DTDS_trop','O3_2DTDU_trop','O3_2DTRE_trop','O3_2DTRI_trop', + 'O3_SRF','NO_2DTDS','NO_TDLgt','NO2_2DTDD','NO2_2DTDS','NO2_TDAcf','CO_SRF','TROPE3D_P','TROP_P', + 'CDNUMC','SFDMS','so4_a1_sfgaex1','so4_a2_sfgaex1','so4_a3_sfgaex1','so4_a5_sfgaex1','soa_a1_sfgaex1', + 'soa_a2_sfgaex1','soa_a3_sfgaex1','GS_soa_a1','GS_soa_a2','GS_soa_a3','AQSO4_H2O2','AQSO4_O3', + 'SFSO2','SO2_CLXF','SO2','DF_SO2','AQ_SO2','GS_SO2','WD_SO2','ABURDENSO4_STR','ABURDENSO4_TRO', + 'ABURDENSO4','ABURDENBC','ABURDENDUST','ABURDENMOM','ABURDENPOM','ABURDENSEASALT', + 'ABURDENSOA','AODSO4_STR','AODSO4_TRO', + 'EXTINCT','AODABS','AODABSBC','CLDICE','CLDLIQ','CLD_CAL_TMPLIQ','CLD_CAL_TMPICE','Mass_bc_srf', + 'Mass_dst_srf','Mass_mom_srf','Mass_ncl_srf','Mass_pom_srf','Mass_so4_srf','Mass_soa_srf','Mass_bc_850', + 'Mass_dst_850','Mass_mom_850','Mass_ncl_850','Mass_pom_850','Mass_so4_850','Mass_soa_850','Mass_bc_500', + 'Mass_dst_500','Mass_mom_500','Mass_ncl_500','Mass_pom_500','Mass_so4_500','Mass_soa_500','Mass_bc_330', + 'Mass_dst_330','Mass_mom_330','Mass_ncl_330','Mass_pom_330','Mass_so4_330','Mass_soa_330','Mass_bc_200', + 'Mass_dst_200','Mass_mom_200','Mass_ncl_200','Mass_pom_200','Mass_so4_200','Mass_soa_200', + 'O3_2DTDD','O3_2DCIP','O3_2DCIL','CO_2DTDS','CO_2DTDD','CO_2DCEP','CO_2DCEL','NO_2DTDD', + 'FLNTC','SAODVIS', + 'H2OLNZ', + 'dst_a1SF','dst_a3SF', + 'PHIS','CLOUD','TGCLDIWP','TGCLDCWP','AREL', + 'CLDTOT_ISCCP','MEANCLDALB_ISCCP','MEANPTOP_ISCCP','CLD_CAL', + 'CLDTOT_CAL_LIQ','CLDTOT_CAL_ICE','CLDTOT_CAL_UN', + 'CLDHGH_CAL_LIQ','CLDHGH_CAL_ICE','CLDHGH_CAL_UN', + 'CLDMED_CAL_LIQ','CLDMED_CAL_ICE','CLDMED_CAL_UN', + 'CLDLOW_CAL_LIQ','CLDLOW_CAL_ICE','CLDLOW_CAL_UN', + 'CLWMODIS','CLIMODIS' + +fincl2 = 'PS', 'FLUT','PRECT','U200','V200','U850','V850', + 'TCO','SCO','TREFHTMN','TREFHTMX','TREFHT','QREFHT' +fincl3 = 'PS', 'PSL','PRECT','TUQ','TVQ','UBOT','VBOT','TREFHT','FLUT','OMEGA500','TBOT','U850','V850','U200','V200','T200','T500','Z700' +fincl4 = 'PRECT' +fincl5 = 'O3_SRF' +fincl6 = 'CO_2DMSD','NO2_2DMSD','NO_2DMSD','O3_2DMSD','O3_2DMSD_trop' + +! -- chemUCI settings ------------------ +history_chemdyg_summary = .true. +history_gaschmbudget_2D = .false. +history_gaschmbudget_2D_levels = .false. +history_gaschmbudget_num = 6 !! no impact if history_gaschmbudget_2D = .false. + +! -- MAM5 settings ------------------ +is_output_interactive_volc = .true. diff --git a/cime_config/testmods_dirs/bench/wcycl/lores/user_nl_elm b/cime_config/testmods_dirs/bench/wcycl/lores/user_nl_elm index a93edc10b690..cd1adab77404 100644 --- a/cime_config/testmods_dirs/bench/wcycl/lores/user_nl_elm +++ b/cime_config/testmods_dirs/bench/wcycl/lores/user_nl_elm @@ -1,6 +1,40 @@ - finidat = ' ' - hist_dov2xy = .true.,.true. - hist_fincl2 = 'H2OSNO', 'FSNO', 'QRUNOFF', 'QSNOMELT', 'FSNO_EFF', 'SNORDSL', 'SNOW', 'FSDS', 'FSR', 'FLDS', 'FIRE', 'FIRA' - hist_mfilt = 1,365 - hist_nhtfrq = -24,-24 - hist_avgflag_pertape = 'A','A' +hist_dov2xy = .true.,.true. +hist_fexcl1 = 'AGWDNPP','ALTMAX_LASTYEAR','AVAIL_RETRANSP','AVAILC','BAF_CROP', + 'BAF_PEATF','BIOCHEM_PMIN_TO_PLANT','CH4_SURF_AERE_SAT','CH4_SURF_AERE_UNSAT','CH4_SURF_DIFF_SAT', + 'CH4_SURF_DIFF_UNSAT','CH4_SURF_EBUL_SAT','CH4_SURF_EBUL_UNSAT','CMASS_BALANCE_ERROR','cn_scalar', + 'COL_PTRUNC','CONC_CH4_SAT','CONC_CH4_UNSAT','CONC_O2_SAT','CONC_O2_UNSAT', + 'cp_scalar','CWDC_HR','CWDC_LOSS','CWDC_TO_LITR2C','CWDC_TO_LITR3C', + 'CWDC_vr','CWDN_TO_LITR2N','CWDN_TO_LITR3N','CWDN_vr','CWDP_TO_LITR2P', + 'CWDP_TO_LITR3P','CWDP_vr','DWT_CONV_CFLUX_DRIBBLED','F_CO2_SOIL','F_CO2_SOIL_vr', + 'F_DENIT_vr','F_N2O_DENIT','F_N2O_NIT','F_NIT_vr','FCH4_DFSAT', + 'FINUNDATED_LAG','FPI_P_vr','FPI_vr','FROOTC_LOSS','HR_vr', + 'LABILEP_TO_SECONDP','LABILEP_vr','LAND_UPTAKE','LEAF_MR','leaf_npimbalance', + 'LEAFC_LOSS','LEAFC_TO_LITTER','LFC2','LITR1_HR','LITR1C_TO_SOIL1C', + 'LITR1C_vr','LITR1N_TNDNCY_VERT_TRANS','LITR1N_TO_SOIL1N','LITR1N_vr','LITR1P_TNDNCY_VERT_TRANS', + 'LITR1P_TO_SOIL1P','LITR1P_vr','LITR2_HR','LITR2C_TO_SOIL2C','LITR2C_vr', + 'LITR2N_TNDNCY_VERT_TRANS','LITR2N_TO_SOIL2N','LITR2N_vr','LITR2P_TNDNCY_VERT_TRANS','LITR2P_TO_SOIL2P', + 'LITR2P_vr','LITR3_HR','LITR3C_TO_SOIL3C','LITR3C_vr','LITR3N_TNDNCY_VERT_TRANS', + 'LITR3N_TO_SOIL3N','LITR3N_vr','LITR3P_TNDNCY_VERT_TRANS','LITR3P_TO_SOIL3P','LITR3P_vr', + 'M_LITR1C_TO_LEACHING','M_LITR2C_TO_LEACHING','M_LITR3C_TO_LEACHING','M_SOIL1C_TO_LEACHING','M_SOIL2C_TO_LEACHING', + 'M_SOIL3C_TO_LEACHING','M_SOIL4C_TO_LEACHING','NDEPLOY','NEM','nlim_m', + 'o2_decomp_depth_unsat','OCCLP_vr','PDEPLOY','PLANT_CALLOC','PLANT_NDEMAND', + 'PLANT_NDEMAND_COL','PLANT_PALLOC','PLANT_PDEMAND','PLANT_PDEMAND_COL','plim_m', + 'POT_F_DENIT','POT_F_NIT','POTENTIAL_IMMOB','POTENTIAL_IMMOB_P','PRIMP_TO_LABILEP', + 'PRIMP_vr','PROD1P_LOSS','QOVER_LAG','RETRANSN_TO_NPOOL','RETRANSP_TO_PPOOL', + 'SCALARAVG_vr','SECONDP_TO_LABILEP','SECONDP_TO_OCCLP','SECONDP_vr','SMIN_NH4_vr', + 'SMIN_NO3_vr','SMINN_TO_SOIL1N_L1','SMINN_TO_SOIL2N_L2','SMINN_TO_SOIL2N_S1','SMINN_TO_SOIL3N_L3', + 'SMINN_TO_SOIL3N_S2','SMINN_TO_SOIL4N_S3','SMINP_TO_SOIL1P_L1','SMINP_TO_SOIL2P_L2','SMINP_TO_SOIL2P_S1', + 'SMINP_TO_SOIL3P_L3','SMINP_TO_SOIL3P_S2','SMINP_TO_SOIL4P_S3','SMINP_vr','SOIL1_HR','SOIL1C_TO_SOIL2C','SOIL1C_vr','SOIL1N_TNDNCY_VERT_TRANS','SOIL1N_TO_SOIL2N','SOIL1N_vr', + 'SOIL1P_TNDNCY_VERT_TRANS','SOIL1P_TO_SOIL2P','SOIL1P_vr','SOIL2_HR','SOIL2C_TO_SOIL3C', + 'SOIL2C_vr','SOIL2N_TNDNCY_VERT_TRANS','SOIL2N_TO_SOIL3N','SOIL2N_vr','SOIL2P_TNDNCY_VERT_TRANS', + 'SOIL2P_TO_SOIL3P','SOIL2P_vr','SOIL3_HR','SOIL3C_TO_SOIL4C','SOIL3C_vr', + 'SOIL3N_TNDNCY_VERT_TRANS','SOIL3N_TO_SOIL4N','SOIL3N_vr','SOIL3P_TNDNCY_VERT_TRANS','SOIL3P_TO_SOIL4P', + 'SOIL3P_vr','SOIL4_HR','SOIL4C_vr','SOIL4N_TNDNCY_VERT_TRANS','SOIL4N_TO_SMINN', + 'SOIL4N_vr','SOIL4P_TNDNCY_VERT_TRANS','SOIL4P_TO_SMINP','SOIL4P_vr','SOLUTIONP_vr', + 'TCS_MONTH_BEGIN','TCS_MONTH_END','TOTCOLCH4','water_scalar','WF', + 'wlim_m','WOODC_LOSS','WTGQ' +hist_fincl1 = 'SNOWDP','COL_FIRE_CLOSS','NPOOL','PPOOL','TOTPRODC' +hist_fincl2 = 'H2OSNO', 'FSNO', 'QRUNOFF', 'QSNOMELT', 'FSNO_EFF', 'SNORDSL', 'SNOW', 'FSDS', 'FSR', 'FLDS', 'FIRE', 'FIRA' +hist_mfilt = 1,365 +hist_nhtfrq = -24,-24 +hist_avgflag_pertape = 'A','A' diff --git a/cime_config/testmods_dirs/config_pes_tests.xml b/cime_config/testmods_dirs/config_pes_tests.xml index 080e496d205b..1ac88ac5fe6f 100644 --- a/cime_config/testmods_dirs/config_pes_tests.xml +++ b/cime_config/testmods_dirs/config_pes_tests.xml @@ -37,6 +37,8 @@ -4 -4 -4 + -4 + -4 -4 @@ -203,6 +205,23 @@ + + + + tests+anvil: --compset GMPAS-JRA1p5-DIB-PISMF, 8 nodes + + -8 + -8 + -8 + -8 + -8 + -8 + -8 + -8 + + + + diff --git a/cime_config/testmods_dirs/io/force_adios/shell_commands b/cime_config/testmods_dirs/io/force_adios/shell_commands new file mode 100644 index 000000000000..e7169a8283bb --- /dev/null +++ b/cime_config/testmods_dirs/io/force_adios/shell_commands @@ -0,0 +1,2 @@ +#!/bin/bash +./xmlchange PIO_TYPENAME="adios" diff --git a/cime_config/tests.py b/cime_config/tests.py index ef54bad2a2c6..1cbf28b83974 100644 --- a/cime_config/tests.py +++ b/cime_config/tests.py @@ -76,11 +76,10 @@ ) }, - "e3sm_land_developer" : { "share" : True, "time" : "0:45:00", - "inherit" : ("e3sm_mosart_developer", "e3sm_mosart_exenoshare", "e3sm_land_exeshare", "e3sm_land_exenoshare", "e3sm_land_debug", "fates_elm_developer"), + "inherit" : ("e3sm_mosart_developer", "e3sm_land_exeshare", "e3sm_land_exenoshare", "e3sm_land_debug", "fates_elm_developer"), "tests" : ( "ERS.f19_f19.I1850ELMCN", "ERS.f19_f19.I20TRELMCN", @@ -95,6 +94,8 @@ "SMS.r05_r05.IELM.elm-topounit", "ERS.ELM_USRDAT.I1850ELM.elm-usrdat", "ERS.r05_r05.IELM.elm-lnd_rof_2way", + "ERS.ELM_USRDAT.I1850CNPRDCTCBC.elm-usrpft_default_I1850CNPRDCTCBC", + "ERS.ELM_USRDAT.I1850CNPRDCTCBC.elm-usrpft_codetest_I1850CNPRDCTCBC", "ERS.r05_r05.IELM.elm-V2_ELM_MOSART_features", "ERS.ELM_USRDAT.IELM.elm-surface_water_dynamics" ) @@ -274,6 +275,7 @@ "ERS_P480_Ld5.TL319_IcoswISC30E3r5.GMPAS-JRA1p5-DIB-PISMF.mpaso-jra_1958", "PEM_P480_Ld5.TL319_IcoswISC30E3r5.GMPAS-JRA1p5-DIB-PISMF.mpaso-jra_1958", "SMS_P480_Ld5.TL319_IcoswISC30E3r5.GMPAS-JRA1p5-DIB-PISMF-TMIX.mpaso-jra_1958", + "SMS_P480_Ld5.TL319_IcoswISC30E3r5.GMPAS-JRA1p5-DIB-PISMF-DSGR.mpaso-jra_1958", ) }, @@ -302,7 +304,7 @@ "SMS.ne30_f19_g16_rx1.A", "ERS_Ld5.T62_oQU120.CMPASO-NYF", "ERS.f09_g16_g.MALISIA", - "ERS_Ld5.TL319_oQU240wLI_ais20.MPAS_LISIO_JRA1p5.mpaso-ocn_glcshelf", + "ERS_Ld5.TL319_oQU240wLI_ais8to30.MPAS_LISIO_JRA1p5.mpaso-ocn_glcshelf", "SMS_P12x2.ne4pg2_oQU480.WCYCL1850NS.allactive-mach_mods", "ERS_Ln9.ne4pg2_ne4pg2.F2010-MMF1.eam-mmf_crmout", ) @@ -321,6 +323,7 @@ "time" : "03:00:00", "tests" : ( "ERS.ne4pg2_oQU480.WCYCL1850NS", + "ERS_Vmoab.ne4pg2_oQU480.WCYCL1850NS", "SMS_D_Ld1.ne30pg2_r05_IcoswISC30E3r5.WCYCL1850.allactive-wcprod", "SMS_D_Ld1.ne30pg2_r05_IcoswISC30E3r5.WCYCLSSP370.allactive-wcprodssp", "ERS_Ld3.ne4pg2_oQU480.F2010", @@ -337,6 +340,7 @@ "ERS_Ld3.ne30pg2_r05_IcoswISC30E3r5.WCYCL1850.allactive-nlmaps", "SMS_D_Ld1.ne30pg2_r05_IcoswISC30E3r5.CRYO1850-DISMF", "ERS.hcru_hcru.I20TRGSWCNPRDCTCBC.elm-erosion", + "ERS.ne30pg2_r05_IcoswISC30E3r5.GPMPAS-JRA.mosart-rof_ocn_2way", ) }, @@ -370,7 +374,7 @@ "ERP_Ln9.ne4pg2_oQU480.WCYCL20TRNS-MMF1.allactive-mmf_fixed_subcycle", "ERS_Ln9.ne4pg2_ne4pg2.FRCE-MMF1.eam-cosp_nhtfrq9", "SMS_Ln5.ne4_ne4.FSCM-ARM97-MMF1", - "SMS_Ln3.ne4pg2_ne4pg2.F2010-MMF2", + "SMS_Ln3.ne4pg2_oQU480.F2010-MMF2", ) }, @@ -570,13 +574,13 @@ "share" : True, "time" : "03:00:00", "tests" : ( - "PFS_P7200.ne120pg2_r05_EC30to60E2r2.F2010.eam-bench-noio", - "PFS_P8640.ne120pg2_r05_EC30to60E2r2.F2010.eam-bench-noio", - "PFS_P10800.ne120pg2_r05_EC30to60E2r2.F2010.eam-bench-noio", - "PFS_P14400.ne120pg2_r05_EC30to60E2r2.F2010.eam-bench-noio", - "PFS_P21600.ne120pg2_r05_EC30to60E2r2.F2010.eam-bench-noio", - "PFS_P43200.ne120pg2_r05_EC30to60E2r2.F2010.eam-bench-noio", - "PFS_P86400.ne120pg2_r05_EC30to60E2r2.F2010.eam-bench-noio", + "PFS_P7200.ne120pg2_r025_RRSwISC6to18E3r5.F2010.eam-bench-noio", + "PFS_P8640.ne120pg2_r025_RRSwISC6to18E3r5.F2010.eam-bench-noio", + "PFS_P10800.ne120pg2_r025_RRSwISC6to18E3r5.F2010.eam-bench-noio", + "PFS_P14400.ne120pg2_r025_RRSwISC6to18E3r5.F2010.eam-bench-noio", + "PFS_P21600.ne120pg2_r025_RRSwISC6to18E3r5.F2010.eam-bench-noio", + "PFS_P43200.ne120pg2_r025_RRSwISC6to18E3r5.F2010.eam-bench-noio", + "PFS_P86400.ne120pg2_r025_RRSwISC6to18E3r5.F2010.eam-bench-noio", ) }, "e3sm_bench_hires" : { @@ -584,29 +588,37 @@ "inherit" : ("e3sm_bench_hires_g", "e3sm_bench_hires_f"), "time" : "03:00:00", "tests" : ( - "PFS_PS.ne120pg2_r025_RRSwISC6to18E3r5.WCYCL1950.bench-wcycl-hires", - "PFS_PM.ne120pg2_r025_RRSwISC6to18E3r5.WCYCL1950.bench-wcycl-hires", - "PFS_PL.ne120pg2_r025_RRSwISC6to18E3r5.WCYCL1950.bench-wcycl-hires", + "PFS_PS.ne120pg2_r025_RRSwISC6to18E3r5.WCYCL1850NS.bench-wcycl-hires", + "PFS_PM.ne120pg2_r025_RRSwISC6to18E3r5.WCYCL1850NS.bench-wcycl-hires", + "PFS_PL.ne120pg2_r025_RRSwISC6to18E3r5.WCYCL1850NS.bench-wcycl-hires", ) }, + "e3sm_bench_hires_tiny" : { + "time" : "03:00:00", + "tests" : ( + "PFS_P16384.T62_RRSwISC6to18E3r5.GMPAS-IAF.bench-gmpas_noio", + "PFS_P16384.ne120pg2_r025_RRSwISC6to18E3r5.F2010.eam-bench-noio", + "PFS.ne120pg2_r025_RRSwISC6to18E3r5.WCYCL1850NS.bench-wcycl-hires", + ) + }, "e3sm_bench_lores_g" : { "share" : True, "time" : "03:00:00", "tests" : ( - "PFS_P320.T62_EC30to60E2r2.GMPAS-IAF.bench-gmpas_noio", - "PFS_P480.T62_EC30to60E2r2.GMPAS-IAF.bench-gmpas_noio", - "PFS_P640.T62_EC30to60E2r2.GMPAS-IAF.bench-gmpas_noio", - "PFS_P960.T62_EC30to60E2r2.GMPAS-IAF.bench-gmpas_noio", - "PFS_P1280.T62_EC30to60E2r2.GMPAS-IAF.bench-gmpas_noio", + "PFS_P320.T62_IcoswISC30E3r5.GMPAS-IAF.bench-gmpas_noio", + "PFS_P480.T62_IcoswISC30E3r5.GMPAS-IAF.bench-gmpas_noio", + "PFS_P640.T62_IcoswISC30E3r5.GMPAS-IAF.bench-gmpas_noio", + "PFS_P960.T62_IcoswISC30E3r5.GMPAS-IAF.bench-gmpas_noio", + "PFS_P1280.T62_IcoswISC30E3r5.GMPAS-IAF.bench-gmpas_noio", ) }, "e3sm_bench_lores_f" : { "share" : True, "time" : "03:00:00", "tests" : ( - "PFS_P1350.ne30pg2_EC30to60E2r2.F2010.eam-bench-noio", - "PFS_P2700.ne30pg2_EC30to60E2r2.F2010.eam-bench-noio", - "PFS_P5400.ne30pg2_EC30to60E2r2.F2010.eam-bench-noio", + "PFS_P1350.ne30pg2_r05_IcoswISC30E3r5.F2010.eam-bench-noio", + "PFS_P2700.ne30pg2_r05_IcoswISC30E3r5.F2010.eam-bench-noio", + "PFS_P5400.ne30pg2_r05_IcoswISC30E3r5.F2010.eam-bench-noio", ) }, "e3sm_bench_lores" : { @@ -614,9 +626,9 @@ "inherit" : ("e3sm_bench_lores_g", "e3sm_bench_lores_f"), "time" : "03:00:00", "tests" : ( - "PFS_PS.ne30pg2_EC30to60E2r2.WCYCL1850.bench-wcycl-lores", - "PFS_PM.ne30pg2_EC30to60E2r2.WCYCL1850.bench-wcycl-lores", - "PFS_PL.ne30pg2_EC30to60E2r2.WCYCL1850.bench-wcycl-lores", + "PFS_PS.ne30pg2_r05_IcoswISC30E3r5.WCYCL1850.bench-wcycl-lores", + "PFS_PM.ne30pg2_r05_IcoswISC30E3r5.WCYCL1850.bench-wcycl-lores", + "PFS_PL.ne30pg2_r05_IcoswISC30E3r5.WCYCL1850.bench-wcycl-lores", ) }, "e3sm_bench_all" : { @@ -754,6 +766,7 @@ "e3sm_gpucxx" : { "tests" : ( "SMS_Ln9.ne4pg2_ne4pg2.F2010-MMF1", + "ERP_Ln9.ne4pg2_ne4pg2.F2010-SCREAMv1", ) }, @@ -803,38 +816,38 @@ # super-BFB OCN "e3sm_superbfb_ocn_opt" : { # opt + pureMPI - #"share" : True, + "share" : True, "time" : "00:30:00", "tests" : ( - "ERS_Ld3.T62_EC30to60E2r2.CMPASO-NYF.pemod-omp1", - "PEM_Lh3.T62_EC30to60E2r2.CMPASO-NYF.pemod-omp1", + "ERS_Ld3.T62_IcoswISC30E3r5.CMPASO-NYF.pemod-omp1", + "PEM_Lh3.T62_IcoswISC30E3r5.CMPASO-NYF.pemod-omp1", ) }, "e3sm_superbfb_ocn_dbg" : { # dbg + pureMPI - #"share" : True, + "share" : True, "time" : "01:00:00", "tests" : ( - "ERS_Ld3_D.T62_EC30to60E2r2.CMPASO-NYF.pemod-omp1", - "PEM_Lh3_D.T62_EC30to60E2r2.CMPASO-NYF.pemod-omp1", + "ERS_Ld3_D.T62_IcoswISC30E3r5.CMPASO-NYF.pemod-omp1", + "PEM_Lh3_D.T62_IcoswISC30E3r5.CMPASO-NYF.pemod-omp1", ) }, "e3sm_superbfb_ocn_opt_thrd" : { # opt + threads - #"share" : True, + "share" : True, "time" : "00:30:00", "tests" : ( - "ERS_Ld3.T62_EC30to60E2r2.CMPASO-NYF.pemod-omp2", - "PET_Lh3.T62_EC30to60E2r2.CMPASO-NYF.pemod-ompfull", + "ERS_Ld3.T62_IcoswISC30E3r5.CMPASO-NYF.pemod-omp2", + "PET_Lh3.T62_IcoswISC30E3r5.CMPASO-NYF.pemod-ompfull", ) }, "e3sm_superbfb_ocn_dbg_thrd" : { # dbg + threads - #"share" : True, + "share" : True, "time" : "01:00:00", "tests" : ( - "ERS_Ld3_D.T62_EC30to60E2r2.CMPASO-NYF.pemod-omp2", - "PET_Lh3_D.T62_EC30to60E2r2.CMPASO-NYF.pemod-ompfull", + "ERS_Ld3_D.T62_IcoswISC30E3r5.CMPASO-NYF.pemod-omp2", + "PET_Lh3_D.T62_IcoswISC30E3r5.CMPASO-NYF.pemod-ompfull", ) }, @@ -845,38 +858,38 @@ # super-BFB ICE "e3sm_superbfb_ice_opt" : { # opt + pureMPI - #"share" : True, + "share" : True, "time" : "00:30:00", "tests" : ( - "ERS_Lh3.T62_EC30to60E2r2.DTESTM.pemod-omp1", - "PEM_Lh3.T62_EC30to60E2r2.DTESTM.pemod-omp1", + "ERS_Lh3.T62_IcoswISC30E3r5.DTESTM.pemod-omp1", + "PEM_Lh3.T62_IcoswISC30E3r5.DTESTM.pemod-omp1", ) }, "e3sm_superbfb_ice_dbg" : { # dbg + pureMPI - #"share" : True, + "share" : True, "time" : "01:00:00", "tests" : ( - "ERS_Lh3_D.T62_EC30to60E2r2.DTESTM.pemod-omp1", - "PEM_Lh3_D.T62_EC30to60E2r2.DTESTM.pemod-omp1", + "ERS_Lh3_D.T62_IcoswISC30E3r5.DTESTM.pemod-omp1", + "PEM_Lh3_D.T62_IcoswISC30E3r5.DTESTM.pemod-omp1", ) }, "e3sm_superbfb_ice_opt_thrd" : { # opt + threads - #"share" : True, + "share" : True, "time" : "00:30:00", "tests" : ( - "ERS_Lh3.T62_EC30to60E2r2.DTESTM.pemod-ompfull", - "PET_Lh3.T62_EC30to60E2r2.DTESTM.pemod-omp2", + "ERS_Lh3.T62_IcoswISC30E3r5.DTESTM.pemod-ompfull", + "PET_Lh3.T62_IcoswISC30E3r5.DTESTM.pemod-omp2", ) }, "e3sm_superbfb_ice_dbg_thrd" : { # dbg + threads - #"share" : True, + "share" : True, "time" : "01:00:00", "tests" : ( - "ERS_Lh3_D.T62_EC30to60E2r2.DTESTM.pemod-ompfull", - "PET_Lh3_D.T62_EC30to60E2r2.DTESTM.pemod-omp2", + "ERS_Lh3_D.T62_IcoswISC30E3r5.DTESTM.pemod-ompfull", + "PET_Lh3_D.T62_IcoswISC30E3r5.DTESTM.pemod-omp2", ) }, @@ -887,38 +900,38 @@ # super-BFB LND "e3sm_superbfb_lnd_opt" : { # opt + pureMPI - #"share" : True, + "share" : True, "time" : "00:30:00", "tests" : ( - "ERS_Lh3.ne30pg2_ne30pg2.IELMTEST.pemod-omp1", - "PEM_Lh3.ne30pg2_ne30pg2.IELMTEST.pemod-omp1", + "ERS_Lh3.r05_r05.IELMTEST.pemod-omp1", + "PEM_Lh3.r05_r05.IELMTEST.pemod-omp1", ) }, "e3sm_superbfb_lnd_dbg" : { # dbg + pureMPI - #"share" : True, + "share" : True, "time" : "01:00:00", "tests" : ( - "ERS_Lh3_D.ne30pg2_ne30pg2.IELMTEST.pemod-omp1", - "PEM_Lh3_D.ne30pg2_ne30pg2.IELMTEST.pemod-omp1", + "ERS_Lh3_D.r05_r05.IELMTEST.pemod-omp1", + "PEM_Lh3_D.r05_r05.IELMTEST.pemod-omp1", ) }, "e3sm_superbfb_lnd_opt_thrd" : { # opt + threads - #"share" : True, + "share" : True, "time" : "00:30:00", "tests" : ( - "PET_Lh3.ne30pg2_ne30pg2.IELMTEST.pemod-omp2", - "ERS_Lh3.ne30pg2_ne30pg2.IELMTEST.pemod-ompfull", + "PET_Lh3.r05_r05.IELMTEST.pemod-omp2", + "ERS_Lh3.r05_r05.IELMTEST.pemod-ompfull", ) }, "e3sm_superbfb_lnd_dbg_thrd" : { # dbg + threads - #"share" : True, + "share" : True, "time" : "01:00:00", "tests" : ( - "PET_Lh3_D.ne30pg2_ne30pg2.IELMTEST.pemod-omp2", - "ERS_Lh3_D.ne30pg2_ne30pg2.IELMTEST.pemod-ompfull", + "PET_Lh3_D.r05_r05.IELMTEST.pemod-omp2", + "ERS_Lh3_D.r05_r05.IELMTEST.pemod-ompfull", ) }, @@ -929,7 +942,7 @@ # super-BFB ROF "e3sm_superbfb_rof_opt" : { # opt + pureMPI - #"share" : True, + "share" : True, "time" : "00:30:00", "tests" : ( "ERS_Ld3.r05_r05.RMOSGPCC.pemod-omp1", @@ -938,7 +951,7 @@ }, "e3sm_superbfb_rof_dbg" : { # dbg + pureMPI - #"share" : True, + "share" : True, "time" : "01:00:00", "tests" : ( "ERS_Ld3_D.r05_r05.RMOSGPCC.pemod-omp1", @@ -947,7 +960,7 @@ }, "e3sm_superbfb_rof_opt_thrd" : { # opt + threads - #"share" : True, + "share" : True, "time" : "00:30:00", "tests" : ( "PET_Ld3.r05_r05.RMOSGPCC.pemod-omp2", @@ -956,7 +969,7 @@ }, "e3sm_superbfb_rof_dbg_thrd" : { # dbg + threads - #"share" : True, + "share" : True, "time" : "01:00:00", "tests" : ( "PET_Ld3_D.r05_r05.RMOSGPCC.pemod-omp2", @@ -971,7 +984,7 @@ # super-BFB ATM "e3sm_superbfb_atm_opt" : { # opt + pureMPI - #"share" : True, + "share" : True, "time" : "00:30:00", "tests" : ( "ERS_Lh3.ne30pg2_ne30pg2.FAQP.pemod-omp1", @@ -980,7 +993,7 @@ }, "e3sm_superbfb_atm_dbg" : { # dbg + pureMPI - #"share" : True, + "share" : True, "time" : "01:00:00", "tests" : ( "ERS_Lh3_D.ne30pg2_ne30pg2.FAQP.pemod-omp1", @@ -989,7 +1002,7 @@ }, "e3sm_superbfb_atm_opt_thrd" : { # opt + threads - #"share" : True, + "share" : True, "time" : "00:30:00", "tests" : ( "PET_Lh3.ne30pg2_ne30pg2.FAQP.pemod-omp2", @@ -998,7 +1011,7 @@ }, "e3sm_superbfb_atm_dbg_thrd" : { # dbg + threads - #"share" : True, + "share" : True, "time" : "01:00:00", "tests" : ( "PET_Lh3_D.ne30pg2_ne30pg2.FAQP.pemod-omp2", @@ -1013,38 +1026,38 @@ # super-BFB all-active "e3sm_superbfb_wcycl_opt" : { # opt + pureMPI - #"share" : True, + "share" : True, "time" : "01:00:00", "tests" : ( - "ERS_Ld3.ne30pg2_EC30to60E2r2.WCYCL1850.pemod-omp1", - "PEM_Ld3.ne30pg2_EC30to60E2r2.WCYCL1850.pemod-omp1", + "ERS_Ld3.ne30pg2_r05_IcoswISC30E3r5.WCYCL1850.pemod-omp1", + "PEM_Ld3.ne30pg2_r05_IcoswISC30E3r5.WCYCL1850.pemod-omp1", ) }, "e3sm_superbfb_wcycl_dbg" : { # dbg + pureMPI - #"share" : True, + "share" : True, "time" : "02:00:00", "tests" : ( - "ERS_Ld3_D.ne30pg2_EC30to60E2r2.WCYCL1850.pemod-omp1", - "PEM_Ld3_D.ne30pg2_EC30to60E2r2.WCYCL1850.pemod-omp1", + "ERS_Ld3_D.ne30pg2_r05_IcoswISC30E3r5.WCYCL1850.pemod-omp1", + "PEM_Ld3_D.ne30pg2_r05_IcoswISC30E3r5.WCYCL1850.pemod-omp1", ) }, "e3sm_superbfb_wcycl_opt_thrd" : { # opt + threads - #"share" : True, + "share" : True, "time" : "01:00:00", "tests" : ( - "PET_Ld3.ne30pg2_EC30to60E2r2.WCYCL1850.pemod-omp2", - "ERS_Ld3.ne30pg2_EC30to60E2r2.WCYCL1850.pemod-ompfull", + "PET_Ld3.ne30pg2_r05_IcoswISC30E3r5.WCYCL1850.pemod-omp2", + "ERS_Ld3.ne30pg2_r05_IcoswISC30E3r5.WCYCL1850.pemod-ompfull", ) }, "e3sm_superbfb_wcycl_dbg_thrd" : { # dbg + threads - #"share" : True, + "share" : True, "time" : "02:00:00", "tests" : ( - "PET_Ld3_D.ne30pg2_EC30to60E2r2.WCYCL1850.pemod-omp2", - "ERS_Ld3_D.ne30pg2_EC30to60E2r2.WCYCL1850.pemod-omp2", + "PET_Ld3_D.ne30pg2_r05_IcoswISC30E3r5.WCYCL1850.pemod-omp2", + "ERS_Ld3_D.ne30pg2_r05_IcoswISC30E3r5.WCYCL1850.pemod-omp2", ) }, diff --git a/components/cmake/find_dep_packages.cmake b/components/cmake/find_dep_packages.cmake index 9d5628bb0bd4..24e513b9b5e4 100644 --- a/components/cmake/find_dep_packages.cmake +++ b/components/cmake/find_dep_packages.cmake @@ -11,33 +11,30 @@ # This will allow users to easily specify a different location for all their cases by # simply setting ${Package}_ROOT in their shell. -# Kokkos' find_package needs to come before other find_packages -# that may define Kokkos targets so we can avoid duplicate target -# errors. -if (USE_KOKKOS) +# If using albany or trilinos, we should already have kokkos +if (USE_ALBANY OR USE_TRILINOS) + find_package(Trilinos REQUIRED) + # When Albany becomes a nice cmake package, that finds its deps, you can + # move this line above if (USE_TRILINOS), and turn that if in elseif. + # Until then, we must find Albany *after* trilinos has been found + if (USE_ALBANY) + find_package(Albany REQUIRED) + endif() +elseif (USE_KOKKOS) # Kokkos will be built in the sharedlibs if Kokkos_ROOT is # unset. if (NOT DEFINED ENV{Kokkos_ROOT}) + # Kokkos will be built in the sharedlibs if Kokkos_ROOT is unset. set(ENV{Kokkos_ROOT} ${INSTALL_SHAREDPATH}) endif() - find_package(Kokkos REQUIRED) endif() -# Albany depends on Trilinos -if (USE_ALBANY OR USE_TRILINOS) - find_package(Trilinos REQUIRED) -endif() - if (USE_MOAB) find_package(MOAB REQUIRED) endif() -if (USE_ALBANY) - find_package(Albany REQUIRED) -endif() - if (USE_PETSC) find_package(PETSc REQUIRED) endif() diff --git a/components/data_comps/dlnd/src/dlnd_comp_mod.F90 b/components/data_comps/dlnd/src/dlnd_comp_mod.F90 index bf723259be48..fbd6e35cf87d 100644 --- a/components/data_comps/dlnd/src/dlnd_comp_mod.F90 +++ b/components/data_comps/dlnd/src/dlnd_comp_mod.F90 @@ -29,6 +29,10 @@ module dlnd_comp_mod use dlnd_shr_mod , only: domain_fracname ! namelist input use dlnd_shr_mod , only: nullstr +#ifdef HAVE_MOAB + use seq_comm_mct, only : mlnid ! id of moab lnd app + use iso_c_binding +#endif ! !PUBLIC TYPES: implicit none private ! except @@ -100,6 +104,15 @@ subroutine dlnd_comp_init(Eclock, x2l, l2x, & scmMode, scmlat, scmlon) ! !DESCRIPTION: initialize dlnd model +#ifdef HAVE_MOAB + use iMOAB, only: iMOAB_DefineTagStorage, & + iMOAB_SetIntTagStorage, iMOAB_SetDoubleTagStorage, & + iMOAB_ResolveSharedEntities, iMOAB_CreateVertices, & + iMOAB_UpdateMeshInfo +#ifdef MOABDEBUG + use iMOAB, only: iMOAB_WriteMesh +#endif +#endif implicit none ! !INPUT/OUTPUT PARAMETERS: @@ -135,6 +148,18 @@ subroutine dlnd_comp_init(Eclock, x2l, l2x, & character(nec_len) :: nec_str ! elevation class, as character string character(*), parameter :: domain_fracname_unset = 'null' +#ifdef HAVE_MOAB + character*400 tagname + real(R8) latv, lonv + integer iv, tagindex, ilat, ilon + real(R8), allocatable, target :: data(:) + integer(IN), pointer :: idata(:) ! temporary + real(R8), dimension(:), allocatable :: moab_vert_coords ! temporary +#ifdef MOABDEBUG + character*100 outfile, wopts +#endif +#endif + !--- formats --- character(*), parameter :: F00 = "('(dlnd_comp_init) ',8a)" character(*), parameter :: F0L = "('(dlnd_comp_init) ',a, l2)" @@ -256,6 +281,119 @@ subroutine dlnd_comp_init(Eclock, x2l, l2x, & call t_stopf('dlnd_initmctdom') +#ifdef HAVE_MOAB + ilat = mct_aVect_indexRA(ggrid%data,'lat') + ilon = mct_aVect_indexRA(ggrid%data,'lon') + allocate(moab_vert_coords(lsize*3)) + do iv = 1, lsize + lonv = ggrid%data%rAttr(ilon, iv) * SHR_CONST_PI/180. + latv = ggrid%data%rAttr(ilat, iv) * SHR_CONST_PI/180. + moab_vert_coords(3*iv-2)=COS(latv)*COS(lonv) + moab_vert_coords(3*iv-1)=COS(latv)*SIN(lonv) + moab_vert_coords(3*iv )=SIN(latv) + enddo + + ! create the vertices with coordinates from MCT domain + ierr = iMOAB_CreateVertices(mlnid, lsize*3, 3, moab_vert_coords) + if (ierr .ne. 0) & + call shr_sys_abort('Error: fail to create MOAB vertices in data lnd model') + + tagname='GLOBAL_ID'//C_NULL_CHAR + ierr = iMOAB_DefineTagStorage(mlnid, tagname, & + 0, & ! dense, integer + 1, & ! number of components + tagindex ) + if (ierr .ne. 0) & + call shr_sys_abort('Error: fail to retrieve GLOBAL_ID tag ') + + ! get list of global IDs for Dofs + call mct_gsMap_orderedPoints(gsMap, my_task, idata) + + ierr = iMOAB_SetIntTagStorage ( mlnid, tagname, lsize, & + 0, & ! vertex type + idata) + if (ierr .ne. 0) & + call shr_sys_abort('Error: fail to set GLOBAL_ID tag ') + + ierr = iMOAB_ResolveSharedEntities( mlnid, lsize, idata ); + if (ierr .ne. 0) & + call shr_sys_abort('Error: fail to resolve shared entities') + + deallocate(moab_vert_coords) + deallocate(idata) + + ierr = iMOAB_UpdateMeshInfo( mlnid ) + if (ierr .ne. 0) & + call shr_sys_abort('Error: fail to update mesh info ') + + allocate(data(lsize)) + ierr = iMOAB_DefineTagStorage( mlnid, "area:aream:frac:mask"//C_NULL_CHAR, & + 1, & ! dense, double + 1, & ! number of components + tagindex ) + if (ierr > 0 ) & + call shr_sys_abort('Error: fail to create tag: area:aream:frac:mask' ) + + data(:) = ggrid%data%rAttr(mct_aVect_indexRA(ggrid%data,'area'),:) + tagname='area'//C_NULL_CHAR + ierr = iMOAB_SetDoubleTagStorage ( mlnid, tagname, lsize, & + 0, & ! set data on vertices + data) + if (ierr > 0 ) & + call shr_sys_abort('Error: fail to get area tag ') + + ! set the same data for aream (model area) as area + ! data(:) = ggrid%data%rAttr(mct_aVect_indexRA(ggrid%data,'aream'),:) + tagname='aream'//C_NULL_CHAR + ierr = iMOAB_SetDoubleTagStorage ( mlnid, tagname, lsize, & + 0, & ! set data on vertices + data) + if (ierr > 0 ) & + call shr_sys_abort('Error: fail to set aream tag ') + + data(:) = ggrid%data%rAttr(mct_aVect_indexRA(ggrid%data,'mask'),:) + tagname='mask'//C_NULL_CHAR + ierr = iMOAB_SetDoubleTagStorage ( mlnid, tagname, lsize, & + 0, & ! set data on vertices + data) + if (ierr > 0 ) & + call shr_sys_abort('Error: fail to set mask tag ') + + data(:) = ggrid%data%rAttr(mct_aVect_indexRA(ggrid%data,'frac'),:) + tagname='frac'//C_NULL_CHAR + ierr = iMOAB_SetDoubleTagStorage ( mlnid, tagname, lsize, & + 0, & ! set data on vertices + data) + if (ierr > 0 ) & + call shr_sys_abort('Error: fail to set frac tag ') + + deallocate(data) + + ! define tags + ierr = iMOAB_DefineTagStorage( mlnid, trim(seq_flds_x2l_fields)//C_NULL_CHAR, & + 1, & ! dense, double + 1, & ! number of components + tagindex ) + if (ierr > 0 ) & + call shr_sys_abort('Error: fail to create seq_flds_x2l_fields tags ') + + ierr = iMOAB_DefineTagStorage( mlnid, trim(seq_flds_l2x_fields)//C_NULL_CHAR, & + 1, & ! dense, double + 1, & ! number of components + tagindex ) + if (ierr > 0 ) & + call shr_sys_abort('Error: fail to create seq_flds_l2x_fields tags ') +#ifdef MOABDEBUG + ! debug test + outfile = 'LndDataMesh.h5m'//C_NULL_CHAR + wopts = ';PARALLEL=WRITE_PART'//C_NULL_CHAR ! + ! write out the mesh file to disk + ierr = iMOAB_WriteMesh(mlnid, trim(outfile), trim(wopts)) + if (ierr .ne. 0) then + call shr_sys_abort(subname//' ERROR in writing data mesh lnd ') + endif +#endif +#endif !---------------------------------------------------------------------------- ! Initialize MCT attribute vectors !---------------------------------------------------------------------------- @@ -339,8 +477,15 @@ subroutine dlnd_comp_run(EClock, x2l, l2x, & inst_suffix, logunit, case_name) ! !DESCRIPTION: run method for dlnd model - implicit none +#ifdef HAVE_MOAB +#ifdef MOABDEBUG + use iMOAB, only: iMOAB_WriteMesh +#endif + use seq_flds_mod , only: seq_flds_l2x_fields + use seq_flds_mod , only: moab_set_tag_from_av +#endif + implicit none ! !INPUT/OUTPUT PARAMETERS: type(ESMF_Clock) , intent(in) :: EClock type(mct_aVect) , intent(inout) :: x2l @@ -366,6 +511,17 @@ subroutine dlnd_comp_run(EClock, x2l, l2x, & integer(IN) :: nu ! unit number logical :: write_restart ! restart now character(len=18) :: date_str +#ifdef HAVE_MOAB + real(R8), allocatable, target :: datam(:) + type(mct_list) :: temp_list + integer :: size_list, index_list, lsize + type(mct_string) :: mctOStr ! + character*400 tagname, mct_field +#ifdef MOABDEBUG + integer :: cur_dlnd_stepno, ierr + character*100 outfile, wopts, lnum +#endif +#endif character(*), parameter :: F00 = "('(dlnd_comp_run) ',8a)" character(*), parameter :: F04 = "('(dlnd_comp_run) ',2a,2i8,'s')" @@ -464,6 +620,32 @@ subroutine dlnd_comp_run(EClock, x2l, l2x, & call t_stopf('DLND_RUN') +#ifdef HAVE_MOAB + lsize = mct_avect_lsize(l2x) ! is it the same as mct_avect_lsize(avstrm) ? + allocate(datam(lsize)) ! + call mct_list_init(temp_list ,seq_flds_l2x_fields) + size_list=mct_list_nitem (temp_list) + do index_list = 1, size_list + call mct_list_get(mctOStr,index_list,temp_list) + mct_field = mct_string_toChar(mctOStr) + tagname= trim(mct_field)//C_NULL_CHAR + call moab_set_tag_from_av(tagname, l2x, index_list, mlnid, datam, lsize) ! loop over all a2x fields, not just a few + enddo + call mct_list_clean(temp_list) + deallocate(datam) ! maybe we should keep it around, deallocate at the final only? + +#ifdef MOABDEBUG + call seq_timemgr_EClockGetData( EClock, stepno=cur_dlnd_stepno ) + write(lnum,"(I0.2)")cur_dlnd_stepno + outfile = 'dlnd_comp_run_'//trim(lnum)//'.h5m'//C_NULL_CHAR + wopts = 'PARALLEL=WRITE_PART'//C_NULL_CHAR + ierr = iMOAB_WriteMesh(mlnid, outfile, wopts) + if (ierr > 0 ) then + write(logunit,*) 'Failed to write data lnd component state ' + endif +#endif +#endif + end subroutine dlnd_comp_run !=============================================================================== diff --git a/components/data_comps/dlnd/src/lnd_comp_mct.F90 b/components/data_comps/dlnd/src/lnd_comp_mct.F90 index f5193ca84580..b699ec217f00 100644 --- a/components/data_comps/dlnd/src/lnd_comp_mct.F90 +++ b/components/data_comps/dlnd/src/lnd_comp_mct.F90 @@ -16,7 +16,11 @@ module lnd_comp_mct use dlnd_comp_mod , only: dlnd_comp_init, dlnd_comp_run, dlnd_comp_final use dlnd_shr_mod , only: dlnd_shr_read_namelists use seq_flds_mod , only: seq_flds_x2l_fields, seq_flds_l2x_fields - +#ifdef HAVE_MOAB + use seq_comm_mct, only : mlnid ! iMOAB app id for lnd + use iso_c_binding + use iMOAB , only: iMOAB_RegisterApplication +#endif ! !PUBLIC TYPES: implicit none private ! except @@ -52,7 +56,9 @@ module lnd_comp_mct !=============================================================================== subroutine lnd_init_mct( EClock, cdata, x2l, l2x, NLFilename ) - +#ifdef HAVE_MOAB + use shr_stream_mod, only: shr_stream_getDomainInfo, shr_stream_getFile +#endif ! !DESCRIPTION: initialize dlnd model implicit none @@ -146,13 +152,25 @@ subroutine lnd_init_mct( EClock, cdata, x2l, l2x, NLFilename ) !---------------------------------------------------------------------------- ! Initialize dlnd !---------------------------------------------------------------------------- - +#ifdef HAVE_MOAB + ierr = iMOAB_RegisterApplication(trim("DLND")//C_NULL_CHAR, mpicom, compid, mlnid) + if (ierr .ne. 0) then + write(logunit,*) subname,' error in registering data lnd comp' + call shr_sys_abort(subname//' ERROR in registering data lnd comp') + endif +#endif call dlnd_comp_init(Eclock, x2l, l2x, & seq_flds_x2l_fields, seq_flds_l2x_fields, & SDLND, gsmap, ggrid, mpicom, compid, my_task, master_task, & inst_suffix, inst_name, logunit, read_restart, & scmMode, scmlat, scmlon) - +#ifdef HAVE_MOAB + if (my_task == master_task) then + call seq_infodata_PutData( infodata, lnd_domain=SDLND%domainFile) ! we use the same one for regular case + ! in regular case, it is copied from fatmlndfrc ; so we don't know if it is data land or not + write(logunit,*), ' use this land domain file: ', SDLND%domainFile + endif +#endif !---------------------------------------------------------------------------- ! Fill infodata that needs to be returned from dlnd !---------------------------------------------------------------------------- diff --git a/components/data_comps/docn/cime_config/config_component.xml b/components/data_comps/docn/cime_config/config_component.xml index 5a30c69df6cf..431d358f9951 100644 --- a/components/data_comps/docn/cime_config/config_component.xml +++ b/components/data_comps/docn/cime_config/config_component.xml @@ -13,7 +13,7 @@ This file may have ocn desc entries. --> - DOCN + DOCN null mode prescribed ocean mode slab ocean mode @@ -45,7 +45,7 @@ char - prescribed,sst_aquap1,sst_aquap2,sst_aquap3,sst_aquap4,sst_aquap5,sst_aquap6,sst_aquap7,sst_aquap8,sst_aquap9,sst_aquap10,sst_aquapfile,som,som_aquap,sst_aquap_constant,interannual,null + prescribed,sst_aquap1,sst_aquap2,sst_aquap3,sst_aquap4,sst_aquap5,sst_aquap6,sst_aquap7,sst_aquap8,sst_aquap9,sst_aquap10,sst_aquap11,sst_aquap12,sst_aquap13,sst_aquap14,sst_aquap15,sst_aquapfile,som,som_aquap,sst_aquap_constant,interannual,null prescribed null @@ -63,6 +63,12 @@ sst_aquap8 sst_aquap9 sst_aquap10 + + sst_aquap11 + sst_aquap12 + sst_aquap13 + sst_aquap14 + sst_aquap15 sst_aquapfile sst_aquap_constant diff --git a/components/data_comps/docn/cime_config/namelist_definition_docn.xml b/components/data_comps/docn/cime_config/namelist_definition_docn.xml index 948902e37324..a191d088d7f5 100644 --- a/components/data_comps/docn/cime_config/namelist_definition_docn.xml +++ b/components/data_comps/docn/cime_config/namelist_definition_docn.xml @@ -257,7 +257,7 @@ char streams shr_strdata_nml - SSTDATA,SST_AQUAP1,SST_AQUAP2,SST_AQUAP3,SST_AQUAP4,SST_AQUAP5,SST_AQUAP6,SST_AQUAP7,SST_AQUAP8,SST_AQUAP9,SST_AQUAP10,SST_AQUAPFILE,SST_AQUAP_CONSTANT,SOM,SOM_AQUAP,IAF,NULL,COPYALL + SSTDATA,SST_AQUAP1,SST_AQUAP2,SST_AQUAP3,SST_AQUAP4,SST_AQUAP5,SST_AQUAP6,SST_AQUAP7,SST_AQUAP8,SST_AQUAP9,SST_AQUAP10,SST_AQUAP11,SST_AQUAP12,SST_AQUAP13,SST_AQUAP14,SST_AQUAP15,SST_AQUAPFILE,SST_AQUAP_CONSTANT,SOM,SOM_AQUAP,IAF,NULL,COPYALL General method that operates on the data. This is generally implemented in the data models but is set in the strdata method for @@ -323,6 +323,11 @@ SST_AQUAP8 SST_AQUAP9 SST_AQUAP10 + SST_AQUAP11 + SST_AQUAP12 + SST_AQUAP13 + SST_AQUAP14 + SST_AQUAP15 SST_AQUAPFILE SST_AQUAP_CONSTANT SOM diff --git a/components/data_comps/docn/src/docn_comp_mod.F90 b/components/data_comps/docn/src/docn_comp_mod.F90 index e692882c9db1..43bac32bff73 100644 --- a/components/data_comps/docn/src/docn_comp_mod.F90 +++ b/components/data_comps/docn/src/docn_comp_mod.F90 @@ -984,6 +984,7 @@ subroutine prescribed_sst(xc, yc, lsize, sst_option, sst) integer :: i real(r8) :: tmp, tmp1, pi real(r8) :: rlon(lsize), rlat(lsize) + real(r8) :: mean_SST, delta_SST real(r8), parameter :: pio180 = SHR_CONST_PI/180._r8 @@ -1013,8 +1014,8 @@ subroutine prescribed_sst(xc, yc, lsize, sst_option, sst) ! Control - if (sst_option < 1 .or. sst_option > 10) then - call shr_sys_abort ('prescribed_sst: ERROR: sst_option must be between 1 and 10') + if (sst_option < 1 .or. sst_option > 15) then + call shr_sys_abort ('prescribed_sst: ERROR: sst_option must be between 1 and 15') end if if (sst_option == 1 .or. sst_option == 6 .or. sst_option == 7 .or. sst_option == 8) then @@ -1174,6 +1175,20 @@ subroutine prescribed_sst(xc, yc, lsize, sst_option, sst) end do end if + !------------------------------------------------------------------------------- + ! RCEMIP phase 2 - Mock-Walker + if (sst_option>=11 .and. sst_option<=15) then + if (sst_option==11) then; mean_SST = 295 - TkFrz; delta_SST = 1.250; end if ! MW_295dT1p25 + if (sst_option==12) then; mean_SST = 300 - TkFrz; delta_SST = 0.625; end if ! MW_300dT0p625 + if (sst_option==13) then; mean_SST = 300 - TkFrz; delta_SST = 1.250; end if ! MW_300dT1p25 + if (sst_option==14) then; mean_SST = 300 - TkFrz; delta_SST = 2.500; end if ! MW_300dT2p5 + if (sst_option==15) then; mean_SST = 305 - TkFrz; delta_SST = 1.250; end if ! MW_305dT1p25 + do i = 1, lsize + sst(i) = mean_SST + (delta_SST/2) * cos( rlat(i) * 360/54 ) + end do + end if + !------------------------------------------------------------------------------- + end subroutine prescribed_sst end module docn_comp_mod diff --git a/components/eam/bld/namelist_files/namelist_definition.xml b/components/eam/bld/namelist_files/namelist_definition.xml index b3ecb5e9290a..8228c7d8d2e3 100644 --- a/components/eam/bld/namelist_files/namelist_definition.xml +++ b/components/eam/bld/namelist_files/namelist_definition.xml @@ -5138,6 +5138,17 @@ Format: YYYY Default: 0 + +The cycle year of the volcanic SO2 forcing (3D emissions) data. +Use this in place of ext_frc_cycle_yr if non-default, to allow different +speciciations volcanic emission and aerosols/precursors, which may be +invoked for single forcing simulation design. +if ext_frc_volc_type is 'CYCLICAL'. +Format: YYYY +Default: -1 + + Default: current model date @@ -5189,6 +5200,13 @@ Can be set to 'CYCLICAL', 'SERIAL', 'INTERP_MISSING_MONTHS', or 'FIXED'. Default: 'CYCLICAL' + +Type of time interpolation for fixed lower boundary data. See also ext_frc_volc_cycle_yr. +Can be set to 'NULL','CYCLICAL', 'SERIAL', 'INTERP_MISSING_MONTHS', or 'FIXED'. +Default: 'NULL' + + The cycle year of the fixed lower boundary data diff --git a/components/eam/bld/namelist_files/use_cases/20TR_eam_CMIP6-GHG_chemUCI-Linoz-mam5-vbs.xml b/components/eam/bld/namelist_files/use_cases/20TR_eam_CMIP6-GHG_chemUCI-Linoz-mam5-vbs.xml new file mode 100644 index 000000000000..cd16d6a0d9a6 --- /dev/null +++ b/components/eam/bld/namelist_files/use_cases/20TR_eam_CMIP6-GHG_chemUCI-Linoz-mam5-vbs.xml @@ -0,0 +1,121 @@ + + + + +.true. + + +.true. +.true. +.true. + + +atm/cam/solar/Solar_1850control_input4MIPS_c20181106.nc +18500101 +FIXED + + +atm/cam/ggas/GHG_CMIP-1-2-0_Annual_Global_0000-2014_c20180105.nc +RAMPED + + +CYCLICAL +1850 +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_NO2_aircraft_vertical_1750-2015_1.9x2.5_c20170608.nc + +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_1850_2014_avg_so2_elev_strat_1850.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/emissions-cmip6_e3sm_SOAG0_elev_1850-2014_1.9x2.5_c20230201.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_bc_a4_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a1_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a2_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a4_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_pom_a4_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a1_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a2_elev_1850-2014_c180205.nc + + +CYCLICAL +1850 +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C2H4_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C2H6_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C3H8_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH2O_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH3CHO_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH3COCH3_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CO_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_ISOP_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_ISOP_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_MTERP_surface_1850-2014_1.9x2.5_c20230126.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_NO_surface_1850-2014_1.9x2.5_c20220425.nc +atm/cam/chem/trop_mozart_aero/emis/DMSflux.1850.1deg_latlon_conserv.POPmonthlyClimFromACES4BGC_c20160416.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/emissions-cmip6_e3sm_SOAG0_surf_1850-2014_1.9x2.5_c20230201.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so2_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_bc_a4_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a1_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a2_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a4_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_pom_a4_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a1_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a2_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions_E90_surface_1750-2015_1.9x2.5_c20210408.nc + + + + +CYCLICAL +1849 +oxid_1.9x2.5_L26_1850-2015_c20181106.nc +'' +atm/cam/chem/trop_mozart_aero/oxid +'prsd_O3:O3','prsd_NO3:NO3','prsd_OH:OH' + + +ch4_oxid_1.9x2.5_L26_1990-1999clim.c090804.nc +atm/cam/chem/methane +CYCLICAL +1995 +'' +'prsd_ch4:CH4' + + + + 'A:H2OLNZ:H2O', 'N:O2:O2', 'N:CO2:CO2', + 'A:O3:O3', 'A:N2OLNZ:N2O', 'A:CH4LNZ:CH4', + 'N:CFC11:CFC11', 'N:CFC12:CFC12', + 'M:mam5_mode1:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode1_rrtmg_aeronetdust_c141106.nc', + 'M:mam5_mode2:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode2_rrtmg_c130628.nc', + 'M:mam5_mode3:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode3_rrtmg_aeronetdust_c141106.nc', + 'M:mam5_mode4:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode4_rrtmg_c130628.nc', + 'M:mam5_mode5:$INPUTDATA_ROOT/atm/cam/physprops/mam5_mode5_rrtmg_sig1.2_dgnl.40_c03072023.nc' + + + +3 +1 +'atm/cam/chem/trop_mam/marine_BGC/' +'CYCLICAL' +'monthly_macromolecules_0.1deg_bilinear_latlon_year01_merge_date.nc' +0 +0 +'chla:CHL1','mpoly:TRUEPOLYC','mprot:TRUEPROTC','mlip:TRUELIPC' + + +atm/cam/chem/trop_mozart/ub/Linoz_Chlorine_Loading_CMIP6_0003-2017_c20171114.nc +18500101 +FIXED +1850 +linv3_1849-2017_CMIP6_Hist_10deg_58km_c20230705.nc +atm/cam/chem/trop_mozart/ub +CYCLICAL + + +SERIAL + + +'xactive_lnd' +'O3','H2O2','CH2O','CH3OOH','NO','NO2','HNO3','HO2NO2','PAN','CO','CH3COCH3','C2H5OOH','CH3CHO','H2SO4','SO2','NO3','N2O5','SOAG0','SOAG15','SOAG24','SOAG35','SOAG34','SOAG33','SOAG32','SOAG31' +'NEU' +'C2H5OOH','CH2O','CH3CHO','CH3OOH','H2O2','H2SO4','HNO3','HO2NO2','SO2','SOAG0','SOAG15','SOAG24','SOAG35','SOAG34','SOAG33','SOAG32','SOAG31' +'CH2O', 'CH3O2', 'CH3OOH', 'PAN', 'CO', 'C2H6', 'C3H8', 'C2H4', 'ROHO2', 'CH3COCH3', 'C2H5O2', 'C2H5OOH', 'CH3CHO', 'CH3CO3', 'ISOP', 'ISOPO2', 'MVKMACR', 'MVKO2' +'' + diff --git a/components/eam/bld/namelist_files/use_cases/20TR_eam_CMIP6-LULC_chemUCI-Linoz-mam5-vbs.xml b/components/eam/bld/namelist_files/use_cases/20TR_eam_CMIP6-LULC_chemUCI-Linoz-mam5-vbs.xml new file mode 100644 index 000000000000..e2f53df4dc60 --- /dev/null +++ b/components/eam/bld/namelist_files/use_cases/20TR_eam_CMIP6-LULC_chemUCI-Linoz-mam5-vbs.xml @@ -0,0 +1,124 @@ + + + + +.true. + + +.true. +.true. +.true. + + +atm/cam/solar/Solar_1850control_input4MIPS_c20181106.nc +18500101 +FIXED + + + +808.249e-9 +273.0211e-9 +32.1102e-12 +0.0 + + +CYCLICAL +1850 +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_NO2_aircraft_vertical_1750-2015_1.9x2.5_c20170608.nc + +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_1850_2014_avg_so2_elev_strat_1850.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/emissions-cmip6_e3sm_SOAG0_elev_1850-2014_1.9x2.5_c20230201.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_bc_a4_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a1_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a2_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a4_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_pom_a4_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a1_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a2_elev_1850-2014_c180205.nc + + +CYCLICAL +1850 +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C2H4_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C2H6_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C3H8_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH2O_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH3CHO_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH3COCH3_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CO_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_ISOP_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_ISOP_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_MTERP_surface_1850-2014_1.9x2.5_c20230126.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_NO_surface_1850-2014_1.9x2.5_c20220425.nc +atm/cam/chem/trop_mozart_aero/emis/DMSflux.1850.1deg_latlon_conserv.POPmonthlyClimFromACES4BGC_c20160416.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/emissions-cmip6_e3sm_SOAG0_surf_1850-2014_1.9x2.5_c20230201.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so2_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_bc_a4_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a1_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a2_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a4_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_pom_a4_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a1_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a2_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions_E90_surface_1750-2015_1.9x2.5_c20210408.nc + + + + +CYCLICAL +1849 +oxid_1.9x2.5_L26_1850-2015_c20181106.nc +'' +atm/cam/chem/trop_mozart_aero/oxid +'prsd_O3:O3','prsd_NO3:NO3','prsd_OH:OH' + + +ch4_oxid_1.9x2.5_L26_1990-1999clim.c090804.nc +atm/cam/chem/methane +CYCLICAL +1995 +'' +'prsd_ch4:CH4' + + + + 'A:H2OLNZ:H2O', 'N:O2:O2', 'N:CO2:CO2', + 'A:O3:O3', 'A:N2OLNZ:N2O', 'A:CH4LNZ:CH4', + 'N:CFC11:CFC11', 'N:CFC12:CFC12', + 'M:mam5_mode1:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode1_rrtmg_aeronetdust_c141106.nc', + 'M:mam5_mode2:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode2_rrtmg_c130628.nc', + 'M:mam5_mode3:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode3_rrtmg_aeronetdust_c141106.nc', + 'M:mam5_mode4:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode4_rrtmg_c130628.nc', + 'M:mam5_mode5:$INPUTDATA_ROOT/atm/cam/physprops/mam5_mode5_rrtmg_sig1.2_dgnl.40_c03072023.nc' + + + +3 +1 +'atm/cam/chem/trop_mam/marine_BGC/' +'CYCLICAL' +'monthly_macromolecules_0.1deg_bilinear_latlon_year01_merge_date.nc' +0 +0 +'chla:CHL1','mpoly:TRUEPOLYC','mprot:TRUEPROTC','mlip:TRUELIPC' + + +atm/cam/chem/trop_mozart/ub/Linoz_Chlorine_Loading_CMIP6_0003-2017_c20171114.nc +18500101 +FIXED +1850 +linv3_1849-2017_CMIP6_Hist_10deg_58km_c20230705.nc +atm/cam/chem/trop_mozart/ub +CYCLICAL + + +SERIAL + + +'xactive_lnd' +'O3','H2O2','CH2O','CH3OOH','NO','NO2','HNO3','HO2NO2','PAN','CO','CH3COCH3','C2H5OOH','CH3CHO','H2SO4','SO2','NO3','N2O5','SOAG0','SOAG15','SOAG24','SOAG35','SOAG34','SOAG33','SOAG32','SOAG31' +'NEU' +'C2H5OOH','CH2O','CH3CHO','CH3OOH','H2O2','H2SO4','HNO3','HO2NO2','SO2','SOAG0','SOAG15','SOAG24','SOAG35','SOAG34','SOAG33','SOAG32','SOAG31' +'CH2O', 'CH3O2', 'CH3OOH', 'PAN', 'CO', 'C2H6', 'C3H8', 'C2H4', 'ROHO2', 'CH3COCH3', 'C2H5O2', 'C2H5OOH', 'CH3CHO', 'CH3CO3', 'ISOP', 'ISOPO2', 'MVKMACR', 'MVKO2' +'' + diff --git a/components/eam/bld/namelist_files/use_cases/20TR_eam_CMIP6-aer_chemUCI-Linoz-mam5-vbs.xml b/components/eam/bld/namelist_files/use_cases/20TR_eam_CMIP6-aer_chemUCI-Linoz-mam5-vbs.xml new file mode 100644 index 000000000000..8aedc762728b --- /dev/null +++ b/components/eam/bld/namelist_files/use_cases/20TR_eam_CMIP6-aer_chemUCI-Linoz-mam5-vbs.xml @@ -0,0 +1,119 @@ + + + + +.true. + + +.true. +.true. +.true. + + +atm/cam/solar/Solar_1850control_input4MIPS_c20181106.nc +18500101 +FIXED + + + +808.249e-9 +273.0211e-9 +32.1102e-12 +0.0 + + +INTERP_MISSING_MONTHS +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_NO2_aircraft_vertical_1750-2015_1.9x2.5_c20170608.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so2_elev_1850-2014_c180205_hist-aero_1850-volcano.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/emissions-cmip6_e3sm_SOAG0_elev_1850-2014_1.9x2.5_c20230201.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_bc_a4_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a1_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a2_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a4_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_pom_a4_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a1_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a2_elev_1850-2014_c180205.nc + + +INTERP_MISSING_MONTHS +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C2H4_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C2H6_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C3H8_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH2O_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH3CHO_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH3COCH3_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CO_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_ISOP_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_ISOP_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_MTERP_surface_1850-2014_1.9x2.5_c20230126.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_NO_surface_1850-2014_1.9x2.5_c20220425.nc +atm/cam/chem/trop_mozart_aero/emis/DMSflux.1850-2100.1deg_latlon_conserv.POPmonthlyClimFromACES4BGC_c20160727.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/emissions-cmip6_e3sm_SOAG0_surf_1850-2014_1.9x2.5_c20230201.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so2_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_bc_a4_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a1_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a2_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a4_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_pom_a4_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a1_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a2_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions_E90_surface_1750-2015_1.9x2.5_c20210408.nc + + + + +INTERP_MISSING_MONTHS +oxid_1.9x2.5_L26_1850-2015_c20181106.nc +'' +atm/cam/chem/trop_mozart_aero/oxid +'prsd_O3:O3','prsd_NO3:NO3','prsd_OH:OH' + + +ch4_oxid_1.9x2.5_L26_1990-1999clim.c090804.nc +atm/cam/chem/methane +CYCLICAL +1995 +'' +'prsd_ch4:CH4' + + + + 'A:H2OLNZ:H2O', 'N:O2:O2', 'N:CO2:CO2', + 'A:O3:O3', 'A:N2OLNZ:N2O', 'A:CH4LNZ:CH4', + 'N:CFC11:CFC11', 'N:CFC12:CFC12', + 'M:mam5_mode1:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode1_rrtmg_aeronetdust_c141106.nc', + 'M:mam5_mode2:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode2_rrtmg_c130628.nc', + 'M:mam5_mode3:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode3_rrtmg_aeronetdust_c141106.nc', + 'M:mam5_mode4:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode4_rrtmg_c130628.nc', + 'M:mam5_mode5:$INPUTDATA_ROOT/atm/cam/physprops/mam5_mode5_rrtmg_sig1.2_dgnl.40_c03072023.nc' + + + +3 +1 +'atm/cam/chem/trop_mam/marine_BGC/' +'CYCLICAL' +'monthly_macromolecules_0.1deg_bilinear_latlon_year01_merge_date.nc' +0 +0 +'chla:CHL1','mpoly:TRUEPOLYC','mprot:TRUEPROTC','mlip:TRUELIPC' + +atm/cam/chem/trop_mozart/ub/Linoz_Chlorine_Loading_CMIP6_0003-2017_c20171114.nc +18500101 +FIXED +1850 +linv3_1849-2017_CMIP6_Hist_10deg_58km_c20230705.nc +atm/cam/chem/trop_mozart/ub +CYCLICAL + + +SERIAL + + +'xactive_lnd' +'O3','H2O2','CH2O','CH3OOH','NO','NO2','HNO3','HO2NO2','PAN','CO','CH3COCH3','C2H5OOH','CH3CHO','H2SO4','SO2','NO3','N2O5','SOAG0','SOAG15','SOAG24','SOAG35','SOAG34','SOAG33','SOAG32','SOAG31' +'NEU' +'C2H5OOH','CH2O','CH3CHO','CH3OOH','H2O2','H2SO4','HNO3','HO2NO2','SO2','SOAG0','SOAG15','SOAG24','SOAG35','SOAG34','SOAG33','SOAG32','SOAG31' +'CH2O', 'CH3O2', 'CH3OOH', 'PAN', 'CO', 'C2H6', 'C3H8', 'C2H4', 'ROHO2', 'CH3COCH3', 'C2H5O2', 'C2H5OOH', 'CH3CHO', 'CH3CO3', 'ISOP', 'ISOPO2', 'MVKMACR', 'MVKO2' +'' + diff --git a/components/eam/bld/namelist_files/use_cases/20TR_eam_CMIP6-nat_chemUCI-Linoz-mam5-vbs.xml b/components/eam/bld/namelist_files/use_cases/20TR_eam_CMIP6-nat_chemUCI-Linoz-mam5-vbs.xml new file mode 100644 index 000000000000..493affd96414 --- /dev/null +++ b/components/eam/bld/namelist_files/use_cases/20TR_eam_CMIP6-nat_chemUCI-Linoz-mam5-vbs.xml @@ -0,0 +1,123 @@ + + + + +.true. + + +.true. +.true. +.true. + + +atm/cam/solar/Solar_1850-2299_input4MIPS_c20181106.nc +SERIAL + + + +808.249e-9 +273.0211e-9 +32.1102e-12 +0.0 + + + +INTERP_MISSING_MONTHS +CYCLICAL +1850 +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_NO2_aircraft_vertical_1750-2015_1.9x2.5_c20170608.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so2_elev_1850-2014_c180205_1850-aero_hist-volcano.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/emissions-cmip6_e3sm_SOAG0_elev_1850-2014_1.9x2.5_c20230201.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_bc_a4_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a1_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a2_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a4_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_pom_a4_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a1_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a2_elev_1850-2014_c180205.nc + + +CYCLICAL +1850 +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C2H4_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C2H6_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C3H8_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH2O_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH3CHO_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH3COCH3_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CO_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_ISOP_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_ISOP_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_MTERP_surface_1850-2014_1.9x2.5_c20230126.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_NO_surface_1850-2014_1.9x2.5_c20220425.nc +atm/cam/chem/trop_mozart_aero/emis/DMSflux.1850.1deg_latlon_conserv.POPmonthlyClimFromACES4BGC_c20160416.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/emissions-cmip6_e3sm_SOAG0_surf_1850-2014_1.9x2.5_c20230201.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so2_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_bc_a4_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a1_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a2_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a4_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_pom_a4_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a1_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a2_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions_E90_surface_1750-2015_1.9x2.5_c20210408.nc + + + + +CYCLICAL +1849 +oxid_1.9x2.5_L26_1850-2015_c20181106.nc +'' +atm/cam/chem/trop_mozart_aero/oxid +'prsd_O3:O3','prsd_NO3:NO3','prsd_OH:OH' + + +ch4_oxid_1.9x2.5_L26_1990-1999clim.c090804.nc +atm/cam/chem/methane +CYCLICAL +1995 +'' +'prsd_ch4:CH4' + + + + 'A:H2OLNZ:H2O', 'N:O2:O2', 'N:CO2:CO2', + 'A:O3:O3', 'A:N2OLNZ:N2O', 'A:CH4LNZ:CH4', + 'N:CFC11:CFC11', 'N:CFC12:CFC12', + 'M:mam5_mode1:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode1_rrtmg_aeronetdust_c141106.nc', + 'M:mam5_mode2:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode2_rrtmg_c130628.nc', + 'M:mam5_mode3:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode3_rrtmg_aeronetdust_c141106.nc', + 'M:mam5_mode4:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode4_rrtmg_c130628.nc', + 'M:mam5_mode5:$INPUTDATA_ROOT/atm/cam/physprops/mam5_mode5_rrtmg_sig1.2_dgnl.40_c03072023.nc' + + + +3 +1 +'atm/cam/chem/trop_mam/marine_BGC/' +'CYCLICAL' +'monthly_macromolecules_0.1deg_bilinear_latlon_year01_merge_date.nc' +0 +0 +'chla:CHL1','mpoly:TRUEPOLYC','mprot:TRUEPROTC','mlip:TRUELIPC' + +atm/cam/chem/trop_mozart/ub/Linoz_Chlorine_Loading_CMIP6_0003-2017_c20171114.nc +18500101 +FIXED +1850 +linv3_1849-2017_CMIP6_Hist_10deg_58km_c20230705.nc +atm/cam/chem/trop_mozart/ub +CYCLICAL + + +SERIAL + + +'xactive_lnd' +'O3','H2O2','CH2O','CH3OOH','NO','NO2','HNO3','HO2NO2','PAN','CO','CH3COCH3','C2H5OOH','CH3CHO','H2SO4','SO2','NO3','N2O5','SOAG0','SOAG15','SOAG24','SOAG35','SOAG34','SOAG33','SOAG32','SOAG31' +'NEU' +'C2H5OOH','CH2O','CH3CHO','CH3OOH','H2O2','H2SO4','HNO3','HO2NO2','SO2','SOAG0','SOAG15','SOAG24','SOAG35','SOAG34','SOAG33','SOAG32','SOAG31' +'CH2O', 'CH3O2', 'CH3OOH', 'PAN', 'CO', 'C2H6', 'C3H8', 'C2H4', 'ROHO2', 'CH3COCH3', 'C2H5O2', 'C2H5OOH', 'CH3CHO', 'CH3CO3', 'ISOP', 'ISOPO2', 'MVKMACR', 'MVKO2' +'' + diff --git a/components/eam/bld/namelist_files/use_cases/20TR_eam_CMIP6-ozone_chemUCI-Linoz-mam5-vbs.xml b/components/eam/bld/namelist_files/use_cases/20TR_eam_CMIP6-ozone_chemUCI-Linoz-mam5-vbs.xml new file mode 100644 index 000000000000..58f69d8fe97f --- /dev/null +++ b/components/eam/bld/namelist_files/use_cases/20TR_eam_CMIP6-ozone_chemUCI-Linoz-mam5-vbs.xml @@ -0,0 +1,121 @@ + + + + +.true. + + +.true. +.true. +.true. + + +atm/cam/solar/Solar_1850control_input4MIPS_c20181106.nc +18500101 +FIXED + + + +808.249e-9 +273.0211e-9 +32.1102e-12 +0.0 + + + +CYCLICAL +1850 +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_NO2_aircraft_vertical_1750-2015_1.9x2.5_c20170608.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_1850_2014_avg_so2_elev_strat_1850.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/emissions-cmip6_e3sm_SOAG0_elev_1850-2014_1.9x2.5_c20230201.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_bc_a4_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a1_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a2_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a4_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_pom_a4_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a1_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a2_elev_1850-2014_c180205.nc + + +CYCLICAL +1850 +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C2H4_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C2H6_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C3H8_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH2O_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH3CHO_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH3COCH3_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CO_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_ISOP_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_ISOP_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_MTERP_surface_1850-2014_1.9x2.5_c20230126.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_NO_surface_1850-2014_1.9x2.5_c20220425.nc +atm/cam/chem/trop_mozart_aero/emis/DMSflux.1850.1deg_latlon_conserv.POPmonthlyClimFromACES4BGC_c20160416.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/emissions-cmip6_e3sm_SOAG0_surf_1850-2014_1.9x2.5_c20230201.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so2_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_bc_a4_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a1_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a2_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a4_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_pom_a4_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a1_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a2_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions_E90_surface_1750-2015_1.9x2.5_c20210408.nc + + + + +CYCLICAL +1849 +oxid_1.9x2.5_L26_1850-2015_c20181106.nc +'' +atm/cam/chem/trop_mozart_aero/oxid +'prsd_O3:O3','prsd_NO3:NO3','prsd_OH:OH' + + +ch4_oxid_1.9x2.5_L26_1990-1999clim.c090804.nc +atm/cam/chem/methane +CYCLICAL +1995 +'' +'prsd_ch4:CH4' + + + + 'A:H2OLNZ:H2O', 'N:O2:O2', 'N:CO2:CO2', + 'A:O3:O3', 'A:N2OLNZ:N2O', 'A:CH4LNZ:CH4', + 'N:CFC11:CFC11', 'N:CFC12:CFC12', + 'M:mam5_mode1:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode1_rrtmg_aeronetdust_c141106.nc', + 'M:mam5_mode2:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode2_rrtmg_c130628.nc', + 'M:mam5_mode3:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode3_rrtmg_aeronetdust_c141106.nc', + 'M:mam5_mode4:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode4_rrtmg_c130628.nc', + 'M:mam5_mode5:$INPUTDATA_ROOT/atm/cam/physprops/mam5_mode5_rrtmg_sig1.2_dgnl.40_c03072023.nc' + + + +3 +1 +'atm/cam/chem/trop_mam/marine_BGC/' +'CYCLICAL' +'monthly_macromolecules_0.1deg_bilinear_latlon_year01_merge_date.nc' +0 +0 +'chla:CHL1','mpoly:TRUEPOLYC','mprot:TRUEPROTC','mlip:TRUELIPC' + +atm/cam/chem/trop_mozart/ub/Linoz_Chlorine_Loading_CMIP6_0003-2017_c20171114.nc +SERIAL +linv3_1849-2017_CMIP6_Hist_10deg_58km_c20230705.nc +atm/cam/chem/trop_mozart/ub +INTERP_MISSING_MONTHS + + +SERIAL + + +'xactive_lnd' +'O3','H2O2','CH2O','CH3OOH','NO','NO2','HNO3','HO2NO2','PAN','CO','CH3COCH3','C2H5OOH','CH3CHO','H2SO4','SO2','NO3','N2O5','SOAG0','SOAG15','SOAG24','SOAG35','SOAG34','SOAG33','SOAG32','SOAG31' +'NEU' +'C2H5OOH','CH2O','CH3CHO','CH3OOH','H2O2','H2SO4','HNO3','HO2NO2','SO2','SOAG0','SOAG15','SOAG24','SOAG35','SOAG34','SOAG33','SOAG32','SOAG31' +'CH2O', 'CH3O2', 'CH3OOH', 'PAN', 'CO', 'C2H6', 'C3H8', 'C2H4', 'ROHO2', 'CH3COCH3', 'C2H5O2', 'C2H5OOH', 'CH3CHO', 'CH3CO3', 'ISOP', 'ISOPO2', 'MVKMACR', 'MVKO2' +'' + diff --git a/components/eam/bld/namelist_files/use_cases/20TR_eam_CMIP6-volc_chemUCI-Linoz-mam5-vbs.xml b/components/eam/bld/namelist_files/use_cases/20TR_eam_CMIP6-volc_chemUCI-Linoz-mam5-vbs.xml new file mode 100644 index 000000000000..83d4c4d92717 --- /dev/null +++ b/components/eam/bld/namelist_files/use_cases/20TR_eam_CMIP6-volc_chemUCI-Linoz-mam5-vbs.xml @@ -0,0 +1,124 @@ + + + + +.true. + + +.true. +.true. +.true. + + +atm/cam/solar/Solar_1850control_input4MIPS_c20181106.nc +18500101 +FIXED + + + +808.249e-9 +273.0211e-9 +32.1102e-12 +0.0 + + + +INTERP_MISSING_MONTHS +CYCLICAL +1850 +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_NO2_aircraft_vertical_1750-2015_1.9x2.5_c20170608.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so2_elev_1850-2014_c180205_1850-aero_hist-volcano.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/emissions-cmip6_e3sm_SOAG0_elev_1850-2014_1.9x2.5_c20230201.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_bc_a4_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a1_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a2_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a4_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_pom_a4_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a1_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a2_elev_1850-2014_c180205.nc + + +CYCLICAL +1850 +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C2H4_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C2H6_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C3H8_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH2O_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH3CHO_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH3COCH3_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CO_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_ISOP_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_ISOP_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_MTERP_surface_1850-2014_1.9x2.5_c20230126.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_NO_surface_1850-2014_1.9x2.5_c20220425.nc +atm/cam/chem/trop_mozart_aero/emis/DMSflux.1850.1deg_latlon_conserv.POPmonthlyClimFromACES4BGC_c20160416.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/emissions-cmip6_e3sm_SOAG0_surf_1850-2014_1.9x2.5_c20230201.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so2_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_bc_a4_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a1_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a2_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a4_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_pom_a4_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a1_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a2_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions_E90_surface_1750-2015_1.9x2.5_c20210408.nc + + + + +CYCLICAL +1849 +oxid_1.9x2.5_L26_1850-2015_c20181106.nc +'' +atm/cam/chem/trop_mozart_aero/oxid +'prsd_O3:O3','prsd_NO3:NO3','prsd_OH:OH' + + +ch4_oxid_1.9x2.5_L26_1990-1999clim.c090804.nc +atm/cam/chem/methane +CYCLICAL +1995 +'' +'prsd_ch4:CH4' + + + + 'A:H2OLNZ:H2O', 'N:O2:O2', 'N:CO2:CO2', + 'A:O3:O3', 'A:N2OLNZ:N2O', 'A:CH4LNZ:CH4', + 'N:CFC11:CFC11', 'N:CFC12:CFC12', + 'M:mam5_mode1:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode1_rrtmg_aeronetdust_c141106.nc', + 'M:mam5_mode2:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode2_rrtmg_c130628.nc', + 'M:mam5_mode3:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode3_rrtmg_aeronetdust_c141106.nc', + 'M:mam5_mode4:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode4_rrtmg_c130628.nc', + 'M:mam5_mode5:$INPUTDATA_ROOT/atm/cam/physprops/mam5_mode5_rrtmg_sig1.2_dgnl.40_c03072023.nc' + + + +3 +1 +'atm/cam/chem/trop_mam/marine_BGC/' +'CYCLICAL' +'monthly_macromolecules_0.1deg_bilinear_latlon_year01_merge_date.nc' +0 +0 +'chla:CHL1','mpoly:TRUEPOLYC','mprot:TRUEPROTC','mlip:TRUELIPC' + +atm/cam/chem/trop_mozart/ub/Linoz_Chlorine_Loading_CMIP6_0003-2017_c20171114.nc +18500101 +FIXED +1850 +linv3_1849-2017_CMIP6_Hist_10deg_58km_c20230705.nc +atm/cam/chem/trop_mozart/ub +CYCLICAL + + +SERIAL + + +'xactive_lnd' +'O3','H2O2','CH2O','CH3OOH','NO','NO2','HNO3','HO2NO2','PAN','CO','CH3COCH3','C2H5OOH','CH3CHO','H2SO4','SO2','NO3','N2O5','SOAG0','SOAG15','SOAG24','SOAG35','SOAG34','SOAG33','SOAG32','SOAG31' +'NEU' +'C2H5OOH','CH2O','CH3CHO','CH3OOH','H2O2','H2SO4','HNO3','HO2NO2','SO2','SOAG0','SOAG15','SOAG24','SOAG35','SOAG34','SOAG33','SOAG32','SOAG31' +'CH2O', 'CH3O2', 'CH3OOH', 'PAN', 'CO', 'C2H6', 'C3H8', 'C2H4', 'ROHO2', 'CH3COCH3', 'C2H5O2', 'C2H5OOH', 'CH3CHO', 'CH3CO3', 'ISOP', 'ISOPO2', 'MVKMACR', 'MVKO2' +'' + diff --git a/components/eam/bld/namelist_files/use_cases/20TR_eam_CMIP6-xGHG-xaer_chemUCI-Linoz-mam5-vbs.xml b/components/eam/bld/namelist_files/use_cases/20TR_eam_CMIP6-xGHG-xaer_chemUCI-Linoz-mam5-vbs.xml new file mode 100644 index 000000000000..671eb826ef14 --- /dev/null +++ b/components/eam/bld/namelist_files/use_cases/20TR_eam_CMIP6-xGHG-xaer_chemUCI-Linoz-mam5-vbs.xml @@ -0,0 +1,121 @@ + + + + +.true. + + +.true. +.true. +.true. + + +atm/cam/solar/Solar_1850-2299_input4MIPS_c20181106.nc +SERIAL + + + +808.249e-9 +273.0211e-9 +32.1102e-12 +0.0 + + + +INTERP_MISSING_MONTHS +CYCLICAL +1850 +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_NO2_aircraft_vertical_1750-2015_1.9x2.5_c20170608.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so2_elev_1850-2014_c180205_1850-aero_hist-volcano.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/emissions-cmip6_e3sm_SOAG0_elev_1850-2014_1.9x2.5_c20230201.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_bc_a4_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a1_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a2_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a4_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_pom_a4_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a1_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a2_elev_1850-2014_c180205.nc + + +CYCLICAL +1850 +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C2H4_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C2H6_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C3H8_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH2O_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH3CHO_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH3COCH3_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CO_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_ISOP_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_ISOP_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_MTERP_surface_1850-2014_1.9x2.5_c20230126.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_NO_surface_1850-2014_1.9x2.5_c20220425.nc +atm/cam/chem/trop_mozart_aero/emis/DMSflux.1850.1deg_latlon_conserv.POPmonthlyClimFromACES4BGC_c20160416.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/emissions-cmip6_e3sm_SOAG0_surf_1850-2014_1.9x2.5_c20230201.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so2_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_bc_a4_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a1_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a2_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a4_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_pom_a4_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a1_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a2_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions_E90_surface_1750-2015_1.9x2.5_c20210408.nc + + + + +CYCLICAL +1849 +oxid_1.9x2.5_L26_1850-2015_c20181106.nc +'' +atm/cam/chem/trop_mozart_aero/oxid +'prsd_O3:O3','prsd_NO3:NO3','prsd_OH:OH' + + +ch4_oxid_1.9x2.5_L26_1990-1999clim.c090804.nc +atm/cam/chem/methane +CYCLICAL +1995 +'' +'prsd_ch4:CH4' + + + + 'A:H2OLNZ:H2O', 'N:O2:O2', 'N:CO2:CO2', + 'A:O3:O3', 'A:N2OLNZ:N2O', 'A:CH4LNZ:CH4', + 'N:CFC11:CFC11', 'N:CFC12:CFC12', + 'M:mam5_mode1:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode1_rrtmg_aeronetdust_c141106.nc', + 'M:mam5_mode2:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode2_rrtmg_c130628.nc', + 'M:mam5_mode3:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode3_rrtmg_aeronetdust_c141106.nc', + 'M:mam5_mode4:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode4_rrtmg_c130628.nc', + 'M:mam5_mode5:$INPUTDATA_ROOT/atm/cam/physprops/mam5_mode5_rrtmg_sig1.2_dgnl.40_c03072023.nc' + + + +3 +1 +'atm/cam/chem/trop_mam/marine_BGC/' +'CYCLICAL' +'monthly_macromolecules_0.1deg_bilinear_latlon_year01_merge_date.nc' +0 +0 +'chla:CHL1','mpoly:TRUEPOLYC','mprot:TRUEPROTC','mlip:TRUELIPC' + +atm/cam/chem/trop_mozart/ub/Linoz_Chlorine_Loading_CMIP6_0003-2017_c20171114.nc +SERIAL +linv3_1849-2017_CMIP6_Hist_10deg_58km_c20230705.nc +atm/cam/chem/trop_mozart/ub +INTERP_MISSING_MONTHS + + +SERIAL + + +'xactive_lnd' +'O3','H2O2','CH2O','CH3OOH','NO','NO2','HNO3','HO2NO2','PAN','CO','CH3COCH3','C2H5OOH','CH3CHO','H2SO4','SO2','NO3','N2O5','SOAG0','SOAG15','SOAG24','SOAG35','SOAG34','SOAG33','SOAG32','SOAG31' +'NEU' +'C2H5OOH','CH2O','CH3CHO','CH3OOH','H2O2','H2SO4','HNO3','HO2NO2','SO2','SOAG0','SOAG15','SOAG24','SOAG35','SOAG34','SOAG33','SOAG32','SOAG31' +'CH2O', 'CH3O2', 'CH3OOH', 'PAN', 'CO', 'C2H6', 'C3H8', 'C2H4', 'ROHO2', 'CH3COCH3', 'C2H5O2', 'C2H5OOH', 'CH3CHO', 'CH3CO3', 'ISOP', 'ISOPO2', 'MVKMACR', 'MVKO2' +'' + diff --git a/components/eam/bld/namelist_files/use_cases/20TR_eam_CMIP6-xaer_chemUCI-Linoz-mam5-vbs.xml b/components/eam/bld/namelist_files/use_cases/20TR_eam_CMIP6-xaer_chemUCI-Linoz-mam5-vbs.xml new file mode 100644 index 000000000000..8dd525d7e5d3 --- /dev/null +++ b/components/eam/bld/namelist_files/use_cases/20TR_eam_CMIP6-xaer_chemUCI-Linoz-mam5-vbs.xml @@ -0,0 +1,118 @@ + + + + +.true. + + +.true. +.true. +.true. + + +atm/cam/solar/Solar_1850-2299_input4MIPS_c20181106.nc +SERIAL + + +atm/cam/ggas/GHG_CMIP-1-2-0_Annual_Global_0000-2014_c20180105.nc +RAMPED + + + +INTERP_MISSING_MONTHS +CYCLICAL +1850 +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_NO2_aircraft_vertical_1750-2015_1.9x2.5_c20170608.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so2_elev_1850-2014_c180205_1850-aero_hist-volcano.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/emissions-cmip6_e3sm_SOAG0_elev_1850-2014_1.9x2.5_c20230201.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_bc_a4_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a1_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a2_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a4_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_pom_a4_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a1_elev_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a2_elev_1850-2014_c180205.nc + + +CYCLICAL +1850 +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C2H4_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C2H6_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C3H8_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH2O_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH3CHO_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH3COCH3_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CO_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_ISOP_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_ISOP_surface_1850-2014_1.9x2.5_c20210323.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_MTERP_surface_1850-2014_1.9x2.5_c20230126.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_NO_surface_1850-2014_1.9x2.5_c20220425.nc +atm/cam/chem/trop_mozart_aero/emis/DMSflux.1850.1deg_latlon_conserv.POPmonthlyClimFromACES4BGC_c20160416.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/emissions-cmip6_e3sm_SOAG0_surf_1850-2014_1.9x2.5_c20230201.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so2_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_bc_a4_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a1_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a2_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a4_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_pom_a4_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a1_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a2_surf_1850-2014_c180205.nc +atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions_E90_surface_1750-2015_1.9x2.5_c20210408.nc + + + + +CYCLICAL +1849 +oxid_1.9x2.5_L26_1850-2015_c20181106.nc +'' +atm/cam/chem/trop_mozart_aero/oxid +'prsd_O3:O3','prsd_NO3:NO3','prsd_OH:OH' + + +ch4_oxid_1.9x2.5_L26_1990-1999clim.c090804.nc +atm/cam/chem/methane +CYCLICAL +1995 +'' +'prsd_ch4:CH4' + + + + 'A:H2OLNZ:H2O', 'N:O2:O2', 'N:CO2:CO2', + 'A:O3:O3', 'A:N2OLNZ:N2O', 'A:CH4LNZ:CH4', + 'N:CFC11:CFC11', 'N:CFC12:CFC12', + 'M:mam5_mode1:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode1_rrtmg_aeronetdust_c141106.nc', + 'M:mam5_mode2:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode2_rrtmg_c130628.nc', + 'M:mam5_mode3:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode3_rrtmg_aeronetdust_c141106.nc', + 'M:mam5_mode4:$INPUTDATA_ROOT/atm/cam/physprops/mam4_mode4_rrtmg_c130628.nc', + 'M:mam5_mode5:$INPUTDATA_ROOT/atm/cam/physprops/mam5_mode5_rrtmg_sig1.2_dgnl.40_c03072023.nc' + + + +3 +1 +'atm/cam/chem/trop_mam/marine_BGC/' +'CYCLICAL' +'monthly_macromolecules_0.1deg_bilinear_latlon_year01_merge_date.nc' +0 +0 +'chla:CHL1','mpoly:TRUEPOLYC','mprot:TRUEPROTC','mlip:TRUELIPC' + +atm/cam/chem/trop_mozart/ub/Linoz_Chlorine_Loading_CMIP6_0003-2017_c20171114.nc +SERIAL +linv3_1849-2017_CMIP6_Hist_10deg_58km_c20230705.nc +atm/cam/chem/trop_mozart/ub +INTERP_MISSING_MONTHS + + +SERIAL + + +'xactive_lnd' +'O3','H2O2','CH2O','CH3OOH','NO','NO2','HNO3','HO2NO2','PAN','CO','CH3COCH3','C2H5OOH','CH3CHO','H2SO4','SO2','NO3','N2O5','SOAG0','SOAG15','SOAG24','SOAG35','SOAG34','SOAG33','SOAG32','SOAG31' +'NEU' +'C2H5OOH','CH2O','CH3CHO','CH3OOH','H2O2','H2SO4','HNO3','HO2NO2','SO2','SOAG0','SOAG15','SOAG24','SOAG35','SOAG34','SOAG33','SOAG32','SOAG31' +'CH2O', 'CH3O2', 'CH3OOH', 'PAN', 'CO', 'C2H6', 'C3H8', 'C2H4', 'ROHO2', 'CH3COCH3', 'C2H5O2', 'C2H5OOH', 'CH3CHO', 'CH3CO3', 'ISOP', 'ISOPO2', 'MVKMACR', 'MVKO2' +'' + diff --git a/components/eam/bld/namelist_files/use_cases/RCEMIP_EAMv1.xml b/components/eam/bld/namelist_files/use_cases/RCEMIP_EAMv1.xml index c1c8e9e027ad..146a9483b36f 100644 --- a/components/eam/bld/namelist_files/use_cases/RCEMIP_EAMv1.xml +++ b/components/eam/bld/namelist_files/use_cases/RCEMIP_EAMv1.xml @@ -35,7 +35,7 @@ 0.0 - + diff --git a/components/eam/cime_config/config_component.xml b/components/eam/cime_config/config_component.xml index 1a961b84affe..785a6469650d 100755 --- a/components/eam/cime_config/config_component.xml +++ b/components/eam/cime_config/config_component.xml @@ -51,9 +51,7 @@ -mach $MACH -phys default - &eamv3_phys_defaults; &eamv3_chem_defaults; - &eamv3_phys_defaults; &eamv3_chem_defaults; - &eamv3_phys_defaults; &eamv3_chem_defaults; + &eamv3_phys_defaults; &eamv3_chem_defaults; -bc_dep_to_snow_updates -co2_cycle @@ -71,14 +69,15 @@ -crm samxx -crm_dt 10 - -crm pam -pam_dycor spam -crm_dt 8 - -crm pam -pam_dycor awfl -crm_dt 8 + -crm pam -pam_dycor spam -crm_dt 10 + -crm pam -pam_dycor awfl -crm_dt 10 -use_MMF -nlev 60 -crm_nz 50 - -crm_dx 2000 -crm_nx 64 -crm_ny 1 + -crm_dx 2000 -crm_nx 64 -crm_ny 1 -crm_nx_rad 4 -crm_ny_rad 1 + -crm_dx 3000 -crm_nx 45 -crm_ny 1 -crm_nx_rad 5 -crm_ny_rad 1 -MMF_microphysics_scheme sam1mom -chem none -MMF_microphysics_scheme p3 -chem none - -crm_nx_rad 4 -crm_ny_rad 1 -rad rrtmgp -rrtmgpxx - -use_MMF_VT + -rad rrtmgp -rrtmgpxx + -use_MMF_VT -use_MMF_ESMT -aquaplanet -aquaplanet -rce @@ -125,6 +124,15 @@ 1850_E3SMv1_superfast_ar5-emis 1850S_E3SMv1_superfast_ar5-emis 20TR_eam_CMIP6_chemUCI-Linoz-mam5-vbs + 20TR_eam_CMIP6_chemUCI-Linoz-mam5-vbs + 20TR_eam_CMIP6-GHG_chemUCI-Linoz-mam5-vbs + 20TR_eam_CMIP6-aer_chemUCI-Linoz-mam5-vbs + 20TR_eam_CMIP6-nat_chemUCI-Linoz-mam5-vbs + 20TR_eam_CMIP6-xGHG-xaer_chemUCI-Linoz-mam5-vbs + 20TR_eam_CMIP6-xaer_chemUCI-Linoz-mam5-vbs + 20TR_eam_CMIP6-ozone_chemUCI-Linoz-mam5-vbs + 20TR_eam_CMIP6-lulc_chemUCI-Linoz-mam5-vbs + 20TR_eam_CMIP6-volc_chemUCI-Linoz-mam5-vbs 20TR_eam_CMIP6_chemUCI-Linoz-mam5-vbs SSP585_eam_CMIP6_chemUCI-Linoz-mam5-vbs SSP370_eam_CMIP6_chemUCI-Linoz-mam5-vbs diff --git a/components/eam/cime_config/config_compsets.xml b/components/eam/cime_config/config_compsets.xml index 39971fbb0945..6b3c41321eea 100644 --- a/components/eam/cime_config/config_compsets.xml +++ b/components/eam/cime_config/config_compsets.xml @@ -229,6 +229,50 @@ 2000_EAM%RCE-MMF2_SLND_SICE_DOCN%AQPCONST_SROF_SGLC_SWAV + + + FRCE-MW_295dT1p25 + 2000_EAM%RCE_SLND_SICE_DOCN%AQP11_SROF_SGLC_SWAV + + + FRCE-MW_300dT0p625 + 2000_EAM%RCE_SLND_SICE_DOCN%AQP12_SROF_SGLC_SWAV + + + FRCE-MW_300dT1p25 + 2000_EAM%RCE_SLND_SICE_DOCN%AQP13_SROF_SGLC_SWAV + + + FRCE-MW_300dT2p5 + 2000_EAM%RCE_SLND_SICE_DOCN%AQP14_SROF_SGLC_SWAV + + + FRCE-MW_305dT1p25 + 2000_EAM%RCE_SLND_SICE_DOCN%AQP15_SROF_SGLC_SWAV + + + + FRCE-MW-MMF1_295dT1p25 + 2000_EAM%RCE-MMF1_SLND_SICE_DOCN%AQP11_SROF_SGLC_SWAV + + + FRCE-MW-MMF1_300dT0p625 + 2000_EAM%RCE-MMF1_SLND_SICE_DOCN%AQP12_SROF_SGLC_SWAV + + + FRCE-MW-MMF1_300dT1p25 + 2000_EAM%RCE-MMF1_SLND_SICE_DOCN%AQP13_SROF_SGLC_SWAV + + + FRCE-MW-MMF1_300dT2p5 + 2000_EAM%RCE-MMF1_SLND_SICE_DOCN%AQP14_SROF_SGLC_SWAV + + + FRCE-MW-MMF1_305dT1p25 + 2000_EAM%RCE-MMF1_SLND_SICE_DOCN%AQP15_SROF_SGLC_SWAV + + + @@ -272,12 +316,12 @@ F20TR-MMF1 - 20TR_EAM%CMIP6-MMF1_ELM%SP_MPASSI%PRES_DOCN%DOM_MOSART_SGLC_SWAV + 20TR_EAM%MMF1_ELM%SP_MPASSI%PRES_DOCN%DOM_MOSART_SGLC_SWAV F20TR-MMF1 - 20TR_EAM%CMIP6-MMF2_ELM%SP_MPASSI%PRES_DOCN%DOM_MOSART_SGLC_SWAV + 20TR_EAM%MMF2_ELM%SP_MPASSI%PRES_DOCN%DOM_MOSART_SGLC_SWAV diff --git a/components/eam/cime_config/config_pes.xml b/components/eam/cime_config/config_pes.xml index 002e41d5a883..2b50fded44a2 100644 --- a/components/eam/cime_config/config_pes.xml +++ b/components/eam/cime_config/config_pes.xml @@ -772,17 +772,17 @@ - - improv pelayout for tri-grid BGC tests with EAM+DOCN - - -4 - -4 - -4 - -4 - -4 - -4 - -4 - -4 + + improv pelayout for any EAM compset on ne30np4.pg2 grid + + -6 + -6 + -6 + -6 + -6 + -6 + -6 + -6 diff --git a/components/eam/cime_config/testdefs/testmods_dirs/eam/wcprod/user_nl_elm b/components/eam/cime_config/testdefs/testmods_dirs/eam/wcprod/user_nl_elm index cd1adab77404..9224c77e0f0a 100644 --- a/components/eam/cime_config/testdefs/testmods_dirs/eam/wcprod/user_nl_elm +++ b/components/eam/cime_config/testdefs/testmods_dirs/eam/wcprod/user_nl_elm @@ -33,7 +33,7 @@ hist_fexcl1 = 'AGWDNPP','ALTMAX_LASTYEAR','AVAIL_RETRANSP','AVAILC','BAF_CROP', 'SOIL4N_vr','SOIL4P_TNDNCY_VERT_TRANS','SOIL4P_TO_SMINP','SOIL4P_vr','SOLUTIONP_vr', 'TCS_MONTH_BEGIN','TCS_MONTH_END','TOTCOLCH4','water_scalar','WF', 'wlim_m','WOODC_LOSS','WTGQ' -hist_fincl1 = 'SNOWDP','COL_FIRE_CLOSS','NPOOL','PPOOL','TOTPRODC' +hist_fincl1 = 'SNOWDP','COL_FIRE_CLOSS','NPOOL','PPOOL','TOTPRODC','LND_FRC_DUST_MBL' hist_fincl2 = 'H2OSNO', 'FSNO', 'QRUNOFF', 'QSNOMELT', 'FSNO_EFF', 'SNORDSL', 'SNOW', 'FSDS', 'FSR', 'FLDS', 'FIRE', 'FIRA' hist_mfilt = 1,365 hist_nhtfrq = -24,-24 diff --git a/components/eam/cime_config/testdefs/testmods_dirs/eam/wcprod_F2010/user_nl_elm b/components/eam/cime_config/testdefs/testmods_dirs/eam/wcprod_F2010/user_nl_elm index cd1adab77404..9224c77e0f0a 100644 --- a/components/eam/cime_config/testdefs/testmods_dirs/eam/wcprod_F2010/user_nl_elm +++ b/components/eam/cime_config/testdefs/testmods_dirs/eam/wcprod_F2010/user_nl_elm @@ -33,7 +33,7 @@ hist_fexcl1 = 'AGWDNPP','ALTMAX_LASTYEAR','AVAIL_RETRANSP','AVAILC','BAF_CROP', 'SOIL4N_vr','SOIL4P_TNDNCY_VERT_TRANS','SOIL4P_TO_SMINP','SOIL4P_vr','SOLUTIONP_vr', 'TCS_MONTH_BEGIN','TCS_MONTH_END','TOTCOLCH4','water_scalar','WF', 'wlim_m','WOODC_LOSS','WTGQ' -hist_fincl1 = 'SNOWDP','COL_FIRE_CLOSS','NPOOL','PPOOL','TOTPRODC' +hist_fincl1 = 'SNOWDP','COL_FIRE_CLOSS','NPOOL','PPOOL','TOTPRODC','LND_FRC_DUST_MBL' hist_fincl2 = 'H2OSNO', 'FSNO', 'QRUNOFF', 'QSNOMELT', 'FSNO_EFF', 'SNORDSL', 'SNOW', 'FSDS', 'FSR', 'FLDS', 'FIRE', 'FIRA' hist_mfilt = 1,365 hist_nhtfrq = -24,-24 diff --git a/components/eam/cime_config/testdefs/testmods_dirs/eam/wcprod_F20TR/user_nl_elm b/components/eam/cime_config/testdefs/testmods_dirs/eam/wcprod_F20TR/user_nl_elm index cd1adab77404..9224c77e0f0a 100644 --- a/components/eam/cime_config/testdefs/testmods_dirs/eam/wcprod_F20TR/user_nl_elm +++ b/components/eam/cime_config/testdefs/testmods_dirs/eam/wcprod_F20TR/user_nl_elm @@ -33,7 +33,7 @@ hist_fexcl1 = 'AGWDNPP','ALTMAX_LASTYEAR','AVAIL_RETRANSP','AVAILC','BAF_CROP', 'SOIL4N_vr','SOIL4P_TNDNCY_VERT_TRANS','SOIL4P_TO_SMINP','SOIL4P_vr','SOLUTIONP_vr', 'TCS_MONTH_BEGIN','TCS_MONTH_END','TOTCOLCH4','water_scalar','WF', 'wlim_m','WOODC_LOSS','WTGQ' -hist_fincl1 = 'SNOWDP','COL_FIRE_CLOSS','NPOOL','PPOOL','TOTPRODC' +hist_fincl1 = 'SNOWDP','COL_FIRE_CLOSS','NPOOL','PPOOL','TOTPRODC','LND_FRC_DUST_MBL' hist_fincl2 = 'H2OSNO', 'FSNO', 'QRUNOFF', 'QSNOMELT', 'FSNO_EFF', 'SNORDSL', 'SNOW', 'FSDS', 'FSR', 'FLDS', 'FIRE', 'FIRA' hist_mfilt = 1,365 hist_nhtfrq = -24,-24 diff --git a/components/eam/cime_config/usermods_dirs/rcemip/user_nl_cpl b/components/eam/cime_config/usermods_dirs/rcemip/user_nl_cpl index 3ecd465f7a14..3a47a8bb2ff9 100644 --- a/components/eam/cime_config/usermods_dirs/rcemip/user_nl_cpl +++ b/components/eam/cime_config/usermods_dirs/rcemip/user_nl_cpl @@ -31,4 +31,5 @@ seq_flux_mct_albdif = 0.07 seq_flux_mct_albdir = 0.07 seq_flux_atmocn_minwind = 1 -constant_zenith_deg = 42.05 \ No newline at end of file +constant_zenith_deg = 42.04 + diff --git a/components/eam/src/chemistry/mozart/chemistry.F90 b/components/eam/src/chemistry/mozart/chemistry.F90 index f78ceda1dea7..3412e1b9bf92 100644 --- a/components/eam/src/chemistry/mozart/chemistry.F90 +++ b/components/eam/src/chemistry/mozart/chemistry.F90 @@ -106,6 +106,13 @@ module chemistry integer :: ext_frc_fixed_ymd = 0 integer :: ext_frc_fixed_tod = 0 + ! alternative type and cycle year for volcanic and other SO2 for controlling single forcing experiments + ! if NULL, same treatment as for the other species. + ! Possible in the future to modify further and apply to volcanic sector of SO2 alone + + character(len=24) :: ext_frc_volc_type = 'NULL' !'NULL'|'CYCLICAL'|'SERIAL'|'INTERP_MISSING_MONTHS' + integer :: ext_frc_volc_cycle_yr = -1 + real(r8) :: dms_emis_scale = 1._r8 ! fixed stratosphere @@ -515,7 +522,7 @@ subroutine chem_readnl(nlfile) srf_emis_type, srf_emis_cycle_yr, srf_emis_fixed_ymd, srf_emis_fixed_tod, srf_emis_specifier, & fstrat_file, fstrat_list, fstrat_efold_list, & ext_frc_specifier, ext_frc_type, ext_frc_cycle_yr, ext_frc_fixed_ymd, ext_frc_fixed_tod, & - dms_emis_scale + ext_frc_volc_type, ext_frc_volc_cycle_yr, dms_emis_scale namelist /chem_inparm/ chem_rad_passive @@ -689,6 +696,8 @@ subroutine chem_readnl(nlfile) call mpibcast (ext_frc_cycle_yr, 1, mpiint, 0, mpicom) call mpibcast (ext_frc_fixed_ymd, 1, mpiint, 0, mpicom) call mpibcast (ext_frc_fixed_tod, 1, mpiint, 0, mpicom) + call mpibcast (ext_frc_volc_type, len(ext_frc_volc_type), mpichar, 0, mpicom) + call mpibcast (ext_frc_volc_cycle_yr, 1, mpiint, 0, mpicom) call mpibcast (dms_emis_scale, 1, mpir8, 0, mpicom) @@ -1033,6 +1042,8 @@ subroutine chem_init(phys_state, pbuf2d, species_class) , ext_frc_cycle_yr & , ext_frc_fixed_ymd & , ext_frc_fixed_tod & + , ext_frc_volc_type & + , ext_frc_volc_cycle_yr & , xactive_prates & , exo_coldens_file & , tuv_xsect_file & diff --git a/components/eam/src/chemistry/mozart/mo_chemini.F90 b/components/eam/src/chemistry/mozart/mo_chemini.F90 index ff0eb0df15f1..564855d76dc5 100644 --- a/components/eam/src/chemistry/mozart/mo_chemini.F90 +++ b/components/eam/src/chemistry/mozart/mo_chemini.F90 @@ -43,6 +43,8 @@ subroutine chemini & , ext_frc_cycle_yr & , ext_frc_fixed_ymd & , ext_frc_fixed_tod & + , ext_frc_volc_type & + , ext_frc_volc_cycle_yr & , xactive_prates & , exo_coldens_file & , tuv_xsect_file & @@ -133,6 +135,8 @@ subroutine chemini & integer, intent(in) :: ext_frc_cycle_yr integer, intent(in) :: ext_frc_fixed_ymd integer, intent(in) :: ext_frc_fixed_tod + character(len=*), intent(in) :: ext_frc_volc_type + integer, intent(in) :: ext_frc_volc_cycle_yr character(len=*), intent(in) :: srf_emis_type integer, intent(in) :: srf_emis_cycle_yr integer, intent(in) :: srf_emis_fixed_ymd @@ -183,7 +187,8 @@ subroutine chemini & ! ... initialize external forcings module !----------------------------------------------------------------------- call setext_inti() - call extfrc_inti(ext_frc_specifier, ext_frc_type, ext_frc_cycle_yr, ext_frc_fixed_ymd, ext_frc_fixed_tod) + call extfrc_inti(ext_frc_specifier, ext_frc_type, ext_frc_cycle_yr, ext_frc_fixed_ymd, ext_frc_fixed_tod, & + ext_frc_volc_type, ext_frc_volc_cycle_yr) if (masterproc) write(iulog,*) 'chemini: after extfrc_inti on node ',iam !----------------------------------------------------------------------- diff --git a/components/eam/src/chemistry/mozart/mo_extfrc.F90 b/components/eam/src/chemistry/mozart/mo_extfrc.F90 index 23b3f480882e..d00e0d5673e9 100644 --- a/components/eam/src/chemistry/mozart/mo_extfrc.F90 +++ b/components/eam/src/chemistry/mozart/mo_extfrc.F90 @@ -46,7 +46,8 @@ module mo_extfrc contains - subroutine extfrc_inti( extfrc_specifier, extfrc_type, extfrc_cycle_yr, extfrc_fixed_ymd, extfrc_fixed_tod) + subroutine extfrc_inti( extfrc_specifier, extfrc_type, extfrc_cycle_yr, extfrc_fixed_ymd, extfrc_fixed_tod, & + extfrc_volc_type, extfrc_volc_cycle_yr) !----------------------------------------------------------------------- ! ... initialize the surface forcings @@ -71,6 +72,8 @@ subroutine extfrc_inti( extfrc_specifier, extfrc_type, extfrc_cycle_yr, extfrc_f integer , intent(in) :: extfrc_cycle_yr integer , intent(in) :: extfrc_fixed_ymd integer , intent(in) :: extfrc_fixed_tod + character(len=*), intent(in) :: extfrc_volc_type + integer , intent(in) :: extfrc_volc_cycle_yr !----------------------------------------------------------------------- ! ... local variables @@ -204,6 +207,14 @@ subroutine extfrc_inti( extfrc_specifier, extfrc_type, extfrc_cycle_yr, extfrc_f else if( extfrc_type == 'CYCLICAL' ) then write(iulog,*) ' cycle year = ',extfrc_cycle_yr end if + if (extfrc_volc_type /= 'NULL' ) then + write(iulog,*) ' ' + write(iulog,*) 'Volcanic SO2 type = ',extfrc_volc_type + if (extfrc_volc_type == 'CYCLICAL' ) then + write(iulog,*) ' ' + write(iulog,*) 'Volcanic SO2 cycle year = ',extfrc_volc_cycle_yr + end if + end if write(iulog,*) ' ' write(iulog,*) 'there are ',extfrc_cnt,' species with external forcing files' do m = 1,extfrc_cnt @@ -264,11 +275,19 @@ subroutine extfrc_inti( extfrc_specifier, extfrc_type, extfrc_cycle_yr, extfrc_f allocate(forcings(m)%file%in_pbuf(size(forcings(m)%sectors))) forcings(m)%file%in_pbuf(:) = .false. - call trcdata_init( forcings(m)%sectors, & - forcings(m)%filename, filelist, datapath, & - forcings(m)%fields, & - forcings(m)%file, & - rmv_file, extfrc_cycle_yr, extfrc_fixed_ymd, extfrc_fixed_tod, extfrc_type) + if (trim(forcings(m)%species) == 'SO2' .and. extfrc_volc_type /= 'NULL') then + call trcdata_init( forcings(m)%sectors, & + forcings(m)%filename, filelist, datapath, & + forcings(m)%fields, & + forcings(m)%file, rmv_file, extfrc_volc_cycle_yr, & + extfrc_fixed_ymd, extfrc_fixed_tod, extfrc_volc_type) + else + call trcdata_init( forcings(m)%sectors, & + forcings(m)%filename, filelist, datapath, & + forcings(m)%fields, & + forcings(m)%file, & + rmv_file, extfrc_cycle_yr, extfrc_fixed_ymd, extfrc_fixed_tod, extfrc_type) + end if enddo frcing_loop diff --git a/components/eam/src/chemistry/utils/tracer_data.F90 b/components/eam/src/chemistry/utils/tracer_data.F90 index 073aacff6e47..62ccbcef8a25 100644 --- a/components/eam/src/chemistry/utils/tracer_data.F90 +++ b/components/eam/src/chemistry/utils/tracer_data.F90 @@ -660,7 +660,7 @@ subroutine advance_trcdata( flds, file, state, pbuf2d ) call t_startf('read_next_trcdata') call read_next_trcdata(state, flds, file ) call t_stopf('read_next_trcdata') - if(masterproc) write(iulog,*) 'READ_NEXT_TRCDATA ', flds%fldnam + if(masterproc) write(iulog,*) 'READ_NEXT_TRCDATA ', flds%fldnam,data_time end if endif diff --git a/components/eam/src/dynamics/se/dyn_grid.F90 b/components/eam/src/dynamics/se/dyn_grid.F90 index c39b3aea7301..a4a8424f887b 100644 --- a/components/eam/src/dynamics/se/dyn_grid.F90 +++ b/components/eam/src/dynamics/se/dyn_grid.F90 @@ -1,28 +1,28 @@ module dyn_grid - !------------------------------------------------------------------------------------------------- - ! + !------------------------------------------------------------------------------------------------- + ! ! Purpose: Definition of dynamics computational grid. - ! - ! The grid used by the SE dynamics is called the GLL grid, which is - ! made up up of elements that correspond to "blocks". The columns + ! + ! The grid used by the SE dynamics is called the GLL grid, which is + ! made up up of elements that correspond to "blocks". The columns ! within each element are located at the Gauss-Lobatto-Legendre (GLL) ! quadrature points. The GLL nodes can be used as the physics columns ! as well, but this can lead to grid imprinting. The physics can also - ! be done on a quasi-equal area FV grid when fv_nphys>0, which will + ! be done on a quasi-equal area FV grid when fv_nphys>0, which will ! define fv_nphys^2 cells per element. - ! + ! ! Method: Variables are private; interface routines used to extract ! information for use in user code. Global column index range - ! defined using full (unreduced) grid. - ! + ! defined using full (unreduced) grid. + ! ! Entry points: - ! get_block_bounds_d get first and last indices in global + ! get_block_bounds_d get first and last indices in global ! block ordering ! get_block_gcol_d get column indices for given block ! get_block_gcol_cnt_d get number of columns in given block ! get_block_lvl_cnt_d get number of vertical levels in column ! get_block_levels_d get vertical levels in column - ! get_gcol_block_d get global block indices and local columns + ! get_gcol_block_d get global block indices and local columns ! index for given global column index ! get_gcol_block_cnt_d get number of blocks containing data ! from a given global column index @@ -31,14 +31,14 @@ module dyn_grid ! information ! get_horiz_grid_dim_d get horizontal dimensions of dynamics grid ! dyn_grid_get_pref get reference pressures for the dynamics grid - ! dyn_grid_get_elem_coords get coordinates of a specified block element + ! dyn_grid_get_elem_coords get coordinates of a specified block element ! of the dynamics grid ! dyn_grid_find_gcols finds nearest column for given lat/lon - ! dyn_grid_get_colndx get element block/column and MPI process indices + ! dyn_grid_get_colndx get element block/column and MPI process indices ! corresponding to a specified global column index ! ! Author: Jim Edwards and Patrick Worley - ! + ! !------------------------------------------------------------------------------------------------- use element_mod, only: element_t use cam_logfile, only: iulog @@ -60,7 +60,7 @@ module dyn_grid integer, parameter, public :: physgrid_d = 102 ! FV physics grid resolution (physics on GLL grid if NPG=0) - integer, parameter, public :: fv_nphys = NPG + integer, parameter, public :: fv_nphys = NPG integer :: ngcols_d = 0 ! number of dynamics columns logical :: gblocks_need_initialized = .true. @@ -101,6 +101,7 @@ module dyn_grid real(r8), allocatable :: pelon_deg(:) ! pe-local longitudes (degrees) real(r8), pointer :: pearea(:) => null() ! pe-local areas integer(iMap), pointer :: pemap(:) => null() ! pe-local map for PIO decomp + real(r8), pointer :: pearea_scm(:) => null() ! special case: area for SCM (only 1 value) !=================================================================================================== contains @@ -113,9 +114,9 @@ end subroutine dyn_grid_init !================================================================================================= ! subroutine get_block_bounds_d(block_first,block_last) - !--------------------------------------------------------------------------- + !--------------------------------------------------------------------------- ! Purpose: Return first and last indices used in global block ordering - ! + ! ! Author: Jim Edwards !------------------------------Arguments------------------------------------ integer, intent(out) :: block_first ! first (global) index used for blocks @@ -129,9 +130,9 @@ end subroutine get_block_bounds_d !================================================================================================= ! subroutine get_block_gcol_d(blockid,size,cdex) - !--------------------------------------------------------------------------- + !--------------------------------------------------------------------------- ! Purpose: Return list of dynamics column indices in given block - ! + ! ! Author: Jim Edwards !--------------------------------------------------------------------------- implicit none @@ -160,9 +161,9 @@ end subroutine get_block_gcol_d !================================================================================================= ! integer function get_block_gcol_cnt_d(blockid) - !--------------------------------------------------------------------------- + !--------------------------------------------------------------------------- ! Purpose: Return number of dynamics columns in indicated block - ! + ! ! Author: Jim Edwards !------------------------------Arguments------------------------------------ integer, intent(in) :: blockid @@ -243,11 +244,11 @@ subroutine get_gcol_block_d(gcol, cnt, blockid, bcid, localblockid) use kinds, only: int_kind use cam_abortutils, only: endrun !--------------------------------------------------------------------------- - ! Purpose: Return global block index and local column index for + ! Purpose: Return global block index and local column index for ! global column index. Element array is naturally ordered. - ! + ! ! Author: Jim Edwards - ! Modified: replaced linear search with best guess and binary search + ! Modified: replaced linear search with best guess and binary search ! (Pat Worley, 7/2/09) !--------------------------------------------------------------------------- implicit none @@ -378,7 +379,7 @@ integer function get_gcol_block_cnt_d(gcol) !--------------------------------------------------------------------------- ! Purpose: Return number of blocks contain data for the vertical column ! with the given global column index - ! + ! ! Author: Patrick Worley !--------------------------------------------------------------------------- implicit none @@ -392,9 +393,9 @@ end function get_gcol_block_cnt_d !================================================================================================= ! integer function get_block_owner_d(blockid) - !--------------------------------------------------------------------------- + !--------------------------------------------------------------------------- ! Purpose: Return id of processor that "owns" the indicated block - ! + ! ! Author: Jim Edwards !--------------------------------------------------------------------------- implicit none @@ -402,7 +403,7 @@ integer function get_block_owner_d(blockid) integer, intent(in) :: blockid ! global block id !--------------------------------------------------------------------------- if (gblocks_need_initialized) call gblocks_init() - + if (gblocks(blockid)%Owner>-1) then get_block_owner_d=gblocks(blockid)%Owner else @@ -419,7 +420,7 @@ subroutine get_horiz_grid_dim_d(hdim1_d,hdim2_d) ! Purpose: Returns declared horizontal dimensions of computational grid. ! For non-lon/lat grids, declare grid to be one-dimensional, ! i.e., (ngcols_d x 1) - ! + ! ! Author: Patrick Worley !------------------------------Arguments------------------------------------ integer, intent(out) :: hdim1_d ! first horizontal dimension @@ -430,7 +431,7 @@ subroutine get_horiz_grid_dim_d(hdim1_d,hdim2_d) else hdim1_d = ngcols_d end if ! fv_nphys > 0 - + if (present(hdim2_d)) hdim2_d = 1 return @@ -441,7 +442,7 @@ end subroutine get_horiz_grid_dim_d subroutine set_horiz_grid_cnt_d(NumUniqueCols) !--------------------------------------------------------------------------- ! Purpose: Set number of columns in the dynamics computational grid - ! + ! ! Author: Jim Edwards !--------------------------------------------------------------------------- use dimensions_mod, only: nelem, nelemd, np, npsq @@ -454,7 +455,7 @@ subroutine set_horiz_grid_cnt_d(NumUniqueCols) integer :: ie, i, j, ii logical, save :: local_coords_initialized = .false. real(r8) :: areaw(np, np) - type(index_t), pointer :: idx + type(index_t), pointer :: idx !--------------------------------------------------------------------------- if (.not. local_coords_initialized) then ngcols_d = NumUniqueCols @@ -463,12 +464,12 @@ subroutine set_horiz_grid_cnt_d(NumUniqueCols) call endrun('set_horiz_grid_cnt_d: fdofp_local already defined') end if allocate(fdofp_local(npsq, nelemd)) - fdofp_local =0 + fdofp_local =0 do ie = 1, nelemd idx => elem(ie)%idxP do ii = 1, idx%NumUniquePts i = idx%ia(ii) - j = idx%ja(ii) + j = idx%ja(ii) fdofp_local((np*(j-1))+i,ie) = (idx%UniquePtoffset+ii-1) end do end do @@ -480,7 +481,7 @@ subroutine set_horiz_grid_cnt_d(NumUniqueCols) ! Now, fill in the appropriate values ii = 1 do ie = 1, nelemd - areaw = 1.0_r8 / elem(ie)%rspheremp(:,:) + areaw = 1.0_r8 / elem(ie)%rspheremp(:,:) pearea(ii:ii+npsq-1) = reshape(areaw, (/ np*np /)) pemap(ii:ii+npsq-1) = fdofp_local(:,ie) do j = 1, np @@ -503,14 +504,14 @@ end subroutine set_horiz_grid_cnt_d ! subroutine get_horiz_grid_d(nxy,clat_d_out,clon_d_out,area_d_out, & wght_d_out,lat_d_out,lon_d_out,cost_d_out) - !--------------------------------------------------------------------------- + !--------------------------------------------------------------------------- ! Purpose: Return latitude and longitude (in radians), column surface ! area (in radians squared) and surface integration weights ! for global column indices that will be passed to/from - ! physics. Optionally also return estimated physics - ! computational cost per global column for use in load + ! physics. Optionally also return estimated physics + ! computational cost per global column for use in load ! balancing. - ! + ! ! Author: Jim Edwards !------------------------------Arguments------------------------------------ integer, intent(in ) :: nxy ! array sizes @@ -572,7 +573,7 @@ subroutine get_horiz_grid_d(nxy,clat_d_out,clon_d_out,area_d_out, & end if if ( present(clat_d_out) .or. present(clon_d_out) ) then - + allocate( lat_d_rad_temp(nxy) ) allocate( lon_d_rad_temp(nxy) ) allocate( lat_d_deg_temp(nxy) ) @@ -618,7 +619,7 @@ subroutine define_cam_grids() integer(iMap), pointer :: grid_map_d(:,:) integer(iMap), pointer :: grid_map_p(:,:) integer :: ie, i, j, k, mapind ! Loop variables - real(r8) :: area_scm(1), lat, lon + real(r8) :: lat, lon integer :: ncols_p_lcl ! local column count integer :: ncols_p_gbl ! global column count integer(iMap), pointer :: physgrid_map(:) @@ -628,7 +629,7 @@ subroutine define_cam_grids() !--------------------------------------------------------------------------- ! Create grid for data on HOMME GLL nodes !--------------------------------------------------------------------------- - ! When the FV physs grid is used the GLL grid output + ! When the FV physs grid is used the GLL grid output ! variables will use coordinates with the '_d' suffix. gridname = 'GLL' if (fv_nphys > 0) then @@ -670,12 +671,11 @@ subroutine define_cam_grids() call cam_grid_attribute_register(trim(gridname), trim(areaname), & 'gll grid areas', trim(ncolname), pearea, pemap) else - ! if single column model, then this attribute has to be handled - ! by assigning just the SCM point. Else, the model will bomb out - ! when writing the header information to history output - area_scm(1) = 1.0_r8 / elem(1)%rspheremp(1,1) - call cam_grid_attribute_register(trim(gridname), trim(areaname), & - 'gll grid areas', trim(ncolname), area_scm) + ! If single column model, set pearea_scm(1) to be the area as 1 value to simplify + allocate(pearea_scm(1)) + pearea_scm(1) = 1.0_r8 / elem(1)%rspheremp(1,1) + call cam_grid_attribute_register(trim(gridname), trim(areaname), & + 'gll grid areas', trim(ncolname), pearea_scm) end if ! .not. single_column call cam_grid_attribute_register(trim(gridname), 'np', '', np) @@ -687,15 +687,19 @@ subroutine define_cam_grids() deallocate(pelon_deg) ! These can be nullified since the grid object has the reference - nullify(grid_map_d) + nullify(grid_map_d) nullify(pearea) nullify(pemap) + if (.not.single_column .or. scm_multcols) then + else + nullify(pearea_scm) + endif !--------------------------------------------------------------------------- ! Create grid object for physics grid on the dynamics decomposition !--------------------------------------------------------------------------- - ! Following CAM6-SE the 'physgrid_d' grid is created and used to load the - ! PHIS field (i.e. surface topo) on the FV physics grid and then + ! Following CAM6-SE the 'physgrid_d' grid is created and used to load the + ! PHIS field (i.e. surface topo) on the FV physics grid and then ! interpolated to the GLL grid. This ensures consistent treatment of SGH. if (fv_nphys>0) then @@ -822,13 +826,13 @@ subroutine gblocks_init() end do end if - do ie = 1,nelemdmax + do ie = 1,nelemdmax if (ie<=nelemd) then rdispls(iam+1)=elem(ie)%idxP%UniquePtOffset-1 gid(iam+1)=elem(ie)%GlobalID lid(iam+1)=ie recvcounts(iam+1)=elem(ie)%idxP%NumUniquePts - else + else rdispls(iam+1) = 0 recvcounts(iam+1) = 0 gid(iam+1)=0 @@ -882,7 +886,7 @@ subroutine compute_global_area(area_d) end if if (fv_nphys > 0) then - + ncol_fv_gbl = fv_nphys*fv_nphys*nelem ncol_fv_lcl = fv_nphys*fv_nphys*nelemd allocate(rbuf(ncol_fv_gbl)) @@ -948,14 +952,14 @@ subroutine compute_global_area(area_d) deallocate(col_id_global) else ! physics is on GLL grid - + allocate(rbuf(ngcols_d)) - do ie = 1, nelemdmax + do ie = 1, nelemdmax if(ie <= nelemd) then displace(iam+1) = elem(ie)%idxp%UniquePtOffset-1 recvcnts(iam+1) = elem(ie)%idxP%NumUniquePts eb = displace(iam+1) + elem(ie)%idxp%NumUniquePts - areaw = 1.0_r8 / elem(ie)%rspheremp(:,:) + areaw = 1.0_r8 / elem(ie)%rspheremp(:,:) call UniquePoints(elem(ie)%idxP, areaw, area_d(displace(iam+1)+1:eb)) else displace(iam+1) = 0 @@ -1065,7 +1069,7 @@ subroutine compute_global_coords(clat, clon, lat_out, lon_out, corner_lat_out, c ! Gather global latitudes call mpi_allgatherv( lat_rad_local(:), recvcnts(iam+1), mpi_real8, rbuf, & recvcnts(:), displace(:), mpi_real8, mpicom, ierr) - + ! sort latitude according to global element ID do icol = 1,ncol_fv_gbl clat( col_id_global(icol) ) = rbuf(icol) @@ -1074,7 +1078,7 @@ subroutine compute_global_coords(clat, clon, lat_out, lon_out, corner_lat_out, c ! Gather global longitudes call mpi_allgatherv( lon_rad_local(:), recvcnts(iam+1), mpi_real8, rbuf, & recvcnts(:), displace(:), mpi_real8, mpicom, ierr) - + ! sort longitude according to global element ID do icol = 1,ncol_fv_gbl clon( col_id_global(icol) ) = rbuf(icol) @@ -1107,14 +1111,14 @@ subroutine compute_global_coords(clat, clon, lat_out, lon_out, corner_lat_out, c ! Gather latitude call mpi_allgatherv( corner_lat_rad_local(:,c), recvcnts(iam+1), mpi_real8, rbuf, & recvcnts(:), displace(:), mpi_real8, mpicom, ierr) - ! sort latitude + ! sort latitude do icol = 1,ncol_fv_gbl corner_lat_out( col_id_global(icol), c) = rbuf(icol) * rad2deg end do ! Gather longitude call mpi_allgatherv( corner_lon_rad_local(:,c), recvcnts(iam+1), mpi_real8, rbuf, & recvcnts(:), displace(:), mpi_real8, mpicom, ierr) - ! sort longitude + ! sort longitude do icol = 1,ncol_fv_gbl corner_lon_out( col_id_global(icol), c) = rbuf(icol) * rad2deg end do @@ -1179,7 +1183,7 @@ subroutine compute_global_coords(clat, clon, lat_out, lon_out, corner_lat_out, c call mpi_allgatherv(rbuf, recvcnts(iam+1), mpi_real8, clat, & recvcnts(:), displace(:), mpi_real8, mpicom, ierr) if (present(lat_out)) then - rbuf(1:recvcnts(iam+1)) = lat_out(sb:eb) + rbuf(1:recvcnts(iam+1)) = lat_out(sb:eb) call mpi_allgatherv(rbuf, recvcnts(iam+1), mpi_real8, lat_out, & recvcnts(:), displace(:), mpi_real8, mpicom, ierr) end if @@ -1188,12 +1192,12 @@ subroutine compute_global_coords(clat, clon, lat_out, lon_out, corner_lat_out, c call mpi_allgatherv(rbuf, recvcnts(iam+1), mpi_real8, clon, & recvcnts(:), displace(:), mpi_real8, mpicom, ierr) if (present(lon_out)) then - rbuf(1:recvcnts(iam+1)) = lon_out(sb:eb) + rbuf(1:recvcnts(iam+1)) = lon_out(sb:eb) call mpi_allgatherv(rbuf, recvcnts(iam+1), mpi_real8, lon_out, & recvcnts(:), displace(:), mpi_real8, mpicom, ierr) end if end do - + deallocate(rbuf) end if ! fv_nphys > 0 @@ -1275,7 +1279,7 @@ integer function get_dyn_grid_parm(name) result(ival) ival = fv_nphys*fv_nphys*nelem else ival = ngcols_d - end if + end if else if(name.eq.'plev') then ival = plev else if(name.eq.'plevp') then @@ -1318,10 +1322,10 @@ end subroutine dyn_grid_get_pref ! !================================================================================================= ! - subroutine dyn_grid_find_gcols( lat, lon, nclosest, owners, col, lbk, rlat, rlon, idyn_dists ) + subroutine dyn_grid_find_gcols( lat, lon, nclosest, owners, col, lbk, rlat, rlon, idyn_dists ) !--------------------------------------------------------------------------- - ! This returns the lat/lon information (and corresponding MPI task - ! numbers (owners)) of the global model grid columns nearest to the + ! This returns the lat/lon information (and corresponding MPI task + ! numbers (owners)) of the global model grid columns nearest to the ! input satellite coordinate (lat,lon) !--------------------------------------------------------------------------- use shr_const_mod, only: SHR_CONST_REARTH @@ -1415,7 +1419,7 @@ end subroutine dyn_grid_find_gcols ! !================================================================================================= ! - subroutine dyn_grid_get_colndx( igcol, nclosest, owners, col, lbk ) + subroutine dyn_grid_get_colndx( igcol, nclosest, owners, col, lbk ) !------------------------------Arguments------------------------------------ integer, intent(in) :: nclosest integer, intent(in) :: igcol(nclosest) @@ -1437,7 +1441,7 @@ subroutine dyn_grid_get_colndx( igcol, nclosest, owners, col, lbk ) call get_gcol_block_d( igcol(i), 1, blockid, bcid, lclblockid ) owners(i) = get_block_owner_d(blockid(1)) - + if (owners(i)==iam) then lbk(i) = lclblockid(1) ii = igcol(i)-elem(lbk(i))%idxp%UniquePtoffset+1 @@ -1448,7 +1452,7 @@ subroutine dyn_grid_get_colndx( igcol, nclosest, owners, col, lbk ) lbk(i) = -1 col(i) = -1 endif - + end do end subroutine dyn_grid_get_colndx diff --git a/components/eam/src/physics/cam/cam_diagnostics.F90 b/components/eam/src/physics/cam/cam_diagnostics.F90 index ead4f558f05b..5dca258775da 100644 --- a/components/eam/src/physics/cam/cam_diagnostics.F90 +++ b/components/eam/src/physics/cam/cam_diagnostics.F90 @@ -306,6 +306,7 @@ subroutine diag_init() call addfld ('MQ',(/ 'lev' /), 'A','kg/m2','Water vapor mass in layer') call addfld ('TMQ',horiz_only, 'A','kg/m2','Total (vertically integrated) precipitable water', & standard_name='atmosphere_mass_content_of_water_vapor') + call addfld ('TMQS',horiz_only, 'A','kg/m2','Total (vertically integrated) saturated precipitable water') call addfld ('TTQ',horiz_only, 'A', 'kg/m/s','Total (vertically integrated) vapor transport') call addfld ('TUQ',horiz_only, 'A','kg/m/s','Total (vertically integrated) zonal water flux') call addfld ('TVQ',horiz_only, 'A','kg/m/s','Total (vertically integrated) meridional water flux') @@ -1368,6 +1369,14 @@ subroutine diag_phys_writeout(state, psl) if (moist_physics) then + ! Mass of saturated q vertically integrated + call qsat(state%t(:ncol,:), state%pmid(:ncol,:), tem2(:ncol,:), ftem(:ncol,:)) + ftem(:ncol,:) = ftem(:ncol,:) * state%pdel(:ncol,:) * rga + do k=2,pver + ftem(:ncol,1) = ftem(:ncol,1) + ftem(:ncol,k) + end do + call outfld ('TMQS ',ftem, pcols ,lchnk ) + ! Relative humidity call qsat(state%t(:ncol,:), state%pmid(:ncol,:), & tem2(:ncol,:), ftem(:ncol,:)) diff --git a/components/eam/src/physics/crm/crm_physics.F90 b/components/eam/src/physics/crm/crm_physics.F90 index 61ef03f8ca65..39ed6a0876c7 100644 --- a/components/eam/src/physics/crm/crm_physics.F90 +++ b/components/eam/src/physics/crm/crm_physics.F90 @@ -1379,8 +1379,8 @@ subroutine crm_physics_tend(ztodt, state, tend, ptend, pbuf2d, cam_in, cam_out, call pam_mirror_array_readwrite( 'output_ni_mean', crm_output%ni_mean, '' ) call pam_mirror_array_readwrite( 'output_qm_mean', crm_output%qm_mean, '' ) call pam_mirror_array_readwrite( 'output_bm_mean', crm_output%bm_mean, '' ) - call pam_mirror_array_readwrite( 'output_rho_d_mean', crm_output%rho_d_mean, '' ) - call pam_mirror_array_readwrite( 'output_rho_v_mean', crm_output%rho_v_mean, '' ) + call pam_mirror_array_readwrite( 'output_rho_d_mean', crm_output%rho_d_mean, '' ) + call pam_mirror_array_readwrite( 'output_rho_v_mean', crm_output%rho_v_mean, '' ) call pam_mirror_array_readwrite( 'output_qt_ls', crm_output%qt_ls, '' ) call pam_mirror_array_readwrite( 'output_t_ls', crm_output%t_ls, '' ) diff --git a/components/eam/src/physics/crm/pam/CMakeLists.txt b/components/eam/src/physics/crm/pam/CMakeLists.txt index 95075debd4fd..4a8f88f669b0 100644 --- a/components/eam/src/physics/crm/pam/CMakeLists.txt +++ b/components/eam/src/physics/crm/pam/CMakeLists.txt @@ -11,6 +11,9 @@ set(PAM_DRIVER_SRC add_library(pam_driver ${PAM_DRIVER_SRC}) +set(SCREAM_HOME ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../..) +add_library(eamxx_physics INTERFACE ${SCREAM_HOME}/components/eamxx/src/physics/) + if (${USE_CUDA}) # PAM will be CUDA-linked with device symbols resolved at library creation set_target_properties(pam_driver @@ -37,7 +40,6 @@ set(PAM_MICRO p3) set(PAM_SGS shoc) set(PAM_RAD forced) set(PAM_SCREAM_USE_CXX True) -set(SCREAM_HOME ${CMAKE_CURRENT_SOURCE_DIR}/../../../../../..) # removing this once the cime cmake_macros aren't using obsolete # Kokkos settings like KOKKOS_OPTIONS. @@ -124,7 +126,7 @@ target_compile_options(pam_driver PUBLIC ) if (PAM_SCREAM_USE_CXX) - target_link_libraries(pam_driver pam_core physics dynamics pam_scream_cxx_interfaces ekat p3 shoc physics_share scream_share) + target_link_libraries(pam_driver pam_core physics dynamics pam_scream_cxx_interfaces ekat p3 shoc physics_share scream_share eamxx_physics) else() target_link_libraries(pam_driver pam_core physics dynamics ) endif() diff --git a/components/eam/src/physics/crm/pam/external b/components/eam/src/physics/crm/pam/external index 87731d56aeee..3ea20ad38f28 160000 --- a/components/eam/src/physics/crm/pam/external +++ b/components/eam/src/physics/crm/pam/external @@ -1 +1 @@ -Subproject commit 87731d56aeee4bfae4750e17732828ba186367a7 +Subproject commit 3ea20ad38f286730973429e0d491420a6f599f11 diff --git a/components/eam/src/physics/crm/pam/pam_accelerate.h b/components/eam/src/physics/crm/pam/pam_accelerate.h index a48ca628f691..5b277fdca966 100644 --- a/components/eam/src/physics/crm/pam/pam_accelerate.h +++ b/components/eam/src/physics/crm/pam/pam_accelerate.h @@ -17,16 +17,22 @@ inline void pam_accelerate_init( pam::PamCoupler &coupler ) { using yakl::c::parallel_for; using yakl::c::SimpleBounds; using yakl::atomicAdd; + //------------------------------------------------------------------------------------------------ + // The ability to accelerate dry density is implemented, but tests suggested + // that this was contributing to instabilities in PAM. Combined with the + // uncertainty of how to handle dry density in the anelastic case, we will + // disable dry density mean-state acceleration by default. + coupler.set_option("crm_accel_rd",false); + //------------------------------------------------------------------------------------------------ auto &dm_device = coupler.get_data_manager_device_readwrite(); auto nens = coupler.get_option("ncrms"); auto nz = coupler.get_option("crm_nz"); auto ny = coupler.get_option("crm_ny"); auto nx = coupler.get_option("crm_nx"); - auto crm_accel_uv = coupler.get_option("crm_accel_uv"); //------------------------------------------------------------------------------------------------ dm_device.register_and_allocate("accel_save_t", "saved temperature for MSA", {nz,nens}, {"z","nens"} ); - dm_device.register_and_allocate("accel_save_r", "saved dry density for MSA", {nz,nens}, {"z","nens"} ); dm_device.register_and_allocate("accel_save_q", "saved total water for MSA", {nz,nens}, {"z","nens"} ); + dm_device.register_and_allocate("accel_save_r", "saved dry density for MSA", {nz,nens}, {"z","nens"} ); dm_device.register_and_allocate("accel_save_u", "saved uvel for MSA", {nz,nens}, {"z","nens"} ); dm_device.register_and_allocate("accel_save_v", "saved vvel for MSA", {nz,nens}, {"z","nens"} ); //------------------------------------------------------------------------------------------------ @@ -42,40 +48,37 @@ inline void pam_accelerate_diagnose( pam::PamCoupler &coupler ) { auto nz = coupler.get_option("crm_nz"); auto ny = coupler.get_option("crm_ny"); auto nx = coupler.get_option("crm_nx"); + auto crm_accel_rd = coupler.get_option("crm_accel_rd"); auto crm_accel_uv = coupler.get_option("crm_accel_uv"); //------------------------------------------------------------------------------------------------ auto temp = dm_device.get("temp" ); - auto rhod = dm_device.get("density_dry"); auto rhov = dm_device.get("water_vapor"); auto rhol = dm_device.get("cloud_water"); auto rhoi = dm_device.get("ice" ); + auto rhod = dm_device.get("density_dry"); auto uvel = dm_device.get("uvel" ); auto vvel = dm_device.get("vvel" ); auto accel_save_t = dm_device.get("accel_save_t"); - auto accel_save_r = dm_device.get("accel_save_r"); auto accel_save_q = dm_device.get("accel_save_q"); + auto accel_save_r = dm_device.get("accel_save_r"); auto accel_save_u = dm_device.get("accel_save_u"); auto accel_save_v = dm_device.get("accel_save_v"); //------------------------------------------------------------------------------------------------ // compute horizontal means needed later for mean-state acceleration parallel_for( SimpleBounds<2>(nz,nens) , YAKL_LAMBDA (int k, int n) { accel_save_t(k,n) = 0.0; - accel_save_r(k,n) = 0.0; accel_save_q(k,n) = 0.0; - if (crm_accel_uv) { - accel_save_u(k,n) = 0.0; - accel_save_v(k,n) = 0.0; - } + if (crm_accel_rd) { accel_save_r(k,n) = 0.0; } + if (crm_accel_uv) { accel_save_u(k,n) = 0.0; } + if (crm_accel_uv) { accel_save_v(k,n) = 0.0; } }); real r_nx_ny = 1._fp/(nx*ny); // precompute reciprocal to avoid costly divisions parallel_for( SimpleBounds<4>(nz,ny,nx,nens) , YAKL_LAMBDA (int k, int j, int i, int n) { yakl::atomicAdd( accel_save_t(k,n), temp(k,j,i,n) * r_nx_ny ); - yakl::atomicAdd( accel_save_r(k,n), rhod(k,j,i,n) * r_nx_ny ); yakl::atomicAdd( accel_save_q(k,n), ( rhov(k,j,i,n) + rhol(k,j,i,n) + rhoi(k,j,i,n) ) * r_nx_ny ); - if (crm_accel_uv) { - yakl::atomicAdd( accel_save_u(k,n), uvel(k,j,i,n) * r_nx_ny ); - yakl::atomicAdd( accel_save_v(k,n), vvel(k,j,i,n) * r_nx_ny ); - } + if (crm_accel_rd) { yakl::atomicAdd( accel_save_r(k,n), rhod(k,j,i,n) * r_nx_ny ); } + if (crm_accel_uv) { yakl::atomicAdd( accel_save_u(k,n), uvel(k,j,i,n) * r_nx_ny ); } + if (crm_accel_uv) { yakl::atomicAdd( accel_save_v(k,n), vvel(k,j,i,n) * r_nx_ny ); } }); //------------------------------------------------------------------------------------------------ } @@ -86,28 +89,28 @@ inline void pam_accelerate( pam::PamCoupler &coupler, int nstep, int &nstop ) { using yakl::c::SimpleBounds; using yakl::atomicAdd; using yakl::ScalarLiveOut; - auto &dm_device = coupler.get_data_manager_device_readwrite(); - auto nens = coupler.get_option("ncrms"); - auto nz = coupler.get_option("crm_nz"); - auto ny = coupler.get_option("crm_ny"); - auto nx = coupler.get_option("crm_nx"); + auto &dm_device = coupler.get_data_manager_device_readwrite(); + auto nens = coupler.get_option("ncrms"); + auto nz = coupler.get_option("crm_nz"); + auto ny = coupler.get_option("crm_ny"); + auto nx = coupler.get_option("crm_nx"); + auto crm_accel_rd = coupler.get_option("crm_accel_rd"); + auto crm_accel_uv = coupler.get_option("crm_accel_uv"); + real crm_accel_factor = coupler.get_option("crm_accel_factor"); //------------------------------------------------------------------------------------------------ auto temp = dm_device.get("temp" ); - auto rhod = dm_device.get("density_dry"); auto rhov = dm_device.get("water_vapor"); auto rhol = dm_device.get("cloud_water"); auto rhoi = dm_device.get("ice" ); + auto rhod = dm_device.get("density_dry"); auto uvel = dm_device.get("uvel" ); auto vvel = dm_device.get("vvel" ); auto accel_save_t = dm_device.get("accel_save_t"); - auto accel_save_r = dm_device.get("accel_save_r"); auto accel_save_q = dm_device.get("accel_save_q"); + auto accel_save_r = dm_device.get("accel_save_r"); auto accel_save_u = dm_device.get("accel_save_u"); auto accel_save_v = dm_device.get("accel_save_v"); //------------------------------------------------------------------------------------------------ - bool crm_accel_uv = coupler.get_option("crm_accel_uv"); - real crm_accel_factor = coupler.get_option("crm_accel_factor"); - //------------------------------------------------------------------------------------------------ real2d hmean_t ("hmean_t", nz,nens); real2d hmean_r ("hmean_r", nz,nens); real2d hmean_q ("hmean_q", nz,nens); @@ -127,22 +130,18 @@ inline void pam_accelerate( pam::PamCoupler &coupler, int nstep, int &nstop ) { // Compute the horizontal mean for each variable parallel_for( SimpleBounds<2>(nz,nens) , YAKL_LAMBDA (int k, int n) { hmean_t(k,n) = 0.0; - hmean_r(k,n) = 0.0; hmean_q(k,n) = 0.0; - if (crm_accel_uv) { - hmean_u(k,n) = 0.0; - hmean_v(k,n) = 0.0; - } + if (crm_accel_rd) { hmean_r(k,n) = 0.0; } + if (crm_accel_uv) { hmean_u(k,n) = 0.0; } + if (crm_accel_uv) { hmean_v(k,n) = 0.0; } }); real r_nx_ny = 1._fp/(nx*ny); // precompute reciprocal to avoid costly divisions parallel_for( SimpleBounds<4>(nz,ny,nx,nens) , YAKL_LAMBDA (int k, int j, int i, int n) { yakl::atomicAdd( hmean_t(k,n), temp(k,j,i,n) * r_nx_ny ); - yakl::atomicAdd( hmean_r(k,n), rhod(k,j,i,n) * r_nx_ny ); yakl::atomicAdd( hmean_q(k,n), ( rhov(k,j,i,n) + rhol(k,j,i,n) + rhoi(k,j,i,n) ) * r_nx_ny ); - if (crm_accel_uv) { - yakl::atomicAdd( hmean_u(k,n), uvel(k,j,i,n) * r_nx_ny ); - yakl::atomicAdd( hmean_v(k,n), vvel(k,j,i,n) * r_nx_ny ); - } + if (crm_accel_rd) { yakl::atomicAdd( hmean_r(k,n), rhod(k,j,i,n) * r_nx_ny ); } + if (crm_accel_uv) { yakl::atomicAdd( hmean_u(k,n), uvel(k,j,i,n) * r_nx_ny ); } + if (crm_accel_uv) { yakl::atomicAdd( hmean_v(k,n), vvel(k,j,i,n) * r_nx_ny ); } }); //------------------------------------------------------------------------------------------------ // Compute the accelerated tendencies @@ -150,12 +149,10 @@ inline void pam_accelerate( pam::PamCoupler &coupler, int nstep, int &nstop ) { ScalarLiveOut ceaseflag_liveout(false); parallel_for( SimpleBounds<2>(nz,nens) , YAKL_LAMBDA (int k, int n) { ttend_acc(k,n) = hmean_t(k,n) - accel_save_t(k,n); - rtend_acc(k,n) = hmean_r(k,n) - accel_save_r(k,n); qtend_acc(k,n) = hmean_q(k,n) - accel_save_q(k,n); - if (crm_accel_uv) { - utend_acc(k,n) = hmean_u(k,n) - accel_save_u(k,n); - vtend_acc(k,n) = hmean_v(k,n) - accel_save_v(k,n); - } + if (crm_accel_rd) { rtend_acc(k,n) = hmean_r(k,n) - accel_save_r(k,n); } + if (crm_accel_uv) { utend_acc(k,n) = hmean_u(k,n) - accel_save_u(k,n); } + if (crm_accel_uv) { vtend_acc(k,n) = hmean_v(k,n) - accel_save_v(k,n); } if (abs(ttend_acc(k,n)) > dtemp_max) { ceaseflag_liveout = true; } @@ -191,14 +188,11 @@ inline void pam_accelerate( pam::PamCoupler &coupler, int nstep, int &nstop ) { //------------------------------------------------------------------------------------------------ // Apply the accelerated tendencies parallel_for( SimpleBounds<4>(nz,ny,nx,nens) , YAKL_LAMBDA (int k, int j, int i, int n) { - temp(k,j,i,n) = temp(k,j,i,n) + crm_accel_factor * ttend_acc(k,n); - rhod(k,j,i,n) = rhod(k,j,i,n) + crm_accel_factor * rtend_acc(k,n); rhov(k,j,i,n) = rhov(k,j,i,n) + crm_accel_factor * qtend_acc(k,n); - if (crm_accel_uv) { - uvel(k,j,i,n) = uvel(k,j,i,n) + crm_accel_factor * utend_acc(k,n); - vvel(k,j,i,n) = vvel(k,j,i,n) + crm_accel_factor * vtend_acc(k,n); - } + if (crm_accel_rd) { rhod(k,j,i,n) = rhod(k,j,i,n) + crm_accel_factor * rtend_acc(k,n); } + if (crm_accel_uv) { uvel(k,j,i,n) = uvel(k,j,i,n) + crm_accel_factor * utend_acc(k,n); } + if (crm_accel_uv) { vvel(k,j,i,n) = vvel(k,j,i,n) + crm_accel_factor * vtend_acc(k,n); } // apply limiter on temperature temp(k,j,i,n) = std::max( temp_min, temp(k,j,i,n) ); }); @@ -231,4 +225,3 @@ inline void pam_accelerate( pam::PamCoupler &coupler, int nstep, int &nstop ) { }); //------------------------------------------------------------------------------------------------ } - diff --git a/components/eam/src/physics/crm/pam/pam_debug.h b/components/eam/src/physics/crm/pam/pam_debug.h index 113944365d7c..a168710afc6d 100644 --- a/components/eam/src/physics/crm/pam/pam_debug.h +++ b/components/eam/src/physics/crm/pam/pam_debug.h @@ -31,17 +31,23 @@ inline void pam_debug_init( pam::PamCoupler &coupler ) { dm_device.register_and_allocate("debug_save_rhov", "saved rhov for debug", {nz,ny,nx,nens}, {"z","y","x","nens"} ); dm_device.register_and_allocate("debug_save_rhoc", "saved rhoc for debug", {nz,ny,nx,nens}, {"z","y","x","nens"} ); dm_device.register_and_allocate("debug_save_rhoi", "saved rhoi for debug", {nz,ny,nx,nens}, {"z","y","x","nens"} ); + dm_device.register_and_allocate("debug_save_uvel", "saved uvel for debug", {nz,ny,nx,nens}, {"z","y","x","nens"} ); + dm_device.register_and_allocate("debug_save_wvel", "saved wvel for debug", {nz,ny,nx,nens}, {"z","y","x","nens"} ); auto debug_save_temp = dm_device.get("debug_save_temp"); auto debug_save_rhod = dm_device.get("debug_save_rhod"); auto debug_save_rhov = dm_device.get("debug_save_rhov"); auto debug_save_rhoc = dm_device.get("debug_save_rhoc"); auto debug_save_rhoi = dm_device.get("debug_save_rhoi"); + auto debug_save_uvel = dm_device.get("debug_save_uvel"); + auto debug_save_wvel = dm_device.get("debug_save_wvel"); //------------------------------------------------------------------------------------------------ - auto temp = dm_device.get("temp"); - auto rhod = dm_device.get("density_dry"); - auto rhov = dm_device.get("water_vapor"); - auto rhoc = dm_device.get("cloud_water"); - auto rhoi = dm_device.get("ice"); + auto temp = dm_device.get("temp"); + auto rhod = dm_device.get("density_dry"); + auto rhov = dm_device.get("water_vapor"); + auto rhoc = dm_device.get("cloud_water"); + auto rhoi = dm_device.get("ice"); + auto uvel = dm_device.get("uvel"); + auto wvel = dm_device.get("wvel"); //------------------------------------------------------------------------------------------------ parallel_for("copy data to saved debug variables", SimpleBounds<4>(nz,ny,nx,nens), YAKL_LAMBDA (int k, int j, int i, int iens) { @@ -50,6 +56,8 @@ inline void pam_debug_init( pam::PamCoupler &coupler ) { debug_save_rhov(k,j,i,iens) = rhov(k,j,i,iens); debug_save_rhoc(k,j,i,iens) = rhoc(k,j,i,iens); debug_save_rhoi(k,j,i,iens) = rhoi(k,j,i,iens); + debug_save_uvel(k,j,i,iens) = uvel(k,j,i,iens); + debug_save_wvel(k,j,i,iens) = wvel(k,j,i,iens); }); //------------------------------------------------------------------------------------------------ } @@ -59,81 +67,185 @@ void pam_debug_check_state( pam::PamCoupler &coupler, int id, int nstep ) { using yakl::c::parallel_for; using yakl::c::SimpleBounds; auto &dm_device = coupler.get_data_manager_device_readwrite(); - auto &dm_host = coupler.get_data_manager_host_readwrite(); + auto &dm_host = coupler.get_data_manager_host_readonly(); auto nx = coupler.get_option("crm_nx"); auto ny = coupler.get_option("crm_ny"); auto nz = coupler.get_option("crm_nz"); auto nens = coupler.get_option("ncrms"); - auto temp = dm_device.get("temp"); - auto rhod = dm_device.get("density_dry"); - auto rhov = dm_device.get("water_vapor"); - auto rhoc = dm_device.get("cloud_water"); - auto rhoi = dm_device.get("ice"); + auto temp = dm_device.get("temp"); + auto rhod = dm_device.get("density_dry"); + auto rhov = dm_device.get("water_vapor"); + auto rhoc = dm_device.get("cloud_water"); + auto rhoi = dm_device.get("ice"); + auto uvel = dm_device.get("uvel"); + auto wvel = dm_device.get("wvel"); auto debug_save_temp = dm_device.get("debug_save_temp"); auto debug_save_rhod = dm_device.get("debug_save_rhod"); auto debug_save_rhov = dm_device.get("debug_save_rhov"); auto debug_save_rhoc = dm_device.get("debug_save_rhoc"); auto debug_save_rhoi = dm_device.get("debug_save_rhoi"); - real grav = 9.80616; - auto input_phis = dm_host.get("input_phis").createDeviceCopy(); + auto debug_save_uvel = dm_device.get("debug_save_uvel"); + auto debug_save_wvel = dm_device.get("debug_save_wvel"); auto lat = dm_host.get("latitude" ).createDeviceCopy(); auto lon = dm_host.get("longitude" ).createDeviceCopy(); + auto input_phis = dm_host.get("input_phis").createDeviceCopy(); + real grav = 9.80616; + //------------------------------------------------------------------------------------------------ + // logical switches to set which checks are active + bool chk_nan = true; // check for NaN values in select fields + bool chk_neg = true; // check for negative values in select fields + bool chk_low_t = false; // check for low temperatures + bool chk_drop_t = true; // check for large drops in temperature + bool chk_wvel = false; // check for large vertical velocity //------------------------------------------------------------------------------------------------ // Check for invalid values parallel_for("", SimpleBounds<4>(nz,ny,nx,nens), YAKL_LAMBDA (int k, int j, int i, int iens) { + auto phis = input_phis(iens)/grav; + //-------------------------------------------------------------------------- // Check for NaNs - const auto is_nan_t_atm = isnan( temp(k,j,i,iens) ); - const auto is_nan_r_atm = isnan( rhod(k,j,i,iens) ); - const auto is_nan_q_atm = isnan( rhov(k,j,i,iens) ); - if ( is_nan_t_atm || is_nan_r_atm || is_nan_q_atm ) { - auto phis = input_phis(iens)/grav; - PRINTF("PAM-DEBUG nan-found - st:%3.3d id:%2.2d k:%3.3d i:%3.3d n:%3.3d y:%5.1f x:%5.1f ph:%6.1f -- t:%8.2g rd:%8.2g rv:%8.2g rc:%8.2g ri:%8.2g -- t:%8.2g rd:%8.2g rv:%8.2g rc:%8.2g ri:%8.2g \n", - nstep,id,k,i,iens,lat(iens),lon(iens),phis, - temp(k,j,i,iens), - rhod(k,j,i,iens), - rhov(k,j,i,iens), - rhoc(k,j,i,iens), - rhoi(k,j,i,iens), - debug_save_temp(k,j,i,iens), - debug_save_rhod(k,j,i,iens), - debug_save_rhov(k,j,i,iens), - debug_save_rhoc(k,j,i,iens), - debug_save_rhoi(k,j,i,iens) - ); + if (chk_nan) { + const auto is_nan_t_atm = isnan( temp(k,j,i,iens) ); + const auto is_nan_d_atm = isnan( rhod(k,j,i,iens) ); + const auto is_nan_q_atm = isnan( rhov(k,j,i,iens) ); + if ( is_nan_t_atm || is_nan_q_atm || is_nan_d_atm ) { + auto phis = input_phis(iens)/grav; + printf("PAM-DEBUG nan-found - st:%3.3d id:%2.2d k:%3.3d i:%3.3d n:%3.3d y:%5.1f x:%5.1f ph:%6.1f -- t:%8.2g rd:%8.2g rv:%8.2g rc:%8.2g ri:%8.2g u:%8.2g w:%8.2g -- t:%8.2g rd:%8.2g rv:%8.2g rc:%8.2g ri:%8.2g u:%8.2g w:%8.2g \n", + nstep,id,k,i,iens,lat(iens),lon(iens),phis, + temp(k,j,i,iens), + rhod(k,j,i,iens), + rhov(k,j,i,iens), + rhoc(k,j,i,iens), + rhoi(k,j,i,iens), + uvel(k,j,i,iens), + wvel(k,j,i,iens), + debug_save_temp(k,j,i,iens), + debug_save_rhod(k,j,i,iens), + debug_save_rhov(k,j,i,iens), + debug_save_rhoc(k,j,i,iens), + debug_save_rhoi(k,j,i,iens), + debug_save_uvel(k,j,i,iens), + debug_save_wvel(k,j,i,iens) + ); + } } + //-------------------------------------------------------------------------- // Check for negative values - const auto is_neg_t_atm = temp(k,j,i,iens)<0; - const auto is_neg_r_atm = rhod(k,j,i,iens)<0; - const auto is_neg_q_atm = rhov(k,j,i,iens)<0; - if ( is_neg_t_atm || is_neg_r_atm || is_neg_q_atm ) { - auto phis = input_phis(iens)/grav; - PRINTF("PAM-DEBUG neg-found - st:%3.3d id:%2.2d k:%3.3d i:%3.3d n:%3.3d y:%5.1f x:%5.1f ph:%6.1f -- t:%8.2g rd:%8.2g rv:%8.2g rc:%8.2g ri:%8.2g -- t:%8.2g rd:%8.2g rv:%8.2g rc:%8.2g ri:%8.2g \n", - nstep,id,k,i,iens,lat(iens),lon(iens),phis, - temp(k,j,i,iens), - rhod(k,j,i,iens), - rhov(k,j,i,iens), - rhoc(k,j,i,iens), - rhoi(k,j,i,iens), - debug_save_temp(k,j,i,iens), - debug_save_rhod(k,j,i,iens), - debug_save_rhov(k,j,i,iens), - debug_save_rhoc(k,j,i,iens), - debug_save_rhoi(k,j,i,iens) - ); + if (chk_neg) { + const auto is_neg_t_atm = temp(k,j,i,iens)<0; + const auto is_neg_d_atm = rhod(k,j,i,iens)<0; + const auto is_neg_q_atm = rhov(k,j,i,iens)<0; + const auto is_neg_c_atm = rhoc(k,j,i,iens)<0; + const auto is_neg_i_atm = rhoi(k,j,i,iens)<0; + if ( is_neg_t_atm || is_neg_q_atm || is_neg_d_atm || is_neg_c_atm || is_neg_i_atm ) { + auto phis = input_phis(iens)/grav; + printf("PAM-DEBUG neg-found - st:%3.3d id:%2.2d k:%3.3d i:%3.3d n:%3.3d y:%5.1f x:%5.1f ph:%6.1f -- t:%8.2g rd:%8.2g rv:%8.2g rc:%8.2g ri:%8.2g u:%8.2g w:%8.2g -- t:%8.2g rd:%8.2g rv:%8.2g rc:%8.2g ri:%8.2g u:%8.2g w:%8.2g \n", + nstep,id,k,i,iens,lat(iens),lon(iens),phis, + temp(k,j,i,iens), + rhod(k,j,i,iens), + rhov(k,j,i,iens), + rhoc(k,j,i,iens), + rhoi(k,j,i,iens), + uvel(k,j,i,iens), + wvel(k,j,i,iens), + debug_save_temp(k,j,i,iens), + debug_save_rhod(k,j,i,iens), + debug_save_rhov(k,j,i,iens), + debug_save_rhoc(k,j,i,iens), + debug_save_rhoi(k,j,i,iens), + debug_save_uvel(k,j,i,iens), + debug_save_wvel(k,j,i,iens) + ); + } } + //-------------------------------------------------------------------------- + // Check for low temperature + if (chk_low_t) { + const auto is_low_t = temp(k,j,i,iens)<100; + if ( is_low_t ) { + printf("PAM-DEBUG low-T - st:%3.3d id:%2.2d k:%3.3d i:%3.3d n:%3.3d y:%5.1f x:%5.1f ph:%6.1f -- t:%8.2g rd:%8.2g rv:%8.2g rc:%8.2g ri:%8.2g u:%8.2g w:%8.2g -- t:%8.2g rd:%8.2g rv:%8.2g rc:%8.2g ri:%8.2g u:%8.2g w:%8.2g \n", + nstep,id,k,i,iens,lat(iens),lon(iens),phis, + temp(k,j,i,iens), + rhod(k,j,i,iens), + rhov(k,j,i,iens), + rhoc(k,j,i,iens), + rhoi(k,j,i,iens), + uvel(k,j,i,iens), + wvel(k,j,i,iens), + debug_save_temp(k,j,i,iens), + debug_save_rhod(k,j,i,iens), + debug_save_rhov(k,j,i,iens), + debug_save_rhoc(k,j,i,iens), + debug_save_rhoi(k,j,i,iens), + debug_save_uvel(k,j,i,iens), + debug_save_wvel(k,j,i,iens) + ); + } + } + //-------------------------------------------------------------------------- + // Check for large temperature drops + if (chk_drop_t) { + const auto is_drop_t = (temp(k,j,i,iens)-debug_save_temp(k,j,i,iens))<-50; + if ( is_drop_t ) { + printf("PAM-DEBUG drop-T - st:%3.3d id:%2.2d k:%3.3d i:%3.3d n:%3.3d y:%5.1f x:%5.1f ph:%6.1f -- t:%8.2g rd:%8.2g rv:%8.2g rc:%8.2g ri:%8.2g u:%8.2g w:%8.2g -- t:%8.2g rd:%8.2g rv:%8.2g rc:%8.2g ri:%8.2g u:%8.2g w:%8.2g \n", + nstep,id,k,i,iens,lat(iens),lon(iens),phis, + temp(k,j,i,iens), + rhod(k,j,i,iens), + rhov(k,j,i,iens), + rhoc(k,j,i,iens), + rhoi(k,j,i,iens), + uvel(k,j,i,iens), + wvel(k,j,i,iens), + debug_save_temp(k,j,i,iens), + debug_save_rhod(k,j,i,iens), + debug_save_rhov(k,j,i,iens), + debug_save_rhoc(k,j,i,iens), + debug_save_rhoi(k,j,i,iens), + debug_save_uvel(k,j,i,iens), + debug_save_wvel(k,j,i,iens) + ); + } + } + //-------------------------------------------------------------------------- + // Check for large vertical velocity + if (chk_wvel) { + const auto is_large_pos_w = wvel(k,j,i,iens)> 40; + const auto is_large_neg_w = wvel(k,j,i,iens)<-40; + if ( is_large_pos_w || is_large_neg_w ) { + printf("PAM-DEBUG large-W - st:%3.3d id:%2.2d k:%3.3d i:%3.3d n:%3.3d y:%5.1f x:%5.1f ph:%6.1f -- t:%8.2g rd:%8.2g rv:%8.2g rc:%8.2g ri:%8.2g u:%8.2g w:%8.2g -- t:%8.2g rd:%8.2g rv:%8.2g rc:%8.2g ri:%8.2g u:%8.2g w:%8.2g \n", + nstep,id,k,i,iens,lat(iens),lon(iens),phis, + temp(k,j,i,iens), + rhod(k,j,i,iens), + rhov(k,j,i,iens), + rhoc(k,j,i,iens), + rhoi(k,j,i,iens), + uvel(k,j,i,iens), + wvel(k,j,i,iens), + debug_save_temp(k,j,i,iens), + debug_save_rhod(k,j,i,iens), + debug_save_rhov(k,j,i,iens), + debug_save_rhoc(k,j,i,iens), + debug_save_rhoi(k,j,i,iens), + debug_save_uvel(k,j,i,iens), + debug_save_wvel(k,j,i,iens) + ); + } + } + //-------------------------------------------------------------------------- // update saved previous values debug_save_temp(k,j,i,iens) = temp(k,j,i,iens); debug_save_rhod(k,j,i,iens) = rhod(k,j,i,iens); debug_save_rhov(k,j,i,iens) = rhov(k,j,i,iens); debug_save_rhoc(k,j,i,iens) = rhoc(k,j,i,iens); debug_save_rhoi(k,j,i,iens) = rhoi(k,j,i,iens); + debug_save_uvel(k,j,i,iens) = uvel(k,j,i,iens); + debug_save_wvel(k,j,i,iens) = wvel(k,j,i,iens); }); //------------------------------------------------------------------------------------------------ } // print the min and max of PAM state variables to help look for problems // void print_state_min_max( pam::PamCoupler &coupler, std::string id ) { - // auto &dm_device = coupler.get_data_manager_device_readwrite(); + // auto &dm_device = coupler.get_data_manager_device_readonly(); // auto nz = coupler.get_option("crm_nz"); // auto nx = coupler.get_option("crm_nx"); // auto ny = coupler.get_option("crm_ny"); @@ -195,18 +307,18 @@ void pam_debug_check_state( pam::PamCoupler &coupler, int id, int nstep ) { void pam_debug_print_state( pam::PamCoupler &coupler, int id ) { using yakl::c::parallel_for; using yakl::c::SimpleBounds; - auto &dm_device = coupler.get_data_manager_device_readwrite(); + auto &dm_device = coupler.get_data_manager_device_readonly(); auto nz = coupler.get_option("crm_nz"); auto nx = coupler.get_option("crm_nx"); auto ny = coupler.get_option("crm_ny"); auto nens = coupler.get_option("ncrms"); // auto pmid = coupler.compute_pressure_array(); // auto zmid = dm_device.get("vertical_midpoint_height" ); - auto temp = dm_device.get("temp"); - auto rho_v = dm_device.get("water_vapor"); - auto rho_c = dm_device.get("cloud_water"); - auto rho_d = dm_device.get("density_dry"); - auto rho_i = dm_device.get("ice"); + auto temp = dm_device.get("temp"); + auto rho_v = dm_device.get("water_vapor"); + auto rho_c = dm_device.get("cloud_water"); + auto rho_d = dm_device.get("density_dry"); + auto rho_i = dm_device.get("ice"); // parallel_for("", SimpleBounds<4>(nz,ny,nx,nens), YAKL_LAMBDA (int k, int j, int i, int iens) { parallel_for("pam_debug_print_state", SimpleBounds<2>(nz,nx), YAKL_LAMBDA (int k, int i) { int j = 0; diff --git a/components/eam/src/physics/crm/pam/pam_driver.cpp b/components/eam/src/physics/crm/pam/pam_driver.cpp index bfba64696163..c7038343f08a 100644 --- a/components/eam/src/physics/crm/pam/pam_driver.cpp +++ b/components/eam/src/physics/crm/pam/pam_driver.cpp @@ -1,5 +1,4 @@ #include "pam_coupler.h" -// #include "params.h" #include "Dycore.h" #include "Microphysics.h" #include "SGS.h" @@ -14,12 +13,11 @@ #include "pam_output.h" #include "pam_accelerate.h" #include "pam_variance_transport.h" +#include "pam_hyperdiffusion.h" #include "sponge_layer.h" #include "surface_friction.h" #include "scream_cxx_interface_finalize.h" -#include "pam_hyperdiffusion.h" - // Needed for p3_init #include "p3_functions.hpp" #include "p3_f90.hpp" @@ -27,13 +25,78 @@ #include "pam_debug.h" bool constexpr enable_check_state = false; -extern "C" void pam_driver() { + +inline int pam_driver_set_subcycle_timestep( pam::PamCoupler &coupler, real crm_dt_fixed ) { + // calculate the CFL condition and adjust the PAM time loop subcylcing //------------------------------------------------------------------------------------------------ - using yakl::intrinsics::abs; - using yakl::intrinsics::maxval; - using yakl::atomicAdd; using yakl::c::parallel_for; using yakl::c::SimpleBounds; + using yakl::atomicMax; + //------------------------------------------------------------------------------------------------ + auto nens = coupler.get_option("ncrms"); + auto gcm_nlev = coupler.get_option("gcm_nlev"); + auto crm_nz = coupler.get_option("crm_nz"); + auto crm_nx = coupler.get_option("crm_nx"); + auto crm_ny = coupler.get_option("crm_ny"); + auto crm_dx = coupler.get_option("crm_dx"); + auto crm_dy = coupler.get_option("crm_dy"); + auto &dm_device = coupler.get_data_manager_device_readonly(); + auto &dm_host = coupler.get_data_manager_host_readonly(); + auto uvel = dm_device.get("uvel"); + auto wvel = dm_device.get("wvel"); + auto input_zint = dm_host.get("input_zint").createDeviceCopy(); + //------------------------------------------------------------------------------------------------ + yakl::ParallelMax pmax( crm_nz*nens ); + real cfl = 0; + int num_subcycle = 1; + int constexpr max_num_subcycle = 10; + real2d wvel_max("wvel_max",crm_nz,nens); + real2d uvel_max("uvel_max",crm_nz,nens); + real2d cfl_max("cfl_max", crm_nz,nens); + //------------------------------------------------------------------------------------------------ + // initialize max U and W arrays + parallel_for( SimpleBounds<2>(crm_nz,nens) , YAKL_LAMBDA (int k, int n) { + wvel_max(k,n) = 0.0; + uvel_max(k,n) = 0.0; + }); + // calculate max U and W + parallel_for( SimpleBounds<4>(crm_nz,crm_ny,crm_nx,nens) , YAKL_LAMBDA (int k, int j, int i, int n) { + yakl::atomicMax(uvel_max(k,n), std::abs(uvel(k,j,i,n)) ); + yakl::atomicMax(wvel_max(k,n), std::abs(wvel(k,j,i,n)) ); + }); + // find max CFL between horizontal and vertical CFL values + parallel_for( SimpleBounds<2>(crm_nz,nens) , YAKL_LAMBDA (int k, int n) { + int k_gcm = gcm_nlev-1-k; + real crm_dz = input_zint(k_gcm,n) - input_zint(k_gcm+1,n); + real cfl_u = uvel_max(k,n)*crm_dt_fixed/crm_dx; + real cfl_w = wvel_max(k,n)*crm_dt_fixed/crm_dz; + cfl_max(k,n) = std::max(cfl_u,cfl_w); + }); + // calculate final CFL across ensemble + real cfl_loc = yakl::intrinsics::maxval(cfl_max); + cfl = std::max(cfl,cfl_loc); + // update number of subcycles and time step + num_subcycle = std::max(num_subcycle,std::max(1,static_cast(ceil(cfl/0.7)))); + real crm_dt_subcycle = crm_dt_fixed / num_subcycle; + coupler.set_option("crm_dt",crm_dt_subcycle); + // check for excessive subcylcing - don't exit, just print + if(num_subcycle > max_num_subcycle) { + real umax = pmax(uvel_max.data()); + real wmax = pmax(wvel_max.data()); + printf("PAM_DRIVER - WARNING: excessive subcycling!" + " - num_subcycle: %3.3d dt: %8.4f cfl: %8.4f umax: %8.2f wmax: %8.2f \n", + num_subcycle,crm_dt_subcycle,cfl,umax,wmax); + // exit(-1); + } + + return num_subcycle; + //------------------------------------------------------------------------------------------------ +} + + +extern "C" void pam_driver() { + // This is the primary method for running the PAM CRM in E3SM-MMF. + //------------------------------------------------------------------------------------------------ auto &coupler = pam_interface::get_coupler(); //------------------------------------------------------------------------------------------------ // retreive coupler options @@ -42,8 +105,10 @@ extern "C" void pam_driver() { auto crm_nz = coupler.get_option("crm_nz"); auto crm_nx = coupler.get_option("crm_nx"); auto crm_ny = coupler.get_option("crm_ny"); + // auto crm_dx = coupler.get_option("crm_dx"); + // auto crm_dy = coupler.get_option("crm_dy"); auto gcm_dt = coupler.get_option("gcm_dt"); - auto crm_dt = coupler.get_option("crm_dt"); + auto crm_dt_fixed = coupler.get_option("crm_dt"); auto is_first_step = coupler.get_option("is_first_step"); auto is_restart = coupler.get_option("is_restart"); bool use_crm_accel = coupler.get_option("use_crm_accel"); @@ -52,16 +117,19 @@ extern "C" void pam_driver() { //------------------------------------------------------------------------------------------------ // set various coupler options coupler.set_option("gcm_physics_dt",gcm_dt); - #ifdef MMF_PAM_DPP - // this is leftover from debugging, but it might still be useful for testing values of crm_per_phys - coupler.set_option("crm_per_phys",MMF_PAM_DPP); - #else - coupler.set_option("crm_per_phys",2); // # of PAM-C dynamics steps per physics - #endif coupler.set_option("sponge_num_layers",crm_nz*0.3); // depth of sponge layer coupler.set_option("sponge_time_scale",60); // minimum damping timescale at top coupler.set_option("crm_acceleration_ceaseflag",false); //------------------------------------------------------------------------------------------------ + // coupler options for SPAM dycor + coupler.set_option("crm_dyn_per_phys",1); + coupler.set_option("spam_couple_wind_exact_inverse",true); + coupler.set_option("spam_clip_negative_densities",true); + coupler.set_option("spam_clip_vertical_velocities",true); + coupler.set_option("spam_adjust_crm_per_phys_using_vert_cfl",true); + coupler.set_option("spam_target_cfl",0.7); + coupler.set_option("spam_max_w",30.0); + //------------------------------------------------------------------------------------------------ // Allocate the coupler state and retrieve host/device data managers coupler.allocate_coupler_state( crm_nz , crm_ny , crm_nx , nens ); @@ -89,8 +157,10 @@ extern "C" void pam_driver() { // Copy input CRM state (saved by the GCM) to coupler pam_state_copy_input_to_coupler(coupler); - // // update CRM dry density to match GCM and disable dry density forcing - // pam_state_update_dry_density(coupler); + #ifdef MMF_DISABLE_DENSITY_FORCING + // update CRM dry density to match GCM and disable dry density forcing + pam_state_update_dry_density(coupler); + #endif // if debugging - initialize saved state variables and check initial CRM state if (enable_check_state) { @@ -150,12 +220,15 @@ extern "C" void pam_driver() { dycore.declare_current_profile_as_hydrostatic(coupler,/*use_gcm_data=*/true); #endif + #ifdef MMF_DISABLE_DENSITY_RECALL + do_density_save_recall = false; + #endif //------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------ // set number of CRM steps - int nstop = int(gcm_dt/crm_dt); + int nstop = int(gcm_dt/crm_dt_fixed); // for mean-state acceleration adjust nstop and diagnose horizontal means if (use_crm_accel) { @@ -164,50 +237,58 @@ extern "C" void pam_driver() { }; // Run the CRM - real etime_crm = 0; int nstep = 0; - // while (etime_crm < gcm_dt) { while (nstep < nstop) { - if (crm_dt == 0.) { crm_dt = dycore.compute_time_step(coupler); } - if (etime_crm + crm_dt > gcm_dt) { crm_dt = gcm_dt - etime_crm; } + //-------------------------------------------------------------------------- + //-------------------------------------------------------------------------- + auto num_subcycle = pam_driver_set_subcycle_timestep(coupler,crm_dt_fixed); + #if defined(MMF_PAM_DYCOR_SPAM) + dycore.update_dt(coupler); + #endif if (enable_check_state) { pam_debug_check_state(coupler, 1, nstep); } - // Apply forcing tendencies - if (use_MMF_VT) { pam_variance_transport_apply_forcing(coupler); } - coupler.run_module( "apply_gcm_forcing_tendencies" , modules::apply_gcm_forcing_tendencies ); - coupler.run_module( "radiation" , [&] (pam::PamCoupler &coupler) {rad .timeStep(coupler);} ); - if (enable_check_state) { pam_debug_check_state(coupler, 2, nstep); } - - // Dynamics - if (enable_physics_tend_stats) { pam_statistics_save_state(coupler); } - if (do_density_save_recall) { pam_state_save_dry_density(coupler); } - coupler.run_module( "dycore", [&] (pam::PamCoupler &coupler) {dycore.timeStep(coupler);} ); - if (do_density_save_recall) { pam_state_recall_dry_density(coupler); } - if (enable_physics_tend_stats) { pam_statistics_aggregate_tendency(coupler,"dycor"); } - if (enable_check_state) { pam_debug_check_state(coupler, 3, nstep); } - - // Sponge layer damping - if (enable_physics_tend_stats) { pam_statistics_save_state(coupler); } - coupler.run_module( "sponge_layer", modules::sponge_layer ); - if (enable_physics_tend_stats) { pam_statistics_aggregate_tendency(coupler,"sponge"); } - if (enable_check_state) { pam_debug_check_state(coupler, 4, nstep); } - - // Apply hyperdiffusion to account for lack of horizontal mixing in SHOC - pam_hyperdiffusion(coupler); - - // Turbulence - SHOC - coupler.run_module( "compute_surface_friction", modules::compute_surface_friction ); - if (enable_physics_tend_stats) { pam_statistics_save_state(coupler); } - coupler.run_module( "sgs", [&] (pam::PamCoupler &coupler) {sgs .timeStep(coupler);} ); - if (enable_physics_tend_stats) { pam_statistics_aggregate_tendency(coupler,"sgs"); } - if (enable_check_state) { pam_debug_check_state(coupler, 5, nstep); } - - // Microphysics - P3 - if (enable_physics_tend_stats) { pam_statistics_save_state(coupler); } - coupler.run_module( "micro", [&] (pam::PamCoupler &coupler) {micro .timeStep(coupler);} ); - if (enable_physics_tend_stats) { pam_statistics_aggregate_tendency(coupler,"micro"); } - if (enable_check_state) { pam_debug_check_state(coupler, 6, nstep); } + // loop for adaptive subcyling based on CFL + for(int icycle=1; icycle<=num_subcycle; icycle++) { + + // Apply forcing tendencies + if (use_MMF_VT) { pam_variance_transport_apply_forcing(coupler); } + if (enable_check_state) { pam_debug_check_state(coupler, 2, nstep); } + coupler.run_module( "apply_gcm_forcing_tendencies" , modules::apply_gcm_forcing_tendencies ); + if (enable_check_state) { pam_debug_check_state(coupler, 3, nstep); } + coupler.run_module( "radiation" , [&] (pam::PamCoupler &coupler) {rad .timeStep(coupler);} ); + if (enable_check_state) { pam_debug_check_state(coupler, 4, nstep); } + + // Dynamics + if (enable_physics_tend_stats) { pam_statistics_save_state(coupler); } + if (do_density_save_recall) { pam_state_save_dry_density(coupler); } + coupler.run_module( "dycore", [&] (pam::PamCoupler &coupler) {dycore.timeStep(coupler);} ); + if (do_density_save_recall) { pam_state_recall_dry_density(coupler); } + if (enable_physics_tend_stats) { pam_statistics_aggregate_tendency(coupler,"dycor"); } + if (enable_check_state) { pam_debug_check_state(coupler, 5, nstep); } + + // Sponge layer damping + if (enable_physics_tend_stats) { pam_statistics_save_state(coupler); } + coupler.run_module( "sponge_layer", modules::sponge_layer ); + if (enable_physics_tend_stats) { pam_statistics_aggregate_tendency(coupler,"sponge"); } + + // Apply hyperdiffusion to account for lack of horizontal mixing in SHOC + pam_hyperdiffusion(coupler); + + // Turbulence - SHOC + coupler.run_module( "compute_surface_friction", modules::compute_surface_friction ); + if (enable_physics_tend_stats) { pam_statistics_save_state(coupler); } + coupler.run_module( "sgs", [&] (pam::PamCoupler &coupler) {sgs .timeStep(coupler);} ); + if (enable_physics_tend_stats) { pam_statistics_aggregate_tendency(coupler,"sgs"); } + if (enable_check_state) { pam_debug_check_state(coupler, 6, nstep); } + + // Microphysics - P3 + if (enable_physics_tend_stats) { pam_statistics_save_state(coupler); } + coupler.run_module( "micro", [&] (pam::PamCoupler &coupler) {micro .timeStep(coupler);} ); + if (enable_physics_tend_stats) { pam_statistics_aggregate_tendency(coupler,"micro"); } + if (enable_check_state) { pam_debug_check_state(coupler, 7, nstep); } + + } // num_subcycle // CRM mean state acceleration if (use_crm_accel && !coupler.get_option("crm_acceleration_ceaseflag")) { @@ -219,7 +300,6 @@ extern "C" void pam_driver() { pam_radiation_timestep_aggregation(coupler); pam_statistics_timestep_aggregation(coupler); - etime_crm += crm_dt; nstep += 1; } //------------------------------------------------------------------------------------------------ diff --git a/components/eam/src/physics/crm/pam/pam_hyperdiffusion.h b/components/eam/src/physics/crm/pam/pam_hyperdiffusion.h index 83dc83252c68..b632b0e49093 100644 --- a/components/eam/src/physics/crm/pam/pam_hyperdiffusion.h +++ b/components/eam/src/physics/crm/pam/pam_hyperdiffusion.h @@ -25,7 +25,11 @@ inline void pam_hyperdiffusion( pam::PamCoupler &coupler ) { auto uvel = dm_device.get("uvel" ); auto vvel = dm_device.get("vvel" ); //------------------------------------------------------------------------------------------------ - real constexpr hd_timescale = 10.0; // damping time scale [sec] + #ifdef MMF_PAM_HDT + real constexpr hd_timescale = MMF_PAM_HDT; // damping time scale [sec] + #else + real constexpr hd_timescale = 60.0; // damping time scale [sec] + #endif //------------------------------------------------------------------------------------------------ real4d hd_temp("hd_temp",nz,ny,nx,nens); real4d hd_rhod("hd_rhod",nz,ny,nx,nens); diff --git a/components/eam/src/physics/crm/pam/pam_state.h b/components/eam/src/physics/crm/pam/pam_state.h index e8f6e4ab668a..980fb7f4eb0a 100644 --- a/components/eam/src/physics/crm/pam/pam_state.h +++ b/components/eam/src/physics/crm/pam/pam_state.h @@ -108,6 +108,7 @@ inline void pam_state_set_reference_state( pam::PamCoupler &coupler ) { auto &dm_device = coupler.get_data_manager_device_readwrite(); auto nens = coupler.get_option("ncrms"); auto nz = coupler.get_option("crm_nz"); + auto gcm_nlev = coupler.get_option("gcm_nlev"); auto ref_presi = dm_device.get("ref_presi"); auto ref_pres = dm_device.get("ref_pres"); auto ref_rho_d = dm_device.get("ref_density_dry"); @@ -131,6 +132,14 @@ inline void pam_state_set_reference_state( pam::PamCoupler &coupler ) { auto rho_v = dm_device.get("water_vapor"); auto rho_c = dm_device.get("cloud_water"); auto rho_i = dm_device.get("ice"); + + auto &dm_host = coupler.get_data_manager_host_readonly(); + auto input_pmid = dm_host.get("input_pmid").createDeviceCopy(); + auto input_pint = dm_host.get("input_pint").createDeviceCopy(); + + auto lat = dm_host.get("latitude" ).createDeviceCopy(); + auto lon = dm_host.get("longitude" ).createDeviceCopy(); + auto input_phis = dm_host.get("input_phis").createDeviceCopy(); //------------------------------------------------------------------------------------------------ // Set anelastic reference state with current CRM mean state @@ -144,10 +153,9 @@ inline void pam_state_set_reference_state( pam::PamCoupler &coupler ) { real2d hmean_temp ("hmean_temp" ,nz ,nens); real r_nx_ny = 1._fp/(nx*ny); // precompute reciprocal to avoid costly divisions // initialize horizontal means - parallel_for(SimpleBounds<2>(nz,nens), YAKL_LAMBDA (int k, int iens) { + parallel_for(SimpleBounds<2>(nz+1,nens), YAKL_LAMBDA (int k, int iens) { hmean_pint(k,iens) = 0; if (k < nz) { - hmean_pmid (k,iens) = 0; hmean_rho_d(k,iens) = 0; hmean_rho_v(k,iens) = 0; hmean_rho_c(k,iens) = 0; @@ -157,33 +165,37 @@ inline void pam_state_set_reference_state( pam::PamCoupler &coupler ) { }); // calculate horizontal means parallel_for(SimpleBounds<4>(nz,ny,nx,nens), YAKL_LAMBDA (int k, int j, int i, int iens) { - real pmid_tmp = rho_d(k,j,i,iens)*R_d*temp(k,j,i,iens) + rho_v(k,j,i,iens)*R_v*temp(k,j,i,iens); - atomicAdd( hmean_pmid (k,iens), pmid_tmp * r_nx_ny ); atomicAdd( hmean_rho_d(k,iens), rho_d (k,j,i,iens) * r_nx_ny ); atomicAdd( hmean_rho_v(k,iens), rho_v (k,j,i,iens) * r_nx_ny ); atomicAdd( hmean_rho_c(k,iens), rho_c (k,j,i,iens) * r_nx_ny ); atomicAdd( hmean_rho_i(k,iens), rho_i (k,j,i,iens) * r_nx_ny ); atomicAdd( hmean_temp (k,iens), temp (k,j,i,iens) * r_nx_ny ); }); - // calculate interface pressure from mid-level pressure - parallel_for(SimpleBounds<4>(nz+1,ny,nx,nens) , YAKL_LAMBDA (int k, int j, int i, int iens) { - if (k == 0 ) { - real rho = rho_d(k ,j,i,iens)+rho_v(k ,j,i,iens); - real dz = zint(k+1,iens)-zint(k ,iens); - hmean_pint(k,iens) = hmean_pmid(k ,iens) + grav*rho*dz/2; - } else if (k == nz) { - real rho = rho_d(k-1,j,i,iens)+rho_v(k-1,j,i,iens); - real dz = zint(k ,iens)-zint(k-1,iens); - hmean_pint(k,iens) = hmean_pmid(k-1,iens) - grav*rho*dz/2; - } else { - real rhokm1 = rho_d(k-1,j,i,iens)+rho_v(k-1,j,i,iens); - real rhokm0 = rho_d(k ,j,i,iens)+rho_v(k ,j,i,iens); - real dzkm1 = zint(k ,iens)-zint(k-1,iens); - real dzkm0 = zint(k+1,iens)-zint(k ,iens); - hmean_pint(k,iens) = 0.5_fp * ( hmean_pmid(k-1,iens) - grav*rhokm1*dzkm1/2 + - hmean_pmid(k ,iens) + grav*rhokm0*dzkm0/2 ); + + // Use GCM state for reference pressure - previously, the current CRM pressure + // was used, but the way the interface pressure was calculated led to problems + // in edge cases (ex. over topography) - switching to GCM pressure works well + parallel_for( SimpleBounds<2>(nz+1,nens) , YAKL_LAMBDA (int k_crm, int iens) { + int k_gcm = (gcm_nlev+1)-1-k_crm; + hmean_pint(k_crm,iens) = input_pint(k_gcm,iens); + }); + parallel_for(SimpleBounds<2>(nz,nens), YAKL_LAMBDA (int k_crm, int iens) { + int k_gcm = gcm_nlev-1-k_crm; + hmean_pmid(k_crm,iens) = input_pmid(k_gcm,iens); + }); + + // check that interface pressure is reasonable + parallel_for(SimpleBounds<2>(nz,nens) , YAKL_LAMBDA (int k, int iens) { + if ( hmean_pint(k,iens) < hmean_pmid(k,iens) ) { + auto phis = input_phis(iens)/grav; + printf("PAM-STATE - bad interface pressure for reference state - " + "k:%3.3d n:%3.3d y:%5.1f x:%5.1f ph:%6.1f -- " + "pint:%12.4f pmid:%12.4f \n", + k,iens,lat(iens),lon(iens),phis, + hmean_pint(k,iens),hmean_pmid(k,iens)); } }); + // set anelastic reference state from CRM horizontal mean parallel_for(SimpleBounds<2>(nz+1,nens) , YAKL_LAMBDA (int k, int iens) { ref_presi(k,iens) = hmean_pint(k,iens); @@ -258,9 +270,17 @@ inline void pam_state_save_dry_density( pam::PamCoupler &coupler ) { // recall CRM dry density saved previously - only for anelastic case +// Note - The need for this arises because the SPAM dycor diagnoses the dry +// density in a way that preserves the total density to match the reference +// density. However, this is problematic in the presence of the GCM forcing +// which naturally changes the total density. Therefore, we can recall the +// previous dry density and use it to replace the horizontal mean returned from +// the dycor, which ensures that the impact of GCM forcing is preserved while +// also retaining the dry density perturbations created by the dycor. inline void pam_state_recall_dry_density( pam::PamCoupler &coupler ) { using yakl::c::parallel_for; using yakl::c::SimpleBounds; + using yakl::atomicAdd; auto &dm_device = coupler.get_data_manager_device_readwrite(); auto nens = coupler.get_option("ncrms"); auto nz = coupler.get_option("crm_nz"); @@ -269,12 +289,31 @@ inline void pam_state_recall_dry_density( pam::PamCoupler &coupler ) { auto crm_rho_d = dm_device.get("density_dry"); auto tmp_rho_d = dm_device.get("density_dry_save"); //------------------------------------------------------------------------------------------------ - parallel_for( "Recall CRM dry density", - SimpleBounds<4>(nz,ny,nx,nens), - YAKL_LAMBDA (int k_crm, int j, int i, int iens) { - crm_rho_d(k_crm,j,i,iens) = tmp_rho_d(k_crm,j,i,iens); + // initialize horizontal mean of previous CRM dry density + real2d old_hmean_rho_d("old_hmean_rho_d" ,nz,nens); + real2d new_hmean_rho_d("new_hmean_rho_d" ,nz,nens); + parallel_for(SimpleBounds<2>(nz,nens), YAKL_LAMBDA (int k, int iens) { + old_hmean_rho_d(k,iens) = 0; + new_hmean_rho_d(k,iens) = 0; + }); + real r_nx_ny = 1._fp/(nx*ny); // precompute reciprocal to avoid costly divisions + // calculate horizontal mean of previous CRM dry density + parallel_for(SimpleBounds<4>(nz,ny,nx,nens), YAKL_LAMBDA (int k, int j, int i, int iens) { + atomicAdd( old_hmean_rho_d(k,iens), tmp_rho_d(k,j,i,iens) * r_nx_ny ); + atomicAdd( new_hmean_rho_d(k,iens), crm_rho_d(k,j,i,iens) * r_nx_ny ); + }); + // replace horizontal mean dry density with previous value + parallel_for(SimpleBounds<4>(nz,ny,nx,nens), YAKL_LAMBDA (int k, int j, int i, int iens) { + crm_rho_d(k,j,i,iens) = crm_rho_d(k,j,i,iens) - new_hmean_rho_d(k,iens) + old_hmean_rho_d(k,iens); }); //------------------------------------------------------------------------------------------------ + // Original simple appraoch to completely reinstate the previous dry density field + // (this was shown to negatively impact the model stability) + // This was used initially, but the above + // parallel_for( "Recall CRM dry density",SimpleBounds<4>(nz,ny,nx,nens),YAKL_LAMBDA (int k_crm, int j, int i, int iens) { + // crm_rho_d(k_crm,j,i,iens) = tmp_rho_d(k_crm,j,i,iens); + // }); + //------------------------------------------------------------------------------------------------ } diff --git a/components/eam/src/physics/crm/pam/pam_variance_transport.h b/components/eam/src/physics/crm/pam/pam_variance_transport.h index b7067631203f..70b985cc2b7b 100644 --- a/components/eam/src/physics/crm/pam/pam_variance_transport.h +++ b/components/eam/src/physics/crm/pam/pam_variance_transport.h @@ -2,6 +2,7 @@ #include "pam_coupler.h" + inline void pam_variance_transport_init( pam::PamCoupler &coupler ) { using yakl::c::parallel_for; using yakl::c::SimpleBounds; @@ -24,6 +25,7 @@ inline void pam_variance_transport_init( pam::PamCoupler &coupler ) { //------------------------------------------------------------------------------------------------ } + inline void pam_variance_transport_diagnose( pam::PamCoupler &coupler ) { using yakl::c::parallel_for; using yakl::c::SimpleBounds; @@ -34,9 +36,11 @@ inline void pam_variance_transport_diagnose( pam::PamCoupler &coupler ) { auto ny = coupler.get_option("crm_ny"); auto nx = coupler.get_option("crm_nx"); //------------------------------------------------------------------------------------------------ - auto temp = dm_device.get("temp" ); - auto rhov = dm_device.get("water_vapor"); - auto uvel = dm_device.get("uvel" ); + auto temp = dm_device.get("temp" ); + auto rhov = dm_device.get("water_vapor"); + auto rhoc = dm_device.get("cloud_water"); + auto rhoi = dm_device.get("ice" ); + auto uvel = dm_device.get("uvel" ); auto vt_temp = dm_device.get("vt_temp" ); auto vt_rhov = dm_device.get("vt_rhov" ); auto vt_uvel = dm_device.get("vt_uvel" ); @@ -62,15 +66,17 @@ inline void pam_variance_transport_diagnose( pam::PamCoupler &coupler ) { // calculate horizontal mean real r_nx_ny = 1._fp/(nx*ny); // precompute reciprocal to avoid costly divisions parallel_for(SimpleBounds<4>(nz,ny,nx,nens), YAKL_LAMBDA (int k, int j, int i, int n) { + real rhot = rhov(k,j,i,n) + rhoc(k,j,i,n) + rhoi(k,j,i,n); yakl::atomicAdd( temp_mean(k,n), temp(k,j,i,n)*r_nx_ny ); - yakl::atomicAdd( rhov_mean(k,n), rhov(k,j,i,n)*r_nx_ny ); + yakl::atomicAdd( rhov_mean(k,n), rhot *r_nx_ny ); yakl::atomicAdd( uvel_mean(k,n), uvel(k,j,i,n)*r_nx_ny ); }); //------------------------------------------------------------------------------------------------ // calculate fluctuations from horz mean parallel_for(SimpleBounds<4>(nz,ny,nx,nens), YAKL_LAMBDA (int k, int j, int i, int n) { + real rhot = rhov(k,j,i,n) + rhoc(k,j,i,n) + rhoi(k,j,i,n); vt_temp_pert(k,j,i,n) = temp(k,j,i,n) - temp_mean(k,n); - vt_rhov_pert(k,j,i,n) = rhov(k,j,i,n) - rhov_mean(k,n); + vt_rhov_pert(k,j,i,n) = rhot - rhov_mean(k,n); vt_uvel_pert(k,j,i,n) = uvel(k,j,i,n) - uvel_mean(k,n); }); //------------------------------------------------------------------------------------------------ @@ -83,6 +89,7 @@ inline void pam_variance_transport_diagnose( pam::PamCoupler &coupler ) { //------------------------------------------------------------------------------------------------ } + inline void pam_variance_transport_compute_forcing( pam::PamCoupler &coupler ) { using yakl::c::parallel_for; using yakl::c::SimpleBounds; @@ -98,9 +105,6 @@ inline void pam_variance_transport_compute_forcing( pam::PamCoupler &coupler ) { // update CRM variance values pam_variance_transport_diagnose(coupler); //------------------------------------------------------------------------------------------------ - auto temp = dm_device.get("temp" ); - auto rhov = dm_device.get("water_vapor" ); - auto uvel = dm_device.get("uvel" ); auto vt_temp = dm_device.get("vt_temp" ); auto vt_rhov = dm_device.get("vt_rhov" ); auto vt_uvel = dm_device.get("vt_uvel" ); @@ -114,9 +118,9 @@ inline void pam_variance_transport_compute_forcing( pam::PamCoupler &coupler ) { // calculate variance transport forcing parallel_for( SimpleBounds<2>(nz,nens) , YAKL_LAMBDA (int k_crm, int n) { int k_gcm = gcm_nlev-1-k_crm; - vt_temp_forcing_tend(k_crm,n) = ( gcm_vt_temp(k_gcm,n) - vt_temp(k_crm,n) ) * gcm_dt ; - vt_rhov_forcing_tend(k_crm,n) = ( gcm_vt_rhov(k_gcm,n) - vt_rhov(k_crm,n) ) * gcm_dt ; - vt_uvel_forcing_tend(k_crm,n) = ( gcm_vt_uvel(k_gcm,n) - vt_uvel(k_crm,n) ) * gcm_dt ; + vt_temp_forcing_tend(k_crm,n) = ( gcm_vt_temp(k_gcm,n) - vt_temp(k_crm,n) ) / gcm_dt ; + vt_rhov_forcing_tend(k_crm,n) = ( gcm_vt_rhov(k_gcm,n) - vt_rhov(k_crm,n) ) / gcm_dt ; + vt_uvel_forcing_tend(k_crm,n) = ( gcm_vt_uvel(k_gcm,n) - vt_uvel(k_crm,n) ) / gcm_dt ; }); //------------------------------------------------------------------------------------------------ } @@ -131,13 +135,16 @@ inline void pam_variance_transport_apply_forcing( pam::PamCoupler &coupler ) { auto nx = coupler.get_option("crm_nx"); auto crm_dt = coupler.get_option("crm_dt"); //------------------------------------------------------------------------------------------------ + // update CRM variance values + pam_variance_transport_diagnose(coupler); + //------------------------------------------------------------------------------------------------ // min and max perturbation scaling values are used to limit the // large-scale forcing from variance transport. This is meant to // protect against creating unstable situations, although // problematic scenarios were extremely rare in testing. // A scaling limit of +/- 10% was found to be adequate. - real constexpr pert_scale_min = 1.0 - 0.005; - real constexpr pert_scale_max = 1.0 + 0.005; + real constexpr pert_scale_min = 1.0 - 0.05; + real constexpr pert_scale_max = 1.0 + 0.05; //------------------------------------------------------------------------------------------------ auto temp = dm_device.get("temp" ); auto rhov = dm_device.get("water_vapor" ); @@ -157,19 +164,22 @@ inline void pam_variance_transport_apply_forcing( pam::PamCoupler &coupler ) { real2d rhov_pert_scale("rhov_pert_scale", nz, nens); real2d uvel_pert_scale("uvel_pert_scale", nz, nens); //------------------------------------------------------------------------------------------------ - // update CRM variance values - pam_variance_transport_diagnose(coupler); - //------------------------------------------------------------------------------------------------ // calculate scaling factor for local perturbations parallel_for( SimpleBounds<2>(nz,nens) , YAKL_LAMBDA (int k, int n) { // initialize scaling factors to 1.0 temp_pert_scale(k,n) = 1.0; rhov_pert_scale(k,n) = 1.0; uvel_pert_scale(k,n) = 1.0; - // set scaling factors as long as there are perturbations to scale - if (vt_temp(k,n)>0.0) { temp_pert_scale(k,n) = sqrt( 1.0 + crm_dt * vt_temp_forcing_tend(k,n) / vt_temp(k,n) ); } - if (vt_rhov(k,n)>0.0) { rhov_pert_scale(k,n) = sqrt( 1.0 + crm_dt * vt_rhov_forcing_tend(k,n) / vt_rhov(k,n) ); } - if (vt_uvel(k,n)>0.0) { uvel_pert_scale(k,n) = sqrt( 1.0 + crm_dt * vt_uvel_forcing_tend(k,n) / vt_uvel(k,n) ); } + // calculate variance scaling factor + real tmp_t_scale = -1.0; + real tmp_q_scale = -1.0; + real tmp_u_scale = -1.0; + if (vt_temp(k,n)>0.0) { tmp_t_scale = 1. + crm_dt * vt_temp_forcing_tend(k,n) / vt_temp(k,n); } + if (vt_rhov(k,n)>0.0) { tmp_q_scale = 1. + crm_dt * vt_rhov_forcing_tend(k,n) / vt_rhov(k,n); } + if (vt_uvel(k,n)>0.0) { tmp_u_scale = 1. + crm_dt * vt_uvel_forcing_tend(k,n) / vt_uvel(k,n); } + if (tmp_t_scale>0.0){ temp_pert_scale(k,n) = sqrt(tmp_t_scale); } + if (tmp_q_scale>0.0){ rhov_pert_scale(k,n) = sqrt(tmp_q_scale); } + if (tmp_u_scale>0.0){ uvel_pert_scale(k,n) = sqrt(tmp_u_scale); } // enforce minimum scaling temp_pert_scale(k,n) = std::max( temp_pert_scale(k,n), pert_scale_min ); rhov_pert_scale(k,n) = std::max( rhov_pert_scale(k,n), pert_scale_min ); @@ -208,9 +218,6 @@ inline void pam_variance_transport_compute_feedback( pam::PamCoupler &coupler ) // update CRM variance values pam_variance_transport_diagnose(coupler); //------------------------------------------------------------------------------------------------ - auto temp = dm_device.get("temp" ); - auto rhov = dm_device.get("water_vapor"); - auto uvel = dm_device.get("uvel" ); auto vt_temp = dm_device.get("vt_temp" ); auto vt_rhov = dm_device.get("vt_rhov" ); auto vt_uvel = dm_device.get("vt_uvel" ); @@ -229,9 +236,9 @@ inline void pam_variance_transport_compute_feedback( pam::PamCoupler &coupler ) parallel_for( SimpleBounds<2>(nz,nens) , YAKL_LAMBDA (int k_crm, int n) { int k_gcm = gcm_nlev-1-k_crm; if (k_crm call outfld('CLOUDFRAC_LIQ_MICRO', cld_frac_l, pcols, lchnk) call outfld('CLOUDFRAC_ICE_MICRO', cld_frac_i, pcols, lchnk) diff --git a/components/eam/src/physics/rrtmgp/radiation.F90 b/components/eam/src/physics/rrtmgp/radiation.F90 index 0c715000951d..5c87c3376d9d 100644 --- a/components/eam/src/physics/rrtmgp/radiation.F90 +++ b/components/eam/src/physics/rrtmgp/radiation.F90 @@ -767,6 +767,18 @@ subroutine radiation_init(state,pbuf) call addfld('FLNTC'//diag(icall), horiz_only, 'A', 'W/m2', & 'Clearsky net longwave flux at top of model', & sampling_seq='rad_lwsw', flag_xyfill=.true.) + call addfld('FLUTOA'//diag(icall), horiz_only, 'A', 'W/m2', & + 'Upwelling longwave flux at top of atmosphere', & + sampling_seq='rad_lwsw', flag_xyfill=.true.) + call addfld('FLNTOA'//diag(icall), horiz_only, 'A', 'W/m2', & + 'Net longwave flux at top of atmosphere', & + sampling_seq='rad_lwsw', flag_xyfill=.true.) + call addfld('FLUTOAC'//diag(icall), horiz_only, 'A', 'W/m2', & + 'Clearsky upwelling longwave flux at top of atmosphere', & + sampling_seq='rad_lwsw', flag_xyfill=.true.) + call addfld('FLNTOAC'//diag(icall), horiz_only, 'A', 'W/m2', & + 'Clearsky net longwave flux at top of atmosphere', & + sampling_seq='rad_lwsw', flag_xyfill=.true.) call addfld('LWCF'//diag(icall), horiz_only, 'A', 'W/m2', & 'Longwave cloud forcing', & sampling_seq='rad_lwsw', flag_xyfill=.true.) @@ -2375,6 +2387,7 @@ subroutine output_fluxes_lw(icall, state, flux_all, flux_clr, qrl, qrlc) ! Working arrays real(r8), dimension(pcols,pver+1) :: flux_up, flux_dn, flux_net integer :: ncol + integer :: ktop_rad = 1 ncol = state%ncol @@ -2412,6 +2425,12 @@ subroutine output_fluxes_lw(icall, state, flux_all, flux_clr, qrl, qrlc) call outfld('FLUTC'//diag(icall), flux_clr%flux_up(1:ncol,ktop), ncol, state%lchnk) call outfld('FLDSC'//diag(icall), flux_clr%flux_dn(1:ncol,kbot+1), ncol, state%lchnk) + ! TOA fluxes (above model top, use index to rad top) + call outfld('FLUTOA'//diag(icall), flux_all%flux_up(1:ncol,ktop_rad), ncol, state%lchnk) + call outfld('FLNTOA'//diag(icall), flux_all%flux_net(1:ncol,ktop_rad), ncol, state%lchnk) + call outfld('FLUTOAC'//diag(icall), flux_clr%flux_up(1:ncol,ktop_rad), ncol, state%lchnk) + call outfld('FLNTOAC'//diag(icall), flux_clr%flux_net(1:ncol,ktop_rad), ncol, state%lchnk) + ! Calculate and output the cloud radiative effect (LWCF in history) cloud_radiative_effect(1:ncol) = flux_all%flux_net(1:ncol,ktop) - flux_clr%flux_net(1:ncol,ktop) call outfld('LWCF'//diag(icall), cloud_radiative_effect, ncol, state%lchnk) diff --git a/components/eam/tools/mkatmsrffile/mkatmsrffile.py b/components/eam/tools/mkatmsrffile/mkatmsrffile.py new file mode 100644 index 000000000000..101671488f30 --- /dev/null +++ b/components/eam/tools/mkatmsrffile/mkatmsrffile.py @@ -0,0 +1,304 @@ +#!/usr/bin/env python3 +#--------------------------------------------------------------------------------------------------- +''' +This is a replacement for the legacy mkatmsrffile tool created for CESM. +All legacy functionality is reproduced. + +Created April, 2024 by Walter Hannah (LLNL) +''' +#--------------------------------------------------------------------------------------------------- +''' +The map file used to generate the atmsrf files can be created a few different ways. +For a typical E3SM configuration we recommend using a conservative, monotone map. +Here is an example command that can be used to generate one as of NCO version 5.2.2 + + SRC_GRID=${DIN_LOC_ROOT}/../mapping/grids/1x1d.nc + DST_GRID=${GRID_ROOT}/ne${NE}pg2_scrip.nc + MAP_FILE=${MAP_ROOT}/map_1x1_to_ne${NE}pg2_traave.nc + ncremap -a traave --src_grd=${SRC_GRID} --dst_grd=${DST_GRID} --map_file=${MAP_FILE} + +''' +#--------------------------------------------------------------------------------------------------- +import datetime, os, numpy as np, xarray as xr, numba, itertools, subprocess as sp +user, host = os.getenv('USER'), os.getenv('HOST') +source_code_meta = 'mkatmsrffile.py' +#--------------------------------------------------------------------------------------------------- +class clr:END,RED,GREEN,MAGENTA,CYAN = '\033[0m','\033[31m','\033[32m','\033[35m','\033[36m' +#--------------------------------------------------------------------------------------------------- +usage = ''' +python mkatmsrffile.py --map_file + --vegetation_file + --soil_water_file + --dst_grid + [--output-root ] + [--date-stamp ] + +Purpose: + This tool generates a file needed to prescribe atmospheric dry deposition of aerosols at the surface. + +Environment + + This tool requires a few special packages, such as xarray, numba, and itertools. + These are all included in the E3SM unified environment: + https://e3sm.org/resources/tools/other-tools/e3sm-unified-environment/ + + Otherwise a simple conda environment can be created: + conda create --name example_env --channel conda-forge xarray numpy numba scikit-learn netcdf4 + +The following output file is created: + + atmsrf__.nc + +''' +from optparse import OptionParser +parser = OptionParser(usage=usage) +parser.add_option('--map_file', + dest='map_file', + default=None, + help='Mapping file from a 1x1 degree grid to the target atmosphere grid') +parser.add_option('--vegetation_file', + dest='vegetation_file', + default=None, + help='Path to file containing area fractions of surface types and plant functional type (PFT) data (regrid_vegetation.nc)') +parser.add_option('--soil_water_file', + dest='soil_water_file', + default=None, + help='Path to file containing soil water data (clim_soilw.nc)') +parser.add_option('--dst_grid', + dest='dst_grid', + default=None, + help='destination atmosphere grid name') +parser.add_option('--output_root', + dest='output_root', + default='./', + help='Output path for atmsrf files') +parser.add_option('--date-stamp', + dest='date_stamp', + default=None, + help='Creation date stamp for atmsrf files') +(opts, args) = parser.parse_args() +#--------------------------------------------------------------------------------------------------- +def main(): + #----------------------------------------------------------------------------- + # check for valid input arguments + if opts.map_file is None: + raise ValueError(f'{clr.RED}map_file was not specified{clr.END}') + if opts.vegetation_file is None: + raise ValueError(f'{clr.RED}vegetation_file was not specified{clr.END}') + if opts.soil_water_file is None: + raise ValueError(f'{clr.RED}soil_water_file was not specified{clr.END}') + if opts.dst_grid is None: + raise ValueError(f'{clr.RED}dst_grid was not specified{clr.END}') + #----------------------------------------------------------------------------- + # check existence of input files and output path + if not os.path.exists(opts.vegetation_file) : + raise ValueError(f'{clr.RED}Vegetaion file does not exist:{clr.END} {opts.vegetation_file}') + if not os.path.exists(opts.soil_water_file) : + raise ValueError(f'{clr.RED}Soil water file does not exist:{clr.END} {opts.soil_water_file}') + if not os.path.exists(opts.output_root) : + raise ValueError(f'{clr.RED}Output root path does not exist:{clr.END} {opts.output_root}') + + #----------------------------------------------------------------------------- + # Set date stamp for file name + + if opts.date_stamp is None: + cdate = datetime.datetime.now().strftime('%Y%m%d') + else: + cdate = opts.date_stamp + + #----------------------------------------------------------------------------- + # specify output file name + + output_file = f'{opts.output_root}/atm_srf_{opts.dst_grid}_{cdate}.nc' + + #----------------------------------------------------------------------------- + # open input files as datasets + + ds_map = xr.open_dataset(opts.map_file) + ds_veg = xr.open_dataset(opts.vegetation_file) + ds_slw = xr.open_dataset(opts.soil_water_file) + + #----------------------------------------------------------------------------- + # check that dimension sizes are consistent + + nxy_veg = len(ds_veg.lat) * len(ds_veg.lon) + nxy_slw = len(ds_slw.lat) * len(ds_slw.lon) + n_a = len(ds_map.n_a) + n_b = len(ds_map.n_b) + + if nxy_veg!=nxy_slw or n_a!=nxy_veg or n_a!=nxy_slw: + err_msg = f'{clr.RED}Input file dimension sizes are inconsistent:{clr.END}' + err_msg += f' n_a: {n_a} nxy_veg: {nxy_veg} nxy_slw: {nxy_slw}' + raise ValueError(err_msg) + + ntime = 12 # expected length of time dimension + + if len(ds_veg.time)!=ntime: + err_msg = f'vegetation_file time record error:' + err_msg += f' expected length = {ntime}, actual length = {len(ds_veg.time)}' + raise ValueError(err_msg) + + if len(ds_slw.time)!=ntime: + err_msg = f'soil_water_file time record error:' + err_msg += f' expected length = {ntime}, actual length = {len(ds_slw.time)}' + raise ValueError(err_msg) + + if len(ds_veg.lat)!=len(ds_slw.lat): + err_msg = f'inconsistent latitude coordinate lengths:' + err_msg += f' ds_veg.lat = {len(ds_veg.lat)}' + err_msg += f' ds_slw.lat = {len(ds_slw.lat)}' + raise ValueError(err_msg) + + if len(ds_veg.lon)!=len(ds_slw.lon): + err_msg = f'inconsistent latitude coordinate lengths:' + err_msg += f' ds_veg.lon = {len(ds_veg.lon)}' + err_msg += f' ds_slw.lon = {len(ds_slw.lon)}' + raise ValueError(err_msg) + + #----------------------------------------------------------------------------- + # print some informative stuff + + print(f''' + File and parameter values: + {clr.GREEN}map_file {clr.END}: {opts.map_file} + {clr.GREEN}vegetation_file {clr.END}: {opts.vegetation_file} + {clr.GREEN}soil_water_file {clr.END}: {opts.soil_water_file} + {clr.GREEN}output_root {clr.END}: {opts.output_root} + {clr.GREEN}output_file {clr.END}: {output_file} + {clr.GREEN}dst_grid {clr.END}: {opts.dst_grid} + {clr.GREEN}map_file n_a {clr.END}: {n_a} + {clr.GREEN}map_file n_b {clr.END}: {n_b} + ''') + + #----------------------------------------------------------------------------- + # Load input data + # (also convert percentage to fraction [0,1]) + LANDMASK_in = ds_veg['LANDMASK' ].values + PCT_LAKE_in = ds_veg['PCT_LAKE' ].values/1e2 + PCT_URBAN_in = ds_veg['PCT_URBAN' ].values/1e2 + PCT_WETLAND_in = ds_veg['PCT_WETLAND'].values/1e2 + PCT_PFT_in = ds_veg['PCT_PFT' ].values/1e2 + SOILW_in = ds_slw['SOILW' ].values + #----------------------------------------------------------------------------- + # Adjust input data based on land fraction (for consistency with fortran tool) + nlat = len(ds_veg.lat) + nlon = len(ds_veg.lon) + adjust_inputs(ntime, nlat, nlon, LANDMASK_in, PCT_LAKE_in, PCT_URBAN_in, PCT_WETLAND_in, SOILW_in) + #----------------------------------------------------------------------------- + # Remap data to the atmosphere grid + + n_s = len(ds_map.n_s) + wgt = ds_map.S.values + row = ds_map.row.values-1 + col = ds_map.col.values-1 + + shp_1D = (n_b) + shp_2D = (ntime,n_b) + + SOILW = apply_map_2D( np.zeros(shp_2D), ntime, n_s, wgt, row, col, np.reshape(SOILW_in,(ntime,-1)) ) + + PCT_LAKE = apply_map_1D( np.zeros(shp_1D), n_s, wgt, row, col, np.reshape(PCT_LAKE_in ,-1) ) + PCT_URBAN = apply_map_1D( np.zeros(shp_1D), n_s, wgt, row, col, np.reshape(PCT_URBAN_in ,-1) ) + PCT_WETLAND = apply_map_1D( np.zeros(shp_1D), n_s, wgt, row, col, np.reshape(PCT_WETLAND_in,-1) ) + + npft = len(ds_veg.PCT_PFT[:,0,0]) + PCT_PFT = np.zeros((npft,n_b)) + for p in range(npft): + PCT_PFT[p,:] = apply_map_1D( np.zeros(shp_1D), n_s, wgt, row, col, np.reshape(PCT_PFT_in[p,:,:],-1) ) + + #----------------------------------------------------------------------------- + # Compute fields to output + + nclass_landuse = 11 + fraction_landuse = np.zeros([nclass_landuse,n_b]) + total_soilw = np.zeros([ntime,n_b]) + + for i in range(n_b): + # Calculate total_land as sum as all surface type fractions + total_land = PCT_LAKE[i] + PCT_URBAN[i] + PCT_WETLAND[i] + for p in range(npft): total_land += PCT_PFT[p,i] + # Adjust lake area fraction + if total_land<1.0: + PCT_LAKE[i] = PCT_LAKE[i] + (1.0 - total_land) + # Calculate total_soilw + fraction_soilw = total_land - ( PCT_LAKE[i] + PCT_WETLAND[i] ) + for t in range(ntime): + total_soilw[t,i] = total_soilw[t,i] + SOILW[t,i] * fraction_soilw + + # Calculate fraction_landuse - n-1 indexing is used to correspond to fortran indexing + fraction_landuse[ 1-1,i] = PCT_URBAN[i] + fraction_landuse[ 2-1,i] = np.sum( PCT_PFT[[n-1 for n in [16,17]] ,i], axis=0) + fraction_landuse[ 3-1,i] = np.sum( PCT_PFT[[n-1 for n in [13,14,15]] ,i], axis=0) + fraction_landuse[ 4-1,i] = np.sum( PCT_PFT[[n-1 for n in [5,6,7,8,9]],i], axis=0) + fraction_landuse[ 5-1,i] = np.sum( PCT_PFT[[n-1 for n in [2,3,4]] ,i], axis=0) + fraction_landuse[ 6-1,i] = PCT_WETLAND[i] + fraction_landuse[ 7-1,i] = PCT_LAKE[i] + fraction_landuse[ 8-1,i] = PCT_PFT[1-1,i] + fraction_landuse[11-1,i] = np.sum( PCT_PFT[[n-1 for n in [10,11,12]] ,i], axis=0) + + # Normalize fraction_landuse if it does not sum to 1 +/- tolerance + fraction_landuse_tolerance = 0.001 + fraction_landuse_sum = np.sum(fraction_landuse[:,i]) + fraction_landuse_error = fraction_landuse_sum - 1.0 + if np.absolute(fraction_landuse_error) > fraction_landuse_tolerance: + for c in range(nclass_landuse): + fraction_landuse[c,i] = fraction_landuse[c,i] / fraction_landuse_sum + + #----------------------------------------------------------------------------- + # Create output file and add fields + + ds_out = xr.Dataset() + ds_out['fraction_landuse'] = xr.DataArray(fraction_landuse,dims=['class','ncol']) + ds_out['soilw'] = xr.DataArray(SOILW ,dims=['month','ncol']) + ds_out['lon'] = ds_map.xc_b.rename({'n_b':'ncol'}) + ds_out['lat'] = ds_map.yc_b.rename({'n_b':'ncol'}) + + ds_out.attrs['title'] = 'E3SM atmosphere surface data' + ds_out.attrs['source_code'] = source_code_meta + ds_out.attrs['hostname'] = str(host) + ds_out.attrs['history'] = f'created by {user}, '+datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S') + ds_out.attrs['input_map_file'] = opts.map_file + ds_out.attrs['input_vegetation_file'] = opts.vegetation_file + ds_out.attrs['input_soil_water_file'] = opts.soil_water_file + + ds_out.to_netcdf(path=output_file,mode='w') + + #----------------------------------------------------------------------------- + # convert to 64bit_data + + cmd = f'ncks -O --fl_fmt=64bit_data {output_file} {output_file} ' + sp.check_call(cmd,shell=True) + + #----------------------------------------------------------------------------- + # print status message + + print(f'\nsuccessfully created atmsrf file: {clr.MAGENTA}{output_file}{clr.END}') + print() + +#--------------------------------------------------------------------------------------------------- +@numba.njit() +def adjust_inputs(ntime, nlat, nlon, LANDMASK, PCT_LAKE, PCT_URBAN, PCT_WETLAND, SOILW): + for j in range(nlat): + for i in range(nlon): + if LANDMASK[j,i]==0: + PCT_LAKE[j,i] = 1.0 + PCT_URBAN[j,i] = 0.0 + PCT_WETLAND[j,i] = 0.0 + for t in range(ntime): SOILW[t,j,i] = 0.0 + +@numba.njit() +def apply_map_1D( data_out, n_s, wgt, row, col, data_in ): + for k in range(n_s): + data_out[row[k]] = data_out[row[k]] + data_in[col[k]] * wgt[k] + return data_out + +@numba.njit() +def apply_map_2D( data_out, ntime, n_s, wgt, row, col, data_in ): + for t in range(ntime): + for k in range(n_s): + data_out[t,row[k]] = data_out[t,row[k]] + data_in[t,col[k]] * wgt[k] + return data_out +#--------------------------------------------------------------------------------------------------- +if __name__ == '__main__': + main() +#--------------------------------------------------------------------------------------------------- diff --git a/components/eam/tools/mkatmsrffile/Makefile b/components/eam/tools/mkatmsrffile/old_mkatmsrffile/Makefile similarity index 100% rename from components/eam/tools/mkatmsrffile/Makefile rename to components/eam/tools/mkatmsrffile/old_mkatmsrffile/Makefile diff --git a/components/eam/tools/mkatmsrffile/README b/components/eam/tools/mkatmsrffile/old_mkatmsrffile/README similarity index 100% rename from components/eam/tools/mkatmsrffile/README rename to components/eam/tools/mkatmsrffile/old_mkatmsrffile/README diff --git a/components/eam/tools/mkatmsrffile/mkatmsrffile.F90 b/components/eam/tools/mkatmsrffile/old_mkatmsrffile/mkatmsrffile.F90 similarity index 100% rename from components/eam/tools/mkatmsrffile/mkatmsrffile.F90 rename to components/eam/tools/mkatmsrffile/old_mkatmsrffile/mkatmsrffile.F90 diff --git a/components/eam/tools/mkatmsrffile/nml_atmsrf b/components/eam/tools/mkatmsrffile/old_mkatmsrffile/nml_atmsrf similarity index 100% rename from components/eam/tools/mkatmsrffile/nml_atmsrf rename to components/eam/tools/mkatmsrffile/old_mkatmsrffile/nml_atmsrf diff --git a/components/eam/tools/mkatmsrffile/test_mkatmsrffile.sh b/components/eam/tools/mkatmsrffile/old_mkatmsrffile/test_mkatmsrffile.sh similarity index 100% rename from components/eam/tools/mkatmsrffile/test_mkatmsrffile.sh rename to components/eam/tools/mkatmsrffile/old_mkatmsrffile/test_mkatmsrffile.sh diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/shell_commands new file mode 100644 index 000000000000..2520f7b6b12b --- /dev/null +++ b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/shell_commands @@ -0,0 +1,100 @@ +#!/bin/bash + +cime_root=$(./xmlquery --value CIMEROOT) +input_data_dir=$(./xmlquery --value DIN_LOC_ROOT) +atmchange=$cime_root/../components/eamxx/scripts/atmchange +case_name=$(./xmlquery --value CASE) + +# Change run length +./xmlchange RUN_STARTDATE="1994-10-01" + +# Turn on budget reporting +./xmlchange BUDGETS=TRUE + +# For big data +./xmlchange PIO_NETCDF_FORMAT="64bit_data" +./xmlchange PIO_TYPENAME=pnetcdf #adios #,PIO_TYPENAME_ATM=adios +./xmlchange PIO_REARRANGER=1 # use PIO_REARRANGER=3, for ADIOS; PIO_REARRANGER=1 for pnetcdf + +# Turn on cosp and set frequency +$atmchange -b physics::atm_procs_list="mac_aero_mic,rrtmgp,cosp" +$atmchange -b physics::cosp::cosp_frequency_units="hours" +$atmchange -b physics::cosp::cosp_frequency=1 + +# Need to explicitly turn on computing tendencies +$atmchange -b physics::mac_aero_mic::shoc::compute_tendencies=T_mid,qv +$atmchange -b physics::mac_aero_mic::p3::compute_tendencies=T_mid,qv +$atmchange -b physics::rrtmgp::compute_tendencies=T_mid +$atmchange -b homme::compute_tendencies=T_mid,qv + +# Set temperature cut off in dycore threshold to 180K +$atmchange -b vtheta_thresh=180 + +# Change lambda_high +$atmchange -b lambda_high=0.08 + +# use GHG levels more appropriate for sim +# Average from 19940101 - 20150101 +$atmchange -b co2vmr=377.2e-6 +$atmchange -b ch4vmr=1786.6e-9 +$atmchange -b n2ovmr=318.6e-9 +$atmchange -b orbital_year=-9999 +# use CO2 the same in land model +./xmlchange CCSM_CO2_PPMV=377.2 + +# determine grid and set remap files +atm_grid=$(./xmlquery --value ATM_GRID) +if [[ "${atm_grid}" = "ne30np4.pg2" ]]; then + hmapfile="${input_data_dir}/atm/scream/maps/map_ne30pg2_to_ne4pg2_20231201.nc" + armmapfile="${input_data_dir}/atm/scream/maps/map_ne30pg2_to_DecadalSites_c20240130.nc" + # Run with bugfixed SPA file + $atmchange -b spa_data_file="${input_data_dir}/atm/scream/init/spa_v3.LR.F2010.2011-2025.c_20240405.nc" +elif [[ "${atm_grid}" = "ne4np4.pg2" ]]; then + hmapfile="${input_data_dir}/atm/scream/maps/map_ne4pg2_to_ne2pg2_c20240902.nc" + echo "Note: arm remap only works for ne30pg2 atm grids for now" + armmapfile="not-supported-yet" + # Keep default SPA file + # ... (do nothing) +else + echo "Note: horiz/arm remaps only work for ne30pg2 and ne4pg2 atm grids for now" + hmapfile="not-supported-yet" + armmapfile="not-supported-yet" +fi + +# set the output yaml files +output_yaml_files=$(find ${cime_root}/../components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/ -maxdepth 1 -type f) +for file in ${output_yaml_files[@]}; do + # if the word "coarse" is in the file name, do nothing + if [[ "${file}" == *"_coarse.yaml" && "${hmapfile}" == "not-supported-yet" ]]; then + continue + elif [[ "${file}" == *"_arm.yaml" && "${armmapfile}" == "not-supported-yet" ]]; then + continue + else + # TODO: add remap file replacement for different grids + cp -v ${file} ./ + if [ "${file}" == "${output_yaml_files[0]}" ]; then + # First file, reset output list + $atmchange -b output_yaml_files="./$(basename ${file})" + else + # Append to output list + $atmchange -b output_yaml_files+="./$(basename ${file})" + fi + # Replace remap files + sed -i "s|horiz_remap_file:.*_to_ne30.*|horiz_remap_file: ${hmapfile}|" ./$(basename ${file}) + sed -i "s|horiz_remap_file:.*_to_DecadalSites.*|horiz_remap_file: ${armmapfile}|" ./$(basename ${file}) + fi + # replace all filename prefixes so that st_archive works... + sed -i "s|eamxx_output.decadal|${case_name}.scream|" ./$(basename ${file}) +done + +# TODO: +# the only thing remaining is to set the SST data, but for some reason, this is proving difficult +# because it is not super important, leave it commented out for now, until a better solution can be found +# ... also, not sure if the below are specific to a given ocn/sea-ice grid? + +# # Point to new SST forcing +# ./xmlchange --file env_run.xml --id SSTICE_DATA_FILENAME --val "${input_data_dir}/atm/cam/sst/sst_ostia_3600x7200_19940930_20151231_c20240125.nc" +# ./xmlchange --file env_run.xml --id SSTICE_GRID_FILENAME --val "${input_data_dir}/ocn/docn7/domain.ocn.3600x7200.230522.nc" +# ./xmlchange --file env_run.xml --id SSTICE_YEAR_ALIGN --val 1994 +# ./xmlchange --file env_run.xml --id SSTICE_YEAR_START --val 1994 +# ./xmlchange --file env_run.xml --id SSTICE_YEAR_END --val 2015 diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/user_nl_cpl b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/user_nl_cpl new file mode 100644 index 000000000000..3e3a05807216 --- /dev/null +++ b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/user_nl_cpl @@ -0,0 +1 @@ +ocn_surface_flux_scheme = 2 diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/user_nl_elm b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/user_nl_elm new file mode 100644 index 000000000000..93b7ec9e277d --- /dev/null +++ b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/user_nl_elm @@ -0,0 +1,14 @@ +! Override consistency checks since we know our surface data is inconsistent +check_finidat_fsurdat_consistency = .false. +check_finidat_year_consistency = .false. +check_finidat_pct_consistency = .false. +check_dynpft_consistency = .false. + +hist_dov2xy = .true.,.true. +hist_mfilt = 1,1 +hist_nhtfrq = -24,-24 +hist_avgflag_pertape = 'A','A' +hist_fincl1 = 'FIRE', 'FPSN', 'QDRAI', 'QRUNOFF', 'ZWT', 'FSAT', 'H2OSOI', 'EFLX_LH_TOT', + 'QVEGT', 'QVEGE', 'FSH', 'ALBD', 'ALBI', 'TBOT', 'QBOT', 'RAIN', 'SNOW', + 'FSDS', 'FSDSND', 'FSDSNI', 'FSDSVD', 'FSDSVI', 'FLDS' +hist_fincl2 = 'H2OSNO','SOILWATER_10CM','TG' diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.1dailyAVG_native.yaml b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.1dailyAVG_native.yaml new file mode 100644 index 000000000000..181f841eeb81 --- /dev/null +++ b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.1dailyAVG_native.yaml @@ -0,0 +1,16 @@ +%YAML 1.1 +--- +filename_prefix: eamxx_output.decadal.1dailyAVG_native.h +iotype: pnetcdf +Averaging Type: Average +Max Snapshots Per File: 1 +Fields: + Physics PG2: + Field Names: + - snow_depth_land +output_control: + Frequency: 1 + frequency_units: ndays + MPI Ranks in Filename: false +Restart: + force_new_file: true diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.1dailyMAX_native.yaml b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.1dailyMAX_native.yaml new file mode 100644 index 000000000000..a8974c75b35e --- /dev/null +++ b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.1dailyMAX_native.yaml @@ -0,0 +1,17 @@ +%YAML 1.1 +--- +filename_prefix: eamxx_output.decadal.1dailyMAX_native.h +iotype: pnetcdf +Averaging Type: Max +Max Snapshots Per File: 1 +Fields: + Physics PG2: + Field Names: + - T_2m + - precip_total_surf_mass_flux +output_control: + Frequency: 1 + frequency_units: ndays + MPI Ranks in Filename: false +Restart: + force_new_file: true diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.1dailyMIN_native.yaml b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.1dailyMIN_native.yaml new file mode 100644 index 000000000000..8d48a1bedf63 --- /dev/null +++ b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.1dailyMIN_native.yaml @@ -0,0 +1,16 @@ +%YAML 1.1 +--- +filename_prefix: eamxx_output.decadal.1dailyMIN_native.h +iotype: pnetcdf +Averaging Type: Min +Max Snapshots Per File: 1 +Fields: + Physics PG2: + Field Names: + - T_2m +output_control: + Frequency: 1 + frequency_units: ndays + MPI Ranks in Filename: false +Restart: + force_new_file: true diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.1hourlyINST_arm.yaml b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.1hourlyINST_arm.yaml new file mode 100644 index 000000000000..52fc391ca4d9 --- /dev/null +++ b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.1hourlyINST_arm.yaml @@ -0,0 +1,40 @@ +%YAML 1.1 +--- +filename_prefix: eamxx_output.decadal.1hourlyINST_arm.h +iotype: pnetcdf +Averaging Type: Instant +Max Snapshots Per File: 24 # one file per day +horiz_remap_file: ${DIN_LOC_ROOT}/atm/scream/maps/map_ne1024pg2_to_DecadalSites_c20240130.nc +Fields: + Physics PG2: + Field Names: + # 3D + - T_mid + - RelativeHumidity + - qc + - qi + - qr + - qm + - ps + - cldfrac_tot_for_analysis + - cldfrac_liq + - cldfrac_ice_for_analysis + - omega + - tke + - eff_radius_qc + - eff_radius_qi + - nc + - ni + - nr + - bm + - p_mid + - z_mid + - U + - V + - landfrac +output_control: + Frequency: 1 + frequency_units: nhours + MPI Ranks in Filename: false +Restart: + force_new_file: true diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.1hourlyINST_native.yaml b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.1hourlyINST_native.yaml new file mode 100644 index 000000000000..0aba4827ead7 --- /dev/null +++ b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.1hourlyINST_native.yaml @@ -0,0 +1,19 @@ +%YAML 1.1 +--- +filename_prefix: eamxx_output.decadal.1hourlyINST_native.h +iotype: pnetcdf +Averaging Type: Instant +Max Snapshots Per File: 24 +Fields: + Physics PG2: + Field Names: + # For cloud morphology + - SW_flux_up_at_model_top + - LW_flux_up_at_model_top + - precip_total_surf_mass_flux +output_control: + Frequency: 1 + frequency_units: nhours + MPI Ranks in Filename: false +Restart: + force_new_file: true diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.3hourlyAVG_coarse.yaml b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.3hourlyAVG_coarse.yaml new file mode 100644 index 000000000000..d429b11ebd1f --- /dev/null +++ b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.3hourlyAVG_coarse.yaml @@ -0,0 +1,69 @@ +%YAML 1.1 +--- +filename_prefix: eamxx_output.decadal.3hourlyAVG_coarse.h +iotype: pnetcdf +Averaging Type: Average +Max Snapshots Per File: 8 # one file per day +horiz_remap_file: ${DIN_LOC_ROOT}/atm/scream/maps/map_ne1024pg2_to_ne30pg2_mono.20230901.nc +Fields: + Physics PG2: + Field Names: + # 3D fields + - T_mid + - qv + - qc + - qr + - qi + - cldfrac_tot + - cldfrac_liq + - omega + - U + - V + - pseudo_density + - z_mid + # Surface + - surf_sens_flux + - surf_evap + - surface_upward_latent_heat_flux + - ps + - precip_liq_surf_mass_flux + - precip_ice_surf_mass_flux + - surf_mom_flux + - surf_radiative_T + - T_2m + - sfc_flux_dir_nir + - sfc_flux_dir_vis + - sfc_flux_dif_nir + - sfc_flux_dif_vis + - sfc_flux_sw_net + - sfc_flux_lw_dn + # Lowest Level + - U_at_model_bot + - V_at_model_bot + - T_mid_at_model_bot + - qv_at_model_bot + - qc_at_model_bot + - qi_at_model_bot + - qr_at_model_bot + - qm_at_model_bot + - bm_at_model_bot + - SW_flux_up_at_model_top + - SW_flux_dn_at_model_top + - LW_flux_up_at_model_top + - SW_clrsky_flux_up_at_model_top + - LW_clrsky_flux_up_at_model_top + - SW_flux_dn_at_model_bot + - SW_clrsky_flux_dn_at_model_bot + - SW_flux_up_at_model_bot + - SW_clrsky_flux_up_at_model_bot + - LW_flux_dn_at_model_bot + - LW_clrsky_flux_dn_at_model_bot + - LW_flux_up_at_model_bot + - LongwaveCloudForcing + - ShortwaveCloudForcing +output_control: + Frequency: 3 + frequency_units: nhours + MPI Ranks in Filename: false +Restart: + force_new_file: true diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.3hourlyINST_coarse.yaml b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.3hourlyINST_coarse.yaml new file mode 100644 index 000000000000..a2faa1b971c1 --- /dev/null +++ b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.3hourlyINST_coarse.yaml @@ -0,0 +1,68 @@ +%YAML 1.1 +--- +filename_prefix: eamxx_output.decadal.3hourlyINST_coarse.h +iotype: pnetcdf +Averaging Type: Instant +Max Snapshots Per File: 8 # one file per day +horiz_remap_file: ${DIN_LOC_ROOT}/atm/scream/maps/map_ne1024pg2_to_ne30pg2_mono.20230901.nc +Fields: + Physics PG2: + Field Names: + # 2D vars for storm analysis + - SeaLevelPressure + - U_at_model_bot + - V_at_model_bot + - wind_speed_10m + - U_at_925hPa + - V_at_925hPa + - U_at_850hPa + - V_at_850hPa + - U_at_700hPa + - V_at_700hPa + - U_at_500hPa + - V_at_500hPa + - U_at_300hPa + - V_at_300hPa + - ZonalVapFlux + - MeridionalVapFlux + - T_2m + - qv_2m + - T_mid_at_925hPa + - T_mid_at_850hPa + - T_mid_at_700hPa + - T_mid_at_500hPa + - T_mid_at_300hPa + - RelativeHumidity_at_925hPa + - RelativeHumidity_at_850hPa + - RelativeHumidity_at_700hPa + - RelativeHumidity_at_500hPa + - RelativeHumidity_at_300hPa + - z_mid_at_925hPa + - z_mid_at_850hPa + - z_mid_at_700hPa + - z_mid_at_500hPa + - z_mid_at_300hPa + # 2D vars For ACI diagnostics + - SW_clrsky_flux_up_at_model_top + - SW_flux_up_at_model_top + - SW_flux_dn_at_model_top + - LiqWaterPath + - precip_liq_surf_mass_flux + - precip_ice_surf_mass_flux + - IceWaterPath + - cldfrac_tot_for_analysis + - cldfrac_liq + - omega_at_500hPa + - omega_at_700hPa + - omega_at_850hPa + - PotentialTemperature_at_700hPa + - PotentialTemperature_at_1000hPa + # 3D vars for nudging + - U + - V +output_control: + Frequency: 3 + frequency_units: nhours + MPI Ranks in Filename: false +Restart: + force_new_file: true diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.6hourlyAVG_coarse.yaml b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.6hourlyAVG_coarse.yaml new file mode 100644 index 000000000000..437142ba5599 --- /dev/null +++ b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.6hourlyAVG_coarse.yaml @@ -0,0 +1,48 @@ +%YAML 1.1 +--- +filename_prefix: eamxx_output.decadal.6hourlyAVG_coarse.h +iotype: pnetcdf +Averaging Type: Average +Max Snapshots Per File: 4 # one file per day +horiz_remap_file: ${DIN_LOC_ROOT}/atm/scream/maps/map_ne1024pg2_to_ne30pg2_mono.20230901.nc +Fields: + Physics PG2: + Field Names: + # Full 3D Profile + - p3_T_mid_tend + - shoc_T_mid_tend + - rrtmgp_T_mid_tend + - homme_T_mid_tend + - p3_qv_tend + - shoc_qv_tend + - homme_qv_tend + - SW_flux_dn + - SW_flux_up + - LW_flux_dn + - LW_flux_up + # Surface + - surf_sens_flux + - surf_evap + - surface_upward_latent_heat_flux + - ps + - precip_liq_surf_mass_flux + - precip_ice_surf_mass_flux + - surf_mom_flux + - surf_radiative_T + - T_2m + # Lowest Level + - U_at_model_bot + - V_at_model_bot + - SW_flux_dn_at_model_bot + - SW_flux_up_at_model_bot + - LW_flux_dn_at_model_bot + - LW_flux_up_at_model_bot + - SW_flux_up_at_model_top + - SW_flux_dn_at_model_top + - LW_flux_up_at_model_top +output_control: + Frequency: 6 + frequency_units: nhours + MPI Ranks in Filename: false +Restart: + force_new_file: true diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.6hourlyINST_coarse.yaml b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.6hourlyINST_coarse.yaml new file mode 100644 index 000000000000..bb83718a8eb0 --- /dev/null +++ b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.6hourlyINST_coarse.yaml @@ -0,0 +1,39 @@ +%YAML 1.1 +--- +filename_prefix: eamxx_output.decadal.6hourlyINST_coarse.h +iotype: pnetcdf +Averaging Type: Instant +Max Snapshots Per File: 4 # one file per day +horiz_remap_file: ${DIN_LOC_ROOT}/atm/scream/maps/map_ne1024pg2_to_ne30pg2_mono.20230901.nc +Fields: + Physics PG2: + Field Names: + # 3D fields on model levels + - T_mid + - qv + - RelativeHumidity + - U + - V + - omega + - qc + - nc + - qr + - qi + - tke + - o3_volume_mix_ratio + # 2D fields + - VapWaterPath + - LiqWaterPath + - IceWaterPath + - surf_radiative_T + - ps + - qv_2m + - T_2m + - ocnfrac + - landfrac +output_control: + Frequency: 6 + frequency_units: nhours + MPI Ranks in Filename: false +Restart: + force_new_file: true diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.6hourlyINST_native.yaml b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.6hourlyINST_native.yaml new file mode 100644 index 000000000000..c69dc4b2212b --- /dev/null +++ b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.6hourlyINST_native.yaml @@ -0,0 +1,28 @@ +%YAML 1.1 +--- +filename_prefix: eamxx_output.decadal.6hourlyINST_native.h +iotype: pnetcdf +Averaging Type: Instant +Max Snapshots Per File: 4 # one file per day +Fields: + Physics PG2: + Field Names: + # For storm analysis + - SeaLevelPressure + - wind_speed_10m + - z_mid_at_500hPa + - z_mid_at_200hPa + # For wind turbine study + - wind_speed_at_100m_above_surface + # For atmospheric rivers + - ZonalVapFlux + - MeridionalVapFlux + # Others + - omega_at_500hPa + - omega_at_850hPa +output_control: + Frequency: 6 + frequency_units: nhours + MPI Ranks in Filename: false +Restart: + force_new_file: true diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.dailyAVG_coarse.yaml b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.dailyAVG_coarse.yaml new file mode 100644 index 000000000000..2d1e6e7221ef --- /dev/null +++ b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/prod/yaml_outs/eamxx_output.decadal.dailyAVG_coarse.yaml @@ -0,0 +1,95 @@ +%YAML 1.1 +--- +filename_prefix: eamxx_output.decadal.dailyAVG_coarse.h +iotype: pnetcdf +Averaging Type: Average +Max Snapshots Per File: 1 +horiz_remap_file: ${DIN_LOC_ROOT}/atm/scream/maps/map_ne1024pg2_to_ne30pg2_mono.20230901.nc +Fields: + Physics PG2: + Field Names: + # 3D fields + - T_mid + - qv + - RelativeHumidity + - qc + - qi + - qr + - qm + - nc + - ni + - nr + - cldfrac_tot_for_analysis + - cldfrac_ice_for_analysis + - cldfrac_liq + - omega + - U + - V + - z_mid + - p_mid + - tke + # 2D fields + - SW_flux_up_at_model_top + - SW_flux_dn_at_model_top + - LW_flux_up_at_model_top + - SW_clrsky_flux_up_at_model_top + - SW_clrsky_flux_dn_at_model_top + - LW_clrsky_flux_up_at_model_top + - SW_flux_up_at_model_bot + - SW_flux_dn_at_model_bot + - LW_flux_up_at_model_bot + - LW_flux_dn_at_model_bot + - SW_clrsky_flux_up_at_model_bot + - SW_clrsky_flux_dn_at_model_bot + - LW_clrsky_flux_dn_at_model_bot + - ShortwaveCloudForcing + - LongwaveCloudForcing + - ps + - SeaLevelPressure + - T_2m + - qv_2m + - surf_radiative_T + - VapWaterPath + - IceWaterPath + - LiqWaterPath + - RainWaterPath + - ZonalVapFlux + - MeridionalVapFlux + - surf_evap + - surf_sens_flux + - surface_upward_latent_heat_flux + - precip_liq_surf_mass_flux + - precip_ice_surf_mass_flux + - landfrac + - ocnfrac + - PotentialTemperature_at_700hPa + - PotentialTemperature_at_850hPa + - PotentialTemperature_at_1000hPa + - PotentialTemperature_at_2m_above_surface + - omega_at_500hPa + - omega_at_700hPa + - omega_at_850hPa + - RelativeHumidity_at_700hPa + - RelativeHumidity_at_1000hPa + - RelativeHumidity_at_2m_above_surface + - wind_speed_10m + - z_mid_at_700hPa + - z_mid_at_1000hPa + - T_mid_at_850hPa + - T_mid_at_700hPa + # For SST advection + - U_at_10m_above_surface + - V_at_10m_above_surface + # COSP + - isccp_ctptau + - modis_ctptau + - misr_cthtau + - cosp_sunlit + - isccp_cldtot + +output_control: + Frequency: 1 + frequency_units: ndays + MPI Ranks in Filename: false +Restart: + force_new_file: true diff --git a/components/eamxx/cmake/machine-files/aurora.cmake b/components/eamxx/cmake/machine-files/aurora.cmake new file mode 100644 index 000000000000..59157285bab7 --- /dev/null +++ b/components/eamxx/cmake/machine-files/aurora.cmake @@ -0,0 +1,14 @@ +include(${CMAKE_CURRENT_LIST_DIR}/common.cmake) +common_setup() + +include (${EKAT_MACH_FILES_PATH}/kokkos/serial.cmake) +include (${EKAT_MACH_FILES_PATH}/mpi/other.cmake) + +set(EKAT_MPIRUN_EXE "mpiexec" CACHE STRING "" FORCE) +set(EKAT_MPI_NP_FLAG "-np" CACHE STRING "" FORCE) +set(EKAT_MPI_EXTRA_ARGS "--label --cpu-bind depth -envall" CACHE STRING "") +set(EKAT_MPI_THREAD_FLAG "-d" CACHE STRING "") + +set(NETCDF_C_PATH "$ENV{NETCDF_C_PATH}") +set(NETCDF_FORTRAN_PATH "$ENV{NETCDF_FORTRAN_PATH}") +set(PNETCDF_PATH "$ENV{PNETCDF_PATH}") diff --git a/components/eamxx/cmake/machine-files/ghci-oci.cmake b/components/eamxx/cmake/machine-files/ghci-oci.cmake new file mode 100644 index 000000000000..86a2fb1d5302 --- /dev/null +++ b/components/eamxx/cmake/machine-files/ghci-oci.cmake @@ -0,0 +1,2 @@ +include(${CMAKE_CURRENT_LIST_DIR}/common.cmake) +common_setup() diff --git a/components/eamxx/cmake/machine-files/sunspot.cmake b/components/eamxx/cmake/machine-files/sunspot.cmake new file mode 100644 index 000000000000..09ff6d4e6c48 --- /dev/null +++ b/components/eamxx/cmake/machine-files/sunspot.cmake @@ -0,0 +1,10 @@ +include(${CMAKE_CURRENT_LIST_DIR}/common.cmake) +common_setup() + +include (${EKAT_MACH_FILES_PATH}/kokkos/serial.cmake) +include (${EKAT_MACH_FILES_PATH}/mpi/other.cmake) + +set(EKAT_MPIRUN_EXE "mpiexec" CACHE STRING "" FORCE) +set(EKAT_MPI_NP_FLAG "-np" CACHE STRING "" FORCE) +set(EKAT_MPI_EXTRA_ARGS "--label --cpu-bind depth -envall" CACHE STRING "") +set(EKAT_MPI_THREAD_FLAG "-d" CACHE STRING "") diff --git a/components/eamxx/src/physics/cosp/CMakeLists.txt b/components/eamxx/src/physics/cosp/CMakeLists.txt index e6ba4c363794..cd5c966a501a 100644 --- a/components/eamxx/src/physics/cosp/CMakeLists.txt +++ b/components/eamxx/src/physics/cosp/CMakeLists.txt @@ -17,7 +17,7 @@ set(EXTERNAL_SRC ${EAM_COSP_DIR}/external/src/cosp_constants.F90 ${EAM_COSP_DIR}/external/src/simulator/cosp_cloudsat_interface.F90 ${EAM_COSP_DIR}/external/src/cosp_config.F90 - ${EAM_COSP_DIR}/local/cosp.F90 + ${EAM_COSP_DIR}/external/src/cosp.F90 ${EAM_COSP_DIR}/external/src/cosp_stats.F90 ${EAM_COSP_DIR}/external/src/simulator/quickbeam/quickbeam.F90 ${EAM_COSP_DIR}/external/src/simulator/parasol/parasol.F90 diff --git a/components/elm/bld/ELMBuildNamelist.pm b/components/elm/bld/ELMBuildNamelist.pm index 68afd92e132d..cbf067e67607 100755 --- a/components/elm/bld/ELMBuildNamelist.pm +++ b/components/elm/bld/ELMBuildNamelist.pm @@ -1552,13 +1552,19 @@ sub setup_cmdl_maxpft { $nl_flags->{'maxpft'} = $val; if ( ($nl_flags->{'bgc_mode'} ne "sp") && ($nl_flags->{'maxpft'} != $maxpatchpft{$nl_flags->{'use_crop'}}) ) { - fatal_error("** For CN or BGC mode you MUST set max patch PFT's to $maxpatchpft{$nl_flags->{'use_crop'}}\n" . - "**\n" . - "** When the crop model is on then it must be set to $maxpatchpft{'crop'} otherwise to $maxpatchpft{'nocrop'}\n" . - "** Set the bgc mode, crop and maxpft by the following means from highest to lowest precedence:\n" . - "** * by the command-line options -bgc, -crop and -maxpft\n" . - "** * by a default configuration file, specified by -defaults\n" . - "**\n"); + if ($opts->{$var} eq "default") { + fatal_error("** For CN or BGC mode you MUST set max patch PFT $val to $maxpatchpft{$nl_flags->{'use_crop'}}\n" . + "**\n" . + "** When the crop model is on then it must be set to $maxpatchpft{'crop'} otherwise to $maxpatchpft{'nocrop'}\n" . + "** Set the bgc mode, crop and maxpft by the following means from highest to lowest precedence:\n" . + "** * by the command-line options -bgc, -crop and -maxpft\n" . + "** * by a default configuration file, specified by -defaults\n" . + "**\n"); + } else { + message("running with maxpft NOT equal to $maxpatchpft{$nl_flags->{'use_crop'}} is " . + "NOT validated / scientifically supported.\n"); + + } } if ( $nl_flags->{'maxpft'} > $maxpatchpft{$nl_flags->{'use_crop'}} ) { fatal_error("** Max patch PFT's can NOT exceed $maxpatchpft{$nl_flags->{'use_crop'}}\n" . diff --git a/components/elm/bld/namelist_files/namelist_defaults.xml b/components/elm/bld/namelist_files/namelist_defaults.xml index 316292219861..beeae7858595 100644 --- a/components/elm/bld/namelist_files/namelist_defaults.xml +++ b/components/elm/bld/namelist_files/namelist_defaults.xml @@ -485,48 +485,48 @@ lnd/clm2/surfdata_map/surfdata_conusx4v1_simyr2000_c160503.nc dataset (arbitrarily, RCP8.5) for the historical period, because all of the RCP datasets contain the 1850-2000 period as well as the future period. --> -lnd/clm2/surfdata_map/landuse.timeseries_360x720cru_hist_simyr1850-2015_c180220.nc -lnd/clm2/surfdata_map/landuse.timeseries_0.9x1.25_hist_simyr1850-2015_c180306.nc -lnd/clm2/surfdata_map/landuse.timeseries_1.9x2.5_hist_simyr1850-2015_c180306.nc -lnd/clm2/surfdata_map/surfdata.pftdyn_10x15_rcp8.5_simyr1850-2100_c130524.nc -lnd/clm2/surfdata_map/surfdata.pftdyn_48x96_rcp8.5_simyr1850-2100_c130524.nc lnd/clm2/surfdata_map/landuse.timeseries_antarcticax4v1pg2_hist_simyr1850-2015_c210131.nc -lnd/clm2/surfdata_map/surfdata.pftdyn_1x1_tropicAtl_hist_simyr1850-2005_c130627.nc -lnd/clm2/surfdata_map/landuse.timeseries_1x1_brazil_rcp8.5_simyr1850-2100_c140610.nc -lnd/clm2/surfdata_map/landuse.timeseries_ne30np4_hist_simyr1850-2015_c180306.nc - lnd/clm2/surfdata_map/landuse.timeseries_ne30np4.pg2_hist_simyr1850-2015_c210113.nc - lnd/clm2/surfdata_map/landuse.timeseries_ne4pg2_hist_simyr1850-2015_c210722.nc - lnd/clm2/surfdata_map/landuse.timeseries_ne0np4_northamericax4v1.pg2_hist_simyr1850-2015_c211015.nc -lnd/clm2/surfdata_map/surfdata.pftdyn_ne16np4_hist_simyr1850-2005_c160803.nc -lnd/clm2/surfdata_map/surfdata.pftdyn_ne11np4_hist_simyr1850-2005_c160803.nc lnd/clm2/surfdata_map/landuse.timeseries_ne1024pg2_historical_simyr1990-2014_c240109.nc lnd/clm2/surfdata_map/landuse.timeseries_ne256pg2_hist_simyr1850-2015_c240131.nc -lnd/clm2/surfdata_map/landuse.timeseries_0.125x0.125_hist_simyr1850-2015_c191004.nc -lnd/clm2/surfdata_map/landuse.timeseries_0.5x0.5_HIST_simyr1850-2015_c211019.nc -lnd/clm2/surfdata_map/landuse.timeseries_0.5x0.5_hist_simyr1850-2015_c191004.nc @@ -666,7 +666,7 @@ this mask will have smb calculated over the entire global land surface 2000 2100 -lnd/clm2/ndepdata/fndep_elm_cbgc_exp_simyr1849-2101_1.9x2.5_c190103.nc +lnd/clm2/ndepdata/fndep_elm_cbgc_exp_simyr1849-2101_1.9x2.5_ssp245_c240903.nc lnd/clm2/ndepdata/fndep_clm_rcp8.5_simyr1849-2106_1.9x2.5_c100428.nc lnd/clm2/ndepdata/fndep_clm_rcp6.0_simyr1849-2106_1.9x2.5_c100810.nc lnd/clm2/ndepdata/fndep_clm_rcp4.5_simyr1849-2106_1.9x2.5_c100428.nc @@ -899,8 +899,8 @@ this mask will have smb calculated over the entire global land surface 1850 2010 -lnd/clm2/firedata/elmforc.ssp5_hdm_0.5x0.5_simyr1850-2100_c190109.nc -lnd/clm2/firedata/elmforc.ssp5_hdm_0.5x0.5_simyr1850-2100_c190109.nc +lnd/clm2/firedata/elmforc.Li_20181205_mod_hist_SSP2_CMIP6_hdm_0.5x0.5_AVHRR_simyr1850-2100_c240906.nc +lnd/clm2/firedata/elmforc.Li_20181205_mod_hist_SSP2_CMIP6_hdm_0.5x0.5_AVHRR_simyr1850-2100_c240906.nc bilinear @@ -1686,6 +1686,13 @@ this mask will have smb calculated over the entire global land surface lnd/clm2/mappingdata/maps/2.5x3.33/map_1km-merge-10min_HYDRO1K-merge-nomask_to_2.5x3.33_nomask_aave_da_c130405.nc + + +lnd/clm2/mappingdata/maps/0.25x0.25/map_0.01x0.01_nomask_to_0.25x0.25_nomask_aave_da_c240501.nc + + + @@ -1716,7 +1723,7 @@ this mask will have smb calculated over the entire global land surface lnd/clm2/mappingdata/maps/0.5x0.5/map_3x3min_GLOBE-Gardner-mergeGIS_to_0.5x0.5_nomask_aave_da_c190417.nc lnd/clm2/mappingdata/maps/0.5x0.5/map_0.1x0.1_nomask_to_0.5x0.5_nomask_aave_da_c120706.nc +>lnd/clm2/mappingdata/maps/0.5x0.5/map_0.1x0.1_nomask_to_0.5x0.5_nomask_aave_da_c240308.nc lnd/clm2/mappingdata/maps/0.5x0.5/map_ne240np4_nomask_to_0.5x0.5_nomask_aave_da_c120711.nc lnd/clm2/mappingdata/maps/0.5x0.5/map_360x720cru_cruncep_to_0.5x0.5_nomask_aave_da_c190417.nc lnd/clm2/mappingdata/maps/0.5x0.5/map_1km-merge-10min_HYDRO1K-merge-nomask_to_0.5x0.5_nomask_aave_da_c190417.nc +lnd/clm2/mappingdata/maps/0.5x0.5/map_0.01x0.01_nomask_to_0.5x0.5_nomask_aave_da_c240501.nc @@ -1835,6 +1844,8 @@ this mask will have smb calculated over the entire global land surface >lnd/clm2/mappingdata/maps/ne30np4/map_1km-merge-10min_HYDRO1K-merge-nomask_to_ne30np4_nomask_aave_da_c130405.nc lnd/clm2/mappingdata/maps/ne30np4/map_0.5x0.5_GSDTG2000_to_ne30np4_nomask_aave_da_c161010.nc +lnd/clm2/mappingdata/maps/ne30np4/map_0.1x0.1_nomask_to_ne30np4_nomask_aave_da_c231218.nc lnd/clm2/mappingdata/maps/ne30np4/map_ne30np4_to_0.5x0.5rtm_aave_da_110320.nc diff --git a/components/elm/bld/namelist_files/namelist_defaults_tools.xml b/components/elm/bld/namelist_files/namelist_defaults_tools.xml index 113f949ffe82..f97a41314be0 100644 --- a/components/elm/bld/namelist_files/namelist_defaults_tools.xml +++ b/components/elm/bld/namelist_files/namelist_defaults_tools.xml @@ -147,6 +147,7 @@ attributes from the config_cache.xml file (with keys converted to upper-case). AVHRR AVHRR ISRIC-WISE +nomask 3x3min @@ -176,6 +177,8 @@ attributes from the config_cache.xml file (with keys converted to upper-case). 0.5x0.5 0.5x0.5 5x5min +0.01x0.01 + mksrf_flakwat @@ -203,6 +206,7 @@ attributes from the config_cache.xml file (with keys converted to upper-case). mksrf_fslp10 mksrf_fero mksrf_ffert +mksrf_ftoprad lnd/clm2/rawdata/mksrf_navyoro_20min.c010129.nc @@ -313,6 +317,9 @@ attributes from the config_cache.xml file (with keys converted to upper-case). lnd/clm2/rawdata/mksrf_fert.c220309.nc +lnd/clm2/rawdata/mksrf_toprad_0.01x0.01.c240422.nc + diff --git a/components/elm/bld/namelist_files/namelist_definition.xml b/components/elm/bld/namelist_files/namelist_definition.xml index 74e1967fc529..7063d7a11054 100644 --- a/components/elm/bld/namelist_files/namelist_definition.xml +++ b/components/elm/bld/namelist_files/namelist_definition.xml @@ -766,6 +766,10 @@ This option enables more realistic snowpack conditions on glaciers and ice sheets, including a semi-empirical firn densification model. uses the same physics as use_extrasnowlayers but uses the original 5 snow layer scheme + + +Toggle to use new snow thermal conductivity that relies on snow temperature and density. + valid_values="mksrf_fsoitex,mksrf_forganic,mksrf_flakwat,mksrf_fwetlnd,mksrf_fmax,mksrf_fmax,mksrf_fglacier,mksrf_fvocef,mksrf_furbtopo,mksrf_flndtopo,firrig,mksrf_furban,mksrf_fvegtyp,mksrf_fsoicol,mksrf_fsoiord,mksrf_flai,mksrf_fgdp,mksrf_fpeat,mksrf_fabm,mksrf_ftopostats,mksrf_fvic,mksrf_fch4,mksrf_fgrvl,mksrf_fslp10,mksrf_fero,mksrf_ffert,mksrf_ftoprad" > Filename for mksurfdata_map to remap raw data into the output surface dataset @@ -1004,10 +1008,15 @@ ELM-Erosion parameters dataset + input_pathname="abs" group="elmexp" valid_values="" > ELM-Fertilizer dataset + +Topography parameters dataset for TOP solar radiation parameterization + + If TRUE, output variables in double precision for mksurfdata diff --git a/components/elm/bld/namelist_files/use_cases/2015-2100_SSP245_transient.xml b/components/elm/bld/namelist_files/use_cases/2015-2100_SSP245_transient.xml index e313dab6b16a..6e664162609f 100755 --- a/components/elm/bld/namelist_files/use_cases/2015-2100_SSP245_transient.xml +++ b/components/elm/bld/namelist_files/use_cases/2015-2100_SSP245_transient.xml @@ -17,8 +17,10 @@ + + 1850 -2005 +2101 1850 2000 @@ -26,7 +28,7 @@ 2000 1850 -2010 +2100 1850 diff --git a/components/elm/bld/namelist_files/use_cases/2015-2100_SSP370_transient.xml b/components/elm/bld/namelist_files/use_cases/2015-2100_SSP370_transient.xml index 0e8415d3c1ab..0c54a8ce6039 100755 --- a/components/elm/bld/namelist_files/use_cases/2015-2100_SSP370_transient.xml +++ b/components/elm/bld/namelist_files/use_cases/2015-2100_SSP370_transient.xml @@ -18,16 +18,18 @@ 1850 -2005 +2101 1850 +lnd/clm2/ndepdata/fndep_elm_cbgc_exp_simyr1849-2101_1.9x2.5_ssp370_c220614.nc 2000 2000 2000 1850 -2010 +2100 1850 +lnd/clm2/firedata/elmforc.Li_20181205_mod_hist_SSP3_CMIP6_hdm_0.5x0.5_AVHRR_simyr1850-2100_c240906.nc diff --git a/components/elm/bld/namelist_files/use_cases/2015-2100_SSP585_transient.xml b/components/elm/bld/namelist_files/use_cases/2015-2100_SSP585_transient.xml index 2db3549ce5f0..c297dffe1138 100644 --- a/components/elm/bld/namelist_files/use_cases/2015-2100_SSP585_transient.xml +++ b/components/elm/bld/namelist_files/use_cases/2015-2100_SSP585_transient.xml @@ -18,16 +18,18 @@ 1850 -2005 +2101 1850 +lnd/clm2/ndepdata/fndep_elm_cbgc_exp_simyr1849-2101_1.9x2.5_ssp585_c190103.nc 2000 2000 2000 1850 -2010 +2100 1850 +lnd/clm2/firedata/elmforc.Li_20181205_mod_hist_SSP5_CMIP6_hdm_0.5x0.5_AVHRR_simyr1850-2100_c240906.nc diff --git a/components/elm/bld/namelist_files/use_cases/20thC_CMIP6_transient.xml b/components/elm/bld/namelist_files/use_cases/20thC_CMIP6_transient.xml index 4f48bf6326a8..a919a4847910 100644 --- a/components/elm/bld/namelist_files/use_cases/20thC_CMIP6_transient.xml +++ b/components/elm/bld/namelist_files/use_cases/20thC_CMIP6_transient.xml @@ -9,7 +9,7 @@ 1850 -1850-2000 +1850-2015 arb_ic @@ -18,7 +18,7 @@ 1850 -2005 +2101 1850 @@ -27,7 +27,7 @@ 2000 1850 -2010 +2100 1850 @@ -38,6 +38,7 @@ lnd/clm2/initdata_map/20180316.DECKv1b_A1.ne30_oEC.edison.clm2.r.1980-01-01-00000.8575c3f_c20190904.nc lnd/clm2/surfdata_map/landuse.timeseries_0.5x0.5_hist_simyr1850-2015_c240308.nc +lnd/clm2/surfdata_map/landuse.timeseries_0.25x0.25_hist_simyr1850-2015_c240125.nc lnd/clm2/surfdata_map/landuse.timeseries_ne120np4_historical_simyr1850-2015_c190904.nc diff --git a/components/elm/bld/namelist_files/use_cases/20thC_CMIP6xLULC_transient.xml b/components/elm/bld/namelist_files/use_cases/20thC_CMIP6xLULC_transient.xml new file mode 100644 index 000000000000..7a6247bbe27f --- /dev/null +++ b/components/elm/bld/namelist_files/use_cases/20thC_CMIP6xLULC_transient.xml @@ -0,0 +1,48 @@ + + + + +Historical single forcing simulation with land held at 1850 condition +Simulate transient land-use, aerosol deposition, and Nitrogen deposition changes from 1850 to 2005 +Simulate transient land-use, aerosol deposition, and Nitrogen deposition changes from 1850 to 2005 +Simulate transient land-use, aerosol deposition, and Nitrogen deposition changes from 1850 to 2005 + +1850 + +1850-2000 + +arb_ic + + +1850 +1850 +1850 + + +2000 +2000 +2000 + +1850 +1850 +1850 + + + + +lnd/clm2/surfdata_map/surfdata_ne30np4_simyr1850_2015_c171018.nc +lnd/clm2/surfdata_map/landuse.timeseries_ne30np4_hist_simyr1850_2015_c20171018.nc +lnd/clm2/initdata_map/20180316.DECKv1b_A1.ne30_oEC.edison.clm2.r.1980-01-01-00000.8575c3f_c20190904.nc + +lnd/clm2/surfdata_map/surfdata_0.125x0.125_simyr1850_c190730.nc + +lnd/clm2/surfdata_map/surfdata_0.5x0.5_simyr1850_c200609_with_TOP.nc + + +lnd/clm2/surfdata_map/surfdata_ne1024pg2_simyr2010_c211021.nc + +.false. +.false. + + + diff --git a/components/elm/bld/namelist_files/use_cases/20thC_transient.xml b/components/elm/bld/namelist_files/use_cases/20thC_transient.xml index 86035ec6e081..1fe1f2860496 100644 --- a/components/elm/bld/namelist_files/use_cases/20thC_transient.xml +++ b/components/elm/bld/namelist_files/use_cases/20thC_transient.xml @@ -9,7 +9,7 @@ 1850 -1850-2000 +1850-2015 arb_ic diff --git a/components/elm/cime_config/config_component.xml b/components/elm/cime_config/config_component.xml index da060584cfb8..4e637ef55802 100755 --- a/components/elm/cime_config/config_component.xml +++ b/components/elm/cime_config/config_component.xml @@ -72,7 +72,16 @@ 1850_CMIP6bgc_control 1850_SCMIP6_control 1850_SCMIP6_control - 20thC_CMIP6_transient + 20thC_CMIP6_transient + 20thC_CMIP6xLULC_transient + 20thC_CMIP6xLULC_transient + 20thC_CMIP6xLULC_transient + 20thC_CMIP6xLULC_transient + 20thC_CMIP6xLULC_transient + 20thC_CMIP6_transient + 20thC_CMIP6_transient + 20thC_CMIP6_transient + 20thC_CMIP6_transient 20thC_CMIP6bgc_transient 20thC_CMIP6bgc_transient 20thC_bgc_transient diff --git a/components/elm/cime_config/config_pes.xml b/components/elm/cime_config/config_pes.xml index 4af0da699656..39e36221175b 100644 --- a/components/elm/cime_config/config_pes.xml +++ b/components/elm/cime_config/config_pes.xml @@ -237,16 +237,16 @@ - elm: pm-cpu 2 nodes for grid l%360x720cru + elm: pm-cpu 3 nodes for grid l%360x720cru - 192 - 192 - 192 - 192 - 192 - 192 - 192 - 192 + -3 + -3 + -3 + -3 + -3 + -3 + -3 + -3 @@ -568,7 +568,7 @@ - + GIS 20km (low-res) testing config 128 @@ -606,7 +606,7 @@ - + GIS 1-to-10km (high-res) config 128 diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/usrpft_arctic_I1850CNPRDCTCBC/clm_params_c180524-sub12_updated20240201.nc b/components/elm/cime_config/testdefs/testmods_dirs/elm/usrpft_arctic_I1850CNPRDCTCBC/clm_params_c180524-sub12_updated20240201.nc new file mode 100644 index 000000000000..2ec124ef7796 Binary files /dev/null and b/components/elm/cime_config/testdefs/testmods_dirs/elm/usrpft_arctic_I1850CNPRDCTCBC/clm_params_c180524-sub12_updated20240201.nc differ diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/usrpft_arctic_I1850CNPRDCTCBC/shell_commands b/components/elm/cime_config/testdefs/testmods_dirs/elm/usrpft_arctic_I1850CNPRDCTCBC/shell_commands new file mode 100644 index 000000000000..96e201b63194 --- /dev/null +++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/usrpft_arctic_I1850CNPRDCTCBC/shell_commands @@ -0,0 +1,11 @@ +./xmlchange LND_DOMAIN_FILE=domain.lnd.6x1pt_kougarok-NGEE_TransA_navy.nc +./xmlchange ATM_DOMAIN_FILE=domain.lnd.6x1pt_kougarok-NGEE_TransA_navy.nc +./xmlchange LND_DOMAIN_PATH="$DIN_LOC_ROOT/share/domains/domain.clm" +./xmlchange ATM_DOMAIN_PATH="$DIN_LOC_ROOT/share/domains/domain.clm" +./xmlchange ELM_USRDAT_NAME=6x1pt_kougarok-NGEE_TransA +./xmlchange ELM_BLDNML_OPTS=" -maxpft 12 -bgc bgc -nutrient cnp -nutrient_comp_pathway rd -soil_decomp ctc -methane " +./xmlchange DATM_MODE=CLMGSWP3v1 +./xmlchange DATM_CLMNCEP_YR_START=1901 +./xmlchange DATM_CLMNCEP_YR_END=1920 +./xmlchange NTASKS=1 +./xmlchange NTHRDS=1 diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/usrpft_arctic_I1850CNPRDCTCBC/user_nl_elm b/components/elm/cime_config/testdefs/testmods_dirs/elm/usrpft_arctic_I1850CNPRDCTCBC/user_nl_elm new file mode 100644 index 000000000000..1a20f087a947 --- /dev/null +++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/usrpft_arctic_I1850CNPRDCTCBC/user_nl_elm @@ -0,0 +1,7 @@ +fsurdat = '$DIN_LOC_ROOT/lnd/clm2/surfdata_map/surfdata_6x1pt_kougarok-NGEE_TransA_simyr1850_c20201008-sub12.nc' +! below is user-pft file example, developed by B. Sulman et al. (2021) +! 12(+2) arctic PFTs: not_vegetated, arctic_lichen, arctic_bryophyte, (arctic_needleleaf_tree, arctic_broadleaf_tree,) +! arctic_evergreen_shrub_dwarf, arctic_evergreen_shrub_tall, +! arctic_deciduous_shrub_dwarf, arctic_deciduous_shrub_low, arctic_deciduous_shrub_tall, arctic_decidous_shrub_alder, +! arctic_forb, arctic_dry_graminoid, arctic_wet_graminoid + paramfile = '$DIN_LOC_ROOT/lnd/clm2/paramdata/clm_params_c180524-sub12_updated20240201.nc' diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/usrpft_codetest_I1850CNPRDCTCBC/clm_params_c211124vpft.nc b/components/elm/cime_config/testdefs/testmods_dirs/elm/usrpft_codetest_I1850CNPRDCTCBC/clm_params_c211124vpft.nc new file mode 100644 index 000000000000..fce6dda3ca38 Binary files /dev/null and b/components/elm/cime_config/testdefs/testmods_dirs/elm/usrpft_codetest_I1850CNPRDCTCBC/clm_params_c211124vpft.nc differ diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/usrpft_codetest_I1850CNPRDCTCBC/shell_commands b/components/elm/cime_config/testdefs/testmods_dirs/elm/usrpft_codetest_I1850CNPRDCTCBC/shell_commands new file mode 100644 index 000000000000..396d8cea8d66 --- /dev/null +++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/usrpft_codetest_I1850CNPRDCTCBC/shell_commands @@ -0,0 +1,10 @@ +./xmlchange LND_DOMAIN_FILE=domain_42_FLUXNETSITES_simyr1850_c170912.nc +./xmlchange ATM_DOMAIN_FILE=domain_42_FLUXNETSITES_simyr1850_c170912.nc +./xmlchange LND_DOMAIN_PATH="\$DIN_LOC_ROOT/share/domains/domain.clm" +./xmlchange ATM_DOMAIN_PATH="\$DIN_LOC_ROOT/share/domains/domain.clm" +./xmlchange DATM_MODE=CLM1PT +./xmlchange DATM_CLMNCEP_YR_START=2000 +./xmlchange DATM_CLMNCEP_YR_END=2000 +./xmlchange ELM_USRDAT_NAME=42_FLUXNETSITES +./xmlchange NTASKS=1 +./xmlchange NTHRDS=1 diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/usrpft_codetest_I1850CNPRDCTCBC/user_nl_elm b/components/elm/cime_config/testdefs/testmods_dirs/elm/usrpft_codetest_I1850CNPRDCTCBC/user_nl_elm new file mode 100644 index 000000000000..921f5d7714b2 --- /dev/null +++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/usrpft_codetest_I1850CNPRDCTCBC/user_nl_elm @@ -0,0 +1,10 @@ +fsurdat = '$DIN_LOC_ROOT/lnd/clm2/surfdata_map/surfdata_42_FLUXNETSITES_simyr1850_c170912.nc' +! paramfile = '$DIN_LOC_ROOT/lnd/clm2/paramdata/clm_params_c211124.nc' +! +! When 'user-pft' codes ready, comment out the above line while let the following in. +! +! below is user-pft file example, by editing default one as following +! woody=1 for tree, or =2 for shrub, and defined other pft flags: +! climatezone(0-4), nonvascular(0/1), graminoid(0/1), generic_crop(0/1), nfixer(0/1), needleleaf(0/1) +! for not going by default, changing one PFT name by appending '_unexpected'. + paramfile = '$DIN_LOC_ROOT/lnd/clm2/paramdata/clm_params_c211124vpft.nc' diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/usrpft_default_I1850CNPRDCTCBC/shell_commands b/components/elm/cime_config/testdefs/testmods_dirs/elm/usrpft_default_I1850CNPRDCTCBC/shell_commands new file mode 100644 index 000000000000..39d8b8813eda --- /dev/null +++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/usrpft_default_I1850CNPRDCTCBC/shell_commands @@ -0,0 +1,11 @@ +./xmlchange LND_DOMAIN_FILE=domain_42_FLUXNETSITES_simyr1850_c170912.nc +./xmlchange ATM_DOMAIN_FILE=domain_42_FLUXNETSITES_simyr1850_c170912.nc +./xmlchange LND_DOMAIN_PATH="\$DIN_LOC_ROOT/share/domains/domain.clm" +./xmlchange ATM_DOMAIN_PATH="\$DIN_LOC_ROOT/share/domains/domain.clm" +./xmlchange DATM_MODE=CLM1PT +./xmlchange DATM_CLMNCEP_YR_START=2000 +./xmlchange DATM_CLMNCEP_YR_END=2000 +./xmlchange ELM_USRDAT_NAME=42_FLUXNETSITES +./xmlchange NTASKS=1 +./xmlchange NTHRDS=1 + diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/usrpft_default_I1850CNPRDCTCBC/user_nl_elm b/components/elm/cime_config/testdefs/testmods_dirs/elm/usrpft_default_I1850CNPRDCTCBC/user_nl_elm new file mode 100644 index 000000000000..89670835e09d --- /dev/null +++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/usrpft_default_I1850CNPRDCTCBC/user_nl_elm @@ -0,0 +1,2 @@ +fsurdat = '$DIN_LOC_ROOT/lnd/clm2/surfdata_map/surfdata_42_FLUXNETSITES_simyr1850_c170912.nc' +paramfile = '$DIN_LOC_ROOT/lnd/clm2/paramdata/clm_params_c211124.nc' \ No newline at end of file diff --git a/components/elm/src/biogeochem/AllocationMod.F90 b/components/elm/src/biogeochem/AllocationMod.F90 index 2795fd42c8ed..141194397fb0 100644 --- a/components/elm/src/biogeochem/AllocationMod.F90 +++ b/components/elm/src/biogeochem/AllocationMod.F90 @@ -386,7 +386,7 @@ subroutine Allocation1_PlantNPDemand (bounds, num_soilc, filter_soilc, num_soilp use elm_varctl , only : carbonphosphorus_only! use pftvarcon , only: npcropmin, declfact, bfact, aleaff, arootf, astemf, noveg use pftvarcon , only: arooti, fleafi, allconsl, allconss, grperc, grpnow, nsoybean - use pftvarcon , only: percrop + use pftvarcon , only: iscft, percrop use elm_varpar , only: nlevdecomp use elm_varcon , only: nitrif_n2o_loss_frac, secspday ! @@ -583,9 +583,9 @@ subroutine Allocation1_PlantNPDemand (bounds, num_soilc, filter_soilc, num_soilp ! These fluxes should already be in gC/m2/s mr = leaf_mr(p) + froot_mr(p) - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then mr = mr + livestem_mr(p) + livecroot_mr(p) - else if (ivt(p) >= npcropmin) then + else if (iscft(ivt(p))) then if (croplive(p)) mr = mr + livestem_mr(p) + grain_mr(p) end if @@ -672,7 +672,7 @@ subroutine Allocation1_PlantNPDemand (bounds, num_soilc, filter_soilc, num_soilp f5 = 0._r8 ! continued intializations from above - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops if (croplive(p) .and. percrop(ivt(p)) == 0.0_r8 ) then ! same phases appear in subroutine CropPhenology @@ -815,14 +815,14 @@ subroutine Allocation1_PlantNPDemand (bounds, num_soilc, filter_soilc, num_soilp ! determine N requirements ! determine P requirements -X. YANG - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then c_allometry(p) = (1._r8+g1)*(1._r8+f1+f3*(1._r8+f2)) n_allometry(p) = 1._r8/cnl + f1/cnfr + (f3*f4*(1._r8+f2))/cnlw + & (f3*(1._r8-f4)*(1._r8+f2))/cndw p_allometry(p) = 1._r8/cpl + f1/cpfr + (f3*f4*(1._r8+f2))/cplw + & (f3*(1._r8-f4)*(1._r8+f2))/cpdw - else if (ivt(p) >= npcropmin) then ! skip generic crops + else if (iscft(ivt(p))) then ! skip generic crops cng = graincn(ivt(p)) cpg = graincp(ivt(p)) c_allometry(p) = (1._r8+g1)*(1._r8+f1+f5+f3*(1._r8+f2)) @@ -852,10 +852,10 @@ subroutine Allocation1_PlantNPDemand (bounds, num_soilc, filter_soilc, num_soilp ! retransn pool has N from leaves, stems, and roots for ! retranslocation - if (ivt(p) >= npcropmin .and. grain_flag(p) == 1._r8) then + if (iscft(ivt(p)) .and. grain_flag(p) == 1._r8) then avail_retransn(p) = plant_ndemand(p) avail_retransp(p) = plant_pdemand(p) - else if (ivt(p) < npcropmin .and. annsum_potential_gpp(p) > 0._r8) then + else if ((.not. iscft(ivt(p))) .and. annsum_potential_gpp(p) > 0._r8) then avail_retransn(p) = (annmax_retransn(p)/2._r8)*(gpp(p)/annsum_potential_gpp(p))/dt avail_retransp(p) = (annmax_retransp(p)/2._r8)*(gpp(p)/annsum_potential_gpp(p))/dt else @@ -1859,7 +1859,7 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & !$acc routine seq use elm_varctl , only: iulog use pftvarcon , only: noveg - use pftvarcon , only: npcropmin, grperc, grpnow + use pftvarcon , only: iscft, grperc, grpnow use elm_varpar , only: nlevdecomp use elm_varcon , only: nitrif_n2o_loss_frac, secspday ! @@ -2142,7 +2142,7 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & fcur = fcur2(ivt(p)) - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops if (croplive(p)) then f1 = aroot(p) / aleaf(p) f3 = astem(p) / aleaf(p) @@ -2328,7 +2328,7 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & fcur = fcur2(ivt(p)) - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops if (croplive(p)) then f1 = aroot(p) / aleaf(p) f3 = astem(p) / aleaf(p) @@ -2345,10 +2345,10 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & sminn_to_npool(p) = sminn_to_plant_patch(p) sminp_to_ppool(p) = sminp_to_plant_patch(p) - if (ivt(p) >= npcropmin .and. grain_flag(p) == 1._r8) then + if (iscft(ivt(p)) .and. grain_flag(p) == 1._r8) then avail_retransn(p) = retransn(p)/dt avail_retransp(p) = retransp(p)/dt - else if (ivt(p) < npcropmin .and. annsum_potential_gpp(p) > 0._r8) then + else if ((.not. iscft(ivt(p))) .and. annsum_potential_gpp(p) > 0._r8) then avail_retransn(p) = (annmax_retransn(p)/2._r8)*(gpp(p)/annsum_potential_gpp(p))/dt avail_retransp(p) = (annmax_retransp(p)/2._r8)*(gpp(p)/annsum_potential_gpp(p))/dt else @@ -2372,9 +2372,9 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & endif mr = leaf_mr(p) + froot_mr(p) - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then mr = mr + livestem_mr(p) + livecroot_mr(p) - else if (ivt(p) >= npcropmin) then + else if (iscft(ivt(p))) then if (croplive(p)) mr = mr + livestem_mr(p) + grain_mr(p) end if @@ -2466,14 +2466,14 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & plant_calloc(p) = availc(p) ! here no down-regulation on allocatable C here, NP limitation is implemented in leaf-level NP control on GPP - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then c_allometry(p) = (1._r8+g1)*(1._r8+f1+f3*(1._r8+f2)) n_allometry(p) = 1._r8/cnl + f1/cnfr + (f3*f4*(1._r8+f2))/cnlw + & (f3*(1._r8-f4)*(1._r8+f2))/cndw p_allometry(p) = 1._r8/cpl + f1/cpfr + (f3*f4*(1._r8+f2))/cplw + & (f3*(1._r8-f4)*(1._r8+f2))/cpdw - else if (ivt(p) >= npcropmin) then ! skip generic crops + else if (iscft(ivt(p))) then ! skip generic crops cng = graincn(ivt(p)) cpg = graincp(ivt(p)) c_allometry(p) = (1._r8+g1)*(1._r8+f1+f5+f3*(1._r8+f2)) @@ -2549,7 +2549,7 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & cpool_to_xsmrpool(p) = cpool_to_xsmrpool(p) + nlc * (1._r8 - fcur) * (1 + g1) cpool_to_xsmrpool(p) = cpool_to_xsmrpool(p) + nlc * f1 * fcur * (1 + g1) cpool_to_xsmrpool(p) = cpool_to_xsmrpool(p) + nlc * f1 * (1._r8 - fcur) * (1 + g1) - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then cpool_to_xsmrpool(p) = cpool_to_xsmrpool(p) + nlc * f3 * f4 * fcur * (1 + g1) cpool_to_xsmrpool(p) = cpool_to_xsmrpool(p) + nlc * f3 * f4 * (1._r8 - fcur) * (1 + g1) cpool_to_xsmrpool(p) = cpool_to_xsmrpool(p) + nlc * f3 * (1._r8 - f4) * fcur * (1 + g1) @@ -2559,7 +2559,7 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & cpool_to_xsmrpool(p) = cpool_to_xsmrpool(p) + nlc * f2 * f3 * (1._r8 - f4) * fcur * (1 + g1) cpool_to_xsmrpool(p) = cpool_to_xsmrpool(p) + nlc * f2 * f3 * (1._r8 - f4) * (1._r8 - fcur) * (1 + g1) end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops cpool_to_xsmrpool(p) = cpool_to_xsmrpool(p) + nlc * f3 * f4 * fcur * (1 + g1) cpool_to_xsmrpool(p) = cpool_to_xsmrpool(p) + nlc * f3 * f4 * (1._r8 - fcur) * (1 + g1) cpool_to_xsmrpool(p) = cpool_to_xsmrpool(p) + nlc * f3 * (1._r8 - f4) * fcur * (1 + g1) @@ -2580,7 +2580,7 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & 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) - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then cpool_to_livestemc(p) = nlc * f3 * f4 * fcur cpool_to_livestemc_storage(p) = nlc * f3 * f4 * (1._r8 - fcur) cpool_to_deadstemc(p) = nlc * f3 * (1._r8 - f4) * fcur @@ -2590,7 +2590,7 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & 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) end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops cpool_to_livestemc(p) = nlc * f3 * f4 * fcur cpool_to_livestemc_storage(p) = nlc * f3 * f4 * (1._r8 - fcur) cpool_to_deadstemc(p) = nlc * f3 * (1._r8 - f4) * fcur @@ -2633,7 +2633,7 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & npool_to_leafn_storage(p) = (nlc / cnl) * (1._r8 - fcur) npool_to_frootn(p) = (nlc * f1 / cnfr) * fcur npool_to_frootn_storage(p) = (nlc * f1 / cnfr) * (1._r8 - fcur) - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then npool_to_livestemn(p) = (nlc * f3 * f4 / cnlw) * fcur npool_to_livestemn_storage(p) = (nlc * f3 * f4 / cnlw) * (1._r8 - fcur) npool_to_deadstemn(p) = (nlc * f3 * (1._r8 - f4) / cndw) * fcur @@ -2643,7 +2643,7 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & npool_to_deadcrootn(p) = (nlc * f2 * f3 * (1._r8 - f4) / cndw) * fcur npool_to_deadcrootn_storage(p) = (nlc * f2 * f3 * (1._r8 - f4) / cndw) * (1._r8 - fcur) end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops cng = graincn(ivt(p)) npool_to_livestemn(p) = (nlc * f3 * f4 / cnlw) * fcur npool_to_livestemn_storage(p) = (nlc * f3 * f4 / cnlw) * (1._r8 - fcur) @@ -2677,7 +2677,7 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & ppool_to_leafp_storage(p) = (nlc / cpl) * (1._r8 - fcur) ppool_to_frootp(p) = (nlc * f1 / cpfr) * fcur ppool_to_frootp_storage(p) = (nlc * f1 / cpfr) * (1._r8 - fcur) - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then ppool_to_livestemp(p) = (nlc * f3 * f4 / cplw) * fcur ppool_to_livestemp_storage(p) = (nlc * f3 * f4 / cplw) * (1._r8 -fcur) ppool_to_deadstemp(p) = (nlc * f3 * (1._r8 - f4) / cpdw) *fcur @@ -2687,7 +2687,7 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & ppool_to_deadcrootp(p) = (nlc * f2 * f3 * (1._r8 - f4) / cpdw)* fcur ppool_to_deadcrootp_storage(p) = (nlc * f2 * f3 * (1._r8 - f4) / cpdw)* (1._r8 - fcur) end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops cpg = graincp(ivt(p)) ppool_to_livestemp(p) = (nlc * f3 * f4 / cplw) * fcur ppool_to_livestemp_storage(p) = (nlc * f3 * f4 / cplw) * (1._r8 -fcur) @@ -2711,13 +2711,13 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & ! growth is assigned here. gresp_storage = cpool_to_leafc_storage(p) + cpool_to_frootc_storage(p) - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then gresp_storage = gresp_storage + cpool_to_livestemc_storage(p) gresp_storage = gresp_storage + cpool_to_deadstemc_storage(p) gresp_storage = gresp_storage + cpool_to_livecrootc_storage(p) gresp_storage = gresp_storage + cpool_to_deadcrootc_storage(p) end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops gresp_storage = gresp_storage + cpool_to_livestemc_storage(p) gresp_storage = gresp_storage + cpool_to_grainc_storage(p) end if @@ -2748,7 +2748,7 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & npool_to_frootn(p) = cpool_to_frootc(p) / cnfr npool_to_frootn_storage(p) = cpool_to_frootc_storage(p) / cnfr - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then supplement_to_plantn(p) = supplement_to_plantn(p) + cpool_to_livestemc(p) / cnlw - npool_to_livestemn(p) supplement_to_plantn(p) = supplement_to_plantn(p) + cpool_to_livestemc_storage(p) / cnlw & - npool_to_livestemn_storage(p) @@ -2771,7 +2771,7 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & npool_to_deadcrootn(p) = cpool_to_deadcrootc(p) / cndw npool_to_deadcrootn_storage(p) = cpool_to_deadcrootc_storage(p) / cndw end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops cng = graincn(ivt(p)) supplement_to_plantn(p) = supplement_to_plantn(p) + cpool_to_livestemc(p) / cnlw - npool_to_livestemn(p) supplement_to_plantn(p) = supplement_to_plantn(p) + cpool_to_livestemc_storage(p) / cnlw & @@ -2815,7 +2815,7 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & ppool_to_frootp(p) = cpool_to_frootc(p) / cpfr ppool_to_frootp_storage(p) = cpool_to_frootc_storage(p) / cpfr - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then supplement_to_plantp(p) = supplement_to_plantp(p) + max(cpool_to_livestemc(p) / cplw & - ppool_to_livestemp(p),0._r8) @@ -2843,7 +2843,7 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & ppool_to_deadcrootp(p) = cpool_to_deadcrootc(p) / cpdw ppool_to_deadcrootp_storage(p) = cpool_to_deadcrootc_storage(p) / cpdw end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops cpg = graincp(ivt(p)) supplement_to_plantp(p) = supplement_to_plantp(p) + max(cpool_to_livestemc(p) / cplw & - ppool_to_livestemp(p),0._r8) @@ -3891,7 +3891,7 @@ subroutine dynamic_plant_alloc( nutrient_scalar, water_scalar, laindex, alloc_le alloc_froot = min(alloc_froot, 0.4_r8) ! stem allocation - if (woody == 1.0_r8) then + if (woody >= 1.0_r8) then alloc_stem = alloc_s0 * 3.0_r8 * min(nu_scalar,w_scalar) / (2.0_r8 * light_scalar + min(nu_scalar,w_scalar)) else alloc_stem = 0.0_r8 @@ -3908,7 +3908,7 @@ subroutine dynamic_plant_alloc( nutrient_scalar, water_scalar, laindex, alloc_le ! if lai greater than laimax then no allocation to leaf; leaf allocation goes to stem or fine root if (laindex > laimax) then - if (woody == 1.0_r8) then + if (woody >= 1.0_r8) then alloc_stem = alloc_stem + alloc_leaf/2._r8 - 0.005_r8 alloc_froot = alloc_froot + alloc_leaf/2._r8 - 0.005_r8 else diff --git a/components/elm/src/biogeochem/CH4Mod.F90 b/components/elm/src/biogeochem/CH4Mod.F90 index ce2378049fd5..3b3c1fa80611 100644 --- a/components/elm/src/biogeochem/CH4Mod.F90 +++ b/components/elm/src/biogeochem/CH4Mod.F90 @@ -2426,7 +2426,7 @@ subroutine ch4_aere (bounds, & ! !USES: !$acc routine seq use elm_varcon , only : rpi - use pftvarcon , only : nc3_arctic_grass, crop, nc3_nonarctic_grass, nc4_grass, noveg + use pftvarcon , only : graminoid, crop, noveg use CH4varcon , only : transpirationloss, usefrootc, use_aereoxid_prog ! ! !ARGUMENTS: @@ -2563,8 +2563,7 @@ subroutine ch4_aere (bounds, & is_vegetated = .false. end if - if (veg_pp%itype(p) == nc3_arctic_grass .or. crop(veg_pp%itype(p)) == 1 .or. & - veg_pp%itype(p) == nc3_nonarctic_grass .or. veg_pp%itype(p) == nc4_grass) then + if (graminoid(veg_pp%itype(p)) == 1 .or. crop(veg_pp%itype(p)) == 1) then poros_tiller = 0.3_r8 ! Colmer 2003 else poros_tiller = 0.3_r8 * CH4ParamsInst%nongrassporosratio diff --git a/components/elm/src/biogeochem/CNAllocationBetrMod.F90 b/components/elm/src/biogeochem/CNAllocationBetrMod.F90 index 9701eebda607..8cfc342bb404 100644 --- a/components/elm/src/biogeochem/CNAllocationBetrMod.F90 +++ b/components/elm/src/biogeochem/CNAllocationBetrMod.F90 @@ -246,7 +246,7 @@ subroutine Allocation1_PlantNPDemand (bounds, num_soilc, filter_soilc, num_soilp use shr_sys_mod , only: shr_sys_flush use elm_varctl , only: iulog,cnallocate_carbon_only,cnallocate_carbonnitrogen_only,& cnallocate_carbonphosphorus_only - use pftvarcon , only: npcropmin, declfact, bfact, aleaff, arootf, astemf, noveg + use pftvarcon , only: iscft, declfact, bfact, aleaff, arootf, astemf, noveg use pftvarcon , only: arooti, fleafi, allconsl, allconss, grperc, grpnow, nsoybean use elm_varpar , only: nlevdecomp use elm_varcon , only: nitrif_n2o_loss_frac, secspday @@ -643,9 +643,9 @@ subroutine Allocation1_PlantNPDemand (bounds, num_soilc, filter_soilc, num_soilp ! These fluxes should already be in gC/m2/s mr = leaf_mr(p) + froot_mr(p) - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then mr = mr + livestem_mr(p) + livecroot_mr(p) - else if (ivt(p) >= npcropmin) then + else if (iscft(ivt(p))) then if (croplive(p)) mr = mr + livestem_mr(p) + grain_mr(p) end if @@ -726,7 +726,7 @@ subroutine Allocation1_PlantNPDemand (bounds, num_soilc, filter_soilc, num_soilp f5 = 0._r8 ! continued intializations from above - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops if (croplive(p)) then ! same phases appear in subroutine CropPhenology @@ -852,14 +852,14 @@ subroutine Allocation1_PlantNPDemand (bounds, num_soilc, filter_soilc, num_soilp ! based on available C, use constant allometric relationships to ! determine N requirements - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then c_allometry(p) = (1._r8+g1)*(1._r8+f1+f3*(1._r8+f2)) n_allometry(p) = 1._r8/cnl + f1/cnfr + (f3*f4*(1._r8+f2))/cnlw + & (f3*(1._r8-f4)*(1._r8+f2))/cndw p_allometry(p) = 1._r8/cpl + f1/cpfr + (f3*f4*(1._r8+f2))/cplw + & (f3*(1._r8-f4)*(1._r8+f2))/cpdw - else if (ivt(p) >= npcropmin) then ! skip generic crops + else if (iscft(ivt(p))) then ! skip generic crops cng = graincn(ivt(p)) cpg = graincp(ivt(p)) c_allometry(p) = (1._r8+g1)*(1._r8+f1+f5+f3*(1._r8+f2)) @@ -889,10 +889,10 @@ subroutine Allocation1_PlantNPDemand (bounds, num_soilc, filter_soilc, num_soilp ! retransn pool has N from leaves, stems, and roots for ! retranslocation - if (ivt(p) >= npcropmin .and. grain_flag(p) == 1._r8) then + if (iscft(ivt(p)) .and. grain_flag(p) == 1._r8) then avail_retransn(p) = plant_ndemand(p) avail_retransp(p) = plant_pdemand(p) - else if (ivt(p) < npcropmin .and. annsum_potential_gpp(p) > 0._r8) then + else if ((.not. iscft(ivt(p))) .and. annsum_potential_gpp(p) > 0._r8) then avail_retransn(p) = (annmax_retransn(p)/2._r8)*(gpp(p)/annsum_potential_gpp(p))/dt avail_retransp(p) = (annmax_retransp(p)/2._r8)*(gpp(p)/annsum_potential_gpp(p))/dt else @@ -1105,14 +1105,10 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & use shr_sys_mod , only: shr_sys_flush use elm_varctl , only: iulog,cnallocate_carbon_only,cnallocate_carbonnitrogen_only,& cnallocate_carbonphosphorus_only -! use pftvarcon , only: npcropmin, declfact, bfact, aleaff, arootf, astemf -! use pftvarcon , only: arooti, fleafi, allconsl, allconss, grperc, grpnow, nsoybean use pftvarcon , only: noveg - use pftvarcon , only: npcropmin, grperc, grpnow + use pftvarcon , only: iscft, grperc, grpnow use elm_varpar , only: nlevdecomp !!nlevsoi, use elm_varcon , only: nitrif_n2o_loss_frac, secspday -! use landunit_varcon , only: istsoil, istcrop -! use elm_time_manager , only: get_step_size ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds @@ -1393,7 +1389,7 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & fcur = fcur2(ivt(p)) - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops if (croplive(p)) then f1 = aroot(p) / aleaf(p) f3 = astem(p) / aleaf(p) @@ -1412,10 +1408,10 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & plant_n_buffer_patch(p) = plant_n_buffer_patch(p) * (1._r8-dt/taun) plant_p_buffer_patch(p) = plant_p_buffer_patch(p) * (1._r8-dt/taun) - if (ivt(p) >= npcropmin .and. grain_flag(p) == 1._r8) then + if (iscft(ivt(p)) .and. grain_flag(p) == 1._r8) then avail_retransn(p) = retransn(p)/dt avail_retransp(p) = retransp(p)/dt - else if (ivt(p) < npcropmin .and. annsum_potential_gpp(p) > 0._r8) then + else if ((.not. iscft(ivt(p))) .and. annsum_potential_gpp(p) > 0._r8) then avail_retransn(p) = (annmax_retransn(p)/2._r8)*(gpp(p)/annsum_potential_gpp(p))/dt avail_retransp(p) = (annmax_retransp(p)/2._r8)*(gpp(p)/annsum_potential_gpp(p))/dt else @@ -1434,9 +1430,9 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & plant_palloc(p) = sminp_to_ppool(p) + retransp_to_ppool(p) mr = leaf_mr(p) + froot_mr(p) - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then mr = mr + livestem_mr(p) + livecroot_mr(p) - else if (ivt(p) >= npcropmin) then + else if (iscft(ivt(p))) then if (croplive(p)) mr = mr + livestem_mr(p) + grain_mr(p) end if ! try to take mr from xsmr storage pool first @@ -1523,14 +1519,14 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & plant_calloc(p) = availc(p) ! here no down-regulation on allocatable C here, NP limitation is implemented in leaf-level NP control on GPP - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then c_allometry(p) = (1._r8+g1)*(1._r8+f1+f3*(1._r8+f2)) n_allometry(p) = 1._r8/cnl + f1/cnfr + (f3*f4*(1._r8+f2))/cnlw + & (f3*(1._r8-f4)*(1._r8+f2))/cndw p_allometry(p) = 1._r8/cpl + f1/cpfr + (f3*f4*(1._r8+f2))/cplw + & (f3*(1._r8-f4)*(1._r8+f2))/cpdw - else if (ivt(p) >= npcropmin) then ! skip generic crops + else if (iscft(ivt(p))) then ! skip generic crops cng = graincn(ivt(p)) cpg = graincp(ivt(p)) c_allometry(p) = (1._r8+g1)*(1._r8+f1+f5+f3*(1._r8+f2)) @@ -1604,7 +1600,7 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & cpool_to_xsmrpool(p) = cpool_to_xsmrpool(p) + nlc * (1._r8 - fcur) * (1 + g1) cpool_to_xsmrpool(p) = cpool_to_xsmrpool(p) + nlc * f1 * fcur * (1 + g1) cpool_to_xsmrpool(p) = cpool_to_xsmrpool(p) + nlc * f1 * (1._r8 - fcur) * (1 + g1) - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then cpool_to_xsmrpool(p) = cpool_to_xsmrpool(p) + nlc * f3 * f4 * fcur * (1 + g1) cpool_to_xsmrpool(p) = cpool_to_xsmrpool(p) + nlc * f3 * f4 * (1._r8 - fcur) * (1 + g1) cpool_to_xsmrpool(p) = cpool_to_xsmrpool(p) + nlc * f3 * (1._r8 - f4) * fcur * (1 + g1) @@ -1614,7 +1610,7 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & cpool_to_xsmrpool(p) = cpool_to_xsmrpool(p) + nlc * f2 * f3 * (1._r8 - f4) * fcur * (1 + g1) cpool_to_xsmrpool(p) = cpool_to_xsmrpool(p) + nlc * f2 * f3 * (1._r8 - f4) * (1._r8 - fcur) * (1 + g1) end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops cpool_to_xsmrpool(p) = cpool_to_xsmrpool(p) + nlc * f3 * f4 * fcur * (1 + g1) cpool_to_xsmrpool(p) = cpool_to_xsmrpool(p) + nlc * f3 * f4 * (1._r8 - fcur) * (1 + g1) cpool_to_xsmrpool(p) = cpool_to_xsmrpool(p) + nlc * f3 * (1._r8 - f4) * fcur * (1 + g1) @@ -1635,7 +1631,7 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & 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) - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then cpool_to_livestemc(p) = nlc * f3 * f4 * fcur cpool_to_livestemc_storage(p) = nlc * f3 * f4 * (1._r8 - fcur) cpool_to_deadstemc(p) = nlc * f3 * (1._r8 - f4) * fcur @@ -1645,7 +1641,7 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & 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) end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops cpool_to_livestemc(p) = nlc * f3 * f4 * fcur cpool_to_livestemc_storage(p) = nlc * f3 * f4 * (1._r8 - fcur) cpool_to_deadstemc(p) = nlc * f3 * (1._r8 - f4) * fcur @@ -1688,7 +1684,7 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & npool_to_leafn_storage(p) = (nlc / cnl) * (1._r8 - fcur) npool_to_frootn(p) = (nlc * f1 / cnfr) * fcur npool_to_frootn_storage(p) = (nlc * f1 / cnfr) * (1._r8 - fcur) - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then npool_to_livestemn(p) = (nlc * f3 * f4 / cnlw) * fcur npool_to_livestemn_storage(p) = (nlc * f3 * f4 / cnlw) * (1._r8 - fcur) npool_to_deadstemn(p) = (nlc * f3 * (1._r8 - f4) / cndw) * fcur @@ -1698,7 +1694,7 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & npool_to_deadcrootn(p) = (nlc * f2 * f3 * (1._r8 - f4) / cndw) * fcur npool_to_deadcrootn_storage(p) = (nlc * f2 * f3 * (1._r8 - f4) / cndw) * (1._r8 - fcur) end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops cng = graincn(ivt(p)) npool_to_livestemn(p) = (nlc * f3 * f4 / cnlw) * fcur npool_to_livestemn_storage(p) = (nlc * f3 * f4 / cnlw) * (1._r8 - fcur) @@ -1732,7 +1728,7 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & ppool_to_leafp_storage(p) = (nlc / cpl) * (1._r8 - fcur) ppool_to_frootp(p) = (nlc * f1 / cpfr) * fcur ppool_to_frootp_storage(p) = (nlc * f1 / cpfr) * (1._r8 - fcur) - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then ppool_to_livestemp(p) = (nlc * f3 * f4 / cplw) * fcur ppool_to_livestemp_storage(p) = (nlc * f3 * f4 / cplw) * (1._r8 -fcur) ppool_to_deadstemp(p) = (nlc * f3 * (1._r8 - f4) / cpdw) *fcur @@ -1742,7 +1738,7 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & ppool_to_deadcrootp(p) = (nlc * f2 * f3 * (1._r8 - f4) / cpdw)* fcur ppool_to_deadcrootp_storage(p) = (nlc * f2 * f3 * (1._r8 - f4) / cpdw)* (1._r8 - fcur) end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops cpg = graincp(ivt(p)) ppool_to_livestemp(p) = (nlc * f3 * f4 / cplw) * fcur ppool_to_livestemp_storage(p) = (nlc * f3 * f4 / cplw) * (1._r8 -fcur) @@ -1766,13 +1762,13 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & ! growth is assigned here. gresp_storage = cpool_to_leafc_storage(p) + cpool_to_frootc_storage(p) - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then gresp_storage = gresp_storage + cpool_to_livestemc_storage(p) gresp_storage = gresp_storage + cpool_to_deadstemc_storage(p) gresp_storage = gresp_storage + cpool_to_livecrootc_storage(p) gresp_storage = gresp_storage + cpool_to_deadcrootc_storage(p) end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops gresp_storage = gresp_storage + cpool_to_livestemc_storage(p) gresp_storage = gresp_storage + cpool_to_grainc_storage(p) end if @@ -1797,7 +1793,7 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & npool_to_frootn(p) = cpool_to_frootc(p) / cnfr npool_to_frootn_storage(p) = cpool_to_frootc_storage(p) / cnfr - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then supplement_to_sminn_vr(c,1) = supplement_to_sminn_vr(c,1) + cpool_to_livestemc(p) / cnlw - npool_to_livestemn(p) supplement_to_sminn_vr(c,1) = supplement_to_sminn_vr(c,1) + cpool_to_livestemc_storage(p) / cnlw & - npool_to_livestemn_storage(p) @@ -1820,7 +1816,7 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & npool_to_deadcrootn(p) = cpool_to_deadcrootc(p) / cndw npool_to_deadcrootn_storage(p) = cpool_to_deadcrootc_storage(p) / cndw end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops cng = graincn(ivt(p)) supplement_to_sminn_vr(c,1) = supplement_to_sminn_vr(c,1) + cpool_to_livestemc(p) / cnlw - npool_to_livestemn(p) supplement_to_sminn_vr(c,1) = supplement_to_sminn_vr(c,1) + cpool_to_livestemc_storage(p) / cnlw & @@ -1864,7 +1860,7 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & ppool_to_frootp(p) = cpool_to_frootc(p) / cpfr ppool_to_frootp_storage(p) = cpool_to_frootc_storage(p) / cpfr - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then supplement_to_sminp_vr(c,1) = supplement_to_sminp_vr(c,1) + max(cpool_to_livestemc(p) / cplw & - ppool_to_livestemp(p),0._r8) supplement_to_sminp_vr(c,1) = supplement_to_sminp_vr(c,1) + max(cpool_to_livestemc_storage(p) / cplw & @@ -1891,7 +1887,7 @@ subroutine Allocation3_PlantCNPAlloc (bounds , & ppool_to_deadcrootp(p) = cpool_to_deadcrootc(p) / cpdw ppool_to_deadcrootp_storage(p) = cpool_to_deadcrootc_storage(p) / cpdw end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops cpg = graincp(ivt(p)) supplement_to_sminp_vr(c,1) = supplement_to_sminp_vr(c,1) + max(cpool_to_livestemc(p) / cplw & - ppool_to_livestemp(p),0._r8) diff --git a/components/elm/src/biogeochem/CNCarbonFluxType.F90 b/components/elm/src/biogeochem/CNCarbonFluxType.F90 index 092af4fa66bf..a6c56a935f05 100644 --- a/components/elm/src/biogeochem/CNCarbonFluxType.F90 +++ b/components/elm/src/biogeochem/CNCarbonFluxType.F90 @@ -10,7 +10,7 @@ module CNCarbonFluxType use landunit_varcon , only : istsoil, istcrop, istdlak use elm_varctl , only : use_c13, use_fates use CH4varcon , only : allowlakeprod - use pftvarcon , only : npcropmin + use pftvarcon , only : iscft use CNDecompCascadeConType , only : decomp_cascade_con use VegetationType , only : veg_pp use ColumnType , only : col_pp @@ -1675,7 +1675,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil this%cpool_livecroot_storage_gr_patch(p) + & this%cpool_deadcroot_storage_gr_patch(p) - if ( crop_prog .and. veg_pp%itype(p) >= npcropmin )then + if ( crop_prog .and. iscft(veg_pp%itype(p)))then this%mr_patch(p) = & this%mr_patch(p) + & this%grain_mr_patch(p) @@ -1700,7 +1700,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil this%storage_gr_patch(p) ! autotrophic respiration (AR) - if ( crop_prog .and. veg_pp%itype(p) >= npcropmin )then + if ( crop_prog .and. iscft(veg_pp%itype(p)))then this%ar_patch(p) = & this%mr_patch(p) + & this%gr_patch(p) + & @@ -1812,7 +1812,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil this%wood_harvestc_patch(p) = & this%hrv_deadstemc_to_prod10c_patch(p) + & this%hrv_deadstemc_to_prod100c_patch(p) - if ( crop_prog .and. veg_pp%itype(p) >= npcropmin )then + if ( crop_prog .and. iscft(veg_pp%itype(p)))then this%wood_harvestc_patch(p) = & this%wood_harvestc_patch(p) + & this%hrv_cropc_to_prod1c_patch(p) @@ -1842,7 +1842,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil this%m_gresp_xfer_to_fire_patch(p) + & this%m_cpool_to_fire_patch(p) - if ( crop_prog .and. veg_pp%itype(p) >= npcropmin )then + if ( crop_prog .and. iscft(veg_pp%itype(p)))then this%litfall_patch(p) = & this%litfall_patch(p) + & @@ -1878,7 +1878,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil this%hrv_leafc_to_litter_patch(p) + & this%leafc_to_litter_patch(p) - if ( crop_prog .and. veg_pp%itype(p) >= npcropmin )then + if ( crop_prog .and. iscft(veg_pp%itype(p)))then this%leafc_loss_patch(p) = & this%leafc_loss_patch(p) + & this%hrv_leafc_to_prod1c_patch(p) @@ -1920,7 +1920,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil this%hrv_deadcrootc_storage_to_litter_patch(p) + & this%hrv_deadcrootc_xfer_to_litter_patch(p) ! putting the harvested crop stem and grain in the wood loss bdrewniak - if ( crop_prog .and. veg_pp%itype(p) >= npcropmin )then + if ( crop_prog .and. iscft(veg_pp%itype(p)))then this%woodc_loss_patch(p) = & this%woodc_loss_patch(p) + & this%hrv_grainc_to_prod1c_patch(p) + & @@ -2592,7 +2592,7 @@ subroutine summary_cflux_for_ch4( this, bounds, num_soilp, filter_soilp, num_soi this%cpool_to_deadstemc_patch(p) + & this%deadstemc_xfer_to_deadstemc_patch(p) - if ( crop_prog .and. veg_pp%itype(p) >= npcropmin )then + if ( crop_prog .and. iscft(veg_pp%itype(p)))then this%agnpp_patch(p) = & this%agnpp_patch(p) + & this%cpool_to_grainc_patch(p) + & diff --git a/components/elm/src/biogeochem/CNCarbonStateType.F90 b/components/elm/src/biogeochem/CNCarbonStateType.F90 index 2ed04f03231c..b733773fb20d 100644 --- a/components/elm/src/biogeochem/CNCarbonStateType.F90 +++ b/components/elm/src/biogeochem/CNCarbonStateType.F90 @@ -12,7 +12,7 @@ module CNCarbonStateType use elm_varctl , only : iulog, use_vertsoilc, spinup_state use decompMod , only : bounds_type use CNStateType , only : cnstate_type - use pftvarcon , only : npcropmin + use pftvarcon , only : iscft use CNDecompCascadeConType , only : decomp_cascade_con use VegetationPropertiesType , only : veg_vp use abortutils , only : endrun @@ -400,7 +400,7 @@ subroutine InitCold(this, bounds, ratio, c12_carbonstate_vars) ! ! !USES: use landunit_varcon , only: istsoil - use pftvarcon , only: noveg, npcropmin + use pftvarcon , only: noveg ! ! !ARGUMENTS: class(carbonstate_type) :: this @@ -459,7 +459,7 @@ subroutine InitCold(this, bounds, ratio, c12_carbonstate_vars) if (veg_vp%evergreen(veg_pp%itype(p)) == 1._r8) then this%leafc_patch(p) = 1._r8 * ratio this%leafc_storage_patch(p) = 0._r8 - else if (veg_pp%itype(p) >= npcropmin) then ! prognostic crop types + else if (iscft(veg_pp%itype(p))) then ! prognostic crop types this%leafc_patch(p) = 0._r8 this%leafc_storage_patch(p) = 0._r8 else @@ -477,7 +477,7 @@ subroutine InitCold(this, bounds, ratio, c12_carbonstate_vars) this%livestemc_storage_patch(p) = 0._r8 this%livestemc_xfer_patch(p) = 0._r8 - if (veg_vp%woody(veg_pp%itype(p)) == 1._r8) then + if (veg_vp%woody(veg_pp%itype(p)) >= 1.0_r8) then this%deadstemc_patch(p) = 0.1_r8 * ratio else this%deadstemc_patch(p) = 0._r8 @@ -866,7 +866,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil this%gresp_storage_patch(p) + & this%gresp_xfer_patch(p) - if ( crop_prog .and. veg_pp%itype(p) >= npcropmin )then + if ( crop_prog .and. iscft(veg_pp%itype(p)))then this%storvegc_patch(p) = & this%storvegc_patch(p) + & this%grainc_storage_patch(p) + & diff --git a/components/elm/src/biogeochem/CNGapMortalityBeTRMod.F90 b/components/elm/src/biogeochem/CNGapMortalityBeTRMod.F90 index e3965d6eea3a..3bbbf1db1f60 100644 --- a/components/elm/src/biogeochem/CNGapMortalityBeTRMod.F90 +++ b/components/elm/src/biogeochem/CNGapMortalityBeTRMod.F90 @@ -91,7 +91,7 @@ subroutine CNGapMortality (& ! !USES: use elm_time_manager , only: get_days_per_year use elm_varcon , only: secspday - use pftvarcon , only: npcropmin + use pftvarcon , only: iscft use elm_varctl , only: spinup_state, spinup_mortality_factor ! ! !ARGUMENTS: @@ -188,7 +188,7 @@ subroutine CNGapMortality (& * gap_indicator(gid_m_deadcrootn_to_litter) - if (ivt(p) < npcropmin) then + if (.not. iscft(veg_pp%itype(p))) then veg_nf%m_retransn_to_litter(p) = veg_ns%retransn(p) * m & * gap_indicator(gid_m_retransn_to_litter) end if @@ -239,7 +239,7 @@ subroutine CNGapMortality (& veg_pf%m_deadstemp_to_litter(p) = veg_ps%deadstemp(p) * m veg_pf%m_livecrootp_to_litter(p) = veg_ps%livecrootp(p) * m veg_pf%m_deadcrootp_to_litter(p) = veg_ps%deadcrootp(p) * m - if (ivt(p) < npcropmin) then + if (.not. iscft(veg_pp%itype(p))) then veg_pf%m_retransp_to_litter(p) = veg_ps%retransp(p) * m end if diff --git a/components/elm/src/biogeochem/CNNStateUpdate1BeTRMod.F90 b/components/elm/src/biogeochem/CNNStateUpdate1BeTRMod.F90 index 6eee5f923da0..465c92f82b4c 100644 --- a/components/elm/src/biogeochem/CNNStateUpdate1BeTRMod.F90 +++ b/components/elm/src/biogeochem/CNNStateUpdate1BeTRMod.F90 @@ -10,7 +10,7 @@ module CNNStateUpdate1BeTRMod use elm_varpar , only : crop_prog, i_met_lit, i_cel_lit, i_lig_lit, i_cwd use elm_varctl , only : iulog use elm_varcon , only : nitrif_n2o_loss_frac - use pftvarcon , only : npcropmin, nc3crop + use pftvarcon , only : iscft use VegetationPropertiesType , only : veg_vp use CNDecompCascadeConType , only : decomp_cascade_con use CNStateType , only : cnstate_type @@ -90,7 +90,7 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & veg_ns%frootn(p) = veg_ns%frootn(p) + veg_nf%frootn_xfer_to_frootn(p)*dt veg_ns%frootn_xfer(p) = veg_ns%frootn_xfer(p) - veg_nf%frootn_xfer_to_frootn(p)*dt - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then veg_ns%livestemn(p) = veg_ns%livestemn(p) + veg_nf%livestemn_xfer_to_livestemn(p)*dt veg_ns%livestemn_xfer(p) = veg_ns%livestemn_xfer(p) - veg_nf%livestemn_xfer_to_livestemn(p)*dt veg_ns%deadstemn(p) = veg_ns%deadstemn(p) + veg_nf%deadstemn_xfer_to_deadstemn(p)*dt @@ -101,7 +101,7 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & veg_ns%deadcrootn_xfer(p) = veg_ns%deadcrootn_xfer(p) - veg_nf%deadcrootn_xfer_to_deadcrootn(p)*dt end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops ! lines here for consistency; the transfer terms are zero veg_ns%livestemn(p) = veg_ns%livestemn(p) + veg_nf%livestemn_xfer_to_livestemn(p)*dt veg_ns%livestemn_xfer(p) = veg_ns%livestemn_xfer(p) - veg_nf%livestemn_xfer_to_livestemn(p)*dt @@ -116,7 +116,7 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & veg_ns%retransn(p) = veg_ns%retransn(p) + veg_nf%leafn_to_retransn(p)*dt ! live wood turnover and retranslocation fluxes - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then veg_ns%livestemn(p) = veg_ns%livestemn(p) - veg_nf%livestemn_to_deadstemn(p)*dt veg_ns%deadstemn(p) = veg_ns%deadstemn(p) + veg_nf%livestemn_to_deadstemn(p)*dt veg_ns%livestemn(p) = veg_ns%livestemn(p) - veg_nf%livestemn_to_retransn(p)*dt @@ -126,7 +126,7 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & veg_ns%livecrootn(p) = veg_ns%livecrootn(p) - veg_nf%livecrootn_to_retransn(p)*dt veg_ns%retransn(p) = veg_ns%retransn(p) + veg_nf%livecrootn_to_retransn(p)*dt end if - if (ivt(p) >= npcropmin) then ! Beth adds retrans from froot + if (iscft(ivt(p))) then ! Beth adds retrans from froot veg_ns%frootn(p) = veg_ns%frootn(p) - veg_nf%frootn_to_retransn(p)*dt veg_ns%retransn(p) = veg_ns%retransn(p) + veg_nf%frootn_to_retransn(p)*dt veg_ns%livestemn(p) = veg_ns%livestemn(p) - veg_nf%livestemn_to_litter(p)*dt @@ -153,7 +153,7 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & veg_ns%npool(p) = veg_ns%npool(p) - veg_nf%npool_to_frootn_storage(p)*dt veg_ns%frootn_storage(p) = veg_ns%frootn_storage(p) + veg_nf%npool_to_frootn_storage(p)*dt - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then veg_ns%npool(p) = veg_ns%npool(p) - veg_nf%npool_to_livestemn(p)*dt veg_ns%livestemn(p) = veg_ns%livestemn(p) + veg_nf%npool_to_livestemn(p)*dt veg_ns%npool(p) = veg_ns%npool(p) - veg_nf%npool_to_livestemn_storage(p)*dt @@ -172,7 +172,7 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & veg_ns%deadcrootn_storage(p) = veg_ns%deadcrootn_storage(p) + veg_nf%npool_to_deadcrootn_storage(p)*dt end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops veg_ns%npool(p) = veg_ns%npool(p) - veg_nf%npool_to_livestemn(p)*dt veg_ns%livestemn(p) = veg_ns%livestemn(p) + veg_nf%npool_to_livestemn(p)*dt veg_ns%npool(p) = veg_ns%npool(p) - veg_nf%npool_to_livestemn_storage(p)*dt @@ -189,7 +189,7 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & veg_ns%frootn_storage(p) = veg_ns%frootn_storage(p) - veg_nf%frootn_storage_to_xfer(p)*dt veg_ns%frootn_xfer(p) = veg_ns%frootn_xfer(p) + veg_nf%frootn_storage_to_xfer(p)*dt - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then veg_ns%livestemn_storage(p) = veg_ns%livestemn_storage(p) - veg_nf%livestemn_storage_to_xfer(p)*dt veg_ns%livestemn_xfer(p) = veg_ns%livestemn_xfer(p) + veg_nf%livestemn_storage_to_xfer(p)*dt veg_ns%deadstemn_storage(p) = veg_ns%deadstemn_storage(p) - veg_nf%deadstemn_storage_to_xfer(p)*dt @@ -200,7 +200,7 @@ subroutine NStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp, & veg_ns%deadcrootn_xfer(p) = veg_ns%deadcrootn_xfer(p) + veg_nf%deadcrootn_storage_to_xfer(p)*dt end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops ! lines here for consistency; the transfer terms are zero veg_ns%livestemn_storage(p) = veg_ns%livestemn_storage(p) - veg_nf%livestemn_storage_to_xfer(p)*dt veg_ns%livestemn_xfer(p) = veg_ns%livestemn_xfer(p) + veg_nf%livestemn_storage_to_xfer(p)*dt diff --git a/components/elm/src/biogeochem/CNNStateUpdate2BeTRMod.F90 b/components/elm/src/biogeochem/CNNStateUpdate2BeTRMod.F90 index 60100b657aef..70b56142c882 100644 --- a/components/elm/src/biogeochem/CNNStateUpdate2BeTRMod.F90 +++ b/components/elm/src/biogeochem/CNNStateUpdate2BeTRMod.F90 @@ -14,7 +14,7 @@ module CNNStateUpdate2BeTRMod use CNNitrogenFLuxType , only : nitrogenflux_type use VegetationType , only : veg_pp use VegetationDataType , only : veg_ns, veg_nf - use pftvarcon , only : npcropmin + use pftvarcon , only : iscft !! bgc interface & pflotran: use elm_varctl , only : use_pflotran, pf_cmode ! @@ -147,7 +147,7 @@ subroutine NStateUpdate2h(num_soilc, filter_soilc, num_soilp, filter_soilp, & veg_ns%deadcrootn(p) = veg_ns%deadcrootn(p) - veg_nf%hrv_deadcrootn_to_litter(p) * dt veg_ns%retransn(p) = veg_ns%retransn(p) - veg_nf%hrv_retransn_to_litter(p) * dt - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops veg_ns%livestemn(p)= veg_ns%livestemn(p) - veg_nf%hrv_livestemn_to_prod1n(p) * dt veg_ns%leafn(p) = veg_ns%leafn(p) - veg_nf%hrv_leafn_to_prod1n(p) * dt veg_ns%grainn(p) = veg_ns%grainn(p) - veg_nf%hrv_grainn_to_prod1n(p) * dt diff --git a/components/elm/src/biogeochem/CNNitrogenFluxType.F90 b/components/elm/src/biogeochem/CNNitrogenFluxType.F90 index d0b76c195afa..5394e0d05fa1 100644 --- a/components/elm/src/biogeochem/CNNitrogenFluxType.F90 +++ b/components/elm/src/biogeochem/CNNitrogenFluxType.F90 @@ -1078,7 +1078,6 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil ! !USES: use elm_varpar , only: nlevdecomp,ndecomp_cascade_transitions,ndecomp_pools use subgridAveMod , only: p2c - use pftvarcon , only : npcropmin use tracer_varcon , only: is_active_betr_bgc use elm_varpar , only: nlevdecomp_full ! diff --git a/components/elm/src/biogeochem/CNNitrogenStateType.F90 b/components/elm/src/biogeochem/CNNitrogenStateType.F90 index 003e34e132d9..a7f7315c6c83 100644 --- a/components/elm/src/biogeochem/CNNitrogenStateType.F90 +++ b/components/elm/src/biogeochem/CNNitrogenStateType.F90 @@ -12,7 +12,7 @@ module CNNitrogenStateType use elm_varctl , only : use_vertsoilc, use_century_decomp, use_fan use elm_varctl , only : iulog, override_bgc_restart_mismatch_dump, spinup_state use decompMod , only : bounds_type - use pftvarcon , only : npcropmin, nstor + use pftvarcon , only : iscft, nstor use CNDecompCascadeConType , only : decomp_cascade_con use VegetationPropertiesType , only : veg_vp use abortutils , only : endrun @@ -502,7 +502,7 @@ subroutine InitCold(this, bounds, & ! !USES: use elm_varpar , only : crop_prog use decompMod , only : bounds_type - use pftvarcon , only : noveg, npcropmin + use pftvarcon , only : noveg, iscft ! ! !ARGUMENTS: class(nitrogenstate_type) :: this @@ -588,7 +588,7 @@ subroutine InitCold(this, bounds, & ! tree types need to be initialized with some stem mass so that ! roughness length is not zero in canopy flux calculation - if (veg_vp%woody(veg_pp%itype(p)) == 1._r8) then + if (veg_vp%woody(veg_pp%itype(p)) >= 1.0_r8) then this%deadstemn_patch(p) = deadstemc_patch(p) / veg_vp%deadwdcn(veg_pp%itype(p)) else this%deadstemn_patch(p) = 0._r8 @@ -1007,7 +1007,7 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil this%npool_patch(p) + & this%retransn_patch(p) - if ( crop_prog .and. veg_pp%itype(p) >= npcropmin )then + if ( crop_prog .and. iscft(veg_pp%itype(p)))then this%dispvegn_patch(p) = & this%dispvegn_patch(p) + & this%grainn_patch(p) diff --git a/components/elm/src/biogeochem/CNPhenologyBeTRMod.F90 b/components/elm/src/biogeochem/CNPhenologyBeTRMod.F90 index 4bc23896427c..ac3b58538e8f 100644 --- a/components/elm/src/biogeochem/CNPhenologyBeTRMod.F90 +++ b/components/elm/src/biogeochem/CNPhenologyBeTRMod.F90 @@ -693,7 +693,7 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp , & frootn_xfer_to_frootn(p) = 0.0_r8 leafp_xfer_to_leafp(p) = 0.0_r8 frootp_xfer_to_frootp(p) = 0.0_r8 - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then livestemc_xfer_to_livestemc(p) = 0.0_r8 deadstemc_xfer_to_deadstemc(p) = 0.0_r8 livecrootc_xfer_to_livecrootc(p) = 0.0_r8 @@ -714,7 +714,7 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp , & frootc_xfer(p) = 0.0_r8 frootn_xfer(p) = 0.0_r8 frootp_xfer(p) = 0.0_r8 - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then livestemc_xfer(p) = 0.0_r8 livestemn_xfer(p) = 0.0_r8 livestemp_xfer(p) = 0.0_r8 @@ -777,7 +777,7 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp , & ! set carbon fluxes for shifting storage pools to transfer pools leafc_storage_to_xfer(p) = fstor2tran * leafc_storage(p)/dt frootc_storage_to_xfer(p) = fstor2tran * frootc_storage(p)/dt - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then livestemc_storage_to_xfer(p) = fstor2tran * livestemc_storage(p)/dt deadstemc_storage_to_xfer(p) = fstor2tran * deadstemc_storage(p)/dt livecrootc_storage_to_xfer(p) = fstor2tran * livecrootc_storage(p)/dt @@ -788,7 +788,7 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp , & ! set nitrogen fluxes for shifting storage pools to transfer pools leafn_storage_to_xfer(p) = fstor2tran * leafn_storage(p)/dt frootn_storage_to_xfer(p) = fstor2tran * frootn_storage(p)/dt - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then livestemn_storage_to_xfer(p) = fstor2tran * livestemn_storage(p)/dt deadstemn_storage_to_xfer(p) = fstor2tran * deadstemn_storage(p)/dt livecrootn_storage_to_xfer(p) = fstor2tran * livecrootn_storage(p)/dt @@ -798,7 +798,7 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp , & ! set phosphorus fluxes for shifting storage pools to transfer pools leafp_storage_to_xfer(p) = fstor2tran * leafp_storage(p)/dt frootp_storage_to_xfer(p) = fstor2tran * frootp_storage(p)/dt - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then livestemp_storage_to_xfer(p) = fstor2tran * livestemp_storage(p)/dt deadstemp_storage_to_xfer(p) = fstor2tran * deadstemp_storage(p)/dt livecrootp_storage_to_xfer(p) = fstor2tran * livecrootp_storage(p)/dt @@ -1040,7 +1040,7 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & frootn_xfer_to_frootn(p) = 0._r8 leafp_xfer_to_leafp(p) = 0._r8 frootp_xfer_to_frootp(p) = 0._r8 - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then livestemc_xfer_to_livestemc(p) = 0._r8 deadstemc_xfer_to_deadstemc(p) = 0._r8 livecrootc_xfer_to_livecrootc(p) = 0._r8 @@ -1061,7 +1061,7 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & frootc_xfer(p) = 0._r8 frootn_xfer(p) = 0._r8 frootp_xfer(p) = 0._r8 - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then livestemc_xfer(p) = 0._r8 livestemn_xfer(p) = 0._r8 livestemp_xfer(p) = 0._r8 @@ -1148,7 +1148,7 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & ! set carbon fluxes for shifting storage pools to transfer pools leafc_storage_to_xfer(p) = fstor2tran * leafc_storage(p)/dt frootc_storage_to_xfer(p) = fstor2tran * frootc_storage(p)/dt - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then livestemc_storage_to_xfer(p) = fstor2tran * livestemc_storage(p)/dt deadstemc_storage_to_xfer(p) = fstor2tran * deadstemc_storage(p)/dt livecrootc_storage_to_xfer(p) = fstor2tran * livecrootc_storage(p)/dt @@ -1159,7 +1159,7 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & ! set nitrogen fluxes for shifting storage pools to transfer pools leafn_storage_to_xfer(p) = fstor2tran * leafn_storage(p)/dt frootn_storage_to_xfer(p) = fstor2tran * frootn_storage(p)/dt - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then livestemn_storage_to_xfer(p) = fstor2tran * livestemn_storage(p)/dt deadstemn_storage_to_xfer(p) = fstor2tran * deadstemn_storage(p)/dt livecrootn_storage_to_xfer(p) = fstor2tran * livecrootn_storage(p)/dt @@ -1169,7 +1169,7 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & ! set phosphorus fluxes for shifting storage pools to transfer pools leafp_storage_to_xfer(p) = fstor2tran * leafp_storage(p)/dt frootp_storage_to_xfer(p) = fstor2tran * frootp_storage(p)/dt - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then livestemp_storage_to_xfer(p) = fstor2tran * livestemp_storage(p)/dt deadstemp_storage_to_xfer(p) = fstor2tran * deadstemp_storage(p)/dt livecrootp_storage_to_xfer(p) = fstor2tran * livecrootp_storage(p)/dt @@ -1268,7 +1268,7 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & leafc_storage_to_xfer(p) = leafc_storage(p) * bgtr(p) frootc_storage_to_xfer(p) = frootc_storage(p) * bgtr(p) - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then livestemc_storage_to_xfer(p) = livestemc_storage(p) * bgtr(p) deadstemc_storage_to_xfer(p) = deadstemc_storage(p) * bgtr(p) livecrootc_storage_to_xfer(p) = livecrootc_storage(p) * bgtr(p) @@ -1279,7 +1279,7 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & ! set nitrogen fluxes for shifting storage pools to transfer pools 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 + if (woody(ivt(p)) >= 1.0_r8) then livestemn_storage_to_xfer(p) = livestemn_storage(p) * bgtr(p) deadstemn_storage_to_xfer(p) = deadstemn_storage(p) * bgtr(p) livecrootn_storage_to_xfer(p) = livecrootn_storage(p) * bgtr(p) @@ -1290,7 +1290,7 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & ! set phosphorus fluxes for shifting storage pools to transfer pools leafp_storage_to_xfer(p) = leafp_storage(p) * bgtr(p) frootp_storage_to_xfer(p) = frootp_storage(p) * bgtr(p) - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then livestemp_storage_to_xfer(p) = livestemp_storage(p) * bgtr(p) deadstemp_storage_to_xfer(p) = deadstemp_storage(p) * bgtr(p) livecrootp_storage_to_xfer(p) = livecrootp_storage(p) * bgtr(p) @@ -1868,7 +1868,8 @@ subroutine CropPhenologyInit(bounds) ! initialized, and after ecophyscon file is read in. ! ! !USES: - use pftvarcon , only: npcropmin, npcropmax, mnNHplantdate + use elm_varpar , only : mxpft + use pftvarcon , only: iscft, crop, mnNHplantdate use pftvarcon , only: mnSHplantdate, mxNHplantdate use pftvarcon , only: mxSHplantdate use elm_time_manager, only: get_calday @@ -1893,13 +1894,17 @@ subroutine CropPhenologyInit(bounds) ! Convert planting dates into julian day minplantjday(:,:) = huge(1) maxplantjday(:,:) = huge(1) - do n = npcropmin, npcropmax + do n = 0, mxpft + if (iscft(n)) then minplantjday(n,inNH) = int( get_calday( mnNHplantdate(n), 0 ) ) maxplantjday(n,inNH) = int( get_calday( mxNHplantdate(n), 0 ) ) + end if end do - do n = npcropmin, npcropmax + do n = 0, mxpft + if (iscft(n)) then minplantjday(n,inSH) = int( get_calday( mnSHplantdate(n), 0 ) ) maxplantjday(n,inSH) = int( get_calday( mxSHplantdate(n), 0 ) ) + end if end do ! Figure out what hemisphere each PFT is in @@ -2362,7 +2367,7 @@ subroutine CNOnsetGrowth (num_soilp, filter_soilp, & frootn_xfer_to_frootn(p) = t1 * frootn_xfer(p) leafp_xfer_to_leafp(p) = t1 * leafp_xfer(p) frootp_xfer_to_frootp(p) = t1 * frootp_xfer(p) - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then livestemc_xfer_to_livestemc(p) = t1 * livestemc_xfer(p) deadstemc_xfer_to_deadstemc(p) = t1 * deadstemc_xfer(p) livecrootc_xfer_to_livecrootc(p) = t1 * livecrootc_xfer(p) @@ -2391,7 +2396,7 @@ subroutine CNOnsetGrowth (num_soilp, filter_soilp, & frootn_xfer_to_frootn(p) = frootn_xfer(p) / dt leafp_xfer_to_leafp(p) = leafp_xfer(p) / dt frootp_xfer_to_frootp(p) = frootp_xfer(p) / dt - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then livestemc_xfer_to_livestemc(p) = livestemc_xfer(p) / dt deadstemc_xfer_to_deadstemc(p) = deadstemc_xfer(p) / dt livecrootc_xfer_to_livecrootc(p) = livecrootc_xfer(p) / dt @@ -2909,7 +2914,7 @@ subroutine CNLivewoodTurnover (num_soilp, filter_soilp, & p = filter_soilp(fp) ! only calculate these fluxes for woody types - if (woody(ivt(p)) > 0._r8) then + if (woody(ivt(p)) >= 1.0_r8) then if ( nu_com .eq. 'RD') then ! live stem to dead stem turnover diff --git a/components/elm/src/biogeochem/CarbonStateUpdate1Mod.F90 b/components/elm/src/biogeochem/CarbonStateUpdate1Mod.F90 index 057fd0e56b6e..1eb7f64d025a 100644 --- a/components/elm/src/biogeochem/CarbonStateUpdate1Mod.F90 +++ b/components/elm/src/biogeochem/CarbonStateUpdate1Mod.F90 @@ -11,7 +11,7 @@ module CarbonStateUpdate1Mod use elm_varcon , only : dzsoi_decomp use elm_varctl , only : nu_com, use_c13, use_c14 use elm_varctl , only : use_pflotran, pf_cmode, use_fates - use pftvarcon , only : npcropmin, nc3crop + use pftvarcon , only : iscft use CNDecompCascadeConType , only : decomp_cascade_type use CNStateType , only : cnstate_type use CNDecompCascadeConType , only : decomp_cascade_con @@ -274,7 +274,7 @@ subroutine CarbonStateUpdate1(bounds, & veg_cs%leafc_xfer(p) = veg_cs%leafc_xfer(p) - veg_cf%leafc_xfer_to_leafc(p)*dt veg_cs%frootc(p) = veg_cs%frootc(p) + veg_cf%frootc_xfer_to_frootc(p)*dt veg_cs%frootc_xfer(p) = veg_cs%frootc_xfer(p) - veg_cf%frootc_xfer_to_frootc(p)*dt - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then veg_cs%livestemc(p) = veg_cs%livestemc(p) + veg_cf%livestemc_xfer_to_livestemc(p)*dt veg_cs%livestemc_xfer(p) = veg_cs%livestemc_xfer(p) - veg_cf%livestemc_xfer_to_livestemc(p)*dt veg_cs%deadstemc(p) = veg_cs%deadstemc(p) + veg_cf%deadstemc_xfer_to_deadstemc(p)*dt @@ -284,7 +284,7 @@ subroutine CarbonStateUpdate1(bounds, & veg_cs%deadcrootc(p) = veg_cs%deadcrootc(p) + veg_cf%deadcrootc_xfer_to_deadcrootc(p)*dt veg_cs%deadcrootc_xfer(p) = veg_cs%deadcrootc_xfer(p) - veg_cf%deadcrootc_xfer_to_deadcrootc(p)*dt end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops ! lines here for consistency; the transfer terms are zero veg_cs%livestemc(p) = veg_cs%livestemc(p) + veg_cf%livestemc_xfer_to_livestemc(p)*dt veg_cs%livestemc_xfer(p) = veg_cs%livestemc_xfer(p) - veg_cf%livestemc_xfer_to_livestemc(p)*dt @@ -297,13 +297,13 @@ subroutine CarbonStateUpdate1(bounds, & veg_cs%frootc(p) = veg_cs%frootc(p) - veg_cf%frootc_to_litter(p)*dt ! livewood turnover fluxes - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then veg_cs%livestemc(p) = veg_cs%livestemc(p) - veg_cf%livestemc_to_deadstemc(p)*dt veg_cs%deadstemc(p) = veg_cs%deadstemc(p) + veg_cf%livestemc_to_deadstemc(p)*dt veg_cs%livecrootc(p) = veg_cs%livecrootc(p) - veg_cf%livecrootc_to_deadcrootc(p)*dt veg_cs%deadcrootc(p) = veg_cs%deadcrootc(p) + veg_cf%livecrootc_to_deadcrootc(p)*dt end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops veg_cs%livestemc(p) = veg_cs%livestemc(p) - veg_cf%livestemc_to_litter(p)*dt veg_cs%grainc(p) = veg_cs%grainc(p) - veg_cf%grainc_to_food(p)*dt @@ -315,11 +315,11 @@ subroutine CarbonStateUpdate1(bounds, & veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_to_xsmrpool(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%leaf_curmr(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%froot_curmr(p)*dt - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%livestem_curmr(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%livecroot_curmr(p)*dt end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%livestem_curmr(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%grain_curmr(p)*dt end if @@ -333,11 +333,11 @@ subroutine CarbonStateUpdate1(bounds, & if (nu_com .ne. 'RD') then veg_cs%xsmrpool(p) = veg_cs%xsmrpool(p) - veg_cf%xsmrpool_turnover(p)*dt end if - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then veg_cs%xsmrpool(p) = veg_cs%xsmrpool(p) - veg_cf%livestem_xsmr(p)*dt veg_cs%xsmrpool(p) = veg_cs%xsmrpool(p) - veg_cf%livecroot_xsmr(p)*dt end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops veg_cs%xsmrpool(p) = veg_cs%xsmrpool(p) - veg_cf%livestem_xsmr(p)*dt veg_cs%xsmrpool(p) = veg_cs%xsmrpool(p) - veg_cf%grain_xsmr(p)*dt if (harvdate(p) < 999) then ! beginning at harvest, send to atm @@ -355,7 +355,7 @@ subroutine CarbonStateUpdate1(bounds, & veg_cs%frootc(p) = veg_cs%frootc(p) + veg_cf%cpool_to_frootc(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_to_frootc_storage(p)*dt veg_cs%frootc_storage(p) = veg_cs%frootc_storage(p) + veg_cf%cpool_to_frootc_storage(p)*dt - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_to_livestemc(p)*dt veg_cs%livestemc(p) = veg_cs%livestemc(p) + veg_cf%cpool_to_livestemc(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_to_livestemc_storage(p)*dt @@ -373,7 +373,7 @@ subroutine CarbonStateUpdate1(bounds, & veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_to_deadcrootc_storage(p)*dt veg_cs%deadcrootc_storage(p) = veg_cs%deadcrootc_storage(p) + veg_cf%cpool_to_deadcrootc_storage(p)*dt end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if ( iscft(ivt(p))) then ! skip 2 generic crops veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_to_livestemc(p)*dt veg_cs%livestemc(p) = veg_cs%livestemc(p) + veg_cf%cpool_to_livestemc(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_to_livestemc_storage(p)*dt @@ -387,13 +387,13 @@ subroutine CarbonStateUpdate1(bounds, & ! growth respiration fluxes for current growth veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_leaf_gr(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_froot_gr(p)*dt - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_livestem_gr(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_deadstem_gr(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_livecroot_gr(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_deadcroot_gr(p)*dt end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_livestem_gr(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_grain_gr(p)*dt end if @@ -401,13 +401,13 @@ subroutine CarbonStateUpdate1(bounds, & ! growth respiration for transfer growth veg_cs%gresp_xfer(p) = veg_cs%gresp_xfer(p) - veg_cf%transfer_leaf_gr(p)*dt veg_cs%gresp_xfer(p) = veg_cs%gresp_xfer(p) - veg_cf%transfer_froot_gr(p)*dt - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then veg_cs%gresp_xfer(p) = veg_cs%gresp_xfer(p) - veg_cf%transfer_livestem_gr(p)*dt veg_cs%gresp_xfer(p) = veg_cs%gresp_xfer(p) - veg_cf%transfer_deadstem_gr(p)*dt veg_cs%gresp_xfer(p) = veg_cs%gresp_xfer(p) - veg_cf%transfer_livecroot_gr(p)*dt veg_cs%gresp_xfer(p) = veg_cs%gresp_xfer(p) - veg_cf%transfer_deadcroot_gr(p)*dt end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops veg_cs%gresp_xfer(p) = veg_cs%gresp_xfer(p) - veg_cf%transfer_livestem_gr(p)*dt veg_cs%gresp_xfer(p) = veg_cs%gresp_xfer(p) - veg_cf%transfer_grain_gr(p)*dt end if @@ -415,13 +415,13 @@ subroutine CarbonStateUpdate1(bounds, & ! growth respiration at time of storage veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_leaf_storage_gr(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_froot_storage_gr(p)*dt - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_livestem_storage_gr(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_deadstem_storage_gr(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_livecroot_storage_gr(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_deadcroot_storage_gr(p)*dt end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if ( iscft(ivt(p))) then ! skip 2 generic crops veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_livestem_storage_gr(p)*dt veg_cs%cpool(p) = veg_cs%cpool(p) - veg_cf%cpool_grain_storage_gr(p)*dt end if @@ -435,7 +435,7 @@ subroutine CarbonStateUpdate1(bounds, & veg_cs%leafc_xfer(p) = veg_cs%leafc_xfer(p) + veg_cf%leafc_storage_to_xfer(p)*dt veg_cs%frootc_storage(p) = veg_cs%frootc_storage(p) - veg_cf%frootc_storage_to_xfer(p)*dt veg_cs%frootc_xfer(p) = veg_cs%frootc_xfer(p) + veg_cf%frootc_storage_to_xfer(p)*dt - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then veg_cs%livestemc_storage(p) = veg_cs%livestemc_storage(p) - veg_cf%livestemc_storage_to_xfer(p)*dt veg_cs%livestemc_xfer(p) = veg_cs%livestemc_xfer(p) + veg_cf%livestemc_storage_to_xfer(p)*dt veg_cs%deadstemc_storage(p) = veg_cs%deadstemc_storage(p) - veg_cf%deadstemc_storage_to_xfer(p)*dt @@ -447,7 +447,7 @@ subroutine CarbonStateUpdate1(bounds, & veg_cs%gresp_storage(p) = veg_cs%gresp_storage(p) - veg_cf%gresp_storage_to_xfer(p)*dt veg_cs%gresp_xfer(p) = veg_cs%gresp_xfer(p) + veg_cf%gresp_storage_to_xfer(p)*dt end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if ( iscft(ivt(p))) then ! skip 2 generic crops ! lines here for consistency; the transfer terms are zero veg_cs%livestemc_storage(p) = veg_cs%livestemc_storage(p) - veg_cf%livestemc_storage_to_xfer(p)*dt veg_cs%livestemc_xfer(p) = veg_cs%livestemc_xfer(p) + veg_cf%livestemc_storage_to_xfer(p)*dt diff --git a/components/elm/src/biogeochem/CarbonStateUpdate2Mod.F90 b/components/elm/src/biogeochem/CarbonStateUpdate2Mod.F90 index 48174fb8ddfc..4676a1e351d1 100644 --- a/components/elm/src/biogeochem/CarbonStateUpdate2Mod.F90 +++ b/components/elm/src/biogeochem/CarbonStateUpdate2Mod.F90 @@ -9,7 +9,7 @@ module CarbonStateUpdate2Mod use shr_log_mod , only : errMsg => shr_log_errMsg use abortutils , only : endrun use elm_varpar , only : nlevdecomp, i_met_lit, i_cel_lit, i_lig_lit, i_cwd - use pftvarcon , only : npcropmin + use pftvarcon , only : iscft use elm_varctl , only : use_pflotran, pf_cmode use VegetationType , only : veg_pp use tracer_varcon , only : is_active_betr_bgc @@ -186,7 +186,7 @@ subroutine CarbonStateUpdate2h(num_soilc, filter_soilc, num_soilp, filter_soilp, veg_cs%deadcrootc(p) = veg_cs%deadcrootc(p) - veg_cf%hrv_deadcrootc_to_litter(p) * dt ! crops - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops veg_cs%livestemc(p) = veg_cs%livestemc(p) - veg_cf%hrv_livestemc_to_prod1c(p) *dt veg_cs%leafc(p) = veg_cs%leafc(p) - veg_cf%hrv_leafc_to_prod1c(p) *dt veg_cs%grainc(p) = veg_cs%grainc(p) - veg_cf%hrv_grainc_to_prod1c(p) *dt diff --git a/components/elm/src/biogeochem/ComputeSeedMod.F90 b/components/elm/src/biogeochem/ComputeSeedMod.F90 index 61b916d64f35..9b7ebf8838dc 100644 --- a/components/elm/src/biogeochem/ComputeSeedMod.F90 +++ b/components/elm/src/biogeochem/ComputeSeedMod.F90 @@ -124,7 +124,7 @@ subroutine ComputeSeedAmounts(p, & if (pft_type /= noveg) then my_leaf_seed = leafc_seed_param * & SpeciesTypeMultiplier(species, pft_type, COMPONENT_LEAF) - if (veg_vp%woody(pft_type) == 1._r8) then + if (veg_vp%woody(pft_type) >= 1.0_r8) then my_deadstem_seed = deadstemc_seed_param * & SpeciesTypeMultiplier(species, pft_type, COMPONENT_DEADWOOD) end if diff --git a/components/elm/src/biogeochem/CropType.F90 b/components/elm/src/biogeochem/CropType.F90 index bc3d8c44ff41..8394d21ca348 100644 --- a/components/elm/src/biogeochem/CropType.F90 +++ b/components/elm/src/biogeochem/CropType.F90 @@ -417,7 +417,7 @@ subroutine Restart(this, bounds, ncid, flag) use restUtilMod use ncdio_pio use VegetationType , only : veg_pp - use pftvarcon , only : npcropmin, npcropmax + use pftvarcon , only : iscft ! ! !ARGUMENTS: class(crop_type), intent(inout) :: this @@ -454,7 +454,7 @@ subroutine Restart(this, bounds, ncid, flag) interpinic_flag='copy', readvar=readvar, data=restyear) if (readvar) then do p = bounds%begp, bounds%endp - if (veg_pp%itype(p) >= npcropmin .and. veg_pp%itype(p) <= npcropmax .and. & + if (iscft(veg_pp%itype(p)) .and. & veg_pp%active(p)) then this%nyrs_crop_active_patch(p) = restyear end if diff --git a/components/elm/src/biogeochem/DUSTMod.F90 b/components/elm/src/biogeochem/DUSTMod.F90 index ba24f2596697..f53e970423be 100644 --- a/components/elm/src/biogeochem/DUSTMod.F90 +++ b/components/elm/src/biogeochem/DUSTMod.F90 @@ -69,6 +69,7 @@ module DUSTMod real(r8), pointer, private :: vlc_trb_2_patch (:) ! turbulent deposition velocity 2(m/s) real(r8), pointer, private :: vlc_trb_3_patch (:) ! turbulent deposition velocity 3(m/s) real(r8), pointer, private :: vlc_trb_4_patch (:) ! turbulent deposition velocity 4(m/s) + real(r8), pointer, private :: lnd_frc_mbl_patch (:) ! land fraction for dust mobilization (-) real(r8), pointer, private :: mbl_bsn_fct_col (:) ! basin factor contains @@ -121,7 +122,8 @@ subroutine InitAllocate(this, bounds) 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 + allocate(this%lnd_frc_mbl_patch (begp:endp)) ; this%lnd_frc_mbl_patch (:) = spval + allocate(this%mbl_bsn_fct_col (begc:endc)) ; this%mbl_bsn_fct_col (:) = nan end subroutine InitAllocate @@ -167,6 +169,11 @@ subroutine InitHistory(this, bounds) avgflag='A', long_name='turbulent deposition velocity 4', & ptr_patch=this%vlc_trb_4_patch, default='inactive') + this%lnd_frc_mbl_patch(begp:endp) = spval + call hist_addfld1d (fname='LND_FRC_DUST_MBL', units='-', & + avgflag='A', long_name='bare soil fraction for land fraction for dust mobilization', & + ptr_patch=this%lnd_frc_mbl_patch, default='inactive') + end subroutine InitHistory !----------------------------------------------------------------------- @@ -239,7 +246,6 @@ subroutine DustEmission (bounds, & real(r8) :: Cd ! [dimless] The dust emission coefficient, which depends on ! the soil's standardized threshold friction speed -YF 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) @@ -287,6 +293,7 @@ subroutine DustEmission (bounds, & u10 => frictionvel_vars%u10_patch , & ! Input: [real(r8) (:) ] 10-m wind (m/s) (created for dust model) mbl_bsn_fct => dust_vars%mbl_bsn_fct_col , & ! Input: [real(r8) (:) ] basin factor + lnd_frc_mbl => dust_vars%lnd_frc_mbl_patch , & ! Output: [real(r8) (:) ] land fraction for dust mobilization flx_mss_vrt_dst => dust_vars%flx_mss_vrt_dst_patch , & ! Output: [real(r8) (:,:) ] surface dust emission (kg/m**2/s) flx_mss_vrt_dst_tot => dust_vars%flx_mss_vrt_dst_tot_patch & ! Output: [real(r8) (:) ] total dust flux back to atmosphere (pft) ) diff --git a/components/elm/src/biogeochem/DryDepVelocity.F90 b/components/elm/src/biogeochem/DryDepVelocity.F90 index 009de700b455..b6ef82a632ef 100644 --- a/components/elm/src/biogeochem/DryDepVelocity.F90 +++ b/components/elm/src/biogeochem/DryDepVelocity.F90 @@ -145,14 +145,9 @@ subroutine depvel_compute( bounds, & use seq_drydep_mod , only : rcls, h2_a, h2_b, h2_c, ri, rac, rclo, rlu, rgss, rgso use landunit_varcon, only : istsoil, istice, istice_mec, istdlak, istwet use elm_varctl , only : iulog - use pftvarcon , only : noveg, ndllf_evr_tmp_tree, ndllf_evr_brl_tree - use pftvarcon , only : ndllf_dcd_brl_tree, nbrdlf_evr_trp_tree - use pftvarcon , only : nbrdlf_evr_tmp_tree, nbrdlf_dcd_trp_tree - use pftvarcon , only : nbrdlf_dcd_tmp_tree, nbrdlf_dcd_brl_tree - use pftvarcon , only : nbrdlf_evr_shrub, nbrdlf_dcd_tmp_shrub - use pftvarcon , only : nbrdlf_dcd_brl_shrub,nc3_arctic_grass - use pftvarcon , only : nc3_nonarctic_grass, nc4_grass, nc3crop - use pftvarcon , only : nc3irrig, npcropmin, npcropmax + use pftvarcon , only : noveg, nonvascular + use pftvarcon , only : woody, graminoid, iscft, crop + use pftvarcon , only : needleleaf ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds @@ -275,24 +270,31 @@ subroutine depvel_compute( bounds, & !map ELM veg type into Wesely veg type wesveg = wveg_unset - if (elmveg == noveg ) wesveg = 8 - if (elmveg == ndllf_evr_tmp_tree ) wesveg = 5 - if (elmveg == ndllf_evr_brl_tree ) wesveg = 5 - if (elmveg == ndllf_dcd_brl_tree ) wesveg = 5 - if (elmveg == nbrdlf_evr_trp_tree ) wesveg = 4 - if (elmveg == nbrdlf_evr_tmp_tree ) wesveg = 4 - if (elmveg == nbrdlf_dcd_trp_tree ) wesveg = 4 - if (elmveg == nbrdlf_dcd_tmp_tree ) wesveg = 4 - if (elmveg == nbrdlf_dcd_brl_tree ) wesveg = 4 - if (elmveg == nbrdlf_evr_shrub ) wesveg = 11 - if (elmveg == nbrdlf_dcd_tmp_shrub ) wesveg = 11 - if (elmveg == nbrdlf_dcd_brl_shrub ) wesveg = 11 - if (elmveg == nc3_arctic_grass ) wesveg = 3 - if (elmveg == nc3_nonarctic_grass ) wesveg = 3 - if (elmveg == nc4_grass ) wesveg = 3 - if (elmveg == nc3crop ) wesveg = 2 - if (elmveg == nc3irrig ) wesveg = 2 - if (elmveg >= npcropmin .and. elmveg <= npcropmax ) wesveg = 2 + if (elmveg == noveg ) wesveg = 8 + if (nonvascular(elmveg) == 2.0_r8 ) wesveg = 8 ! assuming lichen like bare-ground + !if (elmveg == ndllf_evr_tmp_tree ) wesveg = 5 + !if (elmveg == ndllf_evr_brl_tree ) wesveg = 5 + !if (elmveg == ndllf_dcd_brl_tree ) wesveg = 5 + if (woody(elmveg) == 1.0_r8 .and. needleleaf(elmveg) == 1) wesveg = 5 + !if (elmveg == nbrdlf_evr_trp_tree ) wesveg = 4 + !if (elmveg == nbrdlf_evr_tmp_tree ) wesveg = 4 + !if (elmveg == nbrdlf_dcd_trp_tree ) wesveg = 4 + !if (elmveg == nbrdlf_dcd_tmp_tree ) wesveg = 4 + !if (elmveg == nbrdlf_dcd_brl_tree ) wesveg = 4 + if (woody(elmveg) == 1.0_r8 .and. needleleaf(elmveg) == 0) wesveg = 4 + !if (elmveg == nbrdlf_evr_shrub ) wesveg = 11 + !if (elmveg == nbrdlf_dcd_tmp_shrub ) wesveg = 11 + !if (elmveg == nbrdlf_dcd_brl_shrub ) wesveg = 11 + if (woody(elmveg) == 2.0_r8 ) wesveg = 11 + !if (elmveg == nc3_arctic_grass ) wesveg = 3 + !if (elmveg == nc3_nonarctic_grass ) wesveg = 3 + !if (elmveg == nc4_grass ) wesveg = 3 + if (graminoid(elmveg) == 1.0_r8 ) wesveg = 3 + if (nonvascular(elmveg) == 1.0_r8 ) wesveg = 3 ! assuming moss like grass + !if (elmveg == nc3crop ) wesveg = 2 + !if (elmveg == nc3irrig ) wesveg = 2 + !if (elmveg >= npcropmin .and. elmveg <= npcropmax ) wesveg = 2 + if (crop(elmveg) == 1.0_r8 .or. iscft(elmveg)) wesveg = 2 #ifndef _OPENACC if (wesveg == wveg_unset )then write(iulog,*) 'elmveg = ', elmveg, 'lun_pp%itype = ', lun_pp%itype(l) diff --git a/components/elm/src/biogeochem/FireMod.F90 b/components/elm/src/biogeochem/FireMod.F90 index 0dec0c08a50b..b84aa2c3ab6e 100644 --- a/components/elm/src/biogeochem/FireMod.F90 +++ b/components/elm/src/biogeochem/FireMod.F90 @@ -126,8 +126,8 @@ subroutine FireArea (bounds, & use elm_varcon , only: secspday, spval use elm_varctl , only: use_nofire, spinup_state, spinup_mortality_factor use dynSubgridControlMod , only: run_has_transient_landcover - use pftvarcon , only: nc4_grass, nc3crop, ndllf_evr_tmp_tree - use pftvarcon , only: nbrdlf_evr_trp_tree, nbrdlf_dcd_trp_tree, nbrdlf_evr_shrub + use pftvarcon , only: noveg, woody, graminoid, iscft, crop + use pftvarcon , only: climatezone, needleleaf, evergreen ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds @@ -305,11 +305,12 @@ subroutine FireArea (bounds, & if (pi <= col_pp%npfts(c)) then p = col_pp%pfti(c) + pi - 1 ! For crop veg types - if( veg_pp%itype(p) > nc4_grass )then + if( crop(veg_pp%itype(p)) == 1 .or. iscft(veg_pp%itype(p)))then cropf_col(c) = cropf_col(c) + veg_pp%wtcol(p) end if ! For natural vegetation (non-crop and non-bare-soil) - if( veg_pp%itype(p) >= ndllf_evr_tmp_tree .and. veg_pp%itype(p) <= nc4_grass )then + if( veg_pp%itype(p) /= noveg .and. & + (crop(veg_pp%itype(p)) == 0 .and. .not. iscft(veg_pp%itype(p))) )then lfwt(c) = lfwt(c) + veg_pp%wtcol(p) end if end if @@ -331,7 +332,8 @@ subroutine FireArea (bounds, & ! column-level litter carbon ! is available, so we use leaf carbon to estimate the ! litter carbon for crop PFTs - if( veg_pp%itype(p) > nc4_grass .and. veg_pp%wtcol(p) > 0._r8 .and. leafc_col(c) > 0._r8 )then + if( (crop(veg_pp%itype(p)) == 1 .or. iscft(veg_pp%itype(p))) .and. & + veg_pp%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))*veg_pp%wtcol(p)/cropf_col(c) + & totlitc(c)*leafc(p)/leafc_col(c)*veg_pp%wtcol(p)/cropf_col(c) @@ -368,21 +370,35 @@ subroutine FireArea (bounds, & p = col_pp%pfti(c) + pi - 1 ! For non-crop -- natural vegetation and bare-soil - if( veg_pp%itype(p) < nc3crop .and. cropf_col(c) < 1.0_r8 )then + if( (crop(veg_pp%itype(p)) == 0 .and. .not. iscft(veg_pp%itype(p))) .and. & + cropf_col(c) < 1.0_r8 ) then if( btran2(p) .ne. spval) then if (btran2(p) <= 1._r8 ) then btran_col(c) = btran_col(c)+btran2(p)*veg_pp%wtcol(p) wtlf(c) = wtlf(c)+veg_pp%wtcol(p) end if end if - if( veg_pp%itype(p) == nbrdlf_evr_trp_tree .and. veg_pp%wtcol(p) > 0._r8 )then + ! broadleaf evergreen tropical tree + if( (needleleaf(veg_pp%itype(p)) == 0 .and. & + evergreen(veg_pp%itype(p)) == 1 .and. & + climatezone(veg_pp%itype(p)) == 1 .and. & + woody(veg_pp%itype(p)) == 1.0_r8) .and. & + veg_pp%wtcol(p) > 0._r8 )then trotr1_col(c)=trotr1_col(c)+veg_pp%wtcol(p)*col_pp%wttopounit(c) end if - if( veg_pp%itype(p) == nbrdlf_dcd_trp_tree .and. veg_pp%wtcol(p) > 0._r8 )then + ! broadleaf deciduous tropical tree + if( (needleleaf(veg_pp%itype(p)) == 0 .and. & + evergreen(veg_pp%itype(p)) == 0 .and. & + climatezone(veg_pp%itype(p)) == 1 .and. & + woody(veg_pp%itype(p)) == 1.0_r8) .and. & + veg_pp%wtcol(p) > 0._r8 ) then trotr2_col(c)=trotr2_col(c)+veg_pp%wtcol(p)*col_pp%wttopounit(c) end if if (transient_landcover) then !true when landuse data is used - if( veg_pp%itype(p) == nbrdlf_evr_trp_tree .or. veg_pp%itype(p) == nbrdlf_dcd_trp_tree )then + ! broadleaf tropical tree + if(needleleaf(veg_pp%itype(p)) == 0 .and. & + climatezone(veg_pp%itype(p)) == 1 .and. & + woody(veg_pp%itype(p)) == 1.0_r8)then if(lfpftd(p) > 0._r8)then dtrotr_col(c)=dtrotr_col(c)+lfpftd(p)*col_pp%wttopounit(c) end if @@ -405,7 +421,8 @@ subroutine FireArea (bounds, & ! For NOT bare-soil if( veg_pp%itype(p) /= noveg )then ! For shrub and grass (crop already excluded above) - if( veg_pp%itype(p) >= nbrdlf_evr_shrub )then !for shurb and grass + if( woody(veg_pp%itype(p)) == 2.0_r8 .or. & + graminoid(veg_pp%itype(p)) == 1 )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))*veg_pp%wtcol(p) & @@ -416,7 +433,7 @@ subroutine FireArea (bounds, & lpop_col(c) = lpop_col(c) + (0.2_r8 + 0.8_r8* & exp(-1._r8*SHR_CONST_PI* & (hdmlf/450._r8)**0.5_r8))*veg_pp%wtcol(p)/lfwt(c) - else ! for trees + else if (woody(veg_pp%itype(p)) == 1.0_r8) then ! for trees if( gdp_lf(c) > 20._r8 )then lgdp_col(c) =lgdp_col(c)+0.39_r8*veg_pp%wtcol(p)/(1.0_r8 - cropf_col(c)) else @@ -491,7 +508,8 @@ subroutine FireArea (bounds, & if (pi <= col_pp%npfts(c)) then p = col_pp%pfti(c) + pi - 1 ! For crop - if( forc_t(t) >= SHR_CONST_TKFRZ .and. veg_pp%itype(p) > nc4_grass .and. & + if( forc_t(t) >= SHR_CONST_TKFRZ .and. & + (crop(veg_pp%itype(p)) == 1 .or. iscft(veg_pp%itype(p))) .and. & kmo == abm_lf(c) .and. forc_rain(t)+forc_snow(t) == 0._r8 .and. & burndate(p) >= 999 .and. veg_pp%wtcol(p) > 0._r8 )then ! catch crop burn time @@ -661,7 +679,8 @@ subroutine FireFluxes (num_soilc, filter_soilc, num_soilp, filter_soilp, & ! !USES: !$acc routine seq use pftvarcon , only: cc_leaf,cc_lstem,cc_dstem,cc_other,fm_leaf,fm_lstem,fm_other,fm_root,fm_lroot,fm_droot - use pftvarcon , only: nc3crop,lf_flab,lf_fcel,lf_flig,fr_flab,fr_fcel,fr_flig + use pftvarcon , only: lf_flab,lf_fcel,lf_flig,fr_flab,fr_fcel,fr_flig + use pftvarcon , only: iscft, crop use elm_varpar , only: max_patch_per_col use elm_varctl , only: spinup_state, spinup_mortality_factor use dynSubgridControlMod , only: get_flanduse_timeseries @@ -706,8 +725,6 @@ subroutine FireFluxes (num_soilc, filter_soilc, num_soilp, filter_soilp, & 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 - woody => veg_vp%woody , & ! Input: [real(r8) (:) ] woody lifeform (1=woody, 0=not woody) - cropf_col => cnstate_vars%cropf_col , & ! Input: [real(r8) (:) ] cropland fraction in veg column croot_prof => cnstate_vars%croot_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of coarse roots stem_prof => cnstate_vars%stem_prof_patch , & ! Input: [real(r8) (:,:) ] (1/m) profile of stems @@ -965,7 +982,8 @@ subroutine FireFluxes (num_soilc, filter_soilc, num_soilp, filter_soilp, & c = veg_pp%column(p) itype = veg_pp%itype(p) - if( itype < nc3crop .and. cropf_col(c) < 1.0_r8)then + if( (crop(veg_pp%itype(p)) == 0 .and. .not. iscft(veg_pp%itype(p))) .and. & + cropf_col(c) < 1.0_r8)then ! For non-crop (bare-soil and natural vegetation) if (transient_landcover) then !true when landuse data is used f = (fbac(c)-baf_crop(c))/(1.0_r8-cropf_col(c)) diff --git a/components/elm/src/biogeochem/GapMortalityMod.F90 b/components/elm/src/biogeochem/GapMortalityMod.F90 index 495c46ed0dfc..3a58551ae076 100644 --- a/components/elm/src/biogeochem/GapMortalityMod.F90 +++ b/components/elm/src/biogeochem/GapMortalityMod.F90 @@ -87,7 +87,7 @@ subroutine GapMortality (num_soilc, filter_soilc, num_soilp, filter_soilp, & ! !USES: !$acc routine seq use elm_varcon , only: secspday - use pftvarcon , only: npcropmin + use pftvarcon , only: iscft use elm_varctl , only: spinup_state, spinup_mortality_factor ! ! !ARGUMENTS: @@ -110,7 +110,6 @@ subroutine GapMortality (num_soilc, filter_soilc, num_soilp, filter_soilp, & associate( & ivt => veg_pp%itype , & ! Input: [integer (:) ] pft vegetation type - woody => veg_vp%woody , & ! Input: [real(r8) (:) ] binary flag for woody lifeform croplive => crop_vars%croplive_patch & ! Input: [logical (:) ] flag, true if planted, not harvested ) @@ -143,7 +142,7 @@ subroutine GapMortality (num_soilc, filter_soilc, num_soilp, filter_soilp, & ! displayed pools veg_cf%m_leafc_to_litter(p) = 0._r8 veg_cf%m_livestemc_to_litter(p) = 0._r8 - if(ivt(p) < npcropmin .or. (ivt(p) >= npcropmin .and. croplive(p))) then + if((.not. iscft(ivt(p))) .or. (iscft(ivt(p)) .and. croplive(p))) then veg_cf%m_leafc_to_litter(p) = veg_cs%leafc(p) * m veg_cf%m_livestemc_to_litter(p) = veg_cs%livestemc(p) * m end if @@ -182,7 +181,7 @@ subroutine GapMortality (num_soilc, filter_soilc, num_soilp, filter_soilp, & ! displayed pools veg_nf%m_leafn_to_litter(p) = 0._r8 veg_nf%m_livestemn_to_litter(p) = 0._r8 - if(ivt(p) < npcropmin .or. (ivt(p) >= npcropmin .and. croplive(p))) then + if((.not. iscft(ivt(p))) .or. (iscft(ivt(p)) .and. croplive(p))) then veg_nf%m_leafn_to_litter(p) = veg_ns%leafn(p) * m veg_nf%m_livestemn_to_litter(p) = veg_ns%livestemn(p) * m end if @@ -191,7 +190,7 @@ subroutine GapMortality (num_soilc, filter_soilc, num_soilp, filter_soilp, & veg_nf%m_livecrootn_to_litter(p) = veg_ns%livecrootn(p) * m veg_nf%m_deadcrootn_to_litter(p) = veg_ns%deadcrootn(p) * m veg_nf%m_retransn_to_litter(p) = 0._r8 - if (ivt(p) < npcropmin) then + if (.not. iscft(ivt(p))) then veg_nf%m_retransn_to_litter(p) = veg_ns%retransn(p) * m end if veg_nf%m_npool_to_litter(p) = veg_ns%npool(p) * m @@ -226,7 +225,7 @@ subroutine GapMortality (num_soilc, filter_soilc, num_soilp, filter_soilp, & ! displayed pools veg_pf%m_leafp_to_litter(p) = 0._r8 veg_pf%m_livestemp_to_litter(p) = 0._r8 - if(ivt(p) < npcropmin .or. (ivt(p) >= npcropmin .and. croplive(p))) then + if((.not. iscft(ivt(p))) .or. (iscft(ivt(p)) .and. croplive(p))) then veg_pf%m_leafp_to_litter(p) = veg_ps%leafp(p) * m veg_pf%m_livestemp_to_litter(p) = veg_ps%livestemp(p) * m endif @@ -236,7 +235,7 @@ subroutine GapMortality (num_soilc, filter_soilc, num_soilp, filter_soilp, & veg_pf%m_deadcrootp_to_litter(p) = veg_ps%deadcrootp(p) * m veg_pf%m_retransp_to_litter(p) = 0._r8 - if (ivt(p) < npcropmin) then + if (.not. iscft(ivt(p))) then veg_pf%m_retransp_to_litter(p) = veg_ps%retransp(p) * m end if veg_pf%m_ppool_to_litter(p) = veg_ps%ppool(p) * m @@ -564,7 +563,7 @@ subroutine mortality_rate_soilorder(& ! USES !$acc routine seq - use pftvarcon , only: nbrdlf_evr_trp_tree, nbrdlf_dcd_trp_tree + use pftvarcon , only: woody, needleleaf, climatezone use soilorder_varcon, only: r_mort_soilorder ! @@ -586,7 +585,10 @@ subroutine mortality_rate_soilorder(& do fp = 1,num_soilp p = filter_soilp(fp) c = veg_pp%column(p) - if( veg_pp%itype(p) == nbrdlf_evr_trp_tree .or. veg_pp%itype(p) == nbrdlf_dcd_trp_tree )then + ! broadleaf tropical trees + if( woody(veg_pp%itype(p)) == 1.0_r8 .and. & + needleleaf(veg_pp%itype(p)) == 0 .and. & + climatezone(veg_pp%itype(p)) == 1 )then r_mort_cal(p) = r_mort_soilorder( isoilorder(c) ) else r_mort_cal(p) = 0.02_r8 ! Default mortality rate diff --git a/components/elm/src/biogeochem/GrowthRespMod.F90 b/components/elm/src/biogeochem/GrowthRespMod.F90 index f499dedb2e0f..cb7ad522265f 100644 --- a/components/elm/src/biogeochem/GrowthRespMod.F90 +++ b/components/elm/src/biogeochem/GrowthRespMod.F90 @@ -7,7 +7,7 @@ module GrowthRespMod ! ! !USES: use shr_kind_mod , only : r8 => shr_kind_r8 - use pftvarcon , only : grperc, grpnow, npcropmin + use pftvarcon , only : grperc, grpnow, iscft use VegetationPropertiesType , only : veg_vp use VegetationType , only : veg_pp use VegetationDataType , only : veg_cf @@ -102,7 +102,7 @@ subroutine GrowthResp(num_soilp, filter_soilp) do fp = 1,num_soilp p = filter_soilp(fp) - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops cpool_livestem_gr(p) = cpool_to_livestemc(p) * grperc(ivt(p)) @@ -133,7 +133,7 @@ subroutine GrowthResp(num_soilp, filter_soilp) transfer_froot_gr(p) = frootc_xfer_to_frootc(p) * grperc(ivt(p)) * & (1._r8 - grpnow(ivt(p))) - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then cpool_livestem_gr(p) = cpool_to_livestemc(p) * grperc(ivt(p)) cpool_livestem_storage_gr(p) = cpool_to_livestemc_storage(p) * & grperc(ivt(p)) * grpnow(ivt(p)) diff --git a/components/elm/src/biogeochem/MaintenanceRespMod.F90 b/components/elm/src/biogeochem/MaintenanceRespMod.F90 index ef83ca92ff60..54005275b296 100644 --- a/components/elm/src/biogeochem/MaintenanceRespMod.F90 +++ b/components/elm/src/biogeochem/MaintenanceRespMod.F90 @@ -12,7 +12,7 @@ module MaintenanceRespMod use decompMod , only : bounds_type use abortutils , only : endrun use shr_log_mod , only : errMsg => shr_log_errMsg - use pftvarcon , only : npcropmin + use pftvarcon , only : iscft use SharedParamsMod , only : ParamsShareInst use VegetationPropertiesType , only : veg_vp use SoilStateType , only : soilstate_type @@ -182,10 +182,10 @@ subroutine MaintenanceResp(bounds, & end if - if (woody(ivt(p)) == 1) then + if (woody(ivt(p)) >= 1.0_r8) then livestem_mr(p) = livestemn(p)*br_mr*tc livecroot_mr(p) = livecrootn(p)*br_mr*tc - else if (ivt(p) >= npcropmin .and. livestemn(p) .gt. 0._r8) then + else if (iscft(ivt(p)) .and. livestemn(p) .gt. 0._r8) then livestem_mr(p) = livestemn(p)*br_mr*tc grain_mr(p) = grainn(p)*br_mr*tc end if diff --git a/components/elm/src/biogeochem/NitrogenStateUpdate1Mod.F90 b/components/elm/src/biogeochem/NitrogenStateUpdate1Mod.F90 index 1eefadd7bead..c1b2bfc5d65a 100644 --- a/components/elm/src/biogeochem/NitrogenStateUpdate1Mod.F90 +++ b/components/elm/src/biogeochem/NitrogenStateUpdate1Mod.F90 @@ -9,7 +9,7 @@ module NitrogenStateUpdate1Mod use elm_varpar , only : crop_prog, i_met_lit, i_cel_lit, i_lig_lit, i_cwd use elm_varctl , only : iulog use elm_varcon , only : nitrif_n2o_loss_frac - use pftvarcon , only : npcropmin, nc3crop + use pftvarcon , only : iscft use VegetationPropertiesType , only : veg_vp use CNDecompCascadeConType , only : decomp_cascade_con use CNStateType , only : cnstate_type @@ -286,7 +286,7 @@ subroutine NitrogenStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp veg_ns%frootn(p) = veg_ns%frootn(p) + veg_nf%frootn_xfer_to_frootn(p)*dt veg_ns%frootn_xfer(p) = veg_ns%frootn_xfer(p) - veg_nf%frootn_xfer_to_frootn(p)*dt - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then veg_ns%livestemn(p) = veg_ns%livestemn(p) + veg_nf%livestemn_xfer_to_livestemn(p)*dt veg_ns%livestemn_xfer(p) = veg_ns%livestemn_xfer(p) - veg_nf%livestemn_xfer_to_livestemn(p)*dt veg_ns%deadstemn(p) = veg_ns%deadstemn(p) + veg_nf%deadstemn_xfer_to_deadstemn(p)*dt @@ -297,7 +297,7 @@ subroutine NitrogenStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp veg_ns%deadcrootn_xfer(p) = veg_ns%deadcrootn_xfer(p) - veg_nf%deadcrootn_xfer_to_deadcrootn(p)*dt end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops ! lines here for consistency; the transfer terms are zero veg_ns%livestemn(p) = veg_ns%livestemn(p) + veg_nf%livestemn_xfer_to_livestemn(p)*dt veg_ns%livestemn_xfer(p) = veg_ns%livestemn_xfer(p) - veg_nf%livestemn_xfer_to_livestemn(p)*dt @@ -312,7 +312,7 @@ subroutine NitrogenStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp veg_ns%retransn(p) = veg_ns%retransn(p) + veg_nf%leafn_to_retransn(p)*dt ! live wood turnover and retranslocation fluxes - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then veg_ns%livestemn(p) = veg_ns%livestemn(p) - veg_nf%livestemn_to_deadstemn(p)*dt veg_ns%deadstemn(p) = veg_ns%deadstemn(p) + veg_nf%livestemn_to_deadstemn(p)*dt veg_ns%livestemn(p) = veg_ns%livestemn(p) - veg_nf%livestemn_to_retransn(p)*dt @@ -322,7 +322,7 @@ subroutine NitrogenStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp veg_ns%livecrootn(p) = veg_ns%livecrootn(p) - veg_nf%livecrootn_to_retransn(p)*dt veg_ns%retransn(p) = veg_ns%retransn(p) + veg_nf%livecrootn_to_retransn(p)*dt end if - if (ivt(p) >= npcropmin) then ! Beth adds retrans from froot + if (iscft(ivt(p))) then ! Beth adds retrans from froot veg_ns%frootn(p) = veg_ns%frootn(p) - veg_nf%frootn_to_retransn(p)*dt veg_ns%retransn(p) = veg_ns%retransn(p) + veg_nf%frootn_to_retransn(p)*dt veg_ns%livestemn(p) = veg_ns%livestemn(p) - veg_nf%livestemn_to_litter(p)*dt @@ -354,7 +354,7 @@ subroutine NitrogenStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp veg_ns%npool(p) = veg_ns%npool(p) - veg_nf%npool_to_frootn_storage(p)*dt veg_ns%frootn_storage(p) = veg_ns%frootn_storage(p) + veg_nf%npool_to_frootn_storage(p)*dt - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then veg_ns%npool(p) = veg_ns%npool(p) - veg_nf%npool_to_livestemn(p)*dt veg_ns%livestemn(p) = veg_ns%livestemn(p) + veg_nf%npool_to_livestemn(p)*dt veg_ns%npool(p) = veg_ns%npool(p) - veg_nf%npool_to_livestemn_storage(p)*dt @@ -373,7 +373,7 @@ subroutine NitrogenStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp veg_ns%deadcrootn_storage(p) = veg_ns%deadcrootn_storage(p) + veg_nf%npool_to_deadcrootn_storage(p)*dt end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops veg_ns%npool(p) = veg_ns%npool(p) - veg_nf%npool_to_livestemn(p)*dt veg_ns%livestemn(p) = veg_ns%livestemn(p) + veg_nf%npool_to_livestemn(p)*dt veg_ns%npool(p) = veg_ns%npool(p) - veg_nf%npool_to_livestemn_storage(p)*dt @@ -390,7 +390,7 @@ subroutine NitrogenStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp veg_ns%frootn_storage(p) = veg_ns%frootn_storage(p) - veg_nf%frootn_storage_to_xfer(p)*dt veg_ns%frootn_xfer(p) = veg_ns%frootn_xfer(p) + veg_nf%frootn_storage_to_xfer(p)*dt - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then veg_ns%livestemn_storage(p) = veg_ns%livestemn_storage(p) - veg_nf%livestemn_storage_to_xfer(p)*dt veg_ns%livestemn_xfer(p) = veg_ns%livestemn_xfer(p) + veg_nf%livestemn_storage_to_xfer(p)*dt veg_ns%deadstemn_storage(p) = veg_ns%deadstemn_storage(p) - veg_nf%deadstemn_storage_to_xfer(p)*dt @@ -401,7 +401,7 @@ subroutine NitrogenStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soilp veg_ns%deadcrootn_xfer(p) = veg_ns%deadcrootn_xfer(p) + veg_nf%deadcrootn_storage_to_xfer(p)*dt end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops ! lines here for consistency; the transfer terms are zero veg_ns%livestemn_storage(p) = veg_ns%livestemn_storage(p) - veg_nf%livestemn_storage_to_xfer(p)*dt veg_ns%livestemn_xfer(p) = veg_ns%livestemn_xfer(p) + veg_nf%livestemn_storage_to_xfer(p)*dt diff --git a/components/elm/src/biogeochem/NitrogenStateUpdate2Mod.F90 b/components/elm/src/biogeochem/NitrogenStateUpdate2Mod.F90 index 9121954e6363..d8e6785e52cb 100644 --- a/components/elm/src/biogeochem/NitrogenStateUpdate2Mod.F90 +++ b/components/elm/src/biogeochem/NitrogenStateUpdate2Mod.F90 @@ -14,7 +14,7 @@ module NitrogenStateUpdate2Mod use ColumnDataType , only : col_ns, col_nf use VegetationType , only : veg_pp use VegetationDataType , only : veg_ns, veg_nf - use pftvarcon , only : npcropmin + use pftvarcon , only : iscft ! bgc interface & pflotran: use elm_varctl , only : use_pflotran, pf_cmode ! @@ -172,7 +172,7 @@ subroutine NitrogenStateUpdate2h(num_soilc, filter_soilc, num_soilp, filter_soil veg_ns%retransn(p) = veg_ns%retransn(p) - veg_nf%hrv_retransn_to_litter(p) * dt veg_ns%npool(p) = veg_ns%npool(p) - veg_nf%hrv_npool_to_litter(p) * dt - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops veg_ns%livestemn(p)= veg_ns%livestemn(p) - veg_nf%hrv_livestemn_to_prod1n(p) * dt veg_ns%leafn(p) = veg_ns%leafn(p) - veg_nf%hrv_leafn_to_prod1n(p) * dt veg_ns%grainn(p) = veg_ns%grainn(p) - veg_nf%hrv_grainn_to_prod1n(p) * dt diff --git a/components/elm/src/biogeochem/PhenologyFluxLimitMod.F90 b/components/elm/src/biogeochem/PhenologyFluxLimitMod.F90 index b6d05460c0bb..87b9637d5512 100644 --- a/components/elm/src/biogeochem/PhenologyFluxLimitMod.F90 +++ b/components/elm/src/biogeochem/PhenologyFluxLimitMod.F90 @@ -10,7 +10,7 @@ module PhenologyFLuxLimitMod use VegetationType , only : veg_pp use VegetationPropertiesType , only : veg_vp use elm_time_manager , only : get_step_size - use pftvarcon , only : npcropmin + use pftvarcon , only : iscft use elm_varctl , only : iulog use abortutils , only : endrun implicit none @@ -630,7 +630,7 @@ subroutine carbon_flux_limiter(bounds, num_soilc, filter_soilc,& ystates(s_frootc) = veg_cs%frootc(p) ystates(s_frootc_xfer) = veg_cs%frootc_xfer(p) ystates(s_frootc_storage) = veg_cs%frootc_storage(p) - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then ystates(s_livestemc) = veg_cs%livestemc(p) ystates(s_livestemc_xfer) = veg_cs%livestemc_xfer(p) ystates(s_livestemc_storage) = veg_cs%livestemc_storage(p) @@ -644,7 +644,7 @@ subroutine carbon_flux_limiter(bounds, num_soilc, filter_soilc,& ystates(s_deadcrootc_xfer) = veg_cs%deadcrootc_xfer(p) ystates(s_deadcrootc_storage) = veg_cs%deadcrootc_storage(p) endif - if (ivt(p) >= npcropmin) then + if (iscft(ivt(p))) then ystates(s_livestemc) = veg_cs%livestemc(p) ystates(s_livestemc_xfer) = veg_cs%livestemc_xfer(p) ystates(s_livestemc_storage) = veg_cs%livestemc_storage(p) @@ -662,7 +662,7 @@ subroutine carbon_flux_limiter(bounds, num_soilc, filter_soilc,& + veg_cf%cpool_froot_gr(p) & + veg_cf%cpool_leaf_storage_gr(p) & + veg_cf%cpool_froot_storage_gr(p) - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then ar_p = ar_p & + veg_cf%livestem_curmr(p) & + veg_cf%livecroot_curmr(p) & @@ -675,7 +675,7 @@ subroutine carbon_flux_limiter(bounds, num_soilc, filter_soilc,& + veg_cf%cpool_livecroot_storage_gr(p) & + veg_cf%cpool_deadcroot_storage_gr(p) endif - if (ivt(p) >= npcropmin) then + if (iscft(ivt(p))) then ar_p= ar_p & + veg_cf%livestem_curmr(p) & + veg_cf%grain_curmr(p) & @@ -692,7 +692,7 @@ subroutine carbon_flux_limiter(bounds, num_soilc, filter_soilc,& rfluxes(f_cpool_to_xsmrpool) = veg_cf%cpool_to_xsmrpool(p) rfluxes(f_cpool_to_gresp_storage) = veg_cf%cpool_to_gresp_storage(p) rfluxes(f_cpool_to_ar) = ar_p - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then rfluxes(f_cpool_to_livestemc) = veg_cf%cpool_to_livestemc(p) rfluxes(f_cpool_to_livestemc_storage) = veg_cf%cpool_to_livestemc_storage(p) rfluxes(f_cpool_to_deadstemc) = veg_cf%cpool_to_deadstemc(p) @@ -713,7 +713,7 @@ subroutine carbon_flux_limiter(bounds, num_soilc, filter_soilc,& rfluxes(f_deadcrootc_storage_to_xfer) = veg_cf%deadcrootc_storage_to_xfer(p) rfluxes(f_gresp_storage_to_xfer) = veg_cf%gresp_storage_to_xfer(p) endif - if (ivt(p) >= npcropmin) then + if (iscft(ivt(p))) then rfluxes(f_cpool_to_livestemc) = veg_cf%cpool_to_livestemc(p) rfluxes(f_cpool_to_livestemc_storage) = veg_cf%cpool_to_livestemc_storage(p) rfluxes(f_cpool_to_grainc) = veg_cf%cpool_to_grainc(p) @@ -746,7 +746,7 @@ subroutine carbon_flux_limiter(bounds, num_soilc, filter_soilc,& call fpmax(rfluxes(f_cpool_to_xsmrpool) , veg_cf%cpool_to_xsmrpool(p)) call fpmax(rfluxes(f_cpool_to_gresp_storage) , veg_cf%cpool_to_gresp_storage(p)) - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then call fpmax(rfluxes(f_cpool_to_livestemc) , veg_cf%cpool_to_livestemc(p)) call fpmax(rfluxes(f_cpool_to_livestemc_storage) , veg_cf%cpool_to_livestemc_storage(p)) call fpmax(rfluxes(f_cpool_to_deadstemc) , veg_cf%cpool_to_deadstemc(p)) @@ -767,7 +767,7 @@ subroutine carbon_flux_limiter(bounds, num_soilc, filter_soilc,& call fpmax(rfluxes(f_deadcrootc_storage_to_xfer) , veg_cf%deadcrootc_storage_to_xfer(p)) call fpmax(rfluxes(f_gresp_storage_to_xfer) , veg_cf%gresp_storage_to_xfer(p)) endif - if (ivt(p) >= npcropmin) then + if (iscft(ivt(p))) then call fpmax(rfluxes(f_cpool_to_livestemc) , veg_cf%cpool_to_livestemc(p)) call fpmax(rfluxes(f_cpool_to_livestemc_storage) , veg_cf%cpool_to_livestemc_storage(p)) call fpmax(rfluxes(f_cpool_to_grainc) , veg_cf%cpool_to_grainc(p)) @@ -794,7 +794,7 @@ subroutine carbon_flux_limiter(bounds, num_soilc, filter_soilc,& call ascal(veg_cf%cpool_froot_gr(p) , rscal) call ascal(veg_cf%cpool_leaf_storage_gr(p) , rscal) call ascal(veg_cf%cpool_froot_storage_gr(p) , rscal) - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then call ascal(veg_cf%livestem_curmr(p) , rscal) call ascal(veg_cf%livecroot_curmr(p) , rscal) call ascal(veg_cf%cpool_livestem_gr(p) , rscal) @@ -806,7 +806,7 @@ subroutine carbon_flux_limiter(bounds, num_soilc, filter_soilc,& call ascal(veg_cf%cpool_livecroot_storage_gr(p), rscal) call ascal(veg_cf%cpool_deadcroot_storage_gr(p), rscal) endif - if (ivt(p) >= npcropmin) then + if (iscft(ivt(p))) then call ascal(veg_cf%livestem_curmr(p) , rscal) call ascal(veg_cf%grain_curmr(p) , rscal) call ascal(veg_cf%cpool_livestem_gr(p) , rscal) @@ -864,7 +864,7 @@ subroutine nitrogen_flux_limiter(bounds, num_soilc, filter_soilc,& ystates(s_frootn) = veg_ns%frootn(p) ystates(s_frootn_xfer) = veg_ns%frootn_xfer(p) ystates(s_frootn_storage) = veg_ns%frootn_storage(p) - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then ystates(s_livestemn) = veg_ns%livestemn(p) ystates(s_livestemn_xfer) = veg_ns%livestemn_xfer(p) ystates(s_livestemn_storage) = veg_ns%livestemn_storage(p) @@ -878,7 +878,7 @@ subroutine nitrogen_flux_limiter(bounds, num_soilc, filter_soilc,& ystates(s_deadcrootn_xfer) = veg_ns%deadcrootn_xfer(p) ystates(s_deadcrootn_storage) = veg_ns%deadcrootn_storage(p) endif - if (ivt(p) >= npcropmin) then + if (iscft(ivt(p))) then ystates(s_grainn) = veg_ns%grainn(p) ystates(s_grainn_xfer) = veg_ns%grainn_xfer(p) ystates(s_grainn_storage) = veg_ns%grainn_storage(p) @@ -894,7 +894,7 @@ subroutine nitrogen_flux_limiter(bounds, num_soilc, filter_soilc,& rfluxes(f_npool_to_leafn_storage) = veg_nf%npool_to_leafn_storage(p) rfluxes(f_npool_to_frootn) = veg_nf%npool_to_frootn(p) rfluxes(f_npool_to_frootn_storage) = veg_nf%npool_to_frootn_storage(p) - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then rfluxes(f_npool_to_livestemn) = veg_nf%npool_to_livestemn(p) rfluxes(f_npool_to_livestemn_storage) = veg_nf%npool_to_livestemn_storage(p) rfluxes(f_npool_to_livecrootn) = veg_nf%npool_to_livecrootn(p) @@ -917,7 +917,7 @@ subroutine nitrogen_flux_limiter(bounds, num_soilc, filter_soilc,& rfluxes(f_deadcrootn_xfer_to_deadcrootn) = veg_nf%deadcrootn_xfer_to_deadcrootn(p) endif - if (ivt(p) >= npcropmin) then + if (iscft(ivt(p))) then rfluxes(f_npool_to_livestemn) = veg_nf%npool_to_livestemn(p) rfluxes(f_npool_to_livestemn_storage) = veg_nf%npool_to_livestemn_storage(p) rfluxes(f_npool_to_grainn) = veg_nf%npool_to_grainn(p) @@ -950,7 +950,7 @@ subroutine nitrogen_flux_limiter(bounds, num_soilc, filter_soilc,& call fpmax(rfluxes(f_npool_to_leafn_storage) , veg_nf%npool_to_leafn_storage(p)) call fpmax(rfluxes(f_npool_to_frootn) , veg_nf%npool_to_frootn(p)) call fpmax(rfluxes(f_npool_to_frootn_storage) , veg_nf%npool_to_frootn_storage(p)) - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then call fpmax(rfluxes(f_npool_to_livestemn) , veg_nf%npool_to_livestemn(p)) call fpmax(rfluxes(f_npool_to_livestemn_storage) , veg_nf%npool_to_livestemn_storage(p)) call fpmax(rfluxes(f_npool_to_livecrootn) , veg_nf%npool_to_livecrootn(p)) @@ -973,7 +973,7 @@ subroutine nitrogen_flux_limiter(bounds, num_soilc, filter_soilc,& call fpmax(rfluxes(f_deadcrootn_xfer_to_deadcrootn) , veg_nf%deadcrootn_xfer_to_deadcrootn(p)) endif - if (ivt(p) >= npcropmin) then + if (iscft(ivt(p))) then call fpmax(rfluxes(f_npool_to_livestemn) , veg_nf%npool_to_livestemn(p)) call fpmax(rfluxes(f_npool_to_livestemn_storage) , veg_nf%npool_to_livestemn_storage(p)) call fpmax(rfluxes(f_npool_to_grainn) , veg_nf%npool_to_grainn(p)) @@ -1049,7 +1049,7 @@ subroutine phosphorus_flux_limiter(bounds, num_soilc, filter_soilc,& ystates(s_frootn) = veg_ps%frootp(p) ystates(s_frootn_xfer) = veg_ps%frootp_xfer(p) ystates(s_frootn_storage) = veg_ps%frootp_storage(p) - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then ystates(s_livestemn) = veg_ps%livestemp(p) ystates(s_livestemn_xfer) = veg_ps%livestemp_xfer(p) ystates(s_livestemn_storage) = veg_ps%livestemp_storage(p) @@ -1063,7 +1063,7 @@ subroutine phosphorus_flux_limiter(bounds, num_soilc, filter_soilc,& ystates(s_deadcrootn_xfer) = veg_ps%deadcrootp_xfer(p) ystates(s_deadcrootn_storage) = veg_ps%deadcrootp_storage(p) endif - if (ivt(p) >= npcropmin) then + if (iscft(ivt(p))) then ystates(s_grainn) = veg_ps%grainp(p) ystates(s_grainn_xfer) = veg_ps%grainp_xfer(p) ystates(s_grainn_storage) = veg_ps%grainp_storage(p) @@ -1079,7 +1079,7 @@ subroutine phosphorus_flux_limiter(bounds, num_soilc, filter_soilc,& rfluxes(f_npool_to_leafn_storage) = veg_pf%ppool_to_leafp_storage(p) rfluxes(f_npool_to_frootn) = veg_pf%ppool_to_frootp(p) rfluxes(f_npool_to_frootn_storage) = veg_pf%ppool_to_frootp_storage(p) - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then rfluxes(f_npool_to_livestemn) = veg_pf%ppool_to_livestemp(p) rfluxes(f_npool_to_livestemn_storage) = veg_pf%ppool_to_livestemp_storage(p) rfluxes(f_npool_to_livecrootn) = veg_pf%ppool_to_livecrootp(p) @@ -1102,7 +1102,7 @@ subroutine phosphorus_flux_limiter(bounds, num_soilc, filter_soilc,& rfluxes(f_deadcrootn_xfer_to_deadcrootn) = veg_pf%deadcrootp_xfer_to_deadcrootp(p) endif - if (ivt(p) >= npcropmin) then + if (iscft(ivt(p))) then rfluxes(f_npool_to_livestemn) = veg_pf%ppool_to_livestemp(p) rfluxes(f_npool_to_livestemn_storage) = veg_pf%ppool_to_livestemp_storage(p) rfluxes(f_npool_to_grainn) = veg_pf%ppool_to_grainp(p) @@ -1135,7 +1135,7 @@ subroutine phosphorus_flux_limiter(bounds, num_soilc, filter_soilc,& call fpmax(rfluxes(f_npool_to_leafn_storage) , veg_pf%ppool_to_leafp_storage(p)) call fpmax(rfluxes(f_npool_to_frootn) , veg_pf%ppool_to_frootp(p)) call fpmax(rfluxes(f_npool_to_frootn_storage) , veg_pf%ppool_to_frootp_storage(p)) - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then call fpmax(rfluxes(f_npool_to_livestemn) , veg_pf%ppool_to_livestemp(p)) call fpmax(rfluxes(f_npool_to_livestemn_storage) , veg_pf%ppool_to_livestemp_storage(p)) call fpmax(rfluxes(f_npool_to_livecrootn) , veg_pf%ppool_to_livecrootp(p)) @@ -1158,7 +1158,7 @@ subroutine phosphorus_flux_limiter(bounds, num_soilc, filter_soilc,& call fpmax(rfluxes(f_deadcrootn_xfer_to_deadcrootn) , veg_pf%deadcrootp_xfer_to_deadcrootp(p)) endif - if (ivt(p) >= npcropmin) then + if (iscft(ivt(p))) then call fpmax(rfluxes(f_npool_to_livestemn) , veg_pf%ppool_to_livestemp(p)) call fpmax(rfluxes(f_npool_to_livestemn_storage) , veg_pf%ppool_to_livestemp_storage(p)) call fpmax(rfluxes(f_npool_to_grainn) , veg_pf%ppool_to_grainp(p)) diff --git a/components/elm/src/biogeochem/PhenologyMod.F90 b/components/elm/src/biogeochem/PhenologyMod.F90 index 9f51301acb74..08e9b94da524 100644 --- a/components/elm/src/biogeochem/PhenologyMod.F90 +++ b/components/elm/src/biogeochem/PhenologyMod.F90 @@ -771,7 +771,7 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp, cnstate_vars) frootn_xfer_to_frootn(p) = 0.0_r8 leafp_xfer_to_leafp(p) = 0.0_r8 frootp_xfer_to_frootp(p) = 0.0_r8 - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then livestemc_xfer_to_livestemc(p) = 0.0_r8 deadstemc_xfer_to_deadstemc(p) = 0.0_r8 livecrootc_xfer_to_livecrootc(p) = 0.0_r8 @@ -792,7 +792,7 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp, cnstate_vars) frootc_xfer(p) = 0.0_r8 frootn_xfer(p) = 0.0_r8 frootp_xfer(p) = 0.0_r8 - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then livestemc_xfer(p) = 0.0_r8 livestemn_xfer(p) = 0.0_r8 livestemp_xfer(p) = 0.0_r8 @@ -855,7 +855,7 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp, cnstate_vars) ! set carbon fluxes for shifting storage pools to transfer pools leafc_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * leafc_storage(p)/dt frootc_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * frootc_storage(p)/dt - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then livestemc_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livestemc_storage(p)/dt deadstemc_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * deadstemc_storage(p)/dt livecrootc_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livecrootc_storage(p)/dt @@ -866,7 +866,7 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp, cnstate_vars) ! set nitrogen fluxes for shifting storage pools to transfer pools leafn_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * leafn_storage(p)/dt frootn_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * frootn_storage(p)/dt - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then livestemn_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livestemn_storage(p)/dt deadstemn_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * deadstemn_storage(p)/dt livecrootn_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livecrootn_storage(p)/dt @@ -876,7 +876,7 @@ subroutine CNSeasonDecidPhenology (num_soilp, filter_soilp, cnstate_vars) ! set phosphorus fluxes for shifting storage pools to transfer pools leafp_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * leafp_storage(p)/dt frootp_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * frootp_storage(p)/dt - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then livestemp_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livestemp_storage(p)/dt deadstemp_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * deadstemp_storage(p)/dt livecrootp_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livecrootp_storage(p)/dt @@ -1116,7 +1116,7 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & frootn_xfer_to_frootn(p) = 0._r8 leafp_xfer_to_leafp(p) = 0._r8 frootp_xfer_to_frootp(p) = 0._r8 - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then livestemc_xfer_to_livestemc(p) = 0._r8 deadstemc_xfer_to_deadstemc(p) = 0._r8 livecrootc_xfer_to_livecrootc(p) = 0._r8 @@ -1137,7 +1137,7 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & frootc_xfer(p) = 0._r8 frootn_xfer(p) = 0._r8 frootp_xfer(p) = 0._r8 - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then livestemc_xfer(p) = 0._r8 livestemn_xfer(p) = 0._r8 livestemp_xfer(p) = 0._r8 @@ -1229,7 +1229,7 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & ! set carbon fluxes for shifting storage pools to transfer pools leafc_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * leafc_storage(p)/dt frootc_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * frootc_storage(p)/dt - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then livestemc_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livestemc_storage(p)/dt deadstemc_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * deadstemc_storage(p)/dt livecrootc_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livecrootc_storage(p)/dt @@ -1240,7 +1240,7 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & ! set nitrogen fluxes for shifting storage pools to transfer pools leafn_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * leafn_storage(p)/dt frootn_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * frootn_storage(p)/dt - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then livestemn_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livestemn_storage(p)/dt deadstemn_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * deadstemn_storage(p)/dt livecrootn_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livecrootn_storage(p)/dt @@ -1250,7 +1250,7 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & ! set phosphorus fluxes for shifting storage pools to transfer pools leafp_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * leafp_storage(p)/dt frootp_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * frootp_storage(p)/dt - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then livestemp_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livestemp_storage(p)/dt deadstemp_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * deadstemp_storage(p)/dt livecrootp_storage_to_xfer(p) = PhenolParamsInst%fstor2tran * livecrootp_storage(p)/dt @@ -1352,7 +1352,7 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & leafc_storage_to_xfer(p) = leafc_storage(p) * bgtr(p) frootc_storage_to_xfer(p) = frootc_storage(p) * bgtr(p) - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then livestemc_storage_to_xfer(p) = livestemc_storage(p) * bgtr(p) deadstemc_storage_to_xfer(p) = deadstemc_storage(p) * bgtr(p) livecrootc_storage_to_xfer(p) = livecrootc_storage(p) * bgtr(p) @@ -1363,7 +1363,7 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & ! set nitrogen fluxes for shifting storage pools to transfer pools 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 + if (woody(ivt(p)) >= 1.0_r8) then livestemn_storage_to_xfer(p) = livestemn_storage(p) * bgtr(p) deadstemn_storage_to_xfer(p) = deadstemn_storage(p) * bgtr(p) livecrootn_storage_to_xfer(p) = livecrootn_storage(p) * bgtr(p) @@ -1374,7 +1374,7 @@ subroutine CNStressDecidPhenology (num_soilp, filter_soilp , & ! set phosphorus fluxes for shifting storage pools to transfer pools leafp_storage_to_xfer(p) = leafp_storage(p) * bgtr(p) frootp_storage_to_xfer(p) = frootp_storage(p) * bgtr(p) - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then livestemp_storage_to_xfer(p) = livestemp_storage(p) * bgtr(p) deadstemp_storage_to_xfer(p) = deadstemp_storage(p) * bgtr(p) livecrootp_storage_to_xfer(p) = livecrootp_storage(p) * bgtr(p) @@ -2177,7 +2177,8 @@ subroutine CropPhenologyInit(bounds) ! initialized, and after ecophyscon file is read in. ! ! !USES: - use pftvarcon , only: npcropmin, npcropmax, nppercropmin, nppercropmax, mnNHplantdate + use elm_varpar , only : mxpft + use pftvarcon , only: iscft, mnNHplantdate use pftvarcon , only: mnSHplantdate, mxNHplantdate use pftvarcon , only: mxSHplantdate use elm_time_manager, only: get_calday @@ -2203,22 +2204,17 @@ subroutine CropPhenologyInit(bounds) ! Convert planting dates into julian day minplantjday(:,:) = huge(1) maxplantjday(:,:) = huge(1) - do n = npcropmin, npcropmax + do n = 0, mxpft + if (iscft(n)) then minplantjday(n,inNH) = int( get_calday( mnNHplantdate(n), 0 ) ) maxplantjday(n,inNH) = int( get_calday( mxNHplantdate(n), 0 ) ) + end if end do - do n = npcropmin, npcropmax + do n = 0, mxpft + if (iscft(n)) then minplantjday(n,inSH) = int( get_calday( mnSHplantdate(n), 0 ) ) maxplantjday(n,inSH) = int( get_calday( mxSHplantdate(n), 0 ) ) - end do - - do n = nppercropmin, nppercropmax - minplantjday(n,inNH) = int( get_calday( mnNHplantdate(n), 0 ) ) - maxplantjday(n,inNH) = int( get_calday( mxNHplantdate(n), 0 ) ) - end do - do n = nppercropmin, nppercropmax - minplantjday(n,inSH) = int( get_calday( mnSHplantdate(n), 0 ) ) - maxplantjday(n,inSH) = int( get_calday( mxSHplantdate(n), 0 ) ) + end if end do ! Figure out what hemisphere each PFT is in @@ -2694,7 +2690,7 @@ subroutine CNOnsetGrowth (num_soilp, filter_soilp, & frootn_xfer_to_frootn(p) = t1 * frootn_xfer(p) leafp_xfer_to_leafp(p) = t1 * leafp_xfer(p) frootp_xfer_to_frootp(p) = t1 * frootp_xfer(p) - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then livestemc_xfer_to_livestemc(p) = t1 * livestemc_xfer(p) deadstemc_xfer_to_deadstemc(p) = t1 * deadstemc_xfer(p) livecrootc_xfer_to_livecrootc(p) = t1 * livecrootc_xfer(p) @@ -2723,7 +2719,7 @@ subroutine CNOnsetGrowth (num_soilp, filter_soilp, & frootn_xfer_to_frootn(p) = frootn_xfer(p) / dt leafp_xfer_to_leafp(p) = leafp_xfer(p) / dt frootp_xfer_to_frootp(p) = frootp_xfer(p) / dt - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then livestemc_xfer_to_livestemc(p) = livestemc_xfer(p) / dt deadstemc_xfer_to_deadstemc(p) = deadstemc_xfer(p) / dt livecrootc_xfer_to_livecrootc(p) = livecrootc_xfer(p) / dt @@ -2965,7 +2961,7 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & ! ! !USES: !$acc routine seq - use pftvarcon , only : npcropmin + use pftvarcon , only : iscft ! ! !ARGUMENTS: integer , intent(in) :: num_soilp ! number of soil patches in filter @@ -3062,7 +3058,7 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & if (offset_counter(p) == dt) then t1 = 1.0_r8 / dt - if (ivt(p) >= npcropmin) then + if (iscft(ivt(p))) then ! this assumes that offset_counter == dt for crops ! if this were ever changed, we'd need to add code to the "else" leafc_to_litter(p) = (1.0_r8 - presharv(ivt(p))) * ((t1 * leafc(p)) + cpool_to_leafc(p)) @@ -3079,7 +3075,7 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & end if if ( nu_com .eq. 'RD') then - if (ivt(p) >= npcropmin) then + if (iscft(ivt(p))) then if (offset_counter(p) == dt) then t1 = 1.0_r8 / dt @@ -3113,7 +3109,7 @@ subroutine CNOffsetLitterfall (num_soilp, filter_soilp, & else if (offset_counter(p) == dt) then t1 = 1.0_r8 / dt - if (ivt(p) >= npcropmin) then + if (iscft(ivt(p))) then ! this assumes that offset_counter == dt for crops ! if this were ever changed, we'd need to add code to the "else" leafn_to_litter(p) = (1.0_r8 - presharv(ivt(p))) * ((t1 * leafn(p)) + npool_to_leafn(p)) @@ -3315,7 +3311,7 @@ subroutine CNLivewoodTurnover (num_soilp, filter_soilp) p = filter_soilp(fp) ! only calculate these fluxes for woody types - if (woody(ivt(p)) > 0._r8) then + if (woody(ivt(p)) >= 1.0_r8) then if ( nu_com .eq. 'RD') then ! live stem to dead stem turnover @@ -3387,7 +3383,7 @@ subroutine CNLitterToColumn (num_soilp, filter_soilp, & ! !USES: !$acc routine seq use elm_varpar , only : max_patch_per_col, nlevdecomp - use pftvarcon , only : npcropmin + use pftvarcon , only : iscft ! ! !ARGUMENTS: integer , intent(in) :: num_soilp ! number of soil columns in filter @@ -3497,7 +3493,7 @@ subroutine CNLitterToColumn (num_soilp, filter_soilp, & ! new ones for now (slevis) ! The food is now directed to the product pools (BDrewniak) - if (ivt(p) >= npcropmin) then ! add livestemc to litter + if (iscft(ivt(p))) then ! add livestemc to litter ! stem litter carbon fluxes phenology_c_to_litr_met_c(c,j) = phenology_c_to_litr_met_c(c,j) & + livestemc_to_litter(p) * lf_flab(ivt(p)) * wt_col * leaf_prof(p,j) diff --git a/components/elm/src/biogeochem/PhosphorusFluxType.F90 b/components/elm/src/biogeochem/PhosphorusFluxType.F90 index f34d7556f696..52bda3118fd2 100644 --- a/components/elm/src/biogeochem/PhosphorusFluxType.F90 +++ b/components/elm/src/biogeochem/PhosphorusFluxType.F90 @@ -561,7 +561,6 @@ subroutine Summary(this, bounds, num_soilc, filter_soilc, num_soilp, filter_soil ! !USES: use elm_varpar , only: nlevdecomp,ndecomp_cascade_transitions,ndecomp_pools use subgridAveMod , only: p2c - use pftvarcon , only: npcropmin ! pflotran ! use elm_varctl , only: use_pflotran, pf_cmode ! diff --git a/components/elm/src/biogeochem/PhosphorusStateType.F90 b/components/elm/src/biogeochem/PhosphorusStateType.F90 index 0be7dd7f533f..58dbe630c2ef 100644 --- a/components/elm/src/biogeochem/PhosphorusStateType.F90 +++ b/components/elm/src/biogeochem/PhosphorusStateType.F90 @@ -12,7 +12,7 @@ module PhosphorusStateType use elm_varctl , only : use_vertsoilc, use_century_decomp use elm_varctl , only : iulog, override_bgc_restart_mismatch_dump, spinup_state use decompMod , only : bounds_type - use pftvarcon , only : npcropmin, nstor + use pftvarcon , only : iscft, nstor use CNDecompCascadeConType , only : decomp_cascade_con use VegetationPropertiesType , only : veg_vp use abortutils , only : endrun @@ -254,7 +254,7 @@ subroutine InitCold(this, bounds, & ! !USES: use elm_varpar , only : crop_prog use decompMod , only : bounds_type - use pftvarcon , only : noveg, npcropmin + use pftvarcon , only : noveg, iscft ! ! !ARGUMENTS: class(phosphorusstate_type) :: this diff --git a/components/elm/src/biogeochem/PhosphorusStateUpdate1Mod.F90 b/components/elm/src/biogeochem/PhosphorusStateUpdate1Mod.F90 index 63390dc419e2..6e1111169221 100644 --- a/components/elm/src/biogeochem/PhosphorusStateUpdate1Mod.F90 +++ b/components/elm/src/biogeochem/PhosphorusStateUpdate1Mod.F90 @@ -8,7 +8,7 @@ module PhosphorusStateUpdate1Mod use elm_varpar , only : nlevdecomp, ndecomp_pools, ndecomp_cascade_transitions use elm_varpar , only : crop_prog, i_met_lit, i_cel_lit, i_lig_lit, i_cwd use elm_varctl , only : iulog - use pftvarcon , only : npcropmin, nc3crop + use pftvarcon , only : iscft use soilorder_varcon , only : smax,ks_sorption use VegetationPropertiesType , only : veg_vp use CNDecompCascadeConType , only : decomp_cascade_con @@ -244,7 +244,7 @@ subroutine PhosphorusStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soi veg_ps%frootp(p) = veg_ps%frootp(p) + veg_pf%frootp_xfer_to_frootp(p)*dt veg_ps%frootp_xfer(p) = veg_ps%frootp_xfer(p) - veg_pf%frootp_xfer_to_frootp(p)*dt - if (woody(ivt(p)) == 1.0_r8) then + if (woody(ivt(p)) >= 1.0_r8) then veg_ps%livestemp(p) = veg_ps%livestemp(p) + veg_pf%livestemp_xfer_to_livestemp(p)*dt veg_ps%livestemp_xfer(p) = veg_ps%livestemp_xfer(p) - veg_pf%livestemp_xfer_to_livestemp(p)*dt veg_ps%deadstemp(p) = veg_ps%deadstemp(p) + veg_pf%deadstemp_xfer_to_deadstemp(p)*dt @@ -255,7 +255,7 @@ subroutine PhosphorusStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soi veg_ps%deadcrootp_xfer(p) = veg_ps%deadcrootp_xfer(p) - veg_pf%deadcrootp_xfer_to_deadcrootp(p)*dt end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops ! lines here for consistency; the transfer terms are zero veg_ps%livestemp(p) = veg_ps%livestemp(p) + veg_pf%livestemp_xfer_to_livestemp(p)*dt veg_ps%livestemp_xfer(p) = veg_ps%livestemp_xfer(p) - veg_pf%livestemp_xfer_to_livestemp(p)*dt @@ -270,7 +270,7 @@ subroutine PhosphorusStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soi veg_ps%retransp(p) = veg_ps%retransp(p) + veg_pf%leafp_to_retransp(p)*dt ! live wood turnover and retranslocation fluxes - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then veg_ps%livestemp(p) = veg_ps%livestemp(p) - veg_pf%livestemp_to_deadstemp(p)*dt veg_ps%deadstemp(p) = veg_ps%deadstemp(p) + veg_pf%livestemp_to_deadstemp(p)*dt veg_ps%livestemp(p) = veg_ps%livestemp(p) - veg_pf%livestemp_to_retransp(p)*dt @@ -280,7 +280,7 @@ subroutine PhosphorusStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soi veg_ps%livecrootp(p) = veg_ps%livecrootp(p) - veg_pf%livecrootp_to_retransp(p)*dt veg_ps%retransp(p) = veg_ps%retransp(p) + veg_pf%livecrootp_to_retransp(p)*dt end if - if (ivt(p) >= npcropmin) then ! Beth adds retrans from froot + if (iscft(ivt(p))) then ! Beth adds retrans from froot veg_ps%frootp(p) = veg_ps%frootp(p) - veg_pf%frootp_to_retransp(p)*dt veg_ps%retransp(p) = veg_ps%retransp(p) + veg_pf%frootp_to_retransp(p)*dt veg_ps%livestemp(p) = veg_ps%livestemp(p) - veg_pf%livestemp_to_litter(p)*dt @@ -312,7 +312,7 @@ subroutine PhosphorusStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soi veg_ps%ppool(p) = veg_ps%ppool(p) - veg_pf%ppool_to_frootp_storage(p)*dt veg_ps%frootp_storage(p) = veg_ps%frootp_storage(p) + veg_pf%ppool_to_frootp_storage(p)*dt - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then veg_ps%ppool(p) = veg_ps%ppool(p) - veg_pf%ppool_to_livestemp(p)*dt veg_ps%livestemp(p) = veg_ps%livestemp(p) + veg_pf%ppool_to_livestemp(p)*dt veg_ps%ppool(p) = veg_ps%ppool(p) - veg_pf%ppool_to_livestemp_storage(p)*dt @@ -331,7 +331,7 @@ subroutine PhosphorusStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soi veg_ps%deadcrootp_storage(p) = veg_ps%deadcrootp_storage(p) + veg_pf%ppool_to_deadcrootp_storage(p)*dt end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops veg_ps%ppool(p) = veg_ps%ppool(p) - veg_pf%ppool_to_livestemp(p)*dt veg_ps%livestemp(p) = veg_ps%livestemp(p) + veg_pf%ppool_to_livestemp(p)*dt veg_ps%ppool(p) = veg_ps%ppool(p) - veg_pf%ppool_to_livestemp_storage(p)*dt @@ -348,7 +348,7 @@ subroutine PhosphorusStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soi veg_ps%frootp_storage(p) = veg_ps%frootp_storage(p) - veg_pf%frootp_storage_to_xfer(p)*dt veg_ps%frootp_xfer(p) = veg_ps%frootp_xfer(p) + veg_pf%frootp_storage_to_xfer(p)*dt - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then veg_ps%livestemp_storage(p) = veg_ps%livestemp_storage(p) - veg_pf%livestemp_storage_to_xfer(p)*dt veg_ps%livestemp_xfer(p) = veg_ps%livestemp_xfer(p) + veg_pf%livestemp_storage_to_xfer(p)*dt veg_ps%deadstemp_storage(p) = veg_ps%deadstemp_storage(p) - veg_pf%deadstemp_storage_to_xfer(p)*dt @@ -359,7 +359,7 @@ subroutine PhosphorusStateUpdate1(num_soilc, filter_soilc, num_soilp, filter_soi veg_ps%deadcrootp_xfer(p) = veg_ps%deadcrootp_xfer(p) + veg_pf%deadcrootp_storage_to_xfer(p)*dt end if - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops ! lines here for consistency; the transfer terms are zero veg_ps%livestemp_storage(p) = veg_ps%livestemp_storage(p) - veg_pf%livestemp_storage_to_xfer(p)*dt veg_ps%livestemp_xfer(p) = veg_ps%livestemp_xfer(p) + veg_pf%livestemp_storage_to_xfer(p)*dt diff --git a/components/elm/src/biogeochem/PhosphorusStateUpdate2Mod.F90 b/components/elm/src/biogeochem/PhosphorusStateUpdate2Mod.F90 index 2385083451cc..c6b6cd8ee6d3 100644 --- a/components/elm/src/biogeochem/PhosphorusStateUpdate2Mod.F90 +++ b/components/elm/src/biogeochem/PhosphorusStateUpdate2Mod.F90 @@ -12,7 +12,7 @@ module PhosphorusStateUpdate2Mod !use PhosphorusStateType , only : phosphorusstate_type !use PhosphorusFLuxType , only : phosphorusflux_type use VegetationType , only : veg_pp - use pftvarcon , only : npcropmin + use pftvarcon , only : iscft use tracer_varcon , only : is_active_betr_bgc ! bgc interface & pflotran: use elm_varctl , only : use_pflotran, pf_cmode @@ -182,7 +182,7 @@ subroutine PhosphorusStateUpdate2h(num_soilc, filter_soilc, num_soilp, filter_so veg_ps%retransp(p) = veg_ps%retransp(p) - veg_pf%hrv_retransp_to_litter(p) * dt veg_ps%ppool(p) = veg_ps%ppool(p) - veg_pf%hrv_ppool_to_litter(p) * dt - if (ivt(p) >= npcropmin) then ! skip 2 generic crops + if (iscft(ivt(p))) then ! skip 2 generic crops veg_ps%livestemp(p)= veg_ps%livestemp(p) - veg_pf%hrv_livestemp_to_prod1p(p) * dt veg_ps%leafp(p) = veg_ps%leafp(p) - veg_pf%hrv_leafp_to_prod1p(p) * dt veg_ps%grainp(p) = veg_ps%grainp(p) - veg_pf%hrv_grainp_to_prod1p(p) * dt diff --git a/components/elm/src/biogeochem/PrecisionControlMod.F90 b/components/elm/src/biogeochem/PrecisionControlMod.F90 index 89e30c83fd1e..10f601487cda 100644 --- a/components/elm/src/biogeochem/PrecisionControlMod.F90 +++ b/components/elm/src/biogeochem/PrecisionControlMod.F90 @@ -39,7 +39,7 @@ subroutine PrecisionControl(num_soilc, filter_soilc, num_soilp, filter_soilp) !$acc routine seq use elm_varctl , only : iulog, use_c13, use_c14, use_fates use elm_varpar , only : nlevdecomp_full, crop_prog - use pftvarcon , only : nc3crop + use pftvarcon , only : iscft use tracer_varcon , only : is_active_betr_bgc use CNDecompCascadeConType , only : decomp_cascade_con ! @@ -211,7 +211,7 @@ subroutine PrecisionControl(num_soilc, filter_soilc, num_soilp, filter_soilp) veg_ps%frootp_xfer(p) = 0._r8 end if - if ( crop_prog .and. veg_pp%itype(p) >= nc3crop )then + if ( crop_prog .and. iscft(veg_pp%itype(p)))then ! grain C and N if (abs(veg_cs%grainc(p)) < ccrit) then pc = pc + veg_cs%grainc(p) @@ -513,7 +513,7 @@ subroutine PrecisionControl(num_soilc, filter_soilc, num_soilp, filter_soilp) endif end if - if ( crop_prog .and. veg_pp%itype(p) >= nc3crop )then + if ( crop_prog .and. iscft(veg_pp%itype(p)))then ! xsmrpool (C only) if (abs(veg_cs%xsmrpool(p)) < ccrit) then pc = pc + veg_cs%xsmrpool(p) diff --git a/components/elm/src/biogeochem/RootDynamicsMod.F90 b/components/elm/src/biogeochem/RootDynamicsMod.F90 index 3c78043aa6ac..9ea6a9812b0a 100644 --- a/components/elm/src/biogeochem/RootDynamicsMod.F90 +++ b/components/elm/src/biogeochem/RootDynamicsMod.F90 @@ -10,7 +10,7 @@ module RootDynamicsMod use elm_varpar , only : nlevsoi, nlevgrnd use elm_varctl , only : use_vertsoilc use decompMod , only : bounds_type - use pftvarcon , only : noveg, npcropmin, roota_par, rootb_par, root_dmx, evergreen + use pftvarcon , only : noveg, iscft, roota_par, rootb_par, root_dmx, evergreen use CanopyStateType , only: canopystate_type use CNStateType , only : cnstate_type use CNCarbonStateType , only : carbonstate_type @@ -136,7 +136,7 @@ subroutine RootDynamics(bounds, num_soilc, filter_soilc, num_soilp, filter_soilp p = filter_soilp(f) c = pcolumn(p) if (ivt(p) /= noveg) then - if ((ivt(p)) >= npcropmin) then !skip generic crop types + if (iscft(ivt(p))) then !skip generic crop types 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 diff --git a/components/elm/src/biogeochem/SatellitePhenologyMod.F90 b/components/elm/src/biogeochem/SatellitePhenologyMod.F90 index b5d9b1bd3a4b..688b254bd839 100644 --- a/components/elm/src/biogeochem/SatellitePhenologyMod.F90 +++ b/components/elm/src/biogeochem/SatellitePhenologyMod.F90 @@ -304,7 +304,7 @@ subroutine SatellitePhenology(bounds, num_filter, filter, & ! Calculates leaf areas (tlai, elai), stem areas (tsai, esai) and height (htop). ! ! !USES: - use pftvarcon, only : noveg, nbrdlf_dcd_brl_shrub + use pftvarcon, only : woody use elm_varctl, only : use_fates_sp ! ! !ARGUMENTS: @@ -371,7 +371,7 @@ subroutine SatellitePhenology(bounds, num_filter, filter, & ! snow burial fraction for short vegetation (e.g. grasses) as in ! Wang and Zeng, 2007. - if (veg_pp%itype(p) > noveg .and. veg_pp%itype(p) <= nbrdlf_dcd_brl_shrub ) then + if (woody(veg_pp%itype(p)) >= 1.0_r8) then ol = min( max(snow_depth(c)-hbot(p), 0._r8), htop(p)-hbot(p)) fb = 1._r8 - ol / max(1.e-06_r8, htop(p)-hbot(p)) else diff --git a/components/elm/src/biogeochem/VOCEmissionMod.F90 b/components/elm/src/biogeochem/VOCEmissionMod.F90 index cb58227b5235..0a17f8803e73 100644 --- a/components/elm/src/biogeochem/VOCEmissionMod.F90 +++ b/components/elm/src/biogeochem/VOCEmissionMod.F90 @@ -9,13 +9,9 @@ module VOCEmissionMod use shr_log_mod , only : errMsg => shr_log_errMsg use elm_varctl , only : iulog use elm_varpar , only : numpft, nlevcan - use pftvarcon , only : ndllf_evr_tmp_tree, ndllf_evr_brl_tree - use pftvarcon , only : ndllf_dcd_brl_tree, nbrdlf_evr_trp_tree - use pftvarcon , only : nbrdlf_evr_tmp_tree, nbrdlf_dcd_brl_shrub - use pftvarcon , only : nbrdlf_dcd_trp_tree, nbrdlf_dcd_tmp_tree - use pftvarcon , only : nbrdlf_dcd_brl_tree, nbrdlf_evr_shrub - use pftvarcon , only : nc3_arctic_grass , nc3crop - use pftvarcon , only : nc4_grass, noveg + use elm_varpar , only : numveg ! fixed as 16, while numpft above may be variable + use pftvarcon , only : woody, graminoid, iscft, crop + use pftvarcon , only : needleleaf, evergreen use shr_megan_mod , only : shr_megan_megcomps_n, shr_megan_megcomp_t, shr_megan_linkedlist use shr_megan_mod , only : shr_megan_mechcomps_n, shr_megan_mechcomps, shr_megan_mapped_emisfctrs use MEGANFactorsMod , only : Agro, Amat, Anew, Aold, betaT, ct1, ct2, LDF, Ceo @@ -114,7 +110,7 @@ subroutine InitAllocate(this, bounds) ! !LOCAL VARIABLES: integer :: i, imeg integer :: class_num - real(r8) :: factors(numpft) + real(r8) :: factors(numveg) real(r8) :: molec_wght integer :: begg, endg integer :: begp, endp @@ -128,7 +124,8 @@ subroutine InitAllocate(this, bounds) meg_cmp => shr_megan_linkedlist do while(associated(meg_cmp)) - allocate(meg_cmp%emis_factors(numpft)) + !allocate(meg_cmp%emis_factors(numpft)) + allocate(meg_cmp%emis_factors(numveg)) ! TODO: VOCEmission input is with a hard-wired num of pft (16) call megan_factors_get( trim(meg_cmp%name), factors, class_num, molec_wght ) meg_cmp%emis_factors = factors meg_cmp%class_number = class_num @@ -693,21 +690,20 @@ function get_map_EF(ivt_in, g_in, ti_in, vocemis_vars) get_map_EF = 0._r8 - if ( ivt_in == ndllf_evr_tmp_tree & - .or. ivt_in == ndllf_evr_brl_tree) then !fineleaf evergreen + if (woody(ivt_in) == 1.0_r8 .and. evergreen(ivt_in) == 1 & + .and. needleleaf(ivt_in) == 1) then !fineleaf evergreen trees get_map_EF = vocemis_vars%efisop_grc(2,g_in, ti_in) - else if (ivt_in == ndllf_dcd_brl_tree) then !fineleaf deciduous + else if (woody(ivt_in) == 1.0_r8 .and. evergreen(ivt_in) == 0 & + .and. needleleaf(ivt_in) == 1) then !fineleaf deciduous trees get_map_EF = vocemis_vars%efisop_grc(3,g_in, ti_in) - else if (ivt_in >= nbrdlf_evr_trp_tree & - .and. ivt_in <= nbrdlf_dcd_brl_tree) then !broadleaf trees + else if (woody(ivt_in) == 1.0_r8 & + .and. needleleaf(ivt_in) == 0) then !broadleaf trees get_map_EF = vocemis_vars%efisop_grc(1,g_in,ti_in) - else if (ivt_in >= nbrdlf_evr_shrub & - .and. ivt_in <= nbrdlf_dcd_brl_shrub) then !shrubs + else if (woody(ivt_in) == 2.0_r8) then !shrubs get_map_EF = vocemis_vars%efisop_grc(4,g_in, ti_in) - else if (ivt_in >= nc3_arctic_grass & - .and. ivt_in <= nc4_grass) then !grass + else if (graminoid(ivt_in) == 1) then !grass get_map_EF = vocemis_vars%efisop_grc(5,g_in, ti_in) - else if (ivt_in >= nc3crop) then !crops + else if (crop(ivt_in) == 1 .or. iscft(ivt_in)) then !crops get_map_EF = vocemis_vars%efisop_grc(6,g_in, ti_in) end if @@ -970,7 +966,8 @@ function get_gamma_A(ivt_in, elai240_in,elai_in,nclass_in) real(r8) :: elai_prev ! lai for previous timestep real(r8) :: fnew, fgro, fmat, fold ! fractions of leaves at different phenological stages !----------------------------------------------------------------------- - if ( (ivt_in == ndllf_dcd_brl_tree) .or. (ivt_in >= nbrdlf_dcd_trp_tree) ) then ! non-evergreen + !if ( (ivt_in == ndllf_dcd_brl_tree) .or. (ivt_in >= nbrdlf_dcd_trp_tree) ) then ! non-evergreen + if ( (woody(ivt_in) == 1.0_r8) .and. (evergreen(ivt_in) <= 0) ) then ! non-evergreen tree if ( (elai240_in > 0.0_r8) .and. (elai240_in < 1.e30_r8) )then elai_prev = 2._r8*elai240_in-elai_in ! have accumulated average lai over last timestep diff --git a/components/elm/src/biogeochem/VegStructUpdateMod.F90 b/components/elm/src/biogeochem/VegStructUpdateMod.F90 index 6796ab1993ad..5943da355a04 100644 --- a/components/elm/src/biogeochem/VegStructUpdateMod.F90 +++ b/components/elm/src/biogeochem/VegStructUpdateMod.F90 @@ -37,8 +37,8 @@ subroutine VegStructUpdate(num_soilp, filter_soilp, & ! vegetation structure (LAI, SAI, height) ! ! !USES: - use pftvarcon , only : noveg, nc3crop, nc3irrig, nbrdlf_evr_shrub, nbrdlf_dcd_brl_shrub - use pftvarcon , only : ncorn, ncornirrig, npcropmin, ztopmx, laimx + use pftvarcon , only : noveg, woody, iscft, crop + use pftvarcon , only : ncorn, ncornirrig, ztopmx, laimx use pftvarcon , only : nmiscanthus, nmiscanthusirrig, nswitchgrass, nswitchgrassirrig use elm_time_manager , only : get_rad_step_size use elm_varctl , only : spinup_state, spinup_mortality_factor @@ -83,7 +83,6 @@ subroutine VegStructUpdate(num_soilp, filter_soilp, & associate( & ivt => veg_pp%itype , & ! Input: [integer (:) ] pft vegetation type - woody => veg_vp%woody , & ! Input: [real(r8) (:) ] binary flag for woody lifeform (1=woody, 0=not woody) slatop => veg_vp%slatop , & ! Input: [real(r8) (:) ] specific leaf area at top of canopy, projected area basis [m^2/gC] dsladlai => veg_vp%dsladlai , & ! Input: [real(r8) (:) ] dSLA/dLAI, projected area basis [m^2/gC] z0mr => veg_vp%z0mr , & ! Input: [real(r8) (:) ] ratio of momentum roughness length to canopy top height (-) @@ -148,7 +147,7 @@ subroutine VegStructUpdate(num_soilp, filter_soilp, & ! alpha are set by PFT, and alpha is scaled to CLM time step by multiplying by ! dt and dividing by dtsmonth (seconds in average 30 day month) ! tsai_min scaled by 0.5 to match MODIS satellite derived values - if (ivt(p) == nc3crop .or. ivt(p) == nc3irrig) then ! generic crops + if (crop(ivt(p)) == 1 .and. .not. iscft(ivt(p))) then ! generic crops tsai_alpha = 1.0_r8-1.0_r8*dt/dtsmonth tsai_min = 0.1_r8 @@ -159,12 +158,12 @@ subroutine VegStructUpdate(num_soilp, filter_soilp, & tsai_min = tsai_min * 0.5_r8 tsai(p) = max(tsai_alpha*tsai_old+max(tlai_old-tlai(p),0._r8),tsai_min) - if (woody(ivt(p)) == 1._r8) then + if (woody(ivt(p)) >= 1.0_r8) then ! trees and shrubs ! if shrubs have a squat taper - if (ivt(p) >= nbrdlf_evr_shrub .and. ivt(p) <= nbrdlf_dcd_brl_shrub) then + if (woody(ivt(p)) == 2.0_r8) then taper = 10._r8 ! otherwise have a tall taper else @@ -194,7 +193,7 @@ subroutine VegStructUpdate(num_soilp, filter_soilp, & hbot(p) = max(0._r8, min(3._r8, htop(p)-1._r8)) - else if (ivt(p) >= npcropmin) then ! prognostic crops + else if (iscft(ivt(p))) then ! prognostic crops if (tlai(p) >= laimx(ivt(p))) peaklai(p) = 1 ! used in CNAllocation @@ -248,7 +247,7 @@ subroutine VegStructUpdate(num_soilp, filter_soilp, & ! adjust lai and sai for burying by snow. ! snow burial fraction for short vegetation (e.g. grasses) as in ! Wang and Zeng, 2007. - if (ivt(p) > noveg .and. ivt(p) <= nbrdlf_dcd_brl_shrub ) then + if (woody(ivt(p)) >= 1.0_r8 ) then ol = min( max(snow_depth(c)-hbot(p), 0._r8), htop(p)-hbot(p)) fb = 1._r8 - ol / max(1.e-06_r8, htop(p)-hbot(p)) else diff --git a/components/elm/src/biogeophys/CanopyFluxesMod.F90 b/components/elm/src/biogeophys/CanopyFluxesMod.F90 index 6c96e70e172d..fd6cd3ab163e 100755 --- a/components/elm/src/biogeophys/CanopyFluxesMod.F90 +++ b/components/elm/src/biogeophys/CanopyFluxesMod.F90 @@ -17,7 +17,7 @@ module CanopyFluxesMod use elm_varctl , only : use_hydrstress use elm_varpar , only : nlevgrnd, nlevsno use elm_varcon , only : namep - use pftvarcon , only : nbrdlf_dcd_tmp_shrub, nsoybean , nsoybeanirrig + use pftvarcon , only : crop, nfixer use decompMod , only : bounds_type use PhotosynthesisMod , only : Photosynthesis, PhotosynthesisTotal, Fractionation, PhotoSynthesisHydraulicStress use SoilMoistStressMod , only : calc_effective_soilporosity, calc_volumetric_h2oliq @@ -869,7 +869,8 @@ subroutine CanopyFluxes(bounds, num_nolakeurbanp, filter_nolakeurbanp, & p = filterp(f) c = veg_pp%column(p) if(.not.veg_pp%is_fates(p)) then - if (veg_pp%itype(p) == nsoybean .or. veg_pp%itype(p) == nsoybeanirrig) then + ! soybean (crop with N fixation) + if (crop(veg_pp%itype(p)) >= 1 .and. nfixer(veg_pp%itype(p)) == 1) then btran(p) = min(1._r8, btran(p) * 1.25_r8) end if @@ -909,7 +910,8 @@ subroutine CanopyFluxes(bounds, num_nolakeurbanp, filter_nolakeurbanp, & do f = 1, fn p = filterp(f) c = veg_pp%column(p) - if (veg_pp%itype(p) == nsoybean .or. veg_pp%itype(p) == nsoybeanirrig) then + ! soybean (crop with N fixation) + if (crop(veg_pp%itype(p)) >= 1 .and. nfixer(veg_pp%itype(p)) == 1) then btran(p) = min(1._r8, btran(p) * 1.25_r8) end if end do diff --git a/components/elm/src/biogeophys/PhotosynthesisMod.F90 b/components/elm/src/biogeophys/PhotosynthesisMod.F90 index 65ddbbb71553..aee433610da7 100644 --- a/components/elm/src/biogeophys/PhotosynthesisMod.F90 +++ b/components/elm/src/biogeophys/PhotosynthesisMod.F90 @@ -225,7 +225,6 @@ subroutine Photosynthesis ( bounds, fn, filterp, & !$acc routine seq use elm_varcon , only : rgas, tfrz use elm_varctl , only : carbon_only - use pftvarcon , only : nbrdlf_dcd_tmp_shrub, nsoybean, nsoybeanirrig, npcropmin use pftvarcon , only : vcmax_np1, vcmax_np2, vcmax_np3, vcmax_np4, jmax_np1, jmax_np2, jmax_np3 ! ! !ARGUMENTS: @@ -388,6 +387,7 @@ subroutine Photosynthesis ( bounds, fn, filterp, & gb_mol => photosyns_vars%gb_mol_patch , & ! Output: [real(r8) (:) ] leaf boundary layer conductance (umol H2O/m**2/s) gs_mol => photosyns_vars%gs_mol_patch , & ! Output: [real(r8) (:,:) ] leaf stomatal conductance (umol H2O/m**2/s) vcmax_z => photosyns_vars%vcmax_z_patch , & ! Output: [real(r8) (:,:) ] maximum rate of carboxylation (umol co2/m**2/s) + vcmax25_top => photosyns_vars%vcmax25_top_patch , & ! Output: [real(r8) (:) ] maximum rate of carboxylation at top canopy at 25oC (umol co2/m**2/s) cp => photosyns_vars%cp_patch , & ! Output: [real(r8) (:) ] CO2 compensation point (Pa) kc => photosyns_vars%kc_patch , & ! Output: [real(r8) (:) ] Michaelis-Menten constant for CO2 (Pa) ko => photosyns_vars%ko_patch , & ! Output: [real(r8) (:) ] Michaelis-Menten constant for O2 (Pa) @@ -789,6 +789,9 @@ subroutine Photosynthesis ( bounds, fn, filterp, & vcmax_z(p,iv) = vcmax_z(p,iv) * btran(p) lmr_z(p,iv) = lmr_z(p,iv) * btran(p) + + ! output variable + vcmax25_top(p) = vcmax25top end do ! canopy layer loop end do ! patch loop @@ -1594,7 +1597,6 @@ subroutine PhotosynthesisHydraulicStress ( bounds, fn, filterp, & use elm_varctl , only : carbon_only !use elm_varctl , only : lnc_opt, reduce_dayl_factor, vcmax_opt use elm_varpar , only : nlevsoi - use pftvarcon , only : nbrdlf_dcd_tmp_shrub, npcropmin use pftvarcon , only : vcmax_np1, vcmax_np2, vcmax_np3, vcmax_np4, jmax_np1, jmax_np2, jmax_np3 use ColumnType , only : col_pp diff --git a/components/elm/src/biogeophys/PhotosynthesisType.F90 b/components/elm/src/biogeophys/PhotosynthesisType.F90 index 59ae928c23a5..5cb94628d8d2 100644 --- a/components/elm/src/biogeophys/PhotosynthesisType.F90 +++ b/components/elm/src/biogeophys/PhotosynthesisType.F90 @@ -26,6 +26,7 @@ module PhotosynthesisType real(r8), pointer :: ag_patch (:,:) => null()! patch co-limited gross leaf photosynthesis (umol CO2/m**2/s) real(r8), pointer :: an_patch (:,:) => null()! patch net leaf photosynthesis (umol CO2/m**2/s) real(r8), pointer :: vcmax_z_patch (:,:) => null()! patch maximum rate of carboxylation (umol co2/m**2/s) + real(r8), pointer :: vcmax25_top_patch (:) => null()! patch maximum rate of carboxylation at top canopy at 25oC (umol co2/m**2/s) real(r8), pointer :: cp_patch (:) => null()! patch CO2 compensation point (Pa) real(r8), pointer :: kc_patch (:) => null()! patch Michaelis-Menten constant for CO2 (Pa) real(r8), pointer :: ko_patch (:) => null()! patch Michaelis-Menten constant for O2 (Pa) @@ -143,6 +144,7 @@ subroutine InitAllocate(this, bounds) allocate(this%ag_patch (begp:endp,1:nlevcan)) ; this%ag_patch (:,:) = spval allocate(this%an_patch (begp:endp,1:nlevcan)) ; this%an_patch (:,:) = spval allocate(this%vcmax_z_patch (begp:endp,1:nlevcan)) ; this%vcmax_z_patch (:,:) = spval + allocate(this%vcmax25_top_patch (begp:endp)) ; this%vcmax25_top_patch (:) = spval allocate(this%cp_patch (begp:endp)) ; this%cp_patch (:) = spval allocate(this%kc_patch (begp:endp)) ; this%kc_patch (:) = spval allocate(this%ko_patch (begp:endp)) ; this%ko_patch (:) = spval @@ -263,6 +265,12 @@ subroutine InitHistory(this, bounds) call hist_addfld1d (fname='PSNSHA', units='umolCO2/m^2/s', & avgflag='A', long_name='shaded leaf photosynthesis', & ptr_patch=this%psnsha_patch) + + this%vcmax25_top_patch(begp:endp) = spval + call hist_addfld1d (fname='VCMAX25TOP', units='umolCO2/m^2/s', & + avgflag='A', long_name='vcmax at top canopy at 25oC', & + ptr_patch=this%vcmax25_top_patch, default='inactive') + end if if ( use_c13 ) then @@ -423,6 +431,8 @@ subroutine TimeStepInit (this, bounds) this%psnsun_wj_patch(p) = 0._r8 this%psnsun_wp_patch(p) = 0._r8 + this%vcmax25_top_patch(p) = 0._r8 + this%psnsha_patch(p) = 0._r8 this%psnsha_wc_patch(p) = 0._r8 this%psnsha_wj_patch(p) = 0._r8 diff --git a/components/elm/src/biogeophys/SedYieldMod.F90 b/components/elm/src/biogeophys/SedYieldMod.F90 index 10b0db728149..250929f4a423 100644 --- a/components/elm/src/biogeophys/SedYieldMod.F90 +++ b/components/elm/src/biogeophys/SedYieldMod.F90 @@ -63,7 +63,7 @@ subroutine SoilErosion (bounds, num_soilc, filter_soilc, & use elm_time_manager, only : get_step_size use landunit_varcon , only : istcrop, istsoil, istice use pftvarcon , only : gcbc_p, gcbc_q, gcbr_p, gcbr_q - use pftvarcon , only : nc4_grass + use pftvarcon , only : crop, iscft ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds @@ -218,7 +218,7 @@ subroutine SoilErosion (bounds, num_soilc, filter_soilc, & (veg_cs%livecrootc(p)+veg_cs%deadcrootc(p))*croot_prof(p,1) ) fgndcov = exp( -gcbc_p(veg_pp%itype(p))*PCT_gnd - & gcbr_p(veg_pp%itype(p))*Broot ) - if( veg_pp%itype(p) > nc4_grass )then + if( crop(veg_pp%itype(p)) >= 1 .or. iscft(veg_pp%itype(p)))then Es_Pcrp = Es_Pcrp + pfactor(c) * ftillage * flitho * & fgndcov * veg_pp%wtcol(p) * K * (KE_DT+KE_LD) @@ -266,7 +266,7 @@ subroutine SoilErosion (bounds, num_soilc, filter_soilc, & nh = 0.03_r8 + 0.05_r8*max(Crsd,Clai) fsr = fsr + veg_pp%wtcol(p) * (0.03_r8/nh)**0.6_r8 - if ( veg_pp%itype(p) > nc4_grass ) then + if ( crop(veg_pp%itype(p)) >= 1 .or. iscft(veg_pp%itype(p))) then ftillage_tc = ftillage_tc + ftillage * veg_pp%wtcol(p) Es_Q = Es_Q + 19.1_r8 * qfactor(c) * 2._r8/COH * flitho * fslp * & diff --git a/components/elm/src/biogeophys/SoilTemperatureMod.F90 b/components/elm/src/biogeophys/SoilTemperatureMod.F90 index fa3e822dd2fc..d4a1074bf4a7 100644 --- a/components/elm/src/biogeophys/SoilTemperatureMod.F90 +++ b/components/elm/src/biogeophys/SoilTemperatureMod.F90 @@ -834,7 +834,7 @@ subroutine SoilThermProp (bounds, num_nolakec, filter_nolakec, & use elm_varcon , only : denh2o, denice, tfrz, tkwat, tkice, tkair, cpice, cpliq, thk_bedrock use landunit_varcon , only : istice, istice_mec, istwet use column_varcon , only : icol_roof, icol_sunwall, icol_shadewall, icol_road_perv, icol_road_imperv - use elm_varctl , only : iulog + use elm_varctl , only : iulog, use_T_rho_dependent_snowthk ! ! !ARGUMENTS: type(bounds_type) , intent(in) :: bounds @@ -847,7 +847,7 @@ subroutine SoilThermProp (bounds, num_nolakec, filter_nolakec, & type(soilstate_type) , intent(inout) :: soilstate_vars ! ! !LOCAL VARIABLES: - integer :: l,c,j ! indices + integer :: l,c,j,i ! indices integer :: nlevbed ! # levels to bedrock integer :: fc ! lake filtered column indices real(r8) :: dksat ! thermal conductivity for saturated soil (j/(k s m)) @@ -856,6 +856,17 @@ subroutine SoilThermProp (bounds, num_nolakec, filter_nolakec, & real(r8) :: satw ! relative total water content of soil. real(r8) :: zh2osfc character(len=64) :: event + + real(r8), parameter :: rho_ice = 917._r8 + real(r8) :: k_snw_vals(5) + real(r8) :: k_snw_tmps(5) + real(r8) :: k_snw_coe1(5) + real(r8) :: k_snw_coe2(5) + real(r8) :: k_snw_coe3(5) + data k_snw_tmps(:) /223.0_r8, 248.0_r8, 263.0_r8, 268.0_r8, 273.0_r8/ + data k_snw_coe1(:) /2.564_r8, 2.172_r8, 1.985_r8, 1.883_r8, 1.776_r8/ + data k_snw_coe2(:) /-0.059_r8, 0.015_r8, 0.073_r8, 0.107_r8, 0.147_r8/ + data k_snw_coe3(:) /0.0205_r8, 0.0252_r8, 0.0336_r8, 0.0386_r8, 0.0455_r8/ !----------------------------------------------------------------------- event = 'SoilThermProp' call t_start_lnd( event ) @@ -943,14 +954,39 @@ subroutine SoilThermProp (bounds, num_nolakec, filter_nolakec, & endif endif endif + + if (use_T_rho_dependent_snowthk) then ! choose which snow thermal conductivity to use + if (snl(c)+1 < 1 .AND. (j >= snl(c)+1) .AND. (j <= 0)) then + bw(c,j) = (h2osoi_ice(c,j) + h2osoi_liq(c,j)) / (frac_sno(c) * dz(c,j)) + + do i = 1, 5 + k_snw_vals(i) = k_snw_coe1(i) * (bw(c,j) / rho_ice)**2 - k_snw_coe2(i) * (bw(c,j) / rho_ice) + k_snw_coe3(i) + end do + + do i = 1, size(k_snw_tmps) - 1 + if (k_snw_tmps(i) <= t_soisno(c,j) .and. t_soisno(c,j) <= k_snw_tmps(i + 1)) then + thk(c,j) = k_snw_vals(i) + (t_soisno(c,j) - k_snw_tmps(i)) * (k_snw_vals(i + 1)-k_snw_vals(i)) / (k_snw_tmps(i + 1) - k_snw_tmps(i)) + end if + end do - ! Thermal conductivity of snow, which from Jordan (1991) pp. 18 - ! Only examine levels from snl(c)+1 -> 0 where snl(c) < 1 - if (snl(c)+1 < 1 .AND. (j >= snl(c)+1) .AND. (j <= 0)) then - bw(c,j) = (h2osoi_ice(c,j)+h2osoi_liq(c,j))/(frac_sno(c)*dz(c,j)) - thk(c,j) = tkair + (7.75e-5_r8 *bw(c,j) + 1.105e-6_r8*bw(c,j)*bw(c,j))*(tkice-tkair) - end if + ! Handle edge cases if t_soisno(c,j) is outside the given range + if (t_soisno(c,j) < k_snw_tmps(1)) then + thk(c,j) = k_snw_vals(1) + else if (t_soisno(c,j) > k_snw_tmps(size(k_snw_tmps))) then + thk(c,j) = k_snw_vals(size(k_snw_tmps)) + end if + end if + + + else + ! Thermal conductivity of snow, which from Jordan (1991) pp. 18 + ! Only examine levels from snl(c)+1 -> 0 where snl(c) < 1 + if (snl(c) + 1 < 1 .AND. (j >= snl(c) + 1) .AND. (j <= 0)) then + bw(c,j) = (h2osoi_ice(c,j) + h2osoi_liq(c,j)) / (frac_sno(c) * dz(c,j)) + thk(c,j) = tkair + (7.75e-5_r8 * bw(c,j) + 1.105e-6_r8 * bw(c,j) * bw(c,j)) * (tkice - tkair) + end if + endif end do end do diff --git a/components/elm/src/data_types/ColumnDataType.F90 b/components/elm/src/data_types/ColumnDataType.F90 index 724cefb5cfdf..d0a4a10cd3d6 100644 --- a/components/elm/src/data_types/ColumnDataType.F90 +++ b/components/elm/src/data_types/ColumnDataType.F90 @@ -7538,14 +7538,16 @@ subroutine col_cf_summary(this, bounds, num_soilc, filter_soilc, isotope) c = filter_soilc(fc) this%decomp_cpools_leached(c,l) = 0._r8 end do - do j = 1, nlev - do fc = 1,num_soilc + if(l /= i_cwd)then + do j = 1, nlev + do fc = 1,num_soilc c = filter_soilc(fc) this%decomp_cpools_leached(c,l) = & this%decomp_cpools_leached(c,l) + & this%decomp_cpools_transport_tendency(c,j,l) * dzsoi_decomp(j) - end do - end do + end do + end do + endif do fc = 1,num_soilc c = filter_soilc(fc) this%som_c_leached(c) = & @@ -9784,8 +9786,9 @@ subroutine col_nf_summary(this, bounds, num_soilc, filter_soilc) c = filter_soilc(fc) this%decomp_npools_leached(c,l) = 0._r8 end do - do j = 1, nlev - do fc = 1,num_soilc + if(l /= i_cwd)then + do j = 1, nlev + do fc = 1,num_soilc c = filter_soilc(fc) this%decomp_npools_leached(c,l) = & this%decomp_npools_leached(c,l) + & @@ -9793,8 +9796,9 @@ subroutine col_nf_summary(this, bounds, num_soilc, filter_soilc) this%bgc_npool_inputs(c,l) = this%bgc_npool_inputs(c,l) + & (this%bgc_npool_ext_inputs_vr(c,j,l)-this%bgc_npool_ext_loss_vr(c,j,l))*dzsoi_decomp(j) - end do - end do + end do + end do + endif do fc = 1,num_soilc c = filter_soilc(fc) this%som_n_leached(c) = & @@ -11314,16 +11318,16 @@ subroutine col_pf_summary(this, bounds, num_soilc, filter_soilc) c = filter_soilc(fc) this%decomp_ppools_leached(c,l) = 0._r8 end do - - do j = 1, nlevdecomp - do fc = 1,num_soilc + if(l /= i_cwd)then + do j = 1, nlevdecomp + do fc = 1,num_soilc c = filter_soilc(fc) this%decomp_ppools_leached(c,l) = & this%decomp_ppools_leached(c,l) + & this%decomp_ppools_transport_tendency(c,j,l) * dzsoi_decomp(j) - end do - end do - + end do + end do + endif do fc = 1,num_soilc c = filter_soilc(fc) this%som_p_leached(c) = & diff --git a/components/elm/src/data_types/VegetationDataType.F90 b/components/elm/src/data_types/VegetationDataType.F90 index 45dc063b8533..3bc7021f1509 100644 --- a/components/elm/src/data_types/VegetationDataType.F90 +++ b/components/elm/src/data_types/VegetationDataType.F90 @@ -17,7 +17,7 @@ module VegetationDataType use elm_varcon , only : spval, ispval, sb use elm_varcon , only : c13ratio, c14ratio use landunit_varcon , only : istsoil, istcrop - use pftvarcon , only : npcropmin, noveg, nstor + use pftvarcon , only : iscft, noveg, nstor use elm_varctl , only : iulog, use_cn, spinup_state, spinup_mortality_factor, use_fates use elm_varctl , only : nu_com, use_crop, use_c13 use elm_varctl , only : use_lch4, use_betr @@ -2447,7 +2447,7 @@ subroutine veg_cs_init(this, begp, endp, carbon_type, ratio) if (veg_vp%evergreen(veg_pp%itype(p)) == 1._r8) then this%leafc(p) = 1._r8 * ratio this%leafc_storage(p) = 0._r8 - else if (veg_pp%itype(p) >= npcropmin) then ! prognostic crop types + else if (iscft(veg_pp%itype(p))) then ! prognostic crop types this%leafc(p) = 0._r8 this%leafc_storage(p) = 0._r8 else @@ -2465,7 +2465,7 @@ subroutine veg_cs_init(this, begp, endp, carbon_type, ratio) this%livestemc_storage(p) = 0._r8 this%livestemc_xfer(p) = 0._r8 - if (veg_vp%woody(veg_pp%itype(p)) == 1._r8) then + if (veg_vp%woody(veg_pp%itype(p)) >= 1.0_r8) then this%deadstemc(p) = 0.1_r8 * ratio else this%deadstemc(p) = 0._r8 @@ -3572,7 +3572,7 @@ subroutine veg_cs_summary(this, bounds, num_soilc, filter_soilc, num_soilp, filt this%gresp_storage(p) + & this%gresp_xfer(p) - if ( crop_prog .and. veg_pp%itype(p) >= npcropmin )then + if ( crop_prog .and. iscft(veg_pp%itype(p)))then this%storvegc(p) = & this%storvegc(p) + & this%grainc_storage(p) + & @@ -3937,7 +3937,7 @@ subroutine veg_ns_init(this, begp, endp, veg_cs) ! tree types need to be initialized with some stem mass so that ! roughness length is not zero in canopy flux calculation - if (veg_vp%woody(veg_pp%itype(p)) == 1._r8) then + if (veg_vp%woody(veg_pp%itype(p)) >= 1.0_r8) then this%deadstemn(p) = veg_cs%deadstemc(p) / veg_vp%deadwdcn(veg_pp%itype(p)) else this%deadstemn(p) = 0._r8 @@ -4249,7 +4249,7 @@ subroutine veg_ns_summary(this, bounds, num_soilc, filter_soilc, num_soilp, filt this%npool(p) + & this%retransn(p) - if ( crop_prog .and. veg_pp%itype(p) >= npcropmin )then + if ( crop_prog .and. iscft(veg_pp%itype(p)))then this%dispvegn(p) = & this%dispvegn(p) + & this%grainn(p) @@ -4621,7 +4621,7 @@ subroutine veg_ps_init(this, begp, endp, veg_cs) ! tree types need to be initialized with some stem mass so that ! roughness length is not zero in canopy flux calculation - if (veg_vp%woody(veg_pp%itype(p)) == 1._r8) then + if (veg_vp%woody(veg_pp%itype(p)) >= 1.0_r8) then this%deadstemp(p) = veg_cs%deadstemc(p) / veg_vp%deadwdcp(veg_pp%itype(p)) else this%deadstemp(p) = 0._r8 @@ -4997,7 +4997,7 @@ subroutine veg_ps_summary (this, bounds, num_soilc, filter_soilc, num_soilp, fil this%ppool(p) + & this%retransp(p) - if ( crop_prog .and. veg_pp%itype(p) >= npcropmin )then + if ( crop_prog .and. iscft(veg_pp%itype(p)))then this%dispvegp(p) = & this%dispvegp(p) + & this%grainp(p) @@ -8189,7 +8189,7 @@ subroutine veg_cf_summary(this, bounds, num_soilp, filter_soilp, num_soilc, filt this%cpool_livecroot_storage_gr(p) + & this%cpool_deadcroot_storage_gr(p) - if ( crop_prog .and. veg_pp%itype(p) >= npcropmin )then + if ( crop_prog .and. iscft(veg_pp%itype(p)))then this%mr(p) = & this%mr(p) + & this%grain_mr(p) @@ -8214,7 +8214,7 @@ subroutine veg_cf_summary(this, bounds, num_soilp, filter_soilp, num_soilc, filt this%storage_gr(p) ! autotrophic respiration (AR) - if ( crop_prog .and. veg_pp%itype(p) >= npcropmin )then + if ( crop_prog .and. iscft(veg_pp%itype(p)))then this%ar(p) = & this%mr(p) + & this%gr(p) + & @@ -8324,8 +8324,7 @@ subroutine veg_cf_summary(this, bounds, num_soilp, filter_soilp, num_soilc, filt this%wood_harvestc(p) = & this%hrv_deadstemc_to_prod10c(p) + & this%hrv_deadstemc_to_prod100c(p) - - if ( crop_prog .and. veg_pp%itype(p) >= npcropmin )then + if ( crop_prog .and. iscft(veg_pp%itype(p)))then this%wood_harvestc(p) = & this%wood_harvestc(p) + & this%hrv_cropc_to_prod1c(p) @@ -8355,7 +8354,7 @@ subroutine veg_cf_summary(this, bounds, num_soilp, filter_soilp, num_soilc, filt this%m_gresp_xfer_to_fire(p) + & this%m_cpool_to_fire(p) - if ( crop_prog .and. veg_pp%itype(p) >= npcropmin )then + if ( crop_prog .and. iscft(veg_pp%itype(p)))then this%litfall(p) = & this%litfall(p) + & this%livestemc_to_litter(p) + & @@ -8394,7 +8393,7 @@ subroutine veg_cf_summary(this, bounds, num_soilp, filter_soilp, num_soilc, filt this%leafc_loss(p) = this%leafc_loss(p) + & this%hrv_leafc_to_litter(p) - if ( crop_prog .and. veg_pp%itype(p) >= npcropmin )then + if ( crop_prog .and. iscft(veg_pp%itype(p)))then this%leafc_loss(p) = & this%leafc_loss(p) + & this%hrv_leafc_to_prod1c(p) @@ -8438,7 +8437,7 @@ subroutine veg_cf_summary(this, bounds, num_soilp, filter_soilp, num_soilc, filt this%hrv_deadcrootc_storage_to_litter(p) + & this%hrv_deadcrootc_xfer_to_litter(p) ! putting the harvested crop stem and grain in the wood loss bdrewniak - if ( crop_prog .and. veg_pp%itype(p) >= npcropmin )then + if ( crop_prog .and. iscft(veg_pp%itype(p)))then this%woodc_loss(p) = & this%woodc_loss(p) + & this%hrv_grainc_to_prod1c(p) + & @@ -8563,7 +8562,7 @@ subroutine veg_cf_summary_for_ch4( this, bounds, num_soilp, filter_soilp) this%cpool_to_deadstemc(p) + & this%deadstemc_xfer_to_deadstemc(p) - if ( crop_prog .and. veg_pp%itype(p) >= npcropmin )then + if ( crop_prog .and. iscft(veg_pp%itype(p)))then this%agnpp(p) = & this%agnpp(p) + & this%cpool_to_grainc(p) + & @@ -9721,7 +9720,7 @@ subroutine veg_nf_summary(this, bounds, num_soilc, filter_soilc, num_soilp, filt this%wood_harvestn(p) = & this%hrv_deadstemn_to_prod10n(p) + & this%hrv_deadstemn_to_prod100n(p) - if ( crop_prog .and. veg_pp%itype(p) >= npcropmin )then + if ( crop_prog .and. iscft(veg_pp%itype(p)))then this%wood_harvestn(p) = & this%wood_harvestn(p) + & this%hrv_cropn_to_prod1n(p) @@ -10777,7 +10776,7 @@ subroutine veg_pf_summary(this, bounds, num_soilc, filter_soilc, num_soilp, filt this%wood_harvestp(p) = & this%hrv_deadstemp_to_prod10p(p) + & this%hrv_deadstemp_to_prod100p(p) - if ( crop_prog .and. veg_pp%itype(p) >= npcropmin )then + if ( crop_prog .and. iscft(veg_pp%itype(p)))then this%wood_harvestp(p) = & this%wood_harvestp(p) + & this%hrv_cropp_to_prod1p(p) diff --git a/components/elm/src/data_types/VegetationPropertiesType.F90 b/components/elm/src/data_types/VegetationPropertiesType.F90 index 205477791956..12f9a7b22ffa 100644 --- a/components/elm/src/data_types/VegetationPropertiesType.F90 +++ b/components/elm/src/data_types/VegetationPropertiesType.F90 @@ -17,7 +17,7 @@ module VegetationPropertiesType ! !PUBLIC TYPES: type, public :: vegetation_properties_type integer , pointer :: noveg (:) => null() ! value for not vegetated - integer , pointer :: tree (:) => null() ! tree or not? + !integer , pointer :: tree (:) => null() ! tree or not? real(r8), pointer :: smpso (:) => null() ! soil water potential at full stomatal opening (mm) real(r8), pointer :: smpsc (:) => null() ! soil water potential at full stomatal closure (mm) real(r8), pointer :: fnitr (:) => null() ! foliage nitrogen limitation factor (-) @@ -143,6 +143,13 @@ module VegetationPropertiesType real(r8), pointer :: nstor(:) => null() !Nitrogen storage pool timescale real(r8), pointer :: br_xr(:) => null() !Base rate for excess respiration real(r8), pointer :: tc_stress => null() !Critial temperature for moisture stress + ! new properties for flexible PFT + real(r8), pointer :: climatezone(:) => null() !climate zone adapted + real(r8), pointer :: nonvascular(:) => null() !nonvascular type or vascular + real(r8), pointer :: graminoid(:) => null() !graminoid or not + logical, pointer :: iscft(:) => null() !.false. = generic crop, .true. = prognostic crop + real(r8), pointer :: needleleaf(:) => null() !needleleaf or broadleaf + real(r8), pointer :: nfixer(:) => null() !cablity of nitrogen fixation from atm. N2 contains @@ -159,7 +166,7 @@ subroutine veg_vp_init(this) ! ! !USES: use elm_varpar, only : numrad, numpft - use pftvarcon , only : ntree, smpso, smpsc, fnitr + use pftvarcon , only : smpso, smpsc, fnitr use pftvarcon , only : z0mr, displar, dleaf, rhol, rhos, taul, taus, xl use pftvarcon , only : c3psn, slatop, dsladlai, leafcn, flnr, woody use pftvarcon , only : lflitcn, frootcn, livewdcn, deadwdcn, froot_leaf, stem_leaf, croot_stem @@ -181,6 +188,8 @@ subroutine veg_vp_init(this) use pftvarcon , only : fnr, act25, kcha, koha, cpha, vcmaxha, jmaxha, tpuha use pftvarcon , only : lmrha, vcmaxhd, jmaxhd, tpuhd, lmrse, qe, theta_cj use pftvarcon , only : bbbopt, mbbopt, nstor, br_xr, tc_stress, lmrhd + ! new properties for flexible PFT + use pftvarcon , only : climatezone, nonvascular, graminoid, iscft,needleleaf, nfixer ! class (vegetation_properties_type) :: this @@ -190,7 +199,7 @@ subroutine veg_vp_init(this) !------------------------------------------------------------------------ allocate(this%noveg (0:numpft)) ; this%noveg (:) =huge(1) - allocate(this%tree (0:numpft)) ; this%tree (:) =huge(1) + !allocate(this%tree (0:numpft)) ; this%tree (:) =huge(1) allocate(this%smpso (0:numpft)) ; this%smpso (:) =spval allocate(this%smpsc (0:numpft)) ; this%smpsc (:) =spval allocate(this%fnitr (0:numpft)) ; this%fnitr (:) =spval @@ -305,14 +314,23 @@ subroutine veg_vp_init(this) allocate(this%tc_stress ) !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + ! new properties for flexible PFT + allocate( this%climatezone(0:numpft)) ; this%climatezone(:) =spval + allocate( this%nonvascular(0:numpft)) ; this%nonvascular(:) =spval + allocate( this%graminoid(0:numpft)) ; this%graminoid(:) =spval + allocate( this%iscft(0:numpft)) ; this%iscft(:) =.false. + allocate( this%needleleaf(0:numpft)) ; this%needleleaf(:) =spval + allocate( this%nfixer(0:numpft)) ; this%nfixer(:) =spval + ! ----------------------------------------------------------------------------------------------------------- do m = 0,numpft - if (m <= ntree) then - this%tree(m) = 1 - else - this%tree(m) = 0 - end if + ! not needed anymore: woody(m)=1 for tree, 2 for shrub, or 0 for any other + !if (woody(m) == 1) then + ! this%tree(m) = 1 + !else + ! this%tree(m) = 0 + !end if do ib = 1,numrad this%rhol(m,ib) = rhol(m,ib) @@ -392,6 +410,13 @@ subroutine veg_vp_init(this) this%mbbopt(m) = mbbopt(m) this%nstor(m) = nstor(m) this%br_xr(m) = br_xr(m) + ! new properties for flexible PFT + this%climatezone(m) = climatezone(m) + this%nonvascular(m) = nonvascular(m) + this%graminoid(m) = graminoid(m) + this%iscft(m) = iscft(m) + this%needleleaf(m) = needleleaf(m) + this%nfixer(m) = nfixer(m) end do diff --git a/components/elm/src/data_types/VegetationType.F90 b/components/elm/src/data_types/VegetationType.F90 index a3711f7c117b..dd8bd7d842d4 100644 --- a/components/elm/src/data_types/VegetationType.F90 +++ b/components/elm/src/data_types/VegetationType.F90 @@ -33,6 +33,11 @@ module VegetationType ! 24 => irrigated soybean ! -------------------------------------------------------- ! + + ! ----------------------user-defined parameter file --------------------------------------------------------------------- + ! NOTE: if user provides own parameter file, with different 'pft_name' or order, + ! the above ilist of default PFTs will be replaced, and arrays of sizes as below will be changed as well. + use shr_kind_mod , only : r8 => shr_kind_r8 use elm_varcon , only : ispval, spval diff --git a/components/elm/src/dyn_subgrid/dynHarvestMod.F90 b/components/elm/src/dyn_subgrid/dynHarvestMod.F90 index 5256f415efe2..07455f77ec6e 100644 --- a/components/elm/src/dyn_subgrid/dynHarvestMod.F90 +++ b/components/elm/src/dyn_subgrid/dynHarvestMod.F90 @@ -202,7 +202,8 @@ subroutine CNHarvest (num_soilc, filter_soilc, num_soilp, filter_soilp, cnstate_ ! Harvest mortality routine for coupled carbon-nitrogen code (CN) ! !USES: - use pftvarcon , only : noveg, nbrdlf_evr_shrub, pprodharv10 + use pftvarcon , only : pprodharv10 + use pftvarcon , only : woody use elm_varcon , only : secspday use elm_time_manager, only : get_days_per_year use GridcellType , only : grc_pp @@ -377,7 +378,7 @@ subroutine CNHarvest (num_soilc, filter_soilc, num_soilp, filter_soilp, cnstate_ ! If this is a tree pft, then ! get the annual harvest "mortality" rate (am) from harvest array ! and convert to rate per second - if (ivt(p) > noveg .and. ivt(p) < nbrdlf_evr_shrub) then + if (woody(ivt(p)) == 1.0_r8) then if (do_harvest) then am = 0._r8 diff --git a/components/elm/src/main/controlMod.F90 b/components/elm/src/main/controlMod.F90 index 24bb855ff61a..1d8f48d7cc7d 100755 --- a/components/elm/src/main/controlMod.F90 +++ b/components/elm/src/main/controlMod.F90 @@ -285,7 +285,7 @@ subroutine control_init( ) use_nofire, use_lch4, use_vertsoilc, use_extralakelayers, & use_vichydro, use_century_decomp, use_cn, use_crop, use_snicar_frc, & use_snicar_ad, use_firn_percolation_and_compaction, use_extrasnowlayers,& - use_vancouver, use_mexicocity, use_noio + use_T_rho_dependent_snowthk, use_vancouver, use_mexicocity, use_noio ! cpl_bypass variables namelist /elm_inparm/ metdata_type, metdata_bypass, metdata_biases, & @@ -727,6 +727,7 @@ subroutine control_spmd() call mpi_bcast (use_extralakelayers, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_extrasnowlayers, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_firn_percolation_and_compaction, 1, MPI_LOGICAL, 0, mpicom, ier) + call mpi_bcast (use_T_rho_dependent_snowthk, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_vichydro, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_century_decomp, 1, MPI_LOGICAL, 0, mpicom, ier) call mpi_bcast (use_cn, 1, MPI_LOGICAL, 0, mpicom, ier) @@ -1031,6 +1032,7 @@ subroutine control_print () write(iulog,*) ' use_extralakelayers = ', use_extralakelayers write(iulog,*) ' use_extrasnowlayers = ', use_extrasnowlayers write(iulog,*) ' use_firn_percolation_and_compaction = ', use_firn_percolation_and_compaction + write(iulog,*) ' use_T_rho_dependent_snowthk = ', use_T_rho_dependent_snowthk write(iulog,*) ' use_vichydro = ', use_vichydro write(iulog,*) ' use_century_decomp = ', use_century_decomp write(iulog,*) ' use_cn = ', use_cn diff --git a/components/elm/src/main/elm_initializeMod.F90 b/components/elm/src/main/elm_initializeMod.F90 index 86e72030b946..b7fe36f24ed9 100755 --- a/components/elm/src/main/elm_initializeMod.F90 +++ b/components/elm/src/main/elm_initializeMod.F90 @@ -59,6 +59,7 @@ subroutine initialize1( ) ! !USES: use elm_varpar , only: elm_varpar_init, natpft_lb, natpft_ub use elm_varpar , only: cft_lb, cft_ub, maxpatch_glcmec + use elm_varpar , only: mxpft, numveg, mxpft_nc, numpft use elm_varpar , only: update_pft_array_bounds use elm_varpar , only: surfpft_lb, surfpft_ub use elm_varcon , only: elm_varcon_init @@ -268,10 +269,10 @@ subroutine initialize1( ) allocate (wt_lunit (begg:endg,1:max_topounits, max_lunit )) allocate (urban_valid (begg:endg,1:max_topounits )) - allocate (wt_nat_patch (begg:endg,1:max_topounits, surfpft_lb:surfpft_ub )) - allocate (wt_cft (begg:endg,1:max_topounits, cft_lb:cft_ub )) - allocate (fert_cft (begg:endg,1:max_topounits, cft_lb:cft_ub )) - allocate (fert_p_cft (begg:endg,1:max_topounits, cft_lb:cft_ub )) + !allocate (wt_nat_patch (begg:endg,1:max_topounits, surfpft_lb:surfpft_ub )) + !allocate (wt_cft (begg:endg,1:max_topounits, cft_lb:cft_ub )) + !allocate (fert_cft (begg:endg,1:max_topounits, cft_lb:cft_ub )) + !allocate (fert_p_cft (begg:endg,1:max_topounits, cft_lb:cft_ub )) if (create_glacier_mec_landunit) then allocate (wt_glc_mec (begg:endg,1:max_topounits, maxpatch_glcmec)) allocate (topo_glc_mec(begg:endg,1:max_topounits, maxpatch_glcmec)) @@ -293,6 +294,14 @@ subroutine initialize1( ) ! Independent of model resolution, Needs to stay before surfrd_get_data call pftconrd() + ! if by user-defined PFT (numbers and names), 'numpft/mxpft_nc' may be changed including other derived indices + ! + ! a few arrays allocation previously done above is moved here i.e. after this 'pftconrd' call + allocate (wt_nat_patch (begg:endg,1:max_topounits, surfpft_lb:surfpft_ub )) + allocate (wt_cft (begg:endg,1:max_topounits, cft_lb:cft_ub )) + allocate (fert_cft (begg:endg,1:max_topounits, cft_lb:cft_ub )) + allocate (fert_p_cft (begg:endg,1:max_topounits, cft_lb:cft_ub )) + call soilorder_conrd() ! Read in FATES parameter values early in the call sequence as well diff --git a/components/elm/src/main/elm_varctl.F90 b/components/elm/src/main/elm_varctl.F90 index 46b0d3c65a41..fb9ca0dbd24e 100644 --- a/components/elm/src/main/elm_varctl.F90 +++ b/components/elm/src/main/elm_varctl.F90 @@ -380,6 +380,7 @@ module elm_varctl logical, public :: use_mexicocity = .false. logical, public :: use_noio = .false. logical, public :: use_var_soil_thick = .false. + logical, public :: use_T_rho_dependent_snowthk = .false. logical, public :: use_atm_downscaling_to_topunit = .false. character(len = SHR_KIND_CS), public :: precip_downscaling_method = 'ERMM' ! Precip downscaling method values can be ERMM or FNM logical, public :: use_lake_wat_storage = .false. diff --git a/components/elm/src/main/elm_varpar.F90 b/components/elm/src/main/elm_varpar.F90 index 21e8f659210f..1f82d65ec7eb 100644 --- a/components/elm/src/main/elm_varpar.F90 +++ b/components/elm/src/main/elm_varpar.F90 @@ -48,20 +48,23 @@ module elm_varpar integer, parameter :: ndst = 4 ! number of dust size classes (BGC only) integer, parameter :: dst_src_nbr = 3 ! number of size distns in src soil (BGC only) integer, parameter :: sz_nbr = 200 ! number of sub-grid bins in large bin of dust size distribution (BGC only) - integer, parameter :: mxpft = 50 ! maximum number of PFT's for any mode; + !integer, parameter :: mxpft = 50 ! maximum number of PFT's for any mode; + integer :: mxpft = 50 ! maximum number of PFT's for any mode; + ! can be modified from reading pft-physiology in 'main/pftvarcon.F90:pftconrd' ! FIX(RF,032414) might we set some of these automatically from reading pft-physiology? integer, parameter :: numveg = 16 ! number of veg types (without specific crop) integer, parameter :: nlayer = 3 ! number of VIC soil layer --Added by AWang integer :: nlayert ! number of VIC soil layer + 3 lower thermal layers - integer :: numpft = mxpft ! actual # of patches (without bare), a total that spans LUs + integer :: numpft = 50 ! actual # of patches (without bare), a total that spans LUs integer :: numcft = 36 ! actual # of crops logical :: crop_prog = .true. ! If prognostic crops is turned on integer :: maxpatch_urb= 5 ! max number of urban patches (columns) in urban landunit integer :: mxpft_nc ! maximum number of PFT's when use_crop=False; - integer :: maxpatch_pft ! max number of plant functional types in naturally vegetated landunit (namelist setting) + integer :: maxpatch_pft ! max number of plant functional types in naturally vegetated landunit (namelist setting: maxpft) + ! This number must be exactly matched with 'natpft' in surfdata.nc integer, parameter :: nsoilorder = 15 ! number of soil orders diff --git a/components/elm/src/main/filterMod.F90 b/components/elm/src/main/filterMod.F90 index 768235bea40a..e1dde9445598 100644 --- a/components/elm/src/main/filterMod.F90 +++ b/components/elm/src/main/filterMod.F90 @@ -272,7 +272,7 @@ subroutine setFiltersOneGroup(bounds, this_filter, include_inactive, icemask_grc ! ! !USES: use decompMod , only : BOUNDS_LEVEL_CLUMP - use pftvarcon , only : npcropmin, nppercropmin + use pftvarcon , only : iscft, crop, percrop use landunit_varcon, only : istsoil, istcrop, istice_mec use column_varcon, only : icol_road_perv ! @@ -420,17 +420,17 @@ subroutine setFiltersOneGroup(bounds, this_filter, include_inactive, icemask_grc t =veg_pp%topounit(p) if (top_pp%active(t)) then if (veg_pp%active(p) .or. include_inactive) then - if (veg_pp%itype(p) < npcropmin) then + if (.not. iscft(veg_pp%itype(p))) then l =veg_pp%landunit(p) if (lun_pp%itype(l) == istsoil .or. lun_pp%itype(l) == istcrop) then fnc = fnc + 1 this_filter(nc)%soilnopcropp(fnc) = p end if else - if (veg_pp%itype(p) < nppercropmin) then + if (percrop(veg_pp%itype(p)) < 1) then fc = fc + 1 this_filter(nc)%pcropp(fc) = p - else if (veg_pp%itype(p) >= nppercropmin) then + else if (percrop(veg_pp%itype(p)) >= 1) then fpc = fpc + 1 this_filter(nc)%ppercropp(fpc) = p end if diff --git a/components/elm/src/main/pftvarcon.F90 b/components/elm/src/main/pftvarcon.F90 index 2e2a00f4b4ec..fc5bfd54e7d3 100644 --- a/components/elm/src/main/pftvarcon.F90 +++ b/components/elm/src/main/pftvarcon.F90 @@ -9,11 +9,19 @@ module pftvarcon use shr_kind_mod, only : r8 => shr_kind_r8 use shr_log_mod , only : errMsg => shr_log_errMsg use abortutils , only : endrun - use elm_varpar , only : mxpft, numrad, ivis, inir, cft_lb, cft_ub + use elm_varpar , only : mxpft, numrad, ivis, inir use elm_varpar , only: mxpft_nc use elm_varctl , only : iulog, use_vertsoilc use elm_varpar , only : nlevdecomp_full, nsoilorder use elm_varctl , only : nu_com + !------------------------------------------------------------------------------------------- + use elm_varpar , only : crop_prog + use elm_varpar , only : natpft_size, natpft_lb, natpft_ub + use elm_varpar , only : cft_size, cft_lb, cft_ub + use elm_varpar , only : surfpft_size, surfpft_lb, surfpft_ub + use elm_varpar , only : numpft, numcft, maxpatch_pft, max_patch_per_col, maxpatch_urb + use elm_varctl , only : create_crop_landunit + !------------------------------------------------------------------------------------------- ! ! !PUBLIC TYPES: implicit none @@ -107,7 +115,7 @@ module pftvarcon real(r8), allocatable :: dsladlai(:) !dSLA/dLAI [m^2/gC] real(r8), allocatable :: leafcn(:) !leaf C:N [gC/gN] real(r8), allocatable :: flnr(:) !fraction of leaf N in Rubisco [no units] - real(r8), allocatable :: woody(:) !woody lifeform flag (0 or 1) + real(r8), allocatable :: woody(:) !woody lifeform flag (0 = non-woody, 1 = tree, 2 = shrub) real(r8), allocatable :: lflitcn(:) !leaf litter C:N (gC/gN) real(r8), allocatable :: frootcn(:) !fine root C:N (gC/gN) real(r8), allocatable :: livewdcn(:) !live wood (phloem and ray parenchyma) C:N (gC/gN) @@ -116,6 +124,7 @@ module pftvarcon real(r8), allocatable :: grpnow(:) !growth respiration parameter real(r8), allocatable :: rootprof_beta(:) !CLM rooting distribution parameter for C and N inputs [unitless] + ! add pft dependent parameters for phosphorus -X.YANG real(r8), allocatable :: leafcp(:) !leaf C:P [gC/gP] real(r8), allocatable :: lflitcp(:) !leaf litter C:P (gC/gP) @@ -303,6 +312,17 @@ module pftvarcon real(r8), allocatable :: gcbr_p(:) !effectiveness of roots in reducing rainfall-driven erosion real(r8), allocatable :: gcbr_q(:) !effectiveness of roots in reducing runoff-driven erosion + ! new pft properties, together with woody, crop, percrop, evergreen, stress_decid, season_decid, defined above, + ! are introduced to define vegetation properties. This will be well defineing a pft so that no indices needed for codes. + real(r8), allocatable :: climatezone(:) ! distributed climate zone (0 = any zone, 1 = tropical, 2 = temperate, 3 = boreal, 4 = arctic) + real(r8), allocatable :: nonvascular(:) ! nonvascular lifeform flag (0 = vascular, 1 = moss, 2 = lichen) + real(r8), allocatable :: needleleaf(:) ! needleleaf lifeform flag (0 = broadleaf, 1 = needleleaf) + real(r8), allocatable :: graminoid(:) ! graminoid lifeform flag (0 = nonvascular+woody+crop+percrop, 1 = graminoid) + logical , allocatable :: iscft(:) ! crop function type flag (.false. = non_crop or generic crop, i.e. crop when use_crop=false, .true. = prognostic crop with cft created) + real(r8), allocatable :: temp_iscft(:) ! for file read, translated to logical afterwards + real(r8), allocatable :: nfixer(:) ! nitrogen fixer flag (0 = inable, 1 = able to nitrogen fixation from atm. N2) + + ! ! !PUBLIC MEMBER FUNCTIONS: public :: pftconrd ! Read and initialize vegetation (PFT) constants @@ -347,6 +367,10 @@ subroutine pftconrd integer :: dimid ! netCDF dimension id integer :: npft ! number of pfts on pft-physiology file logical :: readv ! read variable in or not + logical :: PFT_DEFAULT ! pft names are default, i.e. NOT user-defined + integer :: ncft0, ncft ! crop pft index of first/last when 'create_crop_landunit' is true + integer :: noncropmax ! max non-crop pft index (to check when 'create_crop_landunit' is true) + real(r8) :: local_iscft ! a local transfer of iscft from logical to integer for use in error checks character(len=32) :: subname = 'pftconrd' ! subroutine name ! ! Expected PFT names: The names expected on the paramfile file and the order they are expected to be in. @@ -410,6 +434,24 @@ subroutine pftconrd expected_pftnames(49) = 'willow ' expected_pftnames(50) = 'irrigated_willow ' + ! read actual 'npft' from parameter file + if (masterproc) then + write(iulog,*) 'Attempting to read PFT physiological data .....' + end if + call getfil (paramfile, locfn, 0) + call ncd_pio_openfile (ncid, trim(locfn), 0) + call ncd_inqdid(ncid,'pft',dimid) + call ncd_inqdlen(ncid,dimid,npft) + + ! now 'mxpft' in 'elm_varpar' updated by npft here + mxpft = npft - 1 + mxpft_nc = npft - 1 ! when .not.use_crop, so here temporarily set and may be changed after read-through PFT-physiology + + ! NOTES: + ! In parameter file, 'npft' (mxpft) [number of pfts in parameter file] can be greater than 'maxpatch_pft' [number of pfts in surfdata file] which also set by namelist 'maxpft', + ! but cannot be less, i.e. there cannot be more pfts in the surface file than there are set of pft parameters, if running the non-crop version of model. + if (npft mxpft_nc) EXIT ! exit the do loop + if(.not. use_fates)then if ( trim(adjustl(pftname(i))) /= trim(expected_pftnames(i)) )then write(iulog,*)'pftconrd: pftname is NOT what is expected, name = ', & trim(pftname(i)), ', expected name = ', trim(expected_pftnames(i)) call endrun(msg='pftconrd: bad name for pft on paramfile dataset'//errMsg(__FILE__, __LINE__)) end if + end if if ( trim(pftname(i)) == 'not_vegetated' ) noveg = i if ( trim(pftname(i)) == 'needleleaf_evergreen_temperate_tree' ) ndllf_evr_tmp_tree = i @@ -1103,12 +1231,210 @@ subroutine pftconrd nppercropmax = nwillowirrig ! last prognostic perennial crop in list end if + !------------------------------------------------------------------------------------------- + ! default: for tree and shrub always 1, now hard-coded as following + woody(ndllf_evr_tmp_tree:nbrdlf_dcd_brl_tree) = 1 + woody(nbrdlf_evr_shrub:nbrdlf_dcd_brl_shrub) = 2 + + ! the following is initialized as 0 above for all PFT. + ! here the hard-coded values (or flags) for default ELM PFT physiology will be working as original + ! when not using those indexing of PFT orders anymore in other codes than here. + needleleaf(noveg+1:ndllf_dcd_brl_tree) = 1 + graminoid(nc3_arctic_grass:nc4_grass) = 1 + iscft(npcropmin:max(npcropmax,nppercropmax)) = .true. + nfixer(nsoybean) = 1 + nfixer(nsoybeanirrig) = 1 + + climatezone(ndllf_evr_tmp_tree) = 2 + climatezone(ndllf_evr_brl_tree) = 3 + climatezone(ndllf_dcd_brl_tree) = 3 + climatezone(nbrdlf_evr_trp_tree) = 1 + climatezone(nbrdlf_evr_tmp_tree) = 2 + climatezone(nbrdlf_dcd_trp_tree) = 1 + climatezone(nbrdlf_dcd_tmp_tree) = 2 + climatezone(nbrdlf_dcd_brl_tree) = 3 + climatezone(nbrdlf_dcd_tmp_shrub)= 2 + climatezone(nbrdlf_dcd_brl_shrub)= 3 + climatezone(nc3_arctic_grass) = 4 + !------------------------------------------------------------------------------------------- + + + ! NOT default PFT file + else + + ! not vegetated checking + noveg = -1 + + ! when user-defined PFTs, if crop included, it must be the default way: + ! cropts must be in one block and after nat-pft if 'create_crop_landunit' or 'use_crop' is true + npcropmin = -1 ! first prognostic crop + npcropmax = -1 ! last prognostic crop in list + nppercropmin = -1 ! first prognostic perennial crop + nppercropmax = -1 ! last prognostic perennial crop in list + + numcft = 0 + ncft = -1 + ncft0 = -1 + noncropmax = 0 + do i = 0, npft-1 + if (crop(i)>=1 .or. percrop(i)>=1 .or. iscft(i)) then + numcft = numcft + 1 ! includes generic_crop, while cft_size NOT (???? todo checking) + + if(use_crop) then + + ! the following assumes that all crop pfts are in a block + + ! if 'generic crop' (crop=1) specifically flagged by iscft=.false. + ! 'crop' will not be counted into prognostic + if (crop(i)>=1 .and. iscft(i)) then + npcropmax = i + if(npcropmin<=0) npcropmin = i + end if + + ! NOTE: there is a misunderstanding in pft physiology parameter file: 'perennial crop' IS NOT 'crop', + ! but still counted into 'numcft' + if(percrop(i)==1) then + nppercropmax = i + if(nppercropmin<=0) nppercropmin = i + end if + + else + if(crop(i)>=1 .or. percrop(i)>=1) then + ! in case either 'crop' or 'generic crop' or both defined, it must be generic, when not use_crop=.true. + iscft(i) = .false. + end if + end if + + ! + if (create_crop_landunit) then + ! make sure all crop-pft are in one block and following nat-pft SO THAT creating crop landunit is possible + ncft = ncft + 1 + if (ncft0<0) ncft0=i + end if + + ! + else if (create_crop_landunit) then + noncropmax = i + + end if + + ! need to check 'noveg' + if ( woody(i)<=0 .and. graminoid(i)<=0 .and. nonvascular(i)<=0 .and. & + .not. iscft(i) .and. crop(i)<=0 .and. percrop(i)<=0) then + if (noveg>=0) then + ! not yet support multiple non-vegetated PFT + ! this also will catch error of no actual PFT if npft>1 + call endrun(msg=' ERROR: more than 1 not vegetated in physiology parameter nc file.'//errMsg(__FILE__, __LINE__)) + else + noveg = i + end if + end if + + ! + end do + + ! make sure non-generic crop indices always beyond natural-pft, even if not available - used in filterMod.F90) + if (npcropmin < 0 .and. npcropmax < 0) then + npcropmin = npft + npcropmax = npft + end if + + ! MUST re-do some constants which already set in 'elm_varpar.F90:elm_varpar_init()' + mxpft_nc = min(maxpatch_pft,npft) - 1 ! user-defined is what max. + numpft = min(maxpatch_pft,npft) - 1 ! actual # of patches (without bare) + + if (create_crop_landunit) then + if (ncft0 /= noncropmax+1) then + call endrun(msg=' ERROR: when create_crop_landunit is true, crop must be following non-crop PFT .'//errMsg(__FILE__, __LINE__)) + end if + if (ncft /= npft-1) then + call endrun(msg=' ERROR: when create_crop_landunit is true, last crop must be the last one of all PFTs .'//errMsg(__FILE__, __LINE__)) + end if + + natpft_size = (numpft + 1) - numcft ! note that numpft doesn't include bare ground -- thus we add 1 + cft_size = numcft + else + natpft_size = numpft + 1 ! note that numpft doesn't include bare ground -- thus we add 1 + cft_size = 0 + end if + natpft_lb = 0 + natpft_ub = natpft_lb + natpft_size - 1 + cft_lb = natpft_ub + 1 + cft_ub = max(cft_lb, cft_lb + cft_size - 1) ! NOTE: if cft_size is ZERO, could be issue (but so far so good) + surfpft_lb = natpft_lb + surfpft_ub = natpft_ub + surfpft_size = natpft_size + max_patch_per_col= max(numpft+1, numcft, maxpatch_urb) + + + end if ! end if 'PFT_DEFAULT' + + ! checking of pft flags' conflict + if ( .not. use_fates ) then + do i = 0, mxpft + if (iscft(i)) local_iscft = 1._r8 + if (.not. iscft(i)) local_iscft = 0._r8 + if (i == noveg) then + if ( (nonvascular(i)+woody(i)+graminoid(i)+max(local_iscft,crop(i)+percrop(i))) >= 1 .or. & + (needleleaf(i)+evergreen(i)+stress_decid(i)+season_decid(i)+nfixer(i)) >= 1 ) then + print *, 'ERROR: Incorrect not-vegetated PFT flags: ', i, ' ', trim(pftname(i)) + call endrun(msg=' ERROR: not_vegetated has at least one positive PFT flag '//errMsg(__FILE__, __LINE__)) + end if + + else if ( (nonvascular(i)+woody(i)+graminoid(i)+max(local_iscft,crop(i)+percrop(i))) >= 1) then + if (nonvascular(i) >= 1 .and. (woody(i)+graminoid(i)+max(local_iscft,crop(i)+percrop(i))) >= 1) then + print *, 'ERROR: Incorrect nonvasculr PFT flags: ', i, ' ', trim(pftname(i)) + call endrun(msg=' ERROR: nonvascular PFT cannot be any of woody/graminoid/crop type '//errMsg(__FILE__, __LINE__)) + else if (woody(i) >= 1 .and. (nonvascular(i)+graminoid(i)+max(local_iscft,crop(i)+percrop(i))) >= 1) then + print *, 'ERROR: Incorrect woody PFT flags: ', i, ' ', trim(pftname(i)) + call endrun(msg=' ERROR: woody PFT cannot be any of nonvascular/graminoid/crop type - '//errMsg(__FILE__, __LINE__)) + else if (graminoid(i) >= 1 .and. (nonvascular(i)+woody(i)+max(local_iscft,crop(i)+percrop(i))) >=1 ) then + print *, 'ERROR: Incorrect graminoid PFT flags: ', i, ' ', trim(pftname(i)) + call endrun(msg=' ERROR: graminoid PFT cannot be any of nonvascular/woody/crop type - '//errMsg(__FILE__, __LINE__)) + else if ( (max(local_iscft,crop(i)+percrop(i))) >= 1 .and. (nonvascular(i)+woody(i)+graminoid(i)) >= 1) then + print *, 'ERROR: Incorrect crop PFT flags: ', i, ' ', trim(pftname(i)) + call endrun(msg=' ERROR: crop PFT cannot be any of nonvascular/woody/graminoid type - '//errMsg(__FILE__, __LINE__)) + end if + + if( (stress_decid(i)*season_decid(i)) >= 1 ) then + print *, 'ERROR: Incorrect stress_decid or season_decid flags: ', i, ' ', trim(pftname(i)) + call endrun(msg=' ERROR: stress_decid AND season_decid cannot be both 1 - '//errMsg(__FILE__, __LINE__)) + elseif( (evergreen(i)*(stress_decid(i)+season_decid(i)) ) >= 1 ) then + print *, 'ERROR: Incorrect evergreen AND season_/stress_decid flags: ', i, ' ', trim(pftname(i)) + call endrun(msg=' ERROR: evergreen AND (stress_decid OR season_decid) cannot be both 1 - '//errMsg(__FILE__, __LINE__)) + end if + + else + + call endrun(msg=' ERROR: not_vegetated AND none of vegetation type for PFT - '//errMsg(__FILE__, __LINE__)) + + end if + + end do + end if + + ! information + if (masterproc) then + write(iulog,*) + write(iulog,*) 'Using PFT physiological parameters from: ', paramfile + write(iulog,*) ' -- index -- name -- climate zone -- -- woody -- -- needleleaf -- -- evergreen -- -- stress_decid -- -- season_decid -- -- graminoid-- -- iscft -- -- crop -- -- perennial crop -- -- nfixer --' + do i = 0, npft-1 + write(iulog,*) i, pftname(i), int(climatezone(i)), int(woody(i)), int(needleleaf(i)), & + int(evergreen(i)), int(stress_decid(i)), int(season_decid(i)), & + int(graminoid(i)), int(temp_iscft(i)), int(crop(i)), int(percrop(i)), int(nfixer(i)) + end do + write(iulog,*) + end if + + + !------------------------------------------------------------------------------------------- + call set_is_pft_known_to_model() - call set_num_cfts_known_to_model() + if (cft_size>0) call set_num_cfts_known_to_model() if( .not. use_fates ) then if( .not. use_crop) then - if ( npcropmax /= mxpft_nc )then + if ( npcropmax /= mxpft_nc .and. crop_prog)then call endrun(msg=' ERROR: npcropmax is NOT the last value'//errMsg(__FILE__, __LINE__)) end if else @@ -1118,6 +1444,7 @@ subroutine pftconrd end if do i = 0, mxpft if(.not. use_crop .and. i > mxpft_nc) EXIT ! exit the do loop + if(.not.PFT_DEFAULT) EXIT ! no checking of indexing PFTs for user-defined if( .not. use_crop) then if ( irrigated(i) == 1.0_r8 .and. (i == nc3irrig .or. & i == ncornirrig .or. & diff --git a/components/elm/src/main/surfrdMod.F90 b/components/elm/src/main/surfrdMod.F90 index 9cbcd4b2b8e0..a8146e5a0f15 100755 --- a/components/elm/src/main/surfrdMod.F90 +++ b/components/elm/src/main/surfrdMod.F90 @@ -1105,6 +1105,8 @@ subroutine surfrd_pftformat( begg, endg, ncid ) end if fert_p_cft = 0.0_r8 + wt_nat_patch(begg:endg, :, :) = 0.0_r8 + wt_cft(begg:endg, :, :) = 0.0_r8 if (.not. create_crop_landunit) then call ncd_io(ncid=ncid, varname='PCT_NAT_PFT', flag='read', data=wt_nat_patch, & dim1name=grlnd, readvar=readvar) @@ -1263,6 +1265,8 @@ subroutine surfrd_veg_all(begg, endg, ncid, ns,ntpu) do nl = begg,endg do t = 1, max_topounits + ! (TODO) the following assumes that rainfed/irrigated crop are ordered side by side + ! indexing is fixed wt_cft(nl,t,nc3crop) = wt_cft(nl,t,nc3crop) + wt_cft(nl,t,nc3irrig) wt_cft(nl,t,nc3irrig) = 0._r8 wt_cft(nl,t,ncorn) = wt_cft(nl,t,ncorn) + wt_cft(nl,t,ncornirrig) @@ -1702,7 +1706,12 @@ subroutine surfrd_get_topo_for_solar_rad(domain,filename) call ncd_io(ncid=ncid, varname='STDEV_ELEV', flag='read', data=domain%stdev_elev, & dim1name=grlnd, readvar=readvar) - if (.not. readvar) call endrun( trim(subname)//' ERROR: STDEV_ELEV NOT on fsurdat file' ) + if (.not. readvar) then + write(iulog,*) trim(subname),' WARNING: STDEV_ELEV NOT on fsurdat file. Try to use STD_ELEV instead.' + call ncd_io(ncid=ncid, varname='STD_ELEV', flag='read', data=domain%stdev_elev, & + dim1name=grlnd, readvar=readvar) + if (.not. readvar) call endrun( trim(subname)//' ERROR: BOTH STD_ELEV and STDEV_ELEV NOT on fsurdat file' ) + endif call ncd_io(ncid=ncid, varname='SKY_VIEW', flag='read', data=domain%sky_view, & dim1name=grlnd, readvar=readvar) if (.not. readvar) call endrun( trim(subname)//' ERROR: SKY_VIEW NOT on fsurdat file' ) diff --git a/components/elm/src/main/surfrdUtilsMod.F90 b/components/elm/src/main/surfrdUtilsMod.F90 index a32570c15a29..2c1e42559dac 100644 --- a/components/elm/src/main/surfrdUtilsMod.F90 +++ b/components/elm/src/main/surfrdUtilsMod.F90 @@ -20,7 +20,7 @@ module surfrdUtilsMod ! !PUBLIC MEMBER FUNCTIONS: public :: check_sums_equal_1_3d ! Confirm that sum(arr(n,t,:)) == 1 for all n public :: check_sums_equal_1_2d ! Confirm that sum(arr(n,:)) == 1 for all n - public :: convert_cft_to_pft ! Conversion of crop CFT to natural veg PFT:w + public :: convert_cft_to_pft ! Conversion of crop CFT to natural veg PFT public :: collapse_crop_types ! Collapse unused crop types into types used in this run public :: collapse_crop_var ! Collapse crop variables according to cft weights determined in previous "collapse" subroutines public :: convert_pft_to_cft ! Conversion of crops from natural veg to CFT @@ -36,7 +36,7 @@ subroutine check_sums_equal_1_3d(arr, lb, name, caller) ! Confirm that sum(arr(n,:)) == 1 for all n. If this isn't true for any n, abort with a message. ! ! Uses - use topounit_varcon, only : max_topounits, has_topounit + use topounit_varcon, only : max_topounits ! !ARGUMENTS: integer , intent(in) :: lb ! lower bound of the first dimension of arr @@ -123,21 +123,22 @@ subroutine convert_cft_to_pft( begg, endg, cftsize, wt_cft ) ! a crop landunit, and put them on the vegetated landunit. ! !USES: use elm_varsur , only : wt_lunit, wt_nat_patch - use elm_varpar , only : cft_size, surfpft_size - use pftvarcon , only : nc3crop + use elm_varpar , only : cft_size + use elm_varpar , only : natpft_size use landunit_varcon , only : istsoil, istcrop use topounit_varcon , only : max_topounits ! !ARGUMENTS: implicit none integer , intent(in) :: begg, endg - integer , intent(in) :: cftsize ! CFT size + integer , intent(in) :: cftsize ! CFT size ! this could be wrong if by input real(r8) , intent(inout) :: wt_cft(begg:,:,:) ! CFT weights ! ! !LOCAL VARIABLES: integer :: g, t ! index !----------------------------------------------------------------------- - SHR_ASSERT_ALL((ubound(wt_cft ) == (/endg,max_topounits, cftsize /)), errMsg(__FILE__, __LINE__)) - SHR_ASSERT_ALL((ubound(wt_nat_patch) == (/endg,max_topounits, nc3crop+cftsize-1/)), errMsg(__FILE__, __LINE__)) + ! note (01-29-2024 by fmyuan@ornl.gov, cftsize --> elm_varpar:cft_size) + SHR_ASSERT_ALL((ubound(wt_cft ) == (/endg,max_topounits, cft_size /)), errMsg(__FILE__, __LINE__)) + SHR_ASSERT_ALL((ubound(wt_nat_patch) == (/endg,max_topounits, natpft_size+cft_size/)), errMsg(__FILE__, __LINE__)) do g = begg, endg do t = 1, max_topounits @@ -145,12 +146,12 @@ subroutine convert_cft_to_pft( begg, endg, cftsize, wt_cft ) ! Move CFT over to PFT and do weighted average of the crop and soil parts wt_nat_patch(g,t,:) = wt_nat_patch(g,t,:) * wt_lunit(g,t,istsoil) wt_cft(g,t,:) = wt_cft(g,t,:) * wt_lunit(g,t,istcrop) - wt_nat_patch(g,t,nc3crop:) = wt_cft(g,t,:) ! Add crop CFT's to end of natural veg PFT's - wt_lunit(g,t,istsoil) = (wt_lunit(g,t,istsoil) + wt_lunit(g,t,istcrop)) ! Add crop landunit to soil landunit + wt_nat_patch(g,t,natpft_size:) = wt_cft(g,t,:) ! Add crop CFT's to end of natural veg PFT's + wt_lunit(g,t,istsoil) = (wt_lunit(g,t,istsoil) + wt_lunit(g,t,istcrop)) ! Add crop landunit to soil landunit wt_nat_patch(g,t,:) = wt_nat_patch(g,t,:) / wt_lunit(g,t,istsoil) - wt_lunit(g,t,istcrop) = 0.0_r8 ! Zero out crop CFT's + wt_lunit(g,t,istcrop) = 0.0_r8 ! Zero out crop CFT's else - wt_nat_patch(g,t,nc3crop:) = 0.0_r8 ! Make sure generic crops are zeroed out + wt_nat_patch(g,t,natpft_size:) = 0.0_r8 ! Make sure generic crops are zeroed out end if end do end do @@ -169,9 +170,7 @@ subroutine convert_pft_to_cft( begg, endg ) ! the new crop landunit ! !USES: use elm_varsur , only : wt_lunit, wt_nat_patch, wt_cft - use elm_varpar , only : cft_size, surfpft_size use elm_varpar , only : cft_size, cft_lb, cft_ub, surfpft_lb, surfpft_ub - use pftvarcon , only : nc3crop use landunit_varcon , only : istsoil, istcrop use topounit_varcon , only : max_topounits ! !ARGUMENTS: @@ -261,7 +260,6 @@ subroutine collapse_crop_var(crop_var, begg, endg) use elm_varpar, only: cft_lb, cft_ub, cft_size use pftvarcon , only: is_pft_known_to_model use topounit_varcon , only : max_topounits ! TKT - use GridcellType, only : grc_pp ! ! !ARGUMENTS: ! Use begg and endg rather than 'bounds', because bounds may not be @@ -309,10 +307,9 @@ subroutine collapse_crop_types(wt_cft, fert_cft, fert_p_cft, begg, endg, verbose ! !USES: use elm_varctl , only : irrigate use elm_varpar , only : cft_lb, cft_ub, cft_size - use pftvarcon , only : nc3crop, nc3irrig, npcropmax, mergetoelmpft use pftvarcon , only: is_pft_known_to_model - use topounit_varcon , only : max_topounits ! TKT - use GridcellType , only : grc_pp ! TKT + use pftvarcon , only : npcropmax, mergetoelmpft + use topounit_varcon , only : max_topounits ! ! !ARGUMENTS: @@ -323,16 +320,15 @@ subroutine collapse_crop_types(wt_cft, fert_cft, fert_p_cft, begg, endg, verbose ! Weight and fertilizer of each CFT in each grid cell; dimensioned [g, cft_lb:cft_ub] ! This array is modified in-place - real(r8), intent(inout) :: wt_cft(begg:,1:, cft_lb:) !TKT - real(r8), intent(inout) :: fert_cft(begg:,1:, cft_lb:) !TKT + real(r8), intent(inout) :: wt_cft(begg:,1:, cft_lb:) + real(r8), intent(inout) :: fert_cft(begg:,1:, cft_lb:) real(r8), intent(inout) :: fert_p_cft(begg:, 1:, cft_lb:) logical, intent(in) :: verbose ! If true, print some extra information ! ! !LOCAL VARIABLES: - integer :: g, t,t2 ! TKT + integer :: g, t,t2 integer :: m - !integer, allocatable :: ntpu(:) ! To store number of topounits per grid TKT real(r8) :: wt_cft_to real(r8) :: wt_cft_from real(r8) :: wt_cft_merge @@ -340,7 +336,7 @@ subroutine collapse_crop_types(wt_cft, fert_cft, fert_p_cft, begg, endg, verbose character(len=*), parameter :: subname = 'collapse_crop_types' !----------------------------------------------------------------------- - SHR_ASSERT_ALL((ubound(wt_cft) == (/endg,max_topounits, cft_ub/)), errMsg(__FILE__, __LINE__)) ! TKT + SHR_ASSERT_ALL((ubound(wt_cft) == (/endg,max_topounits, cft_ub/)), errMsg(__FILE__, __LINE__)) SHR_ASSERT_ALL((ubound(fert_cft) == (/endg,max_topounits, cft_ub/)), errMsg(__FILE__, __LINE__)) SHR_ASSERT_ALL((ubound(fert_p_cft) == (/endg,max_topounits, cft_ub/)), errMsg(__FILE__, __LINE__)) @@ -353,14 +349,12 @@ subroutine collapse_crop_types(wt_cft, fert_cft, fert_p_cft, begg, endg, verbose ! ------------------------------------------------------------------------ ! If not using irrigation, merge irrigated CFTs into rainfed CFTs ! ------------------------------------------------------------------------ - !allocate(ntpu(begg:endg)) if (.not. irrigate) then if (verbose .and. masterproc) then write(iulog,*) trim(subname)//' crop=.T. and irrigate=.F., so merging irrigated pfts with rainfed' end if do g = begg, endg - !ntpu(g) = grc_pp%ntopounits(g) ! Left Hand Side: merged rainfed+irrigated crop pfts from nc3crop to ! npcropmax-1, stride 2 ! Right Hand Side: rainfed crop pfts from nc3crop to npcropmax-1, @@ -369,14 +363,14 @@ subroutine collapse_crop_types(wt_cft, fert_cft, fert_p_cft, begg, endg, verbose ! stride 2 ! where stride 2 means "every other" - do t = 1,max_topounits - wt_cft(g,t, nc3crop:npcropmax-1:2) = & - wt_cft(g,t, nc3crop:npcropmax-1:2) + wt_cft(g,t, nc3irrig:npcropmax:2) ! TKT - wt_cft(g,t, nc3irrig:npcropmax:2) = 0._r8 - end do ! TKT + do t2 = 1, max_topounits + wt_cft(g,t2, cft_lb:cft_ub-1:2) = & + wt_cft(g,t2, cft_lb:cft_ub-1:2) + wt_cft(g,t2, cft_lb+1:cft_ub:2) + wt_cft(g,t2, cft_lb+1:cft_ub:2) = 0._r8 + end do end do - call check_sums_equal_1_3d(wt_cft, begg, 'wt_cft', subname//': irrigation') ! TKT + call check_sums_equal_1_3d(wt_cft, begg, 'wt_cft', subname//': irrigation') end if ! ------------------------------------------------------------------------ @@ -410,8 +404,7 @@ subroutine collapse_crop_types(wt_cft, fert_cft, fert_p_cft, begg, endg, verbose end do end do - call check_sums_equal_1_3d(wt_cft, begg, 'wt_cft', subname//': mergetoelmpft') ! TKT - !deallocate(ntpu) + call check_sums_equal_1_3d(wt_cft, begg, 'wt_cft', subname//': mergetoelmpft') end subroutine collapse_crop_types end module surfrdUtilsMod diff --git a/components/elm/tools/interpinic/src/fmain.F90 b/components/elm/tools/interpinic/src/fmain.F90 index 0f55c12c67c9..a67e6e2627fb 100644 --- a/components/elm/tools/interpinic/src/fmain.F90 +++ b/components/elm/tools/interpinic/src/fmain.F90 @@ -14,7 +14,7 @@ program fmain character(len= 256) :: arg integer :: n !index integer :: nargs !number of arguments - integer, external :: iargc !number of arguments function + integer :: iargc !number of arguments function character(len=256) :: finidati !input initial dataset to read character(len=256) :: finidato !output initial dataset to create character(len=256) :: cmdline !input command line diff --git a/components/elm/tools/interpinic/src/interpinic.F90 b/components/elm/tools/interpinic/src/interpinic.F90 index b75afd3a411d..3d890a14b895 100644 --- a/components/elm/tools/interpinic/src/interpinic.F90 +++ b/components/elm/tools/interpinic/src/interpinic.F90 @@ -146,9 +146,19 @@ subroutine interp_filei (fin, fout, cmdline) call check_ret (nf90_open(fin, NF90_NOWRITE, ncidi )) call check_ret (nf90_open(fout, NF90_NOWRITE, ncido )) call check_ret (nf_inq_format( ncido, ncformat )) - if ( ncformat /= NF_FORMAT_64BIT )then - write (6,*) 'error: output file is NOT in NetCDF large-file format!' - stop + + ! Allow any format for output dataset + + if ( ncformat == NF_FORMAT_CLASSIC )then + write (6,*) 'info: output file is NF_FORMAT_CLASSIC' + else if ( ncformat == NF_FORMAT_64BIT_OFFSET )then + write (6,*) 'info: output file is NF_FORMAT_64BIT_OFFSET' + else if ( ncformat == NF_FORMAT_64BIT_DATA )then + write (6,*) 'info: output file is NF_FORMAT_64BIT_DATA' + else if ( ncformat == NF_FORMAT_NETCDF4 )then + write (6,*) 'info: output file is NF_FORMAT_NETCDF4' + else if ( ncformat == NF_FORMAT_NETCDF4_CLASSIC )then + write (6,*) 'info: output file is NF_FORMAT_NETCDF4_CLASSIC' end if call check_ret (nf90_inq_dimid(ncidi, "column", dimidcols )) @@ -214,12 +224,25 @@ subroutine interp_filei (fin, fout, cmdline) ret = nf90_inq_dimid(ncidi, "month", dimidmon) if (ret == NF90_NOERR) then call check_ret (nf90_inquire_dimension(ncidi, dimidmon, len=nlevmon)) - call check_ret (nf90_inq_dimid(ncido, "month", dimid )) - call check_ret (nf90_inquire_dimension(ncido, dimid, len=dimlen)) - if (dimlen/=nlevmon) then - write (6,*) 'error: input and output nlevmon values disagree' - write (6,*) 'input nlevmon = ',nlevmon,' output nlevmon = ',dimlen - stop + + ! Many restart files have "month" dimension in input dataset + ! It is only necessary that the output dataset contains "month" dimension + ! when a variable in the input dataset contains the "month" dimension + ! Otherwise, the "month" dimension will never be used + ! Warn rather than die when input has "month" and output does not + + ret = nf90_inq_dimid(ncido, "month", dimid ) + if ( ret == nf_ebaddim ) then + write (6,*) 'warning: input has "month" dimension and output does not' + write (6,*) 'warning: interpolation will fail if any input variable uses "month" dimension' + write (6,*) 'chill: many times the "month" dimension is superfluous so this might work...' + else + call check_ret (nf90_inquire_dimension(ncido, dimid, len=dimlen)) + if (dimlen/=nlevmon) then + write (6,*) 'error: input and output nlevmon values disagree' + write (6,*) 'input nlevmon = ',nlevmon,' output nlevmon = ',dimlen + stop + end if end if else write (6,*) 'month dimension does NOT exist on the input dataset' @@ -321,7 +344,9 @@ subroutine interp_filei (fin, fout, cmdline) ! OK now, open the output file for writing ! call check_ret(nf90_close( ncido)) - call check_ret (nf90_open(fout, ior(NF90_WRITE, NF_64BIT_OFFSET), ncido )) + + ! Allow any format for output dataset + call check_ret (nf90_open(fout, NF90_WRITE, ncido )) call addglobal (ncido, cmdline) @@ -1503,8 +1528,7 @@ subroutine addglobal (ncid, cmdline) character(len=10) :: time character(len= 5) :: zone character(len=18) :: datetime - character(len=256):: version = & - "$HeadURL: https://svn-ccsm-models.cgd.ucar.edu/clm2/trunk_tags/clm4_5_1_r085/models/lnd/clm/tools/clm4_5/interpinic/src/interpinic.F90 $" + character(len=256):: version = "" character(len=256) :: revision_id = "$Id: interpinic.F90 54953 2013-11-06 16:29:45Z sacks $" character(len=16) :: logname character(len=16) :: hostname diff --git a/components/elm/tools/interpinic/src/shr_infnan_mod.F90 b/components/elm/tools/interpinic/src/shr_infnan_mod.F90 index 638cad84d20e..31ffb1dff329 100644 --- a/components/elm/tools/interpinic/src/shr_infnan_mod.F90 +++ b/components/elm/tools/interpinic/src/shr_infnan_mod.F90 @@ -2,11 +2,11 @@ module shr_infnan_mod -!! Inf_NaN_Detection module +!! Inf_NaN_Detection module !! Copyright(c) 2003, Lahey Computer Systems, Inc. -!! Copies of this source code, or standalone compiled files +!! Copies of this source code, or standalone compiled files !! derived from this source may not be sold without permission -!! from Lahey Computers Systems. All or part of this module may be +!! from Lahey Computers Systems. All or part of this module may be !! freely incorporated into executable programs which are offered !! for sale. Otherwise, distribution of all or part of this file is !! permitted, provided this copyright notice and header are included. @@ -22,12 +22,12 @@ module shr_infnan_mod !! isneginf(x) - test for a negative "infinite" value !! !! Each function accepts a single or double precision real argument, and -!! returns a true or false value to indicate the presence of the value +!! returns a true or false value to indicate the presence of the value !! being tested for. If the argument is array valued, the function returns !! a conformable logical array, suitable for use with the ANY function, or !! as a logical mask. !! -!! Each function operates by transferring the bit pattern from a real +!! Each function operates by transferring the bit pattern from a real !! variable to an integer container. Unless testing for + or - infinity, !! the sign bit is cleared to zero. The value is exclusive ORed with !! the value being tested for. The integer result of the IEOR function is @@ -48,14 +48,14 @@ module shr_infnan_mod integer, parameter :: Double = selected_int_kind(precision(1.0_r8)) ! Single precision IEEE values - integer(Single), parameter :: sNaN = Z"7FC00000" - integer(Single), parameter :: sPosInf = Z"7F800000" - integer(Single), parameter :: sNegInf = Z"FF800000" + integer(Single), parameter :: sNaN = int(Z"7FC00000") + integer(Single), parameter :: sPosInf = int(Z"7F800000") + integer(Single), parameter :: sNegInf = int(Z"FF800000") ! Double precision IEEE values - integer(Double), parameter :: dNaN = Z"7FF8000000000000" - integer(Double), parameter :: dPosInf = Z"7FF0000000000000" - integer(Double), parameter :: dNegInf = Z"FFF0000000000000" + integer(Double), parameter :: dNaN = int(Z"7FF8000000000000") + integer(Double), parameter :: dPosInf = int(Z"7FF0000000000000") + integer(Double), parameter :: dNegInf = int(Z"FFF0000000000000") ! Locatation of single and double precision sign bit (Intel) ! Subtract one because bit numbering starts at zero @@ -84,22 +84,22 @@ module shr_infnan_mod module procedure sisnan module procedure disnan #endif - end interface + end interface interface shr_infnan_isinf module procedure sisinf module procedure disinf - end interface - + end interface + interface shr_infnan_isposinf module procedure sisposinf module procedure disposinf - end interface - + end interface + interface shr_infnan_isneginf module procedure sisneginf module procedure disneginf - end interface + end interface integer :: shr_sisnan @@ -107,7 +107,7 @@ module shr_infnan_mod integer :: shr_disnan external :: shr_disnan -contains +contains ! ! If FORTRAN intrinsic's exist use them @@ -134,7 +134,7 @@ elemental function sisnan(x) result(res) res = isnan(x) #endif - end function + end function ! Double precision test for NaN elemental function disnan(d) result(res) @@ -156,7 +156,7 @@ elemental function disnan(d) result(res) res = isnan(d) #endif - end function + end function ! ! Otherwise link to a C function call that either uses the C90 isnan function or a x != x check @@ -176,13 +176,13 @@ function c_sisnan_1D(x) result(res) real(r4), intent(in) :: x(:) logical :: res(size(x)) - integer :: i + integer :: i do i = 1, size(x) res(i) = (shr_sisnan(x(i)) /= 0) end do end function c_sisnan_1D - + function c_sisnan_2D(x) result(res) real(r4), intent(in) :: x(:,:) logical :: res(size(x,1),size(x,2)) @@ -195,7 +195,7 @@ function c_sisnan_2D(x) result(res) end do end do end function c_sisnan_2D - + function c_sisnan_3D(x) result(res) real(r4), intent(in) :: x(:,:,:) logical :: res(size(x,1),size(x,2),size(x,3)) @@ -210,7 +210,7 @@ function c_sisnan_3D(x) result(res) end do end do end function c_sisnan_3D - + function c_sisnan_4D(x) result(res) real(r4), intent(in) :: x(:,:,:,:) logical :: res(size(x,1),size(x,2),size(x,3),size(x,4)) @@ -227,7 +227,7 @@ function c_sisnan_4D(x) result(res) end do end do end function c_sisnan_4D - + function c_sisnan_5D(x) result(res) real(r4), intent(in) :: x(:,:,:,:,:) logical :: res(size(x,1),size(x,2),size(x,3),size(x,4),size(x,5)) @@ -246,7 +246,7 @@ function c_sisnan_5D(x) result(res) end do end do end function c_sisnan_5D - + function c_sisnan_6D(x) result(res) real(r4), intent(in) :: x(:,:,:,:,:,:) logical :: res(size(x,1),size(x,2),size(x,3),size(x,4),size(x,5),size(x,6)) @@ -267,7 +267,7 @@ function c_sisnan_6D(x) result(res) end do end do end function c_sisnan_6D - + function c_sisnan_7D(x) result(res) real(r4), intent(in) :: x(:,:,:,:,:,:,:) logical :: res(size(x,1),size(x,2),size(x,3),size(x,4),size(x,5),size(x,6),size(x,7)) @@ -290,7 +290,7 @@ function c_sisnan_7D(x) result(res) end do end do end function c_sisnan_7D - + function c_disnan_scalar(x) result(res) real(r8), intent(in) :: x logical :: res @@ -302,13 +302,13 @@ function c_disnan_1D(x) result(res) real(r8), intent(in) :: x(:) logical :: res(size(x)) - integer :: i + integer :: i do i = 1, size(x) res(i) = (shr_disnan(x(i)) /= 0) end do end function c_disnan_1D - + function c_disnan_2D(x) result(res) real(r8), intent(in) :: x(:,:) logical :: res(size(x,1),size(x,2)) @@ -321,7 +321,7 @@ function c_disnan_2D(x) result(res) end do end do end function c_disnan_2D - + function c_disnan_3D(x) result(res) real(r8), intent(in) :: x(:,:,:) logical :: res(size(x,1),size(x,2),size(x,3)) @@ -336,7 +336,7 @@ function c_disnan_3D(x) result(res) end do end do end function c_disnan_3D - + function c_disnan_4D(x) result(res) real(r8), intent(in) :: x(:,:,:,:) logical :: res(size(x,1),size(x,2),size(x,3),size(x,4)) @@ -353,7 +353,7 @@ function c_disnan_4D(x) result(res) end do end do end function c_disnan_4D - + function c_disnan_5D(x) result(res) real(r8), intent(in) :: x(:,:,:,:,:) logical :: res(size(x,1),size(x,2),size(x,3),size(x,4),size(x,5)) @@ -372,7 +372,7 @@ function c_disnan_5D(x) result(res) end do end do end function c_disnan_5D - + function c_disnan_6D(x) result(res) real(r8), intent(in) :: x(:,:,:,:,:,:) logical :: res(size(x,1),size(x,2),size(x,3),size(x,4),size(x,5),size(x,6)) @@ -393,7 +393,7 @@ function c_disnan_6D(x) result(res) end do end do end function c_disnan_6D - + function c_disnan_7D(x) result(res) real(r8), intent(in) :: x(:,:,:,:,:,:,:) logical :: res(size(x,1),size(x,2),size(x,3),size(x,4),size(x,5),size(x,6),size(x,7)) @@ -418,48 +418,48 @@ function c_disnan_7D(x) result(res) end function c_disnan_7D #endif - + ! Single precision test for Inf elemental function sisinf(x) result(res) real(r4), intent(in) :: x logical :: res res = ieor(ibclr(transfer(x,sPosInf),SPSB), sPosInf) == 0 - end function + end function ! Double precision test for Inf elemental function disinf(d) result(res) real(r8), intent(in) :: d logical :: res res = ieor(ibclr(transfer(d,dPosInf),DPSB), dPosInf) == 0 - end function - + end function + ! Single precision test for +Inf elemental function sisposinf(x) result(res) real(r4), intent(in) :: x logical :: res res = ieor(transfer(x,sPosInf), sPosInf) == 0 - end function + end function ! Double precision test for +Inf elemental function disposinf(d) result(res) real(r8), intent(in) :: d logical :: res res = ieor(transfer(d,dPosInf), dPosInf) == 0 - end function - + end function + ! Single precision test for -Inf elemental function sisneginf(x) result(res) real(r4), intent(in) :: x logical :: res res = ieor(transfer(x,sNegInf), sNegInf) == 0 - end function + end function ! Double precision test for -Inf elemental function disneginf(d) result(res) real(r8), intent(in) :: d logical :: res res = ieor(transfer(d,dNegInf), dNegInf) == 0 - end function + end function end module shr_infnan_mod diff --git a/components/elm/tools/mksurfdata_map/mksurfdata.pl b/components/elm/tools/mksurfdata_map/mksurfdata.pl index 222a9c51bd15..05389d0d579d 100755 --- a/components/elm/tools/mksurfdata_map/mksurfdata.pl +++ b/components/elm/tools/mksurfdata_map/mksurfdata.pl @@ -421,8 +421,8 @@ ($) my $mkopts = "-csmdata $CSMDATA -silent -justvalue -namelist elmexp $usrnam"; foreach my $typ ( "lak", "veg", "voc", "top", "tex", "col","ord", "fmx", "lai", "urb", "org", "glc", "utp", "wet", - "gdp", "peat","abm", "topostats" , "vic", "ch4", - "pho", "grvl", "slp10", "ero", "fert") { + "gdp", "peat","abm", "topostats" , "vic", "ch4", + "pho", "grvl", "slp10", "ero", "fert", "toprad") { my $lmask = `$scrdir/../../bld/queryDefaultNamelist.pl $mopts -silent -options type=$typ,mergeGIS=$merge_gis,hirespft=$hirespft -var lmask`; $lmask = trim($lmask); my $hgrid = `$scrdir/../../bld/queryDefaultNamelist.pl $mopts -options type=$typ,hirespft=$hirespft -var hgrid`; @@ -539,6 +539,7 @@ ($) map_fslp10 = '$map{'slp10'}' map_fero = '$map{'ero'}' map_ffert = '$map{'fert'}' + map_ftoprad = '$map{'toprad'}' mksrf_fsoitex = '$datfil{'tex'}' mksrf_forganic = '$datfil{'org'}' mksrf_flakwat = '$datfil{'lak'}' @@ -563,6 +564,7 @@ ($) mksrf_fslp10 = '$datfil{'slp10'}' mksrf_fero = '$datfil{'ero'}' mksrf_ffert = '$datfil{'fert'}' + mksrf_ftoprad = '$datfil{'toprad'}' EOF my $urbdesc = "urb3den"; my $rcp_option= ""; diff --git a/components/elm/tools/mksurfdata_map/src/Srcfiles b/components/elm/tools/mksurfdata_map/src/Srcfiles index f8bda5dcf61b..96cec841a941 100644 --- a/components/elm/tools/mksurfdata_map/src/Srcfiles +++ b/components/elm/tools/mksurfdata_map/src/Srcfiles @@ -28,6 +28,7 @@ mkVICparamsMod.F90 mkCH4inversionMod.F90 mkSedMod.F90 mkFertMod.F90 +mktopradMod.F90 nanMod.F90 shr_file_mod.F90 shr_sys_mod.F90 diff --git a/components/elm/tools/mksurfdata_map/src/mkfileMod.F90 b/components/elm/tools/mksurfdata_map/src/mkfileMod.F90 index c3f67cc7a12c..50b029efc7d5 100644 --- a/components/elm/tools/mksurfdata_map/src/mkfileMod.F90 +++ b/components/elm/tools/mksurfdata_map/src/mkfileMod.F90 @@ -15,6 +15,7 @@ subroutine mkfile(domain, fname, dynlanduse) use mkpftMod , only : mkpftAtt use mksoilMod , only : mksoilAtt use mkSedMod , only : mksedAtt + use mktopradMod , only : mktopradAtt use mkharvestMod , only : mkharvest_fieldname, mkharvest_numtypes, mkharvest_longname use mkncdio , only : check_ret, ncd_defvar use mkdomainMod @@ -297,6 +298,10 @@ subroutine mkfile(domain, fname, dynlanduse) call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & 'map_fertilizer_file', len_trim(str), trim(str)), subname) + str = get_filename(map_ftoprad) + call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & + 'map_ftoprad_file', len_trim(str), trim(str)), subname) + ! ---------------------------------------------------------------------- ! Define variables ! ---------------------------------------------------------------------- @@ -313,6 +318,8 @@ subroutine mkfile(domain, fname, dynlanduse) call mksedAtt( ncid, dynlanduse, xtype ) + call mktopradAtt( ncid, dynlanduse, xtype ) + if (outnc_1d) then call ncd_defvar(ncid=ncid, varname='AREA' , xtype=nf_double, & dim1name='gridcell',& diff --git a/components/elm/tools/mksurfdata_map/src/mksurfdat.F90 b/components/elm/tools/mksurfdata_map/src/mksurfdat.F90 index d062907cdccf..a936c43052b9 100644 --- a/components/elm/tools/mksurfdata_map/src/mksurfdat.F90 +++ b/components/elm/tools/mksurfdata_map/src/mksurfdat.F90 @@ -44,7 +44,9 @@ program mksurfdat use mkCH4inversionMod , only : mkCH4inversion use mksoilphosphorusMod, only : mksoilphosphorus use mkSedMod , only : mkgrvl, mkslp10, mkEROparams - use mkFertMod , only : mkfert! + use mkFertMod , only : mkfert + use mktopradMod , only : mktoprad +! ! !ARGUMENTS: implicit none @@ -152,6 +154,10 @@ program mksurfdat real(r8), allocatable :: litho(:) ! lithology erodiblity index (unitless) real(r8), allocatable :: nfert(:,:) ! crop nitrogen fertilizer (g/m^2) real(r8), allocatable :: pfert(:,:) ! crop phosphorus fertilizer (g/m^2) + real(r8), allocatable :: sinsl_sinas(:) ! sin(slope)*sin(aspect) / cos(slope) + real(r8), allocatable :: sinsl_cosas(:) ! sin(slope)*cos(aspect) / cos(slope) + real(r8), allocatable :: sky_view(:) ! mean of (sky view factor / cos(slope)) + real(r8), allocatable :: terrain_config(:) ! mean of (terrain configuration factor / cos(slope)) type(domain_type) :: ldomain @@ -187,6 +193,7 @@ program mksurfdat mksrf_fslp10, & mksrf_fero, & mksrf_ffert, & + mksrf_ftoprad, & nglcec, & numpft, & soil_color, & @@ -224,6 +231,7 @@ program mksurfdat map_fslp10, & map_ffert, & map_fero, & + map_ftoprad, & outnc_large_files, & outnc_double, & outnc_dims, & @@ -264,8 +272,9 @@ program mksurfdat ! mksrf_fphosphorus Soil phosphorus dataset ! mksrf_fgrvl ---- Soil gravel content dataset ! mksrf_fslp10 --- Slope percentile dataset - ! mksrf_fero ----- ELM-Erosion parameters dataset + ! mksrf_fero ----- ELM-Erosion parameters dataset ! mksrf_ffert ---- Crop Fertilizer dataset + ! mksrf_ftoprad --- TOP parameters dataset for solar radiation parameterization ! ====================================== ! Must specify mapping file for the different datafiles above ! ====================================== @@ -295,6 +304,7 @@ program mksurfdat ! map_fslp10 ------ Mapping for mksrf_fslp10 ! map_fero -------- Mapping for mksrf_fero ! map_ffert ------- Mapping for mksrf_ffert + ! map_ftoprad_______ Mapping for mksrf_ftoprad ! ====================================== ! Optionally specify setting for: ! ====================================== @@ -464,7 +474,11 @@ program mksurfdat tillage(ns_o) , & litho(ns_o) , & nfert(ns_o,0:numpft) , & - pfert(ns_o,0:numpft) ) + pfert(ns_o,0:numpft) , & + sinsl_sinas(ns_o) , & + sinsl_cosas(ns_o) , & + sky_view(ns_o) , & + terrain_config(ns_o) ) landfrac_pft(:) = spval pctlnd_pft(:) = spval @@ -511,6 +525,10 @@ program mksurfdat litho(:) = spval nfert(:,:) = 0._r8 pfert(:,:) = 0._r8 + sinsl_sinas(:) = spval + sinsl_cosas(:) = spval + sky_view(:) = spval + terrain_config(:) = spval ! ---------------------------------------------------------------------- ! Open diagnostic output log file @@ -581,6 +599,7 @@ program mksurfdat write(ndiag,*)' mapping for slope percentile ',trim(map_fslp10) write(ndiag,*)' mapping for erosion params ',trim(map_fero) write(ndiag,*)' mapping for fertilizer ',trim(map_ffert) + write(ndiag,*)' mapping for TOP params ',trim(map_ftoprad) if (mksrf_fdynuse /= ' ') then write(6,*)'mksrf_fdynuse = ',trim(mksrf_fdynuse) @@ -768,6 +787,12 @@ program mksurfdat nfert_o=nfert, pfert_o=pfert) end if + call mktoprad(ldomain, mapfname=map_ftoprad, datfname=mksrf_ftoprad, varname = 'SINSL_SINAS', ndiag=ndiag, top_o=sinsl_sinas, nodata=0.0_r8) + call mktoprad(ldomain, mapfname=map_ftoprad, datfname=mksrf_ftoprad, varname = 'SINSL_COSAS', ndiag=ndiag, top_o=sinsl_cosas, nodata=0.0_r8) + call mktoprad(ldomain, mapfname=map_ftoprad, datfname=mksrf_ftoprad, varname = 'SKY_VIEW', ndiag=ndiag, top_o=sky_view, nodata=1.0_r8) + call mktoprad(ldomain, mapfname=map_ftoprad, datfname=mksrf_ftoprad, varname = 'TERRAIN_CONFIG', ndiag=ndiag, top_o=terrain_config, nodata=0.0_r8) + + do n = 1,ns_o ! Assume wetland and/or lake when dataset landmask implies ocean @@ -797,6 +822,10 @@ program mksurfdat litho(n) = 0._r8 nfert(n,:) = 0._r8 pfert(n,:) = 0._r8 + sinsl_sinas(n) = 0._r8 + sinsl_cosas(n) = 0._r8 + sky_view(n) = 1._r8 + terrain_config(n)= 0._r8 else pftdata_mask(n) = 1 end if @@ -1103,6 +1132,18 @@ program mksurfdat call check_ret(nf_inq_varid(ncid, 'Litho', varid), subname) call check_ret(nf_put_var_double(ncid, varid, litho), subname) + call check_ret(nf_inq_varid(ncid, 'SINSL_SINAS', varid), subname) + call check_ret(nf_put_var_double(ncid, varid, sinsl_sinas), subname) + + call check_ret(nf_inq_varid(ncid, 'SINSL_COSAS', varid), subname) + call check_ret(nf_put_var_double(ncid, varid, sinsl_cosas), subname) + + call check_ret(nf_inq_varid(ncid, 'SKY_VIEW', varid), subname) + call check_ret(nf_put_var_double(ncid, varid, sky_view), subname) + + call check_ret(nf_inq_varid(ncid, 'TERRAIN_CONFIG', varid), subname) + call check_ret(nf_put_var_double(ncid, varid, terrain_config), subname) + ! Deallocate arrays NOT needed for dynamic-pft section of code deallocate ( organic ) @@ -1123,6 +1164,7 @@ program mksurfdat deallocate ( grvl, slp10 ) deallocate ( ero_c1, ero_c2, ero_c3, tillage, litho ) deallocate ( nfert, pfert ) + deallocate ( sinsl_sinas, sinsl_cosas, sky_view, terrain_config ) ! Synchronize the disk copy of a netCDF dataset with in-memory buffers call check_ret(nf_sync(ncid), subname) diff --git a/components/elm/tools/mksurfdata_map/src/mktopradMod.F90 b/components/elm/tools/mksurfdata_map/src/mktopradMod.F90 new file mode 100644 index 000000000000..0325019706f7 --- /dev/null +++ b/components/elm/tools/mksurfdata_map/src/mktopradMod.F90 @@ -0,0 +1,250 @@ +module mktopradMod +!----------------------------------------------------------------------- +!BOP +! +! !MODULE: mktopradMod +! +! !DESCRIPTION: +! Make topography data for TOP solar radiation parameterization +! +! !REVISION HISTORY: +! Author: Dalei Hao +! +!----------------------------------------------------------------------- +!!USES: + use shr_kind_mod, only : r8 => shr_kind_r8 + use shr_sys_mod , only : shr_sys_flush + implicit none + + SAVE + private ! By default make data private +! +! !PUBLIC MEMBER FUNCTIONS: +! + public mktopradAtt ! Add attributes to output file + + public mktoprad ! Set topography +! +! !PUBLIC DATA MEMBERS: +! +! +! !PRIVATE DATA MEMBERS: +! +! !PRIVATE MEMBER FUNCTIONS: + +!EOP +!=============================================================== +contains +!=============================================================== + +!----------------------------------------------------------------------- +!BOP +! +! !IROUTINE: mktoprad +! +! !INTERFACE: +subroutine mktoprad(ldomain, mapfname, datfname, varname, ndiag, top_o, nodata) +! +! !DESCRIPTION: +! Make topography data for TOP solar radiation parameterization +! +! !USES: + use mkdomainMod , only : domain_type, domain_clean, domain_read, domain_checksame + use mkgridmapMod + use mkvarpar + use mkvarctl + use mkncdio +! +! !ARGUMENTS: + implicit none + type(domain_type), intent(in) :: ldomain + character(len=*) , intent(in) :: mapfname ! input mapping file name + character(len=*) , intent(in) :: datfname ! input data file name + integer , intent(in) :: ndiag ! unit number for diag out + character(len=*) , intent(in) :: varname ! topo variable name + real(r8) , intent(out):: top_o(:) ! output topography data + real(r8) , intent(in) :: nodata ! default value +! +! +! !CALLED FROM: +! subroutine mksrfdat in module mksrfdatMod +! +! !REVISION HISTORY: +! Author: Dalei Hao +! +! +! !LOCAL VARIABLES: +!EOP + type(domain_type) :: tdomain ! local domain + type(gridmap_type) :: tgridmap ! local gridmap + + real(r8), allocatable :: top_i(:) ! input top variable + real(r8), allocatable :: mask_i(:) ! input grid: mask (0, 1) + integer :: ns_i,ns_o ! indices + integer :: k,l,n,m,ni ! indices + integer :: ncidi,dimid,varid ! input netCDF id's + integer :: ier ! error status + character(len=256) :: name ! name of attribute + character(len=256) :: unit ! units of attribute + character(len= 32) :: subname = 'mktop' +!----------------------------------------------------------------------- + + write (6,*) 'Attempting to make topography .....' + call shr_sys_flush(6) + + ns_o = ldomain%ns + + ! ----------------------------------------------------------------- + ! Read input file + ! ----------------------------------------------------------------- + + ! Obtain input grid info, read local fields + + call domain_read(tdomain,datfname) + + ns_i = tdomain%ns + allocate(top_i(ns_i), stat=ier) + if (ier /= 0) then + write(6,*)'mktoprad allocation error'; call abort() + end if + + write (6,*) 'Open topography file: ', trim(datfname) + call check_ret(nf_open(datfname, 0, ncidi), subname) + call check_ret(nf_inq_varid (ncidi, trim(varname), varid), subname) + call check_ret(nf_get_var_double (ncidi, varid, top_i), subname) + call check_ret(nf_close(ncidi), subname) + + ! set mask as 0 when topo data is filled value: -9999 + allocate(mask_i(ns_i), stat=ier) + if (ier /= 0) then + write(6,*)'mktoprad allocation error'; call abort() + end if + + mask_i(:) = 1._r8 + do ni = 1,ns_i + if (top_i(ni) < -1000._r8) then + mask_i(ni) = 0._r8 + end if + enddo + + ! Read mapping file + call gridmap_mapread(tgridmap, mapfname) + + ! Error checks for domain and map consistencies + call domain_checksame( tdomain, ldomain, tgridmap ) + + ! Determine top_o on output grid + top_o(:) = nodata + + call gridmap_areaave(tgridmap, top_i, top_o, nodata=nodata, mask_src=mask_i) + + ! Deallocate dynamic memory + + call domain_clean(tdomain) + call gridmap_clean(tgridmap) + deallocate (top_i) + deallocate (mask_i) + + write (6,*) 'Successfully made topography parameters' + write (6,*) + call shr_sys_flush(6) + +end subroutine mktoprad + +!----------------------------------------------------------------------- + +!----------------------------------------------------------------------- +!BOP +! +! !IROUTINE: mktopradAtt +! +! !INTERFACE: +subroutine mktopradAtt( ncid, dynlanduse, xtype ) +! +! !DESCRIPTION: +! add atttributes to output file regarding the topography module +! +! !USES: + use fileutils , only : get_filename + use mkncdio , only : check_ret, ncd_defvar + use mkvarpar + use mkvarctl + +! !ARGUMENTS: + implicit none + include 'netcdf.inc' + integer, intent(in) :: ncid ! NetCDF file ID to write out to + logical, intent(in) :: dynlanduse ! if dynamic land-use file + integer, intent(in) :: xtype ! external type to output real data as +! +! !CALLED FROM: +! subroutine mkfile in module mkfileMod +! +! !REVISION HISTORY: +! Original Author: Dalei Hao +! +! +! !LOCAL VARIABLES: +!EOP + integer :: dimid ! temporary + character(len=256) :: str ! global attribute string + character(len=32) :: subname = 'mktopAtt' +!----------------------------------------------------------------------- + + if (.not. dynlanduse) then + + ! Add global attributes to file + + str = get_filename(mksrf_fgrvl) + call check_ret(nf_put_att_text(ncid, NF_GLOBAL, & + 'top_raw_data_file_name', len_trim(str), trim(str)), subname) + + ! Define variables + + if (outnc_1d) then + call ncd_defvar(ncid=ncid, varname='SINSL_COSAS', xtype=xtype, & + dim1name='gridcell',& + long_name='sin(slope) * cos(aspect)', units='unitless') + else + call ncd_defvar(ncid=ncid, varname='SINSL_COSAS', xtype=xtype, & + dim1name='lsmlon', dim2name='lsmlat', & + long_name='sin(slope) * cos(aspect)', units='unitless') + end if + + if (outnc_1d) then + call ncd_defvar(ncid=ncid, varname='SINSL_SINAS', xtype=xtype, & + dim1name='gridcell',& + long_name='sin(slope) * sin(aspect)', units='unitless') + else + call ncd_defvar(ncid=ncid, varname='SINSL_SINAS', xtype=xtype, & + dim1name='lsmlon', dim2name='lsmlat', & + long_name='sin(slope) * sin(aspect)', units='unitless') + end if + + if (outnc_1d) then + call ncd_defvar(ncid=ncid, varname='SKY_VIEW', xtype=xtype, & + dim1name='gridcell',& + long_name='sky view factor', units='unitless') + else + call ncd_defvar(ncid=ncid, varname='SKY_VIEW', xtype=xtype, & + dim1name='lsmlon', dim2name='lsmlat', & + long_name='sky view factor', units='unitless') + end if + + if (outnc_1d) then + call ncd_defvar(ncid=ncid, varname='TERRAIN_CONFIG', xtype=xtype, & + dim1name='gridcell',& + long_name='terrain configuration factor', units='unitless') + else + call ncd_defvar(ncid=ncid, varname='TERRAIN_CONFIG', xtype=xtype, & + dim1name='lsmlon', dim2name='lsmlat', & + long_name='terrain configuration factor', units='unitless') + end if + + end if + +end subroutine mktopradAtt + +!----------------------------------------------------------------------- + +end module mktopradMod diff --git a/components/elm/tools/mksurfdata_map/src/mkvarctl.F90 b/components/elm/tools/mksurfdata_map/src/mkvarctl.F90 index 48e745833749..127f0e83124b 100644 --- a/components/elm/tools/mksurfdata_map/src/mkvarctl.F90 +++ b/components/elm/tools/mksurfdata_map/src/mkvarctl.F90 @@ -52,7 +52,8 @@ module mkvarctl character(len=256), public :: mksrf_fslp10 = ' ' ! slope percentile file name character(len=256), public :: mksrf_fero = ' ' ! ELM-Erosion parameters data file name character(len=256), public :: mksrf_ffert = ' ' ! crop fertilizer data file name - integer , public :: numpft = 16 ! number of plant types + character(len=256), public :: mksrf_ftoprad = ' ' ! topography parameters data file name for TOP solar radiation parameterization + integer , public :: numpft = 16 ! number of plant types character(len=256), public :: map_fpft = ' ' ! Mapping file for PFT character(len=256), public :: map_flakwat = ' ' ! Mapping file for lake water @@ -80,6 +81,7 @@ module mkvarctl character(len=256), public :: map_fslp10 = ' ' ! Mapping file for slope percentile character(len=256), public :: map_fero = ' ' ! Mapping file for ELM-Erosion parameters character(len=256), public :: map_ffert = ' ' ! Mapping file for crop fertilizer! + character(len=256), public :: map_ftoprad = ' ' ! Mapping file for topography parameters in TOP solar radiation parameterization ! ! Variables to override data read in with ! (all_urban is mostly for single-point mode, but could be used for sensitivity studies) diff --git a/components/homme/CMakeLists.txt b/components/homme/CMakeLists.txt index 80a89a296910..6fe81180ab54 100644 --- a/components/homme/CMakeLists.txt +++ b/components/homme/CMakeLists.txt @@ -206,7 +206,9 @@ IF (HOMME_USE_KOKKOS) STRING (TOUPPER ${HOMMEXX_EXEC_SPACE} HOMMEXX_EXEC_SPACE_UPPER) - IF (HOMMEXX_EXEC_SPACE_UPPER STREQUAL "HIP") + IF (${HOMMEXX_EXEC_SPACE_UPPER} STREQUAL "SYCL") + SET (HOMMEXX_SYCL_SPACE ON) + ELSEIF (${HOMMEXX_EXEC_SPACE_UPPER} STREQUAL "HIP") SET (HOMMEXX_HIP_SPACE ON) ELSEIF (HOMMEXX_EXEC_SPACE_UPPER STREQUAL "CUDA") SET (HOMMEXX_CUDA_SPACE ON) @@ -303,7 +305,7 @@ SET (HOMMEXX_ENABLE_GPU_F90 FALSE) IF (HOMME_USE_KOKKOS) - IF (CUDA_BUILD OR HIP_BUILD) + IF (CUDA_BUILD OR HIP_BUILD OR SYCL_BUILD) SET (DEFAULT_VECTOR_SIZE 1) SET (HOMMEXX_ENABLE_GPU TRUE) SET (HOMMEXX_ENABLE_GPU_F90 TRUE) @@ -312,7 +314,7 @@ IF (HOMME_USE_KOKKOS) ENDIF() SET (HOMMEXX_VECTOR_SIZE ${DEFAULT_VECTOR_SIZE} CACHE STRING - "If AVX or Cuda or HIP don't take priority, use this software vector size.") + "If AVX or Cuda or HIP or SYCL don't take priority, use this software vector size.") IF (CMAKE_BUILD_TYPE_UPPER MATCHES "DEBUG" OR CMAKE_BUILD_TYPE_UPPER MATCHES "RELWITHDEBINFO") SET (HOMMEXX_DEBUG ON) diff --git a/components/homme/cmake/machineFiles/anvil-bfb.cmake b/components/homme/cmake/machineFiles/anvil-bfb.cmake index d46774646eb1..ab9b1d3edc86 100644 --- a/components/homme/cmake/machineFiles/anvil-bfb.cmake +++ b/components/homme/cmake/machineFiles/anvil-bfb.cmake @@ -20,7 +20,14 @@ ENDIF() # Set kokkos arch, to get correct avx flags SET (Kokkos_ARCH_BDW ON CACHE BOOL "") -SET (WITH_PNETCDF FALSE CACHE FILEPATH "") +EXECUTE_PROCESS(COMMAND pnetcdf-config --prefix + RESULT_VARIABLE PNCCONFIG_RESULT + OUTPUT_VARIABLE PNCCONFIG_OUTPUT + ERROR_VARIABLE PNCCONFIG_ERROR + OUTPUT_STRIP_TRAILING_WHITESPACE +) +SET (PnetCDF_PATH "${PNCCONFIG_OUTPUT}" CACHE STRING "") + # # anvil module system doesn't set environment variables, but will put # nc-config in our path. anvil seperates C and Fortran libraries, diff --git a/components/homme/cmake/machineFiles/anvil.cmake b/components/homme/cmake/machineFiles/anvil.cmake index 325a9caa280f..2abee260b44c 100644 --- a/components/homme/cmake/machineFiles/anvil.cmake +++ b/components/homme/cmake/machineFiles/anvil.cmake @@ -20,7 +20,14 @@ ENDIF() # Set kokkos arch, to get correct avx flags SET (Kokkos_ARCH_BDW ON CACHE BOOL "") -SET (WITH_PNETCDF FALSE CACHE FILEPATH "") +EXECUTE_PROCESS(COMMAND pnetcdf-config --prefix + RESULT_VARIABLE PNCCONFIG_RESULT + OUTPUT_VARIABLE PNCCONFIG_OUTPUT + ERROR_VARIABLE PNCCONFIG_ERROR + OUTPUT_STRIP_TRAILING_WHITESPACE +) +SET (PnetCDF_PATH "${PNCCONFIG_OUTPUT}" CACHE STRING "") + # # anvil module system doesn't set environment variables, but will put # nc-config in our path. anvil seperates C and Fortran libraries, diff --git a/components/homme/cmake/machineFiles/aurora-aot.cmake b/components/homme/cmake/machineFiles/aurora-aot.cmake new file mode 100644 index 000000000000..094ec8882784 --- /dev/null +++ b/components/homme/cmake/machineFiles/aurora-aot.cmake @@ -0,0 +1,64 @@ +#module restore +#module load oneapi/eng-compiler/2022.12.30.005 +#module load intel_compute_runtime/release/agama-devel-627 +#module load spack cmake +#module list + + +SET (SUNSPOT_MACHINE TRUE CACHE BOOL "") + +SET(BUILD_HOMME_WITHOUT_PIOLIBRARY TRUE CACHE BOOL "") +SET(HOMMEXX_MPI_ON_DEVICE FALSE CACHE BOOL "") + +SET(HOMME_FIND_BLASLAPACK TRUE CACHE BOOL "") + +SET(WITH_PNETCDF FALSE CACHE FILEPATH "") + +SET(USE_QUEUING FALSE CACHE BOOL "") + +#temp hack +SET(HOMME_USE_KOKKOS TRUE CACHE BOOL "") + +SET(BUILD_HOMME_PREQX_KOKKOS TRUE CACHE BOOL "") +SET(BUILD_HOMME_THETA_KOKKOS TRUE CACHE BOOL "") + +#set(KOKKOS_HOME "/home/onguba/kokkos-build/mar05-aot/install" CACHE STRING "") +#set(E3SM_KOKKOS_PATH ${KOKKOS_HOME} CACHE STRING "") + +SET(USE_TRILINOS OFF CACHE BOOL "") + +SET(SYCL_BUILD TRUE CACHE BOOL "") +SET(HOMME_ENABLE_COMPOSE FALSE CACHE BOOL "") + +SET(CMAKE_CXX_STANDARD 17) + +SET(CMAKE_C_COMPILER "mpicc" CACHE STRING "") +SET(CMAKE_Fortran_COMPILER "mpifort" CACHE STRING "") +SET(CMAKE_CXX_COMPILER "mpicxx" CACHE STRING "") + +# -fsycl-link-huge-device-code for theta to get build +#JIT flags +#SET(SYCL_COMPILE_FLAGS "-std=c++17 -fsycl -fsycl-device-code-split=per_kernel -fno-sycl-id-queries-fit-in-int -fsycl-unnamed-lambda") +#SET(SYCL_LINK_FLAGS "-fsycl -fsycl-link-huge-device-code -fsycl-device-code-split=per_kernel -fsycl-targets=spir64") + +#AOT flags +SET(SYCL_COMPILE_FLAGS "-std=c++17 -fsycl -fsycl-device-code-split=per_kernel -fno-sycl-id-queries-fit-in-int -fsycl-unnamed-lambda") +SET(SYCL_LINK_FLAGS "-fsycl-max-parallel-link-jobs=32 -fsycl-link-huge-device-code -fsycl -fsycl-device-code-split=per_kernel -fsycl-targets=spir64_gen -Xsycl-target-backend \"-device 12.60.7\"") + +SET(ADD_Fortran_FLAGS "-fc=ifx -fpscomp logicals -O3 -DNDEBUG -DCPRINTEL -g" CACHE STRING "") +SET(ADD_C_FLAGS "-O3 -DNDEBUG " CACHE STRING "") + +SET(ADD_CXX_FLAGS "-std=c++17 -O3 -DNDEBUG ${SYCL_COMPILE_FLAGS}" CACHE STRING "") +SET(ADD_LINKER_FLAGS "-O3 -DNDEBUG ${SYCL_LINK_FLAGS} -fortlib" CACHE STRING "") + +set (ENABLE_OPENMP OFF CACHE BOOL "") +set (ENABLE_COLUMN_OPENMP OFF CACHE BOOL "") +set (ENABLE_HORIZ_OPENMP OFF CACHE BOOL "") + +set (HOMME_TESTING_PROFILE "dev" CACHE STRING "") + +set (USE_NUM_PROCS 4 CACHE STRING "") + +SET (USE_MPI_OPTIONS "--bind-to core" CACHE FILEPATH "") + + diff --git a/components/homme/cmake/machineFiles/aurora-jit.cmake b/components/homme/cmake/machineFiles/aurora-jit.cmake new file mode 100644 index 000000000000..1941fa9eb3f3 --- /dev/null +++ b/components/homme/cmake/machineFiles/aurora-jit.cmake @@ -0,0 +1,58 @@ +#module restore +#module load oneapi/eng-compiler/2022.12.30.005 +#module load intel_compute_runtime/release/agama-devel-627 +#module load spack cmake +#module list + + + +SET(BUILD_HOMME_WITHOUT_PIOLIBRARY TRUE CACHE BOOL "") +SET(HOMMEXX_MPI_ON_DEVICE FALSE CACHE BOOL "") + +SET(HOMME_FIND_BLASLAPACK TRUE CACHE BOOL "") + +SET(WITH_PNETCDF FALSE CACHE FILEPATH "") + +SET(USE_QUEUING FALSE CACHE BOOL "") + +#temp hack +SET(HOMME_USE_KOKKOS TRUE CACHE BOOL "") + +SET(BUILD_HOMME_PREQX_KOKKOS TRUE CACHE BOOL "") +SET(BUILD_HOMME_THETA_KOKKOS TRUE CACHE BOOL "") + +#set(KOKKOS_HOME "/home/onguba/kokkos-build/jan03-2024/install" CACHE STRING "") +#set(E3SM_KOKKOS_PATH ${KOKKOS_HOME} CACHE STRING "") + +SET(USE_TRILINOS OFF CACHE BOOL "") + +SET(SYCL_BUILD TRUE CACHE BOOL "") +SET(HOMME_ENABLE_COMPOSE FALSE CACHE BOOL "") + +SET(CMAKE_CXX_STANDARD 17) + +SET(CMAKE_C_COMPILER "mpicc" CACHE STRING "") +SET(CMAKE_Fortran_COMPILER "mpifort" CACHE STRING "") +SET(CMAKE_CXX_COMPILER "mpicxx" CACHE STRING "") + +# -fsycl-link-huge-device-code for theta to get build +SET(SYCL_COMPILE_FLAGS "-std=c++17 -fsycl -fsycl-device-code-split=per_kernel -fno-sycl-id-queries-fit-in-int -fsycl-unnamed-lambda") +SET(SYCL_LINK_FLAGS "-fsycl -fsycl-link-huge-device-code -fsycl-device-code-split=per_kernel -fsycl-targets=spir64") + +SET(ADD_Fortran_FLAGS "-fc=ifx -O3 -DNDEBUG -DCPRINTEL -g" CACHE STRING "") +SET(ADD_C_FLAGS "-O3 -DNDEBUG " CACHE STRING "") + +SET(ADD_CXX_FLAGS "-std=c++17 -O3 -DNDEBUG ${SYCL_COMPILE_FLAGS}" CACHE STRING "") +SET(ADD_LINKER_FLAGS "-O3 -DNDEBUG ${SYCL_LINK_FLAGS} -fortlib" CACHE STRING "") + +set (ENABLE_OPENMP OFF CACHE BOOL "") +set (ENABLE_COLUMN_OPENMP OFF CACHE BOOL "") +set (ENABLE_HORIZ_OPENMP OFF CACHE BOOL "") + +set (HOMME_TESTING_PROFILE "dev" CACHE STRING "") + +set (USE_NUM_PROCS 4 CACHE STRING "") + +SET (USE_MPI_OPTIONS "--bind-to core" CACHE FILEPATH "") + + diff --git a/components/homme/cmake/machineFiles/chrysalis-bfb.cmake b/components/homme/cmake/machineFiles/chrysalis-bfb.cmake index ddeb7fa78111..b9f0d41a0606 100644 --- a/components/homme/cmake/machineFiles/chrysalis-bfb.cmake +++ b/components/homme/cmake/machineFiles/chrysalis-bfb.cmake @@ -20,7 +20,13 @@ SET (USE_MPI_OPTIONS "-K --cpu_bind=cores" CACHE STRING "") # Set kokkos arch, to get correct avx flags SET (Kokkos_ARCH_ZEN2 ON CACHE BOOL "") -SET (WITH_PNETCDF FALSE CACHE FILEPATH "") +EXECUTE_PROCESS(COMMAND pnetcdf-config --prefix + RESULT_VARIABLE PNCCONFIG_RESULT + OUTPUT_VARIABLE PNCCONFIG_OUTPUT + ERROR_VARIABLE PNCCONFIG_ERROR + OUTPUT_STRIP_TRAILING_WHITESPACE +) +SET (PnetCDF_PATH "${PNCCONFIG_OUTPUT}" CACHE STRING "") EXECUTE_PROCESS(COMMAND nf-config --prefix RESULT_VARIABLE NFCONFIG_RESULT diff --git a/components/homme/cmake/machineFiles/chrysalis.cmake b/components/homme/cmake/machineFiles/chrysalis.cmake index a336809f6d33..68ff76ec8082 100644 --- a/components/homme/cmake/machineFiles/chrysalis.cmake +++ b/components/homme/cmake/machineFiles/chrysalis.cmake @@ -20,7 +20,13 @@ SET (USE_MPI_OPTIONS "-K --cpu_bind=cores" CACHE STRING "") # Set kokkos arch, to get correct avx flags SET (Kokkos_ARCH_ZEN2 ON CACHE BOOL "") -SET (WITH_PNETCDF FALSE CACHE FILEPATH "") +EXECUTE_PROCESS(COMMAND pnetcdf-config --prefix + RESULT_VARIABLE PNCCONFIG_RESULT + OUTPUT_VARIABLE PNCCONFIG_OUTPUT + ERROR_VARIABLE PNCCONFIG_ERROR + OUTPUT_STRIP_TRAILING_WHITESPACE +) +SET (PnetCDF_PATH "${PNCCONFIG_OUTPUT}" CACHE STRING "") EXECUTE_PROCESS(COMMAND nf-config --prefix RESULT_VARIABLE NFCONFIG_RESULT diff --git a/components/homme/cmake/machineFiles/polaris-a100.sh b/components/homme/cmake/machineFiles/polaris-a100.sh new file mode 100644 index 000000000000..2b63c61a55e7 --- /dev/null +++ b/components/homme/cmake/machineFiles/polaris-a100.sh @@ -0,0 +1,74 @@ +#Currently Loaded Modules: +# 1) craype-x86-rome 6) craype/2.7.15 11) cray-libpals/1.1.7 16) nvhpc-mixed/21.9 +# 2) libfabric/1.11.0.4.125 7) cray-dsmml/0.2.2 12) PrgEnv-gnu/8.3.3 17) cudatoolkit-standalone/11.6.2 +# 3) craype-network-ofi 8) cray-pmi/6.1.2 13) gnu-parallel/2021-09-22 18) cmake/3.23.2 +# 4) perftools-base/22.05.0 9) cray-pmi-lib/6.0.17 14) gcc/11.2.0 +# 5) craype-accel-nvidia80 10) cray-pals/1.1.7 15) cray-mpich/8.1.16 + + + +#SET(HOMMEXX_EXEC_SPACE CUDA CACHE STRING "") +#SET(HOMMEXX_MPI_ON_DEVICE FALSE CACHE BOOL "") +#SET(HOMMEXX_CUDA_MAX_WARP_PER_TEAM "16" CACHE STRING "") + +# cray-hdf5-parallel/1.12.0.6 cray-netcdf-hdf5parallel/4.7.4.6 cray-parallel-netcdf/1.12.1.6 +#SET(NETCDF_DIR $ENV{CRAY_NETCDF_HDF5PARALLEL_PREFIX} CACHE FILEPATH "") +#SET(PNETCDF_DIR $ENV{CRAY_PARALLEL_NETCDF_DIR} CACHE FILEPATH "") +#SET(HDF5_DIR $ENV{CRAY_HDF5_PARALLEL_PREFIX} CACHE FILEPATH "") + +#for scorpio +#SET (NetCDF_C_PATH $ENV{CRAY_NETCDF_HDF5PARALLEL_PREFIX} CACHE FILEPATH "") +#SET (NetCDF_Fortran_PATH $ENV{CRAY_NETCDF_HDF5PARALLEL_PREFIX} CACHE FILEPATH "") + +SET(BUILD_HOMME_WITHOUT_PIOLIBRARY TRUE CACHE BOOL "") + +SET(HOMME_FIND_BLASLAPACK FALSE CACHE BOOL "") + +SET(WITH_PNETCDF FALSE CACHE FILEPATH "") + +SET(USE_QUEUING FALSE CACHE BOOL "") + +SET(BUILD_HOMME_THETA_KOKKOS TRUE CACHE BOOL "") + +SET(CUDA_BUILD TRUE CACHE BOOL "") + +#SET(HOMMEXX_BFB_TESTING TRUE CACHE BOOL "") + +SET(USE_TRILINOS OFF CACHE BOOL "") + +SET(Kokkos_ENABLE_OPENMP OFF CACHE BOOL "") +SET(Kokkos_ENABLE_CUDA ON CACHE BOOL "") +SET(Kokkos_ENABLE_CUDA_LAMBDA ON CACHE BOOL "") +SET(Kokkos_ARCH_AMPERE80 ON CACHE BOOL "") +#SET(Kokkos_ARCH_ZEN2 ON CACHE BOOL "") # works, and perf same if both AMPERE80 and ZEN2 are on +#SET(Kokkos_ENABLE_CUDA_UVM ON CACHE BOOL "") +SET(Kokkos_ENABLE_EXPLICIT_INSTANTIATION OFF CACHE BOOL "") +#SET(Kokkos_ENABLE_CUDA_ARCH_LINKING OFF CACHE BOOL "") + +#SET(CMAKE_C_COMPILER "mpicc" CACHE STRING "") +#SET(CMAKE_Fortran_COMPILER "mpifort" CACHE STRING "") +#SET(CMAKE_CXX_COMPILER "mpicxx" CACHE STRING "") +SET(CMAKE_C_COMPILER "cc" CACHE STRING "") +SET(CMAKE_Fortran_COMPILER "ftn" CACHE STRING "") +SET(CMAKE_CXX_COMPILER "CC" CACHE STRING "") + +#SET(CMAKE_C_COMPILER "mpicc" CACHE STRING "") +#SET(CMAKE_Fortran_COMPILER "mpifort" CACHE STRING "") +#SET(CMAKE_CXX_COMPILER "${CMAKE_CURRENT_SOURCE_DIR}/../../externals/kokkos/bin/nvcc_wrapper" CACHE STRING "") + +# Note: need to set MPICH_CXX env variable and perhaps NVCC_WRAPPER_DEFAULT_COMPILER + +SET(CXXLIB_SUPPORTED_CACHE FALSE CACHE BOOL "") + +SET(ENABLE_OPENMP OFF CACHE BOOL "") +SET(ENABLE_COLUMN_OPENMP OFF CACHE BOOL "") +SET(ENABLE_HORIZ_OPENMP OFF CACHE BOOL "") + +SET(CMAKE_VERBOSE_MAKEFILE ON CACHE BOOL "") + +#SET(HOMME_TESTING_PROFILE "dev" CACHE STRING "") + +SET(USE_NUM_PROCS 4 CACHE STRING "") + +SET(USE_MPIEXEC "srun" CACHE STRING "") +#SET(CPRNC_DIR /global/cfs/cdirs/e3sm/tools/cprnc CACHE FILEPATH "") diff --git a/components/homme/cmake/machineFiles/spot-aot-AB2.cmake b/components/homme/cmake/machineFiles/spot-aot-AB2.cmake new file mode 100644 index 000000000000..23fad2361ccf --- /dev/null +++ b/components/homme/cmake/machineFiles/spot-aot-AB2.cmake @@ -0,0 +1,63 @@ +#module restore +#module load oneapi/eng-compiler/2022.12.30.005 +#module load intel_compute_runtime/release/agama-devel-627 +#module load spack cmake +#module list + +SET (SUNSPOT_MACHINE TRUE CACHE BOOL "") + +SET (HOMMEXX_MPI_ON_DEVICE TRUE CACHE BOOL "") + +#SET(BUILD_HOMME_WITHOUT_PIOLIBRARY TRUE CACHE BOOL "") + +SET(HOMME_FIND_BLASLAPACK TRUE CACHE BOOL "") + +SET(WITH_PNETCDF FALSE CACHE FILEPATH "") + +SET(USE_QUEUING FALSE CACHE BOOL "") + +#temp hack +SET(HOMME_USE_KOKKOS TRUE CACHE BOOL "") + +SET(BUILD_HOMME_PREQX_KOKKOS TRUE CACHE BOOL "") +SET(BUILD_HOMME_THETA_KOKKOS TRUE CACHE BOOL "") + +#set(KOKKOS_HOME "/home/onguba/kokkos-build/june22-2024-aot/install" CACHE STRING "") +#set(E3SM_KOKKOS_PATH ${KOKKOS_HOME} CACHE STRING "") + +SET (NetCDF_Fortran_PATH "/lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/netcdf" CACHE STRING "") +SET (NetCDF_C_PATH "/lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/netcdf" CACHE STRING "") + +SET(USE_TRILINOS OFF CACHE BOOL "") + +SET(SYCL_BUILD TRUE CACHE BOOL "") +SET(HOMME_ENABLE_COMPOSE FALSE CACHE BOOL "") + +#SET(CMAKE_CXX_STANDARD 17) +SET(CMAKE_CXX_STANDARD 17 CACHE STRING "CXX Standard") + +SET(CMAKE_C_COMPILER "mpicc" CACHE STRING "") +SET(CMAKE_Fortran_COMPILER "mpifort" CACHE STRING "") +SET(CMAKE_CXX_COMPILER "mpicxx" CACHE STRING "") + +SET(SYCL_COMPILE_FLAGS "-std=c++17 -fsycl -fsycl-device-code-split=per_kernel -fno-sycl-id-queries-fit-in-int -fsycl-unnamed-lambda") +SET(SYCL_LINK_FLAGS "-fsycl-max-parallel-link-jobs=32 -fsycl-link-huge-device-code -fsycl -fsycl-device-code-split=per_kernel -fsycl-targets=spir64_gen -Xsycl-target-backend \"-device 12.60.7\"") + +#-fpscomp does not actually solve the issue with bools in here,another suggestion was -fp-model=precise, not working either +SET(ADD_Fortran_FLAGS " -fc=ifx -fpscomp logicals -O3 -DNDEBUG -DCPRINTEL -g" CACHE STRING "") +SET(ADD_C_FLAGS "-O3 -DNDEBUG " CACHE STRING "") + +SET(ADD_CXX_FLAGS " -std=c++17 -O3 -DNDEBUG ${SYCL_COMPILE_FLAGS}" CACHE STRING "") +SET(ADD_LINKER_FLAGS "-O3 -DNDEBUG ${SYCL_LINK_FLAGS} -fortlib" CACHE STRING "") + +set (ENABLE_OPENMP OFF CACHE BOOL "") +set (ENABLE_COLUMN_OPENMP OFF CACHE BOOL "") +set (ENABLE_HORIZ_OPENMP OFF CACHE BOOL "") + +set (HOMME_TESTING_PROFILE "dev" CACHE STRING "") + +set (USE_NUM_PROCS 4 CACHE STRING "") + +SET (USE_MPI_OPTIONS "--bind-to core" CACHE FILEPATH "") + + diff --git a/components/homme/src/preqx_kokkos/cxx/CamForcing.cpp b/components/homme/src/preqx_kokkos/cxx/CamForcing.cpp index 2b1e6514389e..36ca5f4a95f4 100644 --- a/components/homme/src/preqx_kokkos/cxx/CamForcing.cpp +++ b/components/homme/src/preqx_kokkos/cxx/CamForcing.cpp @@ -51,7 +51,7 @@ void state_forcing( void tracer_forcing( const ExecViewUnmanaged &f_q, const HybridVCoord &hvcoord, const TimeLevel &tl, const int &num_q, - const MoistDry &moisture, const double &dt, + const bool &use_moisture, const double &dt, const ExecViewManaged &ps_v, const ExecViewManaged< Scalar * [Q_NUM_TIME_LEVELS][QSIZE_D][NP][NP][NUM_LEV]> &qdp, @@ -61,7 +61,7 @@ void tracer_forcing( const int np1 = tl.n0; const int np1_qdp = tl.n0_qdp; - if (moisture == MoistDry::MOIST) { + if (use_moisture) { // Remove the m_fq_ps_v buffer since it's not actually needed. // Instead apply the forcing to m_ps_v directly // Bonus - one less parallel reduce in dry cases! @@ -161,7 +161,7 @@ void apply_cam_forcing(const Real &dt) { tracers.fq = decltype(tracers.fq)("fq", elems.num_elems(),tracers.num_tracers()); } tracer_forcing(tracers.fq, hvcoord, tl, tracers.num_tracers(), - sim_params.moisture, dt, elems.m_state.m_ps_v, tracers.qdp, tracers.Q); + sim_params.use_moisture, dt, elems.m_state.m_ps_v, tracers.qdp, tracers.Q); GPTLstop("ApplyCAMForcing"); } diff --git a/components/homme/src/preqx_kokkos/cxx/cxx_f90_interface_preqx.cpp b/components/homme/src/preqx_kokkos/cxx/cxx_f90_interface_preqx.cpp index c75143a9836a..aa21f5c16f29 100644 --- a/components/homme/src/preqx_kokkos/cxx/cxx_f90_interface_preqx.cpp +++ b/components/homme/src/preqx_kokkos/cxx/cxx_f90_interface_preqx.cpp @@ -37,7 +37,7 @@ void init_simulation_params_c (const int& remap_alg, const int& limiter_option, const int& time_step_type, const int& qsize, const int& state_frequency, const Real& nu, const Real& nu_p, const Real& nu_q, const Real& nu_s, const Real& nu_div, const Real& nu_top, const int& hypervis_order, const int& hypervis_subcycle, const double& hypervis_scaling, - const int& ftype, const bool& prescribed_wind, const bool& moisture, const bool& disable_diagnostics, + const int& ftype, const bool& prescribed_wind, const bool& use_moisture, const bool& disable_diagnostics, const bool& use_cpstar, const int& transport_alg, const int& dt_remap_factor, const int& dt_tracer_factor, const double& scale_factor, const double& laplacian_rigid_factor) @@ -90,7 +90,8 @@ void init_simulation_params_c (const int& remap_alg, const int& limiter_option, params.hypervis_subcycle = hypervis_subcycle; params.hypervis_scaling = hypervis_scaling; params.disable_diagnostics = disable_diagnostics; - params.moisture = (moisture ? MoistDry::MOIST : MoistDry::DRY); + params.use_moisture = use_moisture; + params.moisture = params.use_moisture ? MoistDry::MOIST : MoistDry::DRY; //todo-repo-unification params.use_cpstar = use_cpstar; params.transport_alg = transport_alg; // SphereOperators parameters; preqx supports only the sphere. diff --git a/components/homme/src/preqx_kokkos/cxx/prim_advance_exp.cpp b/components/homme/src/preqx_kokkos/cxx/prim_advance_exp.cpp index f7c7600aab8d..58e58f0160bf 100644 --- a/components/homme/src/preqx_kokkos/cxx/prim_advance_exp.cpp +++ b/components/homme/src/preqx_kokkos/cxx/prim_advance_exp.cpp @@ -34,7 +34,7 @@ void prim_advance_exp (TimeLevel& tl, const Real dt, const bool compute_diagnost // Determine the tracers time level tl.n0_qdp= -1; - if (params.moisture == MoistDry::MOIST) { + if (params.use_moisture) { tl.update_tracers_levels(params.qsplit); } diff --git a/components/homme/src/prim_main.F90 b/components/homme/src/prim_main.F90 index bfbe57e8b317..d6901151d365 100644 --- a/components/homme/src/prim_main.F90 +++ b/components/homme/src/prim_main.F90 @@ -20,7 +20,7 @@ program prim_main use element_mod, only: element_t use common_io_mod, only: output_dir, infilenames use common_movie_mod, only: nextoutputstep - use perf_mod, only: t_initf, t_prf, t_finalizef, t_startf, t_stopf ! _EXTERNAL + use perf_mod, only: t_initf, t_prf, t_finalizef, t_startf, t_stopf, t_disablef, t_enablef ! _EXTERNAL use restart_io_mod , only: restartheader_t, writerestart use hybrid_mod, only: hybrid_create #if (defined MODEL_THETA_L && defined ARKODE) @@ -240,6 +240,11 @@ end subroutine finalize_kokkos_f90 nstep = nextoutputstep(tl) do while(tl%nstep= 2) call t_enablef() call t_startf('prim_run') call prim_run_subcycle(elem, hybrid,nets,nete, tstep, .false., tl, hvcoord,1) call t_stopf('prim_run') diff --git a/components/homme/src/share/compose/cedr_kokkos.hpp b/components/homme/src/share/compose/cedr_kokkos.hpp index 42e423e2913a..758f4148a9a4 100644 --- a/components/homme/src/share/compose/cedr_kokkos.hpp +++ b/components/homme/src/share/compose/cedr_kokkos.hpp @@ -18,7 +18,7 @@ typedef Kokkos::Experimental::HIPSpace CedrGpuSpace; # endif # if defined KOKKOS_ENABLE_SYCL typedef Kokkos::Experimental::SYCL CedrGpuExeSpace; -typedef Kokkos::Experimental::SYCL> CedrGpuSpace; +typedef Kokkos::Experimental::SYCL CedrGpuSpace; # endif #endif diff --git a/components/homme/src/share/compose/compose_slmm_siqk.cpp b/components/homme/src/share/compose/compose_slmm_siqk.cpp index 628c023090cb..56564b0b8ca6 100644 --- a/components/homme/src/share/compose/compose_slmm_siqk.cpp +++ b/components/homme/src/share/compose/compose_slmm_siqk.cpp @@ -60,8 +60,10 @@ class TestSphereToRefKernel { // tol is on dx, not (a,b), so adjust slightly. if ( ! info.success || err > 1e4*tol_) { jinfo.nfails++; +#ifndef KOKKOS_ENABLE_SYCL printf("calc_sphere_to_ref ei %d i %d j %d: nits %d re %1.1e\n", ei, i, j, info.n_iterations, err); +#endif } jinfo.sum_nits += info.n_iterations; jinfo.max_nits = max(jinfo.max_nits, info.n_iterations); diff --git a/components/homme/src/share/cxx/Config.hpp b/components/homme/src/share/cxx/Config.hpp index 684f9143beaf..b204b1dbd047 100644 --- a/components/homme/src/share/cxx/Config.hpp +++ b/components/homme/src/share/cxx/Config.hpp @@ -21,7 +21,7 @@ # endif #endif -#if ! defined HOMMEXX_CUDA_SPACE && ! defined HOMMEXX_OPENMP_SPACE && ! defined HOMMEXX_THREADS_SPACE && ! defined HOMMEXX_SERIAL_SPACE && ! defined HOMMEXX_HIP_SPACE +#if ! defined HOMMEXX_CUDA_SPACE && ! defined HOMMEXX_OPENMP_SPACE && ! defined HOMMEXX_THREADS_SPACE && ! defined HOMMEXX_SERIAL_SPACE && ! defined HOMMEXX_HIP_SPACE && ! defined HOMMEXX_SYCL_SPACE # define HOMMEXX_DEFAULT_SPACE #endif diff --git a/components/homme/src/share/cxx/EulerStepFunctorImpl.hpp b/components/homme/src/share/cxx/EulerStepFunctorImpl.hpp index f3029764dac3..f87bb108bebf 100644 --- a/components/homme/src/share/cxx/EulerStepFunctorImpl.hpp +++ b/components/homme/src/share/cxx/EulerStepFunctorImpl.hpp @@ -652,7 +652,10 @@ class EulerStepFunctorImpl { minmax_and_biharmonic(); } } + + GPTLstart("tl-at adv-n-limit"); advect_and_limit(); + GPTLstop("tl-at adv-n-limit"); exchange_qdp_dss_var(); } @@ -667,6 +670,7 @@ class EulerStepFunctorImpl { void run_tracer_phase (const KernelVariables& kv) const { compute_qtens(kv); kv.team_barrier(); + if (m_data.limiter_option == 8) { limiter_optim_iter_full(kv); kv.team_barrier(); @@ -674,6 +678,7 @@ class EulerStepFunctorImpl { limiter_clip_and_sum(kv); kv.team_barrier(); } + apply_spheremp(kv); } diff --git a/components/homme/src/share/cxx/ExecSpaceDefs.cpp b/components/homme/src/share/cxx/ExecSpaceDefs.cpp index 8d496bff5d16..4f3d97135fea 100644 --- a/components/homme/src/share/cxx/ExecSpaceDefs.cpp +++ b/components/homme/src/share/cxx/ExecSpaceDefs.cpp @@ -21,6 +21,10 @@ #include #endif +#ifdef KOKKOS_ENABLE_SYCL +#include +#endif + namespace Homme { // Since we're initializing from inside a Fortran code and don't have access to @@ -52,7 +56,16 @@ void initialize_kokkos () { // It isn't a big deal if we can't get the device count. nd = 1; } +#elif defined(KOKKOS_ENABLE_SYCL) + +//https://developer.codeplay.com/products/computecpp/ce/2.11.0/guides/sycl-for-cuda-developers/migrating-from-cuda-to-sycl + +//to make it build + int nd = 1; + #endif + + #ifdef HOMMEXX_ENABLE_GPU std::stringstream ss; ss << "--kokkos-num-devices=" << nd; @@ -117,6 +130,7 @@ team_num_threads_vectors_for_gpu ( assert(num_warps_total >= max_num_warps); assert(tp.max_threads_usable >= 1 && tp.max_vectors_usable >= 1); +#ifndef KOKKOS_ENABLE_SYCL int num_warps; if (tp.prefer_larger_team) { const int num_warps_usable = @@ -161,6 +175,9 @@ team_num_threads_vectors_for_gpu ( return std::make_pair( num_device_threads / num_vectors, num_vectors ); } +#else + return std::make_pair(16,8); +#endif } } // namespace Parallel diff --git a/components/homme/src/share/cxx/ExecSpaceDefs.hpp b/components/homme/src/share/cxx/ExecSpaceDefs.hpp index cd6649c7ab2d..82f5e803801c 100644 --- a/components/homme/src/share/cxx/ExecSpaceDefs.hpp +++ b/components/homme/src/share/cxx/ExecSpaceDefs.hpp @@ -34,6 +34,10 @@ using HommexxGPU = Kokkos::Cuda; using HommexxGPU = Kokkos::Experimental::HIP; #endif +#ifdef KOKKOS_ENABLE_SYCL +using HommexxGPU = Kokkos::Experimental::SYCL; +#endif + #else using HommexxGPU = void; #endif diff --git a/components/homme/src/share/cxx/GllFvRemap.cpp b/components/homme/src/share/cxx/GllFvRemap.cpp index e36dbc14d74f..7b0400427f38 100644 --- a/components/homme/src/share/cxx/GllFvRemap.cpp +++ b/components/homme/src/share/cxx/GllFvRemap.cpp @@ -16,13 +16,13 @@ namespace Homme { void init_gllfvremap_c (int nelemd, int np, int nf, int nf_max, - bool theta_hydrostatic_mode, + int theta_hydrostatic_mode, CF90Ptr fv_metdet, CF90Ptr g2f_remapd, CF90Ptr f2g_remapd, CF90Ptr D_f, CF90Ptr Dinv_f) { auto& c = Context::singleton(); auto& g = c.get(); - g.init_data(nf, nf_max, theta_hydrostatic_mode, fv_metdet, g2f_remapd, - f2g_remapd, D_f, Dinv_f); + const bool thm = static_cast(theta_hydrostatic_mode); + g.init_data(nf, nf_max, thm, fv_metdet, g2f_remapd, f2g_remapd, D_f, Dinv_f); } GllFvRemap::GllFvRemap () { @@ -52,7 +52,7 @@ void GllFvRemap::init_boundary_exchanges () { } void GllFvRemap -::init_data (const int nf, const int nf_max, bool theta_hydrostatic_mode, +::init_data (const int nf, const int nf_max, const bool theta_hydrostatic_mode, const Real* fv_metdet, const Real* g2f_remapd, const Real* f2g_remapd, const Real* D_f, const Real* Dinv_f) { m_impl->init_data(nf, nf_max, theta_hydrostatic_mode, fv_metdet, diff --git a/components/homme/src/share/cxx/GllFvRemap.hpp b/components/homme/src/share/cxx/GllFvRemap.hpp index 07e4bf58a903..7ebf5a82b71a 100644 --- a/components/homme/src/share/cxx/GllFvRemap.hpp +++ b/components/homme/src/share/cxx/GllFvRemap.hpp @@ -40,7 +40,7 @@ class GllFvRemap { typedef Phys2T::const_type CPhys2T; typedef Phys3T::const_type CPhys3T; - void init_data(const int nf, const int nf_max, bool theta_hydrostatic_mode, + void init_data(const int nf, const int nf_max, const bool theta_hydrostatic_mode, const Real* fv_metdet, const Real* g2f_remapd, const Real* f2g_remapd, const Real* D_f, const Real* Dinv_f); @@ -81,7 +81,7 @@ class GllFvRemap { extern "C" void init_gllfvremap_c(int nelemd, int np, int nf, int nf_max, - const bool theta_hydrostatic_mode, + const int theta_hydrostatic_mode, CF90Ptr fv_metdet, CF90Ptr g2f_remapd, CF90Ptr f2g_remapd, CF90Ptr D_f, CF90Ptr Dinv_f); diff --git a/components/homme/src/share/cxx/GllFvRemapImpl.cpp b/components/homme/src/share/cxx/GllFvRemapImpl.cpp index 6148f69cfa9c..ea1a52f5efdf 100644 --- a/components/homme/src/share/cxx/GllFvRemapImpl.cpp +++ b/components/homme/src/share/cxx/GllFvRemapImpl.cpp @@ -142,7 +142,7 @@ ::init_data (const int nf, const int nf_max, const bool theta_hydrostatic_mode, " nf must be > 1.", Errors::err_not_implemented); auto& sp = Context::singleton().get(); - m_data.use_moisture = sp.moisture == MoistDry::MOIST; + m_data.use_moisture = sp.use_moisture; // Only in the unit test gllfvremap_ut does theta_hydrostatic_mode not already // == sp.theta_hydrostatic_mode. m_data.theta_hydrostatic_mode = sp.theta_hydrostatic_mode = theta_hydrostatic_mode; diff --git a/components/homme/src/share/cxx/HommexxEnums.hpp b/components/homme/src/share/cxx/HommexxEnums.hpp index 59c8f3c9652c..f41ed9d3651e 100644 --- a/components/homme/src/share/cxx/HommexxEnums.hpp +++ b/components/homme/src/share/cxx/HommexxEnums.hpp @@ -40,6 +40,12 @@ enum class ComparisonOp { // =================== Run parameters enums ====================== // +//todo-repo-unification Remove this enum in favor of bool +// SimulationParams::use_moisture once we change EAMxx to use +// use_moisture. Search "todo-repo-unification" for other bits of code to +// remove. +enum class MoistDry { MOIST, DRY }; + enum class ForcingAlg : int { FORCING_OFF =-1, FORCING_0 = 0, @@ -47,11 +53,6 @@ enum class ForcingAlg : int { FORCING_2 = 2, // TODO: Rename FORCING_1 and FORCING_2 to something more descriptive }; -enum class MoistDry { - MOIST, - DRY -}; - enum class AdvectionForm { Conservative, NonConservative diff --git a/components/homme/src/share/cxx/SimulationParams.hpp b/components/homme/src/share/cxx/SimulationParams.hpp index b435911da2e6..9247f54a352c 100644 --- a/components/homme/src/share/cxx/SimulationParams.hpp +++ b/components/homme/src/share/cxx/SimulationParams.hpp @@ -23,7 +23,8 @@ struct SimulationParams void print(std::ostream& out = std::cout); TimeStepType time_step_type; - MoistDry moisture; + bool use_moisture; + MoistDry moisture; //todo-repo-unification RemapAlg remap_alg; TestCase test_case; ForcingAlg ftype = ForcingAlg::FORCING_OFF; @@ -77,7 +78,7 @@ inline void SimulationParams::print (std::ostream& out) { out << "\n************** CXX SimulationParams **********************\n\n"; out << " time_step_type: " << etoi(time_step_type) << "\n"; - out << " moisture: " << (moisture==MoistDry::DRY ? "dry" : "moist") << "\n"; + out << " use_moisture: " << (use_moisture ? "moist" : "dry") << "\n"; out << " remap_alg: " << etoi(remap_alg) << "\n"; out << " test case: " << etoi(test_case) << "\n"; out << " ftype: " << etoi(ftype) << "\n"; diff --git a/components/homme/src/share/cxx/utilities/BfbUtils.hpp b/components/homme/src/share/cxx/utilities/BfbUtils.hpp index e3570874e266..7fb4d042f7f2 100644 --- a/components/homme/src/share/cxx/utilities/BfbUtils.hpp +++ b/components/homme/src/share/cxx/utilities/BfbUtils.hpp @@ -64,7 +64,7 @@ KOKKOS_INLINE_FUNCTION ScalarType int_pow (ScalarType val, int k) { constexpr int max_shift = 30; if (k<0) { - printf ("k = %d\n",k); + Kokkos::printf ("k = %d\n",k); Kokkos::abort("int_pow implemented only for k>=0.\n"); } diff --git a/components/homme/src/share/cxx/utilities/InternalDiagnostics.cpp b/components/homme/src/share/cxx/utilities/InternalDiagnostics.cpp index 3249966c0b5e..ffc9657f4108 100644 --- a/components/homme/src/share/cxx/utilities/InternalDiagnostics.cpp +++ b/components/homme/src/share/cxx/utilities/InternalDiagnostics.cpp @@ -13,6 +13,8 @@ #include "TimeLevel.hpp" #include "mpi/Comm.hpp" +#include + namespace Homme { namespace { @@ -50,10 +52,10 @@ void print_global_state_hash (const std::string& label) { all_reduce_HashType(comm.mpi_comm(), accum, gaccum, 5); if (comm.root()) { for (int i = 0; i < NUM_TIME_LEVELS; ++i) - fprintf(stderr, "hxxhash> %14d %1d %16lx (E %s)\n", + fprintf(stderr, "hxxhash> %14d %1d %16" PRIx64 " (E %s)\n", tl.nstep, i, gaccum[i], label.c_str()); for (int i = 0; i < Q_NUM_TIME_LEVELS; ++i) - fprintf(stderr, "hxxhash> %14d %1d %16lx (T %s)\n", + fprintf(stderr, "hxxhash> %14d %1d %16" PRIx64 " (T %s)\n", tl.nstep, i, gaccum[NUM_TIME_LEVELS+i], label.c_str()); } } diff --git a/components/homme/src/share/cxx/utilities/scream_tridiag.hpp b/components/homme/src/share/cxx/utilities/scream_tridiag.hpp index e18bbc4e7e27..26221db39552 100644 --- a/components/homme/src/share/cxx/utilities/scream_tridiag.hpp +++ b/components/homme/src/share/cxx/utilities/scream_tridiag.hpp @@ -128,6 +128,10 @@ int get_thread_id_within_team_gpu (const TeamMember& team) { // Can't use team.team_rank() here because vector direction also uses physical // threads but TeamMember types don't expose that information. return blockDim.x * threadIdx.y + threadIdx.x; +#elif defined(__SYCL_DEVICE_ONLY__) + auto item = team.item(); + return static_cast(item.get_local_range(1) * item.get_local_id(0) + + item.get_local_id(1)); #else assert(0); return -1; @@ -138,6 +142,9 @@ template KOKKOS_FORCEINLINE_FUNCTION int get_team_nthr_gpu (const TeamMember& team) { #if defined __CUDA_ARCH__ || defined __HIP_DEVICE_COMPILE__ return blockDim.x * blockDim.y; +#elif defined __SYCL_DEVICE_ONLY__ + auto item = team.item(); + return static_cast(item.get_local_range(0) * item.get_local_range(1)); #else assert(0); return -1; @@ -161,6 +168,16 @@ KOKKOS_FORCEINLINE_FUNCTION int get_team_nthr (const Kokkos::Impl::HIPTeamMember& team) { return get_team_nthr_gpu(team); } #endif // KOKKOS_ENABLE_HIP + +#ifdef KOKKOS_ENABLE_SYCL +KOKKOS_FORCEINLINE_FUNCTION +int get_thread_id_within_team (const Kokkos::Impl::SYCLTeamMember& team) +{ return get_thread_id_within_team_gpu(team); } +KOKKOS_FORCEINLINE_FUNCTION +int get_team_nthr (const Kokkos::Impl::SYCLTeamMember& team) +{ return get_team_nthr_gpu(team); } +#endif // KOKKOS_ENABLE_SYCL + template KOKKOS_INLINE_FUNCTION const T& min (const T& a, const T& b) { return a < b ? a : b; } @@ -634,7 +651,7 @@ void bfb (const TeamMember& team, const auto f = [&] (const int& j) { impl::bfb_thomas_solve(dl, d, du, Kokkos::subview(X , Kokkos::ALL(), j)); }; - Kokkos::parallel_for(Kokkos::TeamThreadRange(team, nrhs), f); + Kokkos::parallel_for(Kokkos::TeamVectorRange(team, nrhs), f); } template @@ -664,7 +681,7 @@ void bfb (const TeamMember& team, subview(du, ALL(), j), subview(X , ALL(), j)); }; - Kokkos::parallel_for(Kokkos::TeamThreadRange(team, nrhs), f); + Kokkos::parallel_for(Kokkos::TeamVectorRange(team, nrhs), f); } } // namespace tridiag diff --git a/components/homme/src/share/gllfvremap_mod.F90 b/components/homme/src/share/gllfvremap_mod.F90 index e0e0fa6c4daa..d9dd8e33365a 100644 --- a/components/homme/src/share/gllfvremap_mod.F90 +++ b/components/homme/src/share/gllfvremap_mod.F90 @@ -266,21 +266,22 @@ end subroutine gfr_init subroutine gfr_init_hxx() bind(c) #if KOKKOS_TARGET use control_mod, only: theta_hydrostatic_mode - use iso_c_binding, only: c_bool + use iso_c_binding, only: c_int interface subroutine init_gllfvremap_c(nelemd, np, nf, nf_max, theta_hydrostatic_mode, & fv_metdet, g2f_remapd, f2g_remapd, D_f, Dinv_f) bind(c) - use iso_c_binding, only: c_bool, c_int, c_double + use iso_c_binding, only: c_int, c_double integer (c_int), value, intent(in) :: nelemd, np, nf, nf_max - logical (c_bool), value, intent(in) :: theta_hydrostatic_mode + integer (c_int), value, intent(in) :: theta_hydrostatic_mode real (c_double), dimension(nf*nf,nelemd), intent(in) :: fv_metdet real (c_double), dimension(np,np,nf_max*nf_max), intent(in) :: g2f_remapd real (c_double), dimension(nf_max*nf_max,np,np), intent(in) :: f2g_remapd real (c_double), dimension(nf*nf,2,2,nelemd), intent(in) :: D_f, Dinv_f end subroutine init_gllfvremap_c end interface - logical (c_bool) :: thm - thm = theta_hydrostatic_mode + integer (c_int) :: thm + thm = 0 + if (theta_hydrostatic_mode) thm = 1 call init_gllfvremap_c(nelemd, np, gfr%nphys, nphys_max, thm, & gfr%fv_metdet, gfr%g2f_remapd, gfr%f2g_remapd, gfr%D_f, gfr%Dinv_f) #endif @@ -2088,9 +2089,14 @@ subroutine gfr_f_get_latlon(ie, i, j, lat, lon) type (spherical_polar_t) :: p - p = change_coordinates(gfr%center_f(i,j,ie)) - lat = p%lat - lon = p%lon + if (gfr%is_planar) then + lon = gfr%center_f(i,j,ie)%x + lat = gfr%center_f(i,j,ie)%y + else + p = change_coordinates(gfr%center_f(i,j,ie)) + lat = p%lat + lon = p%lon + end if end subroutine gfr_f_get_latlon subroutine gfr_f_get_corner_latlon(ie, i, j, c, lat, lon) @@ -2103,9 +2109,14 @@ subroutine gfr_f_get_corner_latlon(ie, i, j, c, lat, lon) type (spherical_polar_t) :: p - p = change_coordinates(gfr%corners_f(c,i,j,ie)) - lat = p%lat - lon = p%lon + if (gfr%is_planar) then + lon = gfr%corners_f(c,i,j,ie)%x + lat = gfr%corners_f(c,i,j,ie)%y + else + p = change_coordinates(gfr%corners_f(c,i,j,ie)) + lat = p%lat + lon = p%lon + end if end subroutine gfr_f_get_corner_latlon subroutine gfr_f_get_cartesian3d(ie, i, j, p) @@ -2318,6 +2329,7 @@ subroutine set_ps_Q(elem, nets, nete, timeidx, qidx, nlev) ! Make up a test function for use in unit tests. use coordinate_systems_mod, only: cartesian3D_t, change_coordinates + use physical_constants, only: dd_pi, Lx, Ly type (element_t), intent(inout) :: elem(:) integer, intent(in) :: nets, nete, timeidx, qidx, nlev @@ -2329,7 +2341,13 @@ subroutine set_ps_Q(elem, nets, nete, timeidx, qidx, nlev) do ie = nets, nete do j = 1,np do i = 1,np - p = change_coordinates(elem(ie)%spherep(i,j)) + if (gfr%is_planar) then + p%x = elem(ie)%spherep(i,j)%lon*2*dd_pi/Lx + p%y = elem(ie)%spherep(i,j)%lat*2*dd_pi/Ly + p%z = 0 + else + p = change_coordinates(elem(ie)%spherep(i,j)) + end if elem(ie)%state%ps_v(i,j,timeidx) = & 1.0d3*(1 + 0.05*sin(2*p%x+0.5)*sin(p%y+1.5)*sin(3*p%z+2.5)) q = 0.5*(1 + sin(3*p%x)*sin(3*p%y)*sin(4*p%z)) @@ -2609,7 +2627,8 @@ function check(par, dom_mt, gfr, elem, verbose) result(nerr) logical, intent(in) :: verbose real(kind=real_kind) :: a, b, rd, x, y, f0(np*np), f1(np*np), g(np,np), & - wf(np*np), wg(np,np), qmin, qmax, qmin1, qmax1 + wf(np*np), wg(np,np), qmin, qmax, qmin1, qmax1, lat, lon, latext(2), & + lonext(2), tol integer :: nf, nf2, ie, i, j, k, iremap, info, ilimit, it real(kind=real_kind), allocatable :: Qdp_fv(:,:), ps_v_fv(:,:), & qmins(:,:,:), qmaxs(:,:,:) @@ -2669,6 +2688,31 @@ function check(par, dom_mt, gfr, elem, verbose) result(nerr) nerr = nerr + 1 write(iulog,*) 'gfr> Dinv', ie, rd end if + if (gfr%is_planar) then + lonext(1) = minval(elem(ie)%spherep(:,:)%lon) + lonext(2) = maxval(elem(ie)%spherep(:,:)%lon) + latext(1) = minval(elem(ie)%spherep(:,:)%lat) + latext(2) = maxval(elem(ie)%spherep(:,:)%lat) + tol = max(lonext(2) - lonext(1), latext(2) - latext(1))*1.e4*eps + do i = 1, nf + do j = 1, nf + call gfr_f_get_latlon(ie, i, j, lat, lon) + if ( lon < lonext(1) .or. lon > lonext(2) .or. & + lat < latext(1) .or. lat > latext(2)) then + write(iulog,*) 'gfr> planar latlon ctr', ie, latext, lonext, lat, lon + nerr = nerr + 1 + end if + do k = 1, 4 + call gfr_f_get_corner_latlon(ie, i, j, k, lat, lon) + if ( lon < lonext(1) - tol .or. lon > lonext(2) + tol .or. & + lat < latext(1) - tol .or. lat > latext(2) + tol) then + write(iulog,*) 'gfr> planar latlon crn', ie, latext, lonext, lat, lon + nerr = nerr + 1 + end if + end do + end do + end do + end if ! Check that FV -> GLL -> FV recovers the original FV values exactly ! (with no DSS and no limiter). @@ -2839,8 +2883,8 @@ function test_sphere2ref() result(nerr) use kinds, only: iulog type (cartesian3D_t) :: corners(4), sphere - real (real_kind) :: refin(2), refout(2), err - integer :: i, j, n, nerr + real (real_kind) :: refin(2), refout(2), err, tol + integer :: i, j, n, trial, nerr nerr = 0 @@ -2854,18 +2898,28 @@ function test_sphere2ref() result(nerr) do i = 1,n refin(1) = -1 + (1.0_real_kind/(n-1))*(i-1) do j = 1,n - refin(2) = -1 + (1.0_real_kind/(n-1))*(j-1) - call ref2sphere(corners, refin(1), refin(2), sphere) - call sphere2ref(corners, sphere, refout(1), refout(2)) - err = abs(refin(1) - refout(1)) + abs(refin(2) - refout(2)) - if (err > 15*eps .or. & - maxval(abs(refout)) > 1 + 5*eps .or. & - any(refout /= refout)) then - write(iulog,*) refin(1), refin(2) - write(iulog,*) refout(1), refout(2) - write(iulog,*) err - nerr = nerr + 1 - end if + do trial = 1, 2 + refin(2) = -1 + (1.0_real_kind/(n-1))*(j-1) + call ref2sphere(corners, refin(1), refin(2), sphere) + if (trial == 2) then + sphere%x = 0.9d0*sphere%x + sphere%y = 0.9d0*sphere%y + sphere%z = 0.9d0*sphere%z + end if + call sphere2ref(corners, sphere, refout(1), refout(2)) + err = abs(refin(1) - refout(1)) + abs(refin(2) - refout(2)) + tol = 15*eps + if (trial == 2) tol = 1e-6 + if (err > tol .or. & + maxval(abs(refout)) > 1 + 5*eps .or. & + any(refout /= refout)) then + write(iulog,*) 'gfr> test_sphere2ref trial', trial + write(iulog,*) refin(1), refin(2) + write(iulog,*) refout(1), refout(2) + write(iulog,*) err + nerr = nerr + 1 + end if + end do end do end do if (nerr /= 0) write(iulog,*) 'test_sphere2ref FAILED' diff --git a/components/homme/src/theta-l_kokkos/cxx/CamForcing.cpp b/components/homme/src/theta-l_kokkos/cxx/CamForcing.cpp index 02b999db16e9..bd7cee3e7c0a 100644 --- a/components/homme/src/theta-l_kokkos/cxx/CamForcing.cpp +++ b/components/homme/src/theta-l_kokkos/cxx/CamForcing.cpp @@ -33,7 +33,7 @@ static void apply_cam_forcing_tracers(const Real dt, ForcingFunctor& ff, if ( p.ftype == ForcingAlg::FORCING_2) adjustment = true; #endif - ff.tracers_forcing(dt, tl.n0, tl.n0_qdp, adjustment, p.moisture); + ff.tracers_forcing(dt, tl.n0, tl.n0_qdp, adjustment, p.use_moisture); GPTLstop("ApplyCAMForcing_tracers"); } diff --git a/components/homme/src/theta-l_kokkos/cxx/DirkFunctorImpl.hpp b/components/homme/src/theta-l_kokkos/cxx/DirkFunctorImpl.hpp index ace1ba920141..d16769079729 100644 --- a/components/homme/src/theta-l_kokkos/cxx/DirkFunctorImpl.hpp +++ b/components/homme/src/theta-l_kokkos/cxx/DirkFunctorImpl.hpp @@ -382,8 +382,8 @@ struct DirkFunctorImpl { kv.team_barrier(); if (it >= maxiter) { - printf("[DIRK] WARNING! Newton reached max iteration count," - " with deltaerr = %3.17f\n", deltaerr); + Kokkos::printf("[DIRK] WARNING! Newton reached max iteration count," + " with deltaerr = %3.17f\n", deltaerr); nerr = 1; } diff --git a/components/homme/src/theta-l_kokkos/cxx/ForcingFunctor.hpp b/components/homme/src/theta-l_kokkos/cxx/ForcingFunctor.hpp index 28a702c1d273..00fa1deef667 100644 --- a/components/homme/src/theta-l_kokkos/cxx/ForcingFunctor.hpp +++ b/components/homme/src/theta-l_kokkos/cxx/ForcingFunctor.hpp @@ -236,7 +236,7 @@ class ForcingFunctor }); } - void tracers_forcing (const Real dt, const int np1, const int np1_qdp, const bool adjustment, const MoistDry moisture) { + void tracers_forcing (const Real dt, const int np1, const int np1_qdp, const bool adjustment, const bool use_moisture) { // The Functor needs to be fully setup to use this function assert (is_setup); @@ -245,7 +245,7 @@ class ForcingFunctor m_np1_qdp = np1_qdp; m_adjustment = adjustment; - m_moist = (moisture==MoistDry::MOIST); + m_moist = use_moisture; Kokkos::parallel_for("temperature, NH perturb press, FQps",m_policy_tracers_pre,*this); Kokkos::fence(); diff --git a/components/homme/src/theta-l_kokkos/cxx/HyperviscosityFunctorImpl.cpp b/components/homme/src/theta-l_kokkos/cxx/HyperviscosityFunctorImpl.cpp index 046e6f9956d4..d160e114475b 100644 --- a/components/homme/src/theta-l_kokkos/cxx/HyperviscosityFunctorImpl.cpp +++ b/components/homme/src/theta-l_kokkos/cxx/HyperviscosityFunctorImpl.cpp @@ -118,9 +118,9 @@ void HyperviscosityFunctorImpl::init_params(const SimulationParams& params) m_eos.init(params.theta_hydrostatic_mode,m_hvcoord); #ifdef HOMMEXX_BFB_TESTING - m_process_nh_vars = true; + m_process_nh_vars = 1; #else - m_process_nh_vars = !params.theta_hydrostatic_mode; + m_process_nh_vars = not params.theta_hydrostatic_mode; #endif } diff --git a/components/homme/src/theta-l_kokkos/cxx/LimiterFunctor.hpp b/components/homme/src/theta-l_kokkos/cxx/LimiterFunctor.hpp index cd3bf7c32526..7914c0a60e3a 100644 --- a/components/homme/src/theta-l_kokkos/cxx/LimiterFunctor.hpp +++ b/components/homme/src/theta-l_kokkos/cxx/LimiterFunctor.hpp @@ -141,8 +141,8 @@ struct LimiterFunctor { [&](const int k,Real& result) { #ifndef HOMMEXX_BFB_TESTING if(diff_as_real(k) < 0){ - printf("WARNING:CAAR: dp3d too small. k=%d, dp3d(k)=%f, dp0=%f \n", - k+1,dp_as_real(k),dp0_as_real(k)); + Kokkos::printf("WARNING:CAAR: dp3d too small. k=%d, dp3d(k)=%f, dp0=%f \n", + k+1,dp_as_real(k),dp0_as_real(k)); } #endif result = result<=diff_as_real(k) ? result : diff_as_real(k); @@ -202,8 +202,8 @@ struct LimiterFunctor { for (int ivec=0; ivec(e.m_forcing); } -void init_functors_c (const bool& allocate_buffer) +void init_functors_c (const int& allocate_buffer) { auto& c = Context::singleton(); diff --git a/components/homme/src/theta-l_kokkos/prim_driver_mod.F90 b/components/homme/src/theta-l_kokkos/prim_driver_mod.F90 index 96b42314453f..e7cc245a2bd7 100644 --- a/components/homme/src/theta-l_kokkos/prim_driver_mod.F90 +++ b/components/homme/src/theta-l_kokkos/prim_driver_mod.F90 @@ -64,7 +64,7 @@ subroutine prim_init2(elem, hybrid, nets, nete, tl, hvcoord) end subroutine prim_init2 subroutine prim_create_c_data_structures (tl, hvcoord, mp) - use iso_c_binding, only : c_loc, c_ptr, c_bool, C_NULL_CHAR + use iso_c_binding, only : c_loc, c_ptr, C_NULL_CHAR use theta_f2c_mod, only : init_reference_element_c, init_simulation_params_c, & init_time_level_c, init_hvcoord_c, init_elements_c use time_mod, only : TimeLevel_t, nsplit @@ -73,7 +73,7 @@ subroutine prim_create_c_data_structures (tl, hvcoord, mp) nu, nu_p, nu_q, nu_s, nu_div, nu_top, vert_remap_q_alg, & hypervis_order, hypervis_subcycle, hypervis_subcycle_tom,& hypervis_scaling, & - ftype, prescribed_wind, moisture, disable_diagnostics, & + ftype, prescribed_wind, use_moisture, disable_diagnostics, & use_cpstar, transport_alg, theta_hydrostatic_mode, & dcmip16_mu, theta_advect_form, test_case, & MAX_STRING_LEN, dt_remap_factor, dt_tracer_factor, & @@ -93,6 +93,8 @@ subroutine prim_create_c_data_structures (tl, hvcoord, mp) type (c_ptr) :: hybrid_am_ptr, hybrid_ai_ptr, hybrid_bm_ptr, hybrid_bi_ptr character(len=MAX_STRING_LEN), target :: test_name + integer :: disable_diagnostics_int, theta_hydrostatic_mode_int, use_moisture_int + ! Initialize the C++ reference element structure (i.e., pseudo-spectral deriv matrix and ref element mass matrix) dvv = deriv1%dvv elem_mp = mp @@ -100,22 +102,30 @@ subroutine prim_create_c_data_structures (tl, hvcoord, mp) ! Fill the simulation params structures in C++ test_name = TRIM(test_case) // C_NULL_CHAR + + disable_diagnostics_int = 0 + if (disable_diagnostics) disable_diagnostics_int = 1 + use_moisture_int = 0 + if (use_moisture) use_moisture_int = 1 + theta_hydrostatic_mode_int = 0 + if (theta_hydrostatic_mode) theta_hydrostatic_mode_int = 1 + call init_simulation_params_c (vert_remap_q_alg, limiter_option, rsplit, qsplit, tstep_type, & qsize, statefreq, nu, nu_p, nu_q, nu_s, nu_div, nu_top, & hypervis_order, hypervis_subcycle, hypervis_subcycle_tom, & hypervis_scaling, & dcmip16_mu, ftype, theta_advect_form, & - LOGICAL(prescribed_wind==1,c_bool), & - LOGICAL(moisture/="dry",c_bool), & - LOGICAL(disable_diagnostics,c_bool), & - LOGICAL(use_cpstar==1,c_bool), & + prescribed_wind, & + use_moisture_int, & + disable_diagnostics_int, & + use_cpstar, & transport_alg, & - LOGICAL(theta_hydrostatic_mode,c_bool), & + theta_hydrostatic_mode_int, & c_loc(test_name), & dt_remap_factor, dt_tracer_factor, & scale_factor, laplacian_rigid_factor, & nsplit, & - LOGICAL(pgrad_correction==1,c_bool), & + pgrad_correction, & dp3d_thresh, vtheta_thresh, internal_diagnostics_level) ! Initialize time level structure in C++ @@ -343,22 +353,23 @@ subroutine prim_init_elements_views (elem) end subroutine prim_init_elements_views subroutine prim_init_kokkos_functors (allocate_buffer) - use iso_c_binding, only : c_bool + !todo-repo-unification Remove the use of c_bool here. It's used in purely + ! F90 code. + use iso_c_binding, only : c_int, c_bool use theta_f2c_mod, only : init_functors_c, init_boundary_exchanges_c - ! ! Optional Input ! - logical(kind=c_bool), optional :: allocate_buffer ! Whether functor memory buffer should be allocated internally - + logical(kind=c_bool), intent(in), optional :: allocate_buffer ! Whether functor memory buffer should be allocated internally + integer(kind=c_int) :: ab ! Initialize the C++ functors in the C++ context ! If no argument allocate_buffer is present, ! let Homme internally allocate buffers + ab = 1 if (present(allocate_buffer)) then - call init_functors_c (logical(allocate_buffer,c_bool)) - else - call init_functors_c (logical(.true.,c_bool)) - endif + if (.not. allocate_buffer) ab = 0 + end if + call init_functors_c (ab) ! Initialize boundary exchange structure in C++ call init_boundary_exchanges_c () diff --git a/components/homme/src/theta-l_kokkos/theta_f2c_mod.F90 b/components/homme/src/theta-l_kokkos/theta_f2c_mod.F90 index 7a4c0424807b..ba39bb03c22b 100644 --- a/components/homme/src/theta-l_kokkos/theta_f2c_mod.F90 +++ b/components/homme/src/theta-l_kokkos/theta_f2c_mod.F90 @@ -11,14 +11,14 @@ subroutine init_simulation_params_c (remap_alg, limiter_option, rsplit, qsplit, qsize, state_frequency, nu, nu_p, nu_q, nu_s, nu_div, nu_top, & hypervis_order, hypervis_subcycle, hypervis_subcycle_tom, & hypervis_scaling, & - dcmip16_mu, ftype, theta_adv_form, prescribed_wind, moisture, & + dcmip16_mu, ftype, theta_adv_form, prescribed_wind, use_moisture, & disable_diagnostics, use_cpstar, transport_alg, & theta_hydrostatic_mode, test_case_name, dt_remap_factor, & dt_tracer_factor, scale_factor, laplacian_rigid_factor, & nsplit, pgrad_correction, dp3d_thresh, vtheta_thresh, & internal_diagnostics_level) bind(c) - use iso_c_binding, only: c_int, c_bool, c_double, c_ptr + use iso_c_binding, only: c_int, c_double, c_ptr ! ! Inputs ! @@ -29,8 +29,8 @@ subroutine init_simulation_params_c (remap_alg, limiter_option, rsplit, qsplit, scale_factor, laplacian_rigid_factor, dp3d_thresh, vtheta_thresh integer(kind=c_int), intent(in) :: hypervis_order, hypervis_subcycle, hypervis_subcycle_tom integer(kind=c_int), intent(in) :: ftype, theta_adv_form - logical(kind=c_bool), intent(in) :: prescribed_wind, moisture, disable_diagnostics, use_cpstar - logical(kind=c_bool), intent(in) :: theta_hydrostatic_mode, pgrad_correction + integer(kind=c_int), intent(in) :: prescribed_wind, use_moisture, disable_diagnostics, use_cpstar + integer(kind=c_int), intent(in) :: theta_hydrostatic_mode, pgrad_correction type(c_ptr), intent(in) :: test_case_name end subroutine init_simulation_params_c @@ -138,11 +138,11 @@ end subroutine init_reference_element_c ! Create C++ functors subroutine init_functors_c (allocate_buffer) bind(c) - use iso_c_binding, only: c_bool + use iso_c_binding, only: c_int ! ! Inputs ! - logical(kind=c_bool), intent(in) :: allocate_buffer + integer(kind=c_int), intent(in) :: allocate_buffer end subroutine init_functors_c ! Initialize C++ boundary exchange structures diff --git a/components/homme/test_execs/CMakeLists.txt b/components/homme/test_execs/CMakeLists.txt index a3113921b029..a007a5532b61 100644 --- a/components/homme/test_execs/CMakeLists.txt +++ b/components/homme/test_execs/CMakeLists.txt @@ -142,8 +142,11 @@ ADD_CUSTOM_TARGET(test-execs) ADD_CUSTOM_TARGET(check COMMAND ${CMAKE_CTEST_COMMAND} "--output-on-failure") +if(NOT BUILD_HOMME_WITHOUT_PIOLIBRARY) # Force cprnc to be built when make check is run ADD_DEPENDENCIES(check cprnc) +endif() + # Create a target for making the reference data ADD_CUSTOM_TARGET(baseline diff --git a/components/homme/test_execs/share_kokkos_ut/CMakeLists.txt b/components/homme/test_execs/share_kokkos_ut/CMakeLists.txt index 3fbeff9f6f2c..bc788462ce6e 100644 --- a/components/homme/test_execs/share_kokkos_ut/CMakeLists.txt +++ b/components/homme/test_execs/share_kokkos_ut/CMakeLists.txt @@ -10,7 +10,7 @@ SET(UTILS_TIMING_DIRS ${UTILS_TIMING_SRC_DIR} ${UTILS_TIMING_BIN_DIR}) # Note: need CUDA_BUILD and HOMMEXX_BFB_TESTING here, since the share # unit tests do not include a config.h file SET (COMMON_DEFINITIONS NP=4 NC=4) -IF (CUDA_BUILD OR HIP_BUILD) +IF (CUDA_BUILD OR HIP_BUILD OR SYCL_BUILD) SET(COMMON_DEFINITIONS ${COMMON_DEFINITIONS} HOMMEXX_ENABLE_GPU_F90) ENDIF() IF (HOMMEXX_BFB_TESTING) @@ -158,7 +158,7 @@ ELSE() SET (NUM_CPUS 1) ENDIF() cxx_unit_test (sphere_op_ut "${SPHERE_OP_UT_F90_SRCS}" "${SPHERE_OP_UT_CXX_SRCS}" "${SPHERE_OP_UT_INCLUDE_DIRS}" "${CONFIG_DEFINES}" ${NUM_CPUS}) -endif () +endif () #BFB ### Limiters unit test ### diff --git a/components/homme/test_execs/thetal_kokkos_ut/CMakeLists.txt b/components/homme/test_execs/thetal_kokkos_ut/CMakeLists.txt index 205635e918cc..e8bf5e20bd03 100644 --- a/components/homme/test_execs/thetal_kokkos_ut/CMakeLists.txt +++ b/components/homme/test_execs/thetal_kokkos_ut/CMakeLists.txt @@ -11,6 +11,8 @@ SET(UTILS_TIMING_BIN_DIR ${HOMME_BINARY_DIR}/utils/cime/CIME/non_py/src/timing) THETAL_KOKKOS_SETUP() # This is needed to compile the lib and test executables with the correct options +#these vars shared between all targets, so changing one var +#for one test only won't work, config is built once and for the last test SET(THIS_CONFIG_IN ${HOMME_SOURCE_DIR}/src/theta-l_kokkos/config.h.cmake.in) SET(THIS_CONFIG_HC ${CMAKE_CURRENT_BINARY_DIR}/config.h.c) SET(THIS_CONFIG_H ${CMAKE_CURRENT_BINARY_DIR}/config.h) @@ -18,6 +20,7 @@ SET (NUM_POINTS 4) SET (NUM_PLEV 12) SET (QSIZE_D 4) SET (PIO_INTERP TRUE) + HommeConfigFile (${THIS_CONFIG_IN} ${THIS_CONFIG_HC} ${THIS_CONFIG_H} ) ADD_LIBRARY(thetal_kokkos_ut_lib diff --git a/components/homme/test_execs/thetal_kokkos_ut/forcing_ut.cpp b/components/homme/test_execs/thetal_kokkos_ut/forcing_ut.cpp index 5e4c51c7ca11..fb301166f429 100644 --- a/components/homme/test_execs/thetal_kokkos_ut/forcing_ut.cpp +++ b/components/homme/test_execs/thetal_kokkos_ut/forcing_ut.cpp @@ -160,8 +160,8 @@ TEST_CASE("forcing", "forcing") { std::cout << "Testing tracers forcing.\n"; for (const bool hydrostatic : {true,false}) { std::cout << " -> hydrostatic mode: " << (hydrostatic ? "true" : "false") << "\n"; - for (const MoistDry moisture : {MoistDry::DRY,MoistDry::MOIST}) { - std::cout << " -> moisture: " << (moisture==MoistDry::MOIST ? "moist" : "dry") << "\n"; + for (const bool use_moisture: {false,true}) { + std::cout << " -> moisture: " << (use_moisture ? "moist" : "dry") << "\n"; for (const bool adjustment : {true,false}) { std::cout << " -> adjustment: " << (adjustment ? "true" : "false") << "\n"; @@ -200,8 +200,8 @@ TEST_CASE("forcing", "forcing") { ff.init_buffers(fbm); // Run tracers forcing (cxx and f90) - ff.tracers_forcing(dt,np1,np1_qdp,adjustment,moisture); - tracers_forcing_f90(dt,np1+1,np1_qdp+1,hydrostatic,moisture==MoistDry::MOIST,adjustment); + ff.tracers_forcing(dt,np1,np1_qdp,adjustment,use_moisture); + tracers_forcing_f90(dt,np1+1,np1_qdp+1,hydrostatic,use_moisture,adjustment); // Compare answers Kokkos::deep_copy(h_dp,state.m_dp3d); diff --git a/components/homme/test_execs/thetal_kokkos_ut/gllfvremap_ut.cpp b/components/homme/test_execs/thetal_kokkos_ut/gllfvremap_ut.cpp index 0f14b0c3e55a..cf9db941ea1c 100644 --- a/components/homme/test_execs/thetal_kokkos_ut/gllfvremap_ut.cpp +++ b/components/homme/test_execs/thetal_kokkos_ut/gllfvremap_ut.cpp @@ -183,7 +183,7 @@ struct Session { p.qsize = qsize; p.hypervis_scaling = 0; p.transport_alg = 0; - p.moisture = MoistDry::MOIST; + p.use_moisture = true; p.theta_hydrostatic_mode = false; p.scale_factor = is_sphere ? PhysicalConstants::rearth0 : 1; p.laplacian_rigid_factor = is_sphere ? 1/p.scale_factor : 0; @@ -725,7 +725,7 @@ static void test_get_temperature (Session& s) { const auto& sp = c.get(); EquationOfState eos; eos.init(theta_hydrostatic_mode, s.h); ElementOps ops; ops.init(s.h); - const bool use_moisture = sp.moisture == MoistDry::MOIST; + const bool use_moisture = sp.use_moisture; const auto state = c.get(); const auto tracers = c.get(); const auto dp3d = state.m_dp3d; diff --git a/components/mosart/src/riverroute/MOSART_physics_mod.F90 b/components/mosart/src/riverroute/MOSART_physics_mod.F90 index cad978577cda..912014904e93 100644 --- a/components/mosart/src/riverroute/MOSART_physics_mod.F90 +++ b/components/mosart/src/riverroute/MOSART_physics_mod.F90 @@ -682,8 +682,8 @@ subroutine Euler ! check for negative channel storage if (negchan < -1.e-10) then - write(iulog,*) 'Error: Negative channel storage found! ',negchan - call shr_sys_abort('mosart: negative channel storage') + write(iulog,*) 'Warning: Negative channel storage found! ',negchan +! call shr_sys_abort('mosart: negative channel storage') endif TRunoff%flow = TRunoff%flow / Tctl%DLevelH2R TRunoff%erowm_regi(:,nt_nmud:nt_nsan) = TRunoff%erowm_regi(:,nt_nmud:nt_nsan) / Tctl%DLevelH2R diff --git a/components/mpas-albany-landice/bld/build-namelist b/components/mpas-albany-landice/bld/build-namelist index 068363fb98c6..15272f7a2dab 100755 --- a/components/mpas-albany-landice/bld/build-namelist +++ b/components/mpas-albany-landice/bld/build-namelist @@ -663,6 +663,7 @@ add_default($nl, 'config_SGH_bed_roughness'); add_default($nl, 'config_SGH_bed_roughness_max'); add_default($nl, 'config_SGH_creep_coefficient'); add_default($nl, 'config_SGH_englacial_porosity'); +add_default($nl, 'config_SGH_use_iceThicknessHydro'); add_default($nl, 'config_SGH_chnl_active'); add_default($nl, 'config_SGH_chnl_include_DCFL'); add_default($nl, 'config_SGH_chnl_alpha'); @@ -673,6 +674,7 @@ add_default($nl, 'config_SGH_incipient_channel_width'); add_default($nl, 'config_SGH_include_pressure_melt'); add_default($nl, 'config_SGH_shmip_forcing'); add_default($nl, 'config_SGH_basal_melt'); +add_default($nl, 'config_SGH_iter_smooth_waterPressureSlopeNormal'); ################################## # Namelist group: AM_globalStats # diff --git a/components/mpas-albany-landice/bld/build-namelist-section b/components/mpas-albany-landice/bld/build-namelist-section index 8f4bc139c98a..4b5e05ec3cd5 100644 --- a/components/mpas-albany-landice/bld/build-namelist-section +++ b/components/mpas-albany-landice/bld/build-namelist-section @@ -225,6 +225,7 @@ add_default($nl, 'config_SGH_bed_roughness'); add_default($nl, 'config_SGH_bed_roughness_max'); add_default($nl, 'config_SGH_creep_coefficient'); add_default($nl, 'config_SGH_englacial_porosity'); +add_default($nl, 'config_SGH_use_iceThicknessHydro'); add_default($nl, 'config_SGH_chnl_active'); add_default($nl, 'config_SGH_chnl_include_DCFL'); add_default($nl, 'config_SGH_chnl_alpha'); @@ -235,6 +236,7 @@ add_default($nl, 'config_SGH_incipient_channel_width'); add_default($nl, 'config_SGH_include_pressure_melt'); add_default($nl, 'config_SGH_shmip_forcing'); add_default($nl, 'config_SGH_basal_melt'); +add_default($nl, 'config_SGH_iter_smooth_waterPressureSlopeNormal'); ################################## # Namelist group: AM_globalStats # diff --git a/components/mpas-albany-landice/bld/namelist_files/albany_input.ais20km.yaml b/components/mpas-albany-landice/bld/namelist_files/albany_input.ais20km.yaml new file mode 100644 index 000000000000..589e163bba7f --- /dev/null +++ b/components/mpas-albany-landice/bld/namelist_files/albany_input.ais20km.yaml @@ -0,0 +1,231 @@ +%YAML 1.1 +--- +ANONYMOUS: + +# Discretization Description + Discretization: + #Exodus Output File Name: albany_output.exo + + Piro: +# Nonlinear Solver Information + NOX: + Nonlinear Solver: Line Search Based + Line Search: + Full Step: + Full Step: 1.0e+00 + Method: Backtrack + Solver Options: + Status Test Check Type: Minimal + Status Tests: + Test Type: Combo + Combo Type: OR + Number of Tests: 2 + Test 0: + Test Type: Combo + Combo Type: AND + Number of Tests: 2 + Test 0: + Test Type: NormF + Norm Type: Two Norm + Scale Type: Unscaled + Tolerance: 1.0e-03 + Test 1: + Test Type: RelativeNormF + Norm Type: Two Norm + Tolerance: 0.9999 + Test 1: + Test Type: MaxIters + Maximum Iterations: 100 + Printing: + Output Precision: 3 + Output Processor: 0 + Output Information: + Error: true + Warning: true + Outer Iteration: true + Parameters: false + Details: false + Linear Solver Details: false + Stepper Iteration: true + Stepper Details: true + Stepper Parameters: true + + Direction: + Method: Newton + Newton: + Forcing Term Method: Type 2 + Rescue Bad Newton Solve: true + Linear Solver: + Write Linear System: false + Tolerance: 1.0e-8 + + Stratimikos Linear Solver: + Stratimikos: + +# Linear Solver Information + Linear Solver Type: Belos + Linear Solver Types: + Belos: + Solver Type: Block GMRES + Solver Types: + Block GMRES: + Output Frequency: 20 + Output Style: 1 + Verbosity: 33 + Maximum Iterations: 200 + Block Size: 1 + Num Blocks: 200 + Flexible Gmres: false + VerboseObject: + Output File: none + Verbosity Level: low + +# Preconditioner Information + Preconditioner Type: MueLu + Preconditioner Types: + + Ifpack2: + Overlap: 1 + Prec Type: ILUT + + MueLu: + Matrix: + PDE equations: 2 + Factories: + myLineDetectionFact: + factory: LineDetectionFactory + 'linedetection: orientation': coordinates + mySemiCoarsenPFact1: + factory: SemiCoarsenPFactory + 'semicoarsen: coarsen rate': 14 + UncoupledAggregationFact2: + factory: UncoupledAggregationFactory + 'aggregation: ordering': graph + 'aggregation: max selected neighbors': 0 + 'aggregation: min agg size': 3 + 'aggregation: phase3 avoid singletons': true + MyCoarseMap2: + factory: CoarseMapFactory + Aggregates: UncoupledAggregationFact2 + myTentativePFact2: + 'tentative: calculate qr': true + factory: TentativePFactory + Aggregates: UncoupledAggregationFact2 + CoarseMap: MyCoarseMap2 + mySaPFact2: + 'sa: eigenvalue estimate num iterations': 10 + 'sa: damping factor': 1.33333e+00 + factory: SaPFactory + P: myTentativePFact2 + myTransferCoordinatesFact: + factory: CoordinatesTransferFactory + CoarseMap: MyCoarseMap2 + Aggregates: UncoupledAggregationFact2 + myTogglePFact: + factory: TogglePFactory + 'semicoarsen: number of levels': 2 + TransferFactories: + P1: mySemiCoarsenPFact1 + P2: mySaPFact2 + Ptent1: mySemiCoarsenPFact1 + Ptent2: myTentativePFact2 + Nullspace1: mySemiCoarsenPFact1 + Nullspace2: myTentativePFact2 + myRestrictorFact: + factory: TransPFactory + P: myTogglePFact + myToggleTransferCoordinatesFact: + factory: ToggleCoordinatesTransferFactory + Chosen P: myTogglePFact + TransferFactories: + Coordinates1: mySemiCoarsenPFact1 + Coordinates2: myTransferCoordinatesFact + myRAPFact: + factory: RAPFactory + P: myTogglePFact + R: myRestrictorFact + TransferFactories: + For Coordinates: myToggleTransferCoordinatesFact + myRepartitionHeuristicFact: + factory: RepartitionHeuristicFactory + A: myRAPFact + 'repartition: min rows per proc': 3000 + 'repartition: max imbalance': 1.327e+00 + 'repartition: start level': 1 + myZoltanInterface: + factory: ZoltanInterface + A: myRAPFact + Coordinates: myToggleTransferCoordinatesFact + number of partitions: myRepartitionHeuristicFact + myRepartitionFact: + factory: RepartitionFactory + A: myRAPFact + Partition: myZoltanInterface + 'repartition: remap parts': true + number of partitions: myRepartitionHeuristicFact + myRebalanceProlongatorFact: + factory: RebalanceTransferFactory + type: Interpolation + P: myTogglePFact + Coordinates: myToggleTransferCoordinatesFact + Nullspace: myTogglePFact + myRebalanceRestrictionFact: + factory: RebalanceTransferFactory + type: Restriction + R: myRestrictorFact + myRebalanceAFact: + factory: RebalanceAcFactory + A: myRAPFact + TransferFactories: { } + mySmoother1: + factory: TrilinosSmoother + type: LINESMOOTHING_BANDEDRELAXATION + 'smoother: pre or post': both + ParameterList: + 'relaxation: type': Gauss-Seidel + 'relaxation: sweeps': 1 + 'relaxation: damping factor': 1.0 + mySmoother3: + factory: TrilinosSmoother + type: RELAXATION + 'smoother: pre or post': both + ParameterList: + 'relaxation: type': Gauss-Seidel + 'relaxation: sweeps': 1 + 'relaxation: damping factor': 1.0 + mySmoother4: + factory: TrilinosSmoother + type: RELAXATION + 'smoother: pre or post': pre + ParameterList: + 'relaxation: type': Gauss-Seidel + 'relaxation: sweeps': 4 + 'relaxation: damping factor': 1.0 + Hierarchy: + max levels: 7 + 'coarse: max size': 2000 + verbosity: None + Finest: + Smoother: mySmoother1 + CoarseSolver: mySmoother4 + P: myRebalanceProlongatorFact + Nullspace: myRebalanceProlongatorFact + CoarseNumZLayers: myLineDetectionFact + LineDetection_Layers: myLineDetectionFact + LineDetection_VertLineIds: myLineDetectionFact + A: myRebalanceAFact + Coordinates: myRebalanceProlongatorFact + Importer: myRepartitionFact + All: + startLevel: 1 + Smoother: mySmoother4 + CoarseSolver: mySmoother4 + P: myRebalanceProlongatorFact + Nullspace: myRebalanceProlongatorFact + CoarseNumZLayers: myLineDetectionFact + LineDetection_Layers: myLineDetectionFact + LineDetection_VertLineIds: myLineDetectionFact + A: myRebalanceAFact + Coordinates: myRebalanceProlongatorFact + Importer: myRepartitionFact + diff --git a/components/mpas-albany-landice/bld/namelist_files/albany_input.ais_4to20km.yaml b/components/mpas-albany-landice/bld/namelist_files/albany_input.ais_4to20km.yaml new file mode 100644 index 000000000000..c3bc0cf8bd56 --- /dev/null +++ b/components/mpas-albany-landice/bld/namelist_files/albany_input.ais_4to20km.yaml @@ -0,0 +1,246 @@ +%YAML 1.1 +--- +ANONYMOUS: + Problem: + Basal Cubature Degree: 4 + LandIce Field Norm: + sliding_velocity_basalside: + Regularization Type: Given Value + Regularization Value: 1.0e-4 + LandIce BCs: + BC 0: + Basal Friction Coefficient: + Type: Power Law + Power Exponent: 0.2 + Mu Type: Field + Effective Pressure Type: Constant + Effective Pressure: 1.0 + # Zero Effective Pressure On Floating Ice At Nodes: true + Zero Beta On Floating Ice: true +# Discretization Description + Discretization: + #Exodus Output File Name: albany_output.exo + + Piro: +# Nonlinear Solver Information + NOX: + Nonlinear Solver: Line Search Based + Line Search: + Full Step: + Full Step: 1.0e+00 + Method: Backtrack + Solver Options: + Status Test Check Type: Minimal + Status Tests: + Test Type: Combo + Combo Type: OR + Number of Tests: 2 + Test 0: + Test Type: Combo + Combo Type: AND + Number of Tests: 2 + Test 0: + Test Type: NormF + Norm Type: Two Norm + Scale Type: Unscaled + Tolerance: 1.0e-03 + Test 1: + Test Type: RelativeNormF + Norm Type: Two Norm + Tolerance: 0.9999 + Test 1: + Test Type: MaxIters + Maximum Iterations: 100 + Printing: + Output Precision: 3 + Output Processor: 0 + Output Information: + Error: true + Warning: true + Outer Iteration: true + Parameters: false + Details: false + Linear Solver Details: false + Stepper Iteration: true + Stepper Details: true + Stepper Parameters: true + + Direction: + Method: Newton + Newton: + Forcing Term Method: Type 2 + Rescue Bad Newton Solve: true + Linear Solver: + Write Linear System: false + Tolerance: 1.0e-8 + + Stratimikos Linear Solver: + Stratimikos: + +# Linear Solver Information + Linear Solver Type: Belos + Linear Solver Types: + Belos: + Solver Type: Block GMRES + Solver Types: + Block GMRES: + Output Frequency: 20 + Output Style: 1 + Verbosity: 33 + Maximum Iterations: 200 + Block Size: 1 + Num Blocks: 200 + Flexible Gmres: false + VerboseObject: + Output File: none + Verbosity Level: low + +# Preconditioner Information + Preconditioner Type: MueLu + Preconditioner Types: + + Ifpack2: + Overlap: 1 + Prec Type: ILUT + + MueLu: + Matrix: + PDE equations: 2 + Factories: + myLineDetectionFact: + factory: LineDetectionFactory + 'linedetection: orientation': coordinates + mySemiCoarsenPFact1: + factory: SemiCoarsenPFactory + 'semicoarsen: coarsen rate': 14 + UncoupledAggregationFact2: + factory: UncoupledAggregationFactory + 'aggregation: ordering': graph + 'aggregation: max selected neighbors': 0 + 'aggregation: min agg size': 3 + 'aggregation: phase3 avoid singletons': true + MyCoarseMap2: + factory: CoarseMapFactory + Aggregates: UncoupledAggregationFact2 + myTentativePFact2: + 'tentative: calculate qr': true + factory: TentativePFactory + Aggregates: UncoupledAggregationFact2 + CoarseMap: MyCoarseMap2 + mySaPFact2: + 'sa: eigenvalue estimate num iterations': 10 + 'sa: damping factor': 1.33333e+00 + factory: SaPFactory + P: myTentativePFact2 + myTransferCoordinatesFact: + factory: CoordinatesTransferFactory + CoarseMap: MyCoarseMap2 + Aggregates: UncoupledAggregationFact2 + myTogglePFact: + factory: TogglePFactory + 'semicoarsen: number of levels': 2 + TransferFactories: + P1: mySemiCoarsenPFact1 + P2: mySaPFact2 + Ptent1: mySemiCoarsenPFact1 + Ptent2: myTentativePFact2 + Nullspace1: mySemiCoarsenPFact1 + Nullspace2: myTentativePFact2 + myRestrictorFact: + factory: TransPFactory + P: myTogglePFact + myToggleTransferCoordinatesFact: + factory: ToggleCoordinatesTransferFactory + Chosen P: myTogglePFact + TransferFactories: + Coordinates1: mySemiCoarsenPFact1 + Coordinates2: myTransferCoordinatesFact + myRAPFact: + factory: RAPFactory + P: myTogglePFact + R: myRestrictorFact + TransferFactories: + For Coordinates: myToggleTransferCoordinatesFact + myRepartitionHeuristicFact: + factory: RepartitionHeuristicFactory + A: myRAPFact + 'repartition: min rows per proc': 3000 + 'repartition: max imbalance': 1.327e+00 + 'repartition: start level': 1 + myZoltanInterface: + factory: ZoltanInterface + A: myRAPFact + Coordinates: myToggleTransferCoordinatesFact + number of partitions: myRepartitionHeuristicFact + myRepartitionFact: + factory: RepartitionFactory + A: myRAPFact + Partition: myZoltanInterface + 'repartition: remap parts': true + number of partitions: myRepartitionHeuristicFact + myRebalanceProlongatorFact: + factory: RebalanceTransferFactory + type: Interpolation + P: myTogglePFact + Coordinates: myToggleTransferCoordinatesFact + Nullspace: myTogglePFact + myRebalanceRestrictionFact: + factory: RebalanceTransferFactory + type: Restriction + R: myRestrictorFact + myRebalanceAFact: + factory: RebalanceAcFactory + A: myRAPFact + TransferFactories: { } + mySmoother1: + factory: TrilinosSmoother + type: LINESMOOTHING_BANDEDRELAXATION + 'smoother: pre or post': both + ParameterList: + 'relaxation: type': Gauss-Seidel + 'relaxation: sweeps': 1 + 'relaxation: damping factor': 1.0 + mySmoother3: + factory: TrilinosSmoother + type: RELAXATION + 'smoother: pre or post': both + ParameterList: + 'relaxation: type': Gauss-Seidel + 'relaxation: sweeps': 1 + 'relaxation: damping factor': 1.0 + mySmoother4: + factory: TrilinosSmoother + type: RELAXATION + 'smoother: pre or post': pre + ParameterList: + 'relaxation: type': Gauss-Seidel + 'relaxation: sweeps': 4 + 'relaxation: damping factor': 1.0 + Hierarchy: + max levels: 7 + 'coarse: max size': 2000 + verbosity: None + Finest: + Smoother: mySmoother1 + CoarseSolver: mySmoother4 + P: myRebalanceProlongatorFact + Nullspace: myRebalanceProlongatorFact + CoarseNumZLayers: myLineDetectionFact + LineDetection_Layers: myLineDetectionFact + LineDetection_VertLineIds: myLineDetectionFact + A: myRebalanceAFact + Coordinates: myRebalanceProlongatorFact + Importer: myRepartitionFact + All: + startLevel: 1 + Smoother: mySmoother4 + CoarseSolver: mySmoother4 + P: myRebalanceProlongatorFact + Nullspace: myRebalanceProlongatorFact + CoarseNumZLayers: myLineDetectionFact + LineDetection_Layers: myLineDetectionFact + LineDetection_VertLineIds: myLineDetectionFact + A: myRebalanceAFact + Coordinates: myRebalanceProlongatorFact + Importer: myRepartitionFact + diff --git a/components/mpas-albany-landice/bld/namelist_files/albany_input.ais_8to30km.yaml b/components/mpas-albany-landice/bld/namelist_files/albany_input.ais_8to30km.yaml new file mode 100644 index 000000000000..c3bc0cf8bd56 --- /dev/null +++ b/components/mpas-albany-landice/bld/namelist_files/albany_input.ais_8to30km.yaml @@ -0,0 +1,246 @@ +%YAML 1.1 +--- +ANONYMOUS: + Problem: + Basal Cubature Degree: 4 + LandIce Field Norm: + sliding_velocity_basalside: + Regularization Type: Given Value + Regularization Value: 1.0e-4 + LandIce BCs: + BC 0: + Basal Friction Coefficient: + Type: Power Law + Power Exponent: 0.2 + Mu Type: Field + Effective Pressure Type: Constant + Effective Pressure: 1.0 + # Zero Effective Pressure On Floating Ice At Nodes: true + Zero Beta On Floating Ice: true +# Discretization Description + Discretization: + #Exodus Output File Name: albany_output.exo + + Piro: +# Nonlinear Solver Information + NOX: + Nonlinear Solver: Line Search Based + Line Search: + Full Step: + Full Step: 1.0e+00 + Method: Backtrack + Solver Options: + Status Test Check Type: Minimal + Status Tests: + Test Type: Combo + Combo Type: OR + Number of Tests: 2 + Test 0: + Test Type: Combo + Combo Type: AND + Number of Tests: 2 + Test 0: + Test Type: NormF + Norm Type: Two Norm + Scale Type: Unscaled + Tolerance: 1.0e-03 + Test 1: + Test Type: RelativeNormF + Norm Type: Two Norm + Tolerance: 0.9999 + Test 1: + Test Type: MaxIters + Maximum Iterations: 100 + Printing: + Output Precision: 3 + Output Processor: 0 + Output Information: + Error: true + Warning: true + Outer Iteration: true + Parameters: false + Details: false + Linear Solver Details: false + Stepper Iteration: true + Stepper Details: true + Stepper Parameters: true + + Direction: + Method: Newton + Newton: + Forcing Term Method: Type 2 + Rescue Bad Newton Solve: true + Linear Solver: + Write Linear System: false + Tolerance: 1.0e-8 + + Stratimikos Linear Solver: + Stratimikos: + +# Linear Solver Information + Linear Solver Type: Belos + Linear Solver Types: + Belos: + Solver Type: Block GMRES + Solver Types: + Block GMRES: + Output Frequency: 20 + Output Style: 1 + Verbosity: 33 + Maximum Iterations: 200 + Block Size: 1 + Num Blocks: 200 + Flexible Gmres: false + VerboseObject: + Output File: none + Verbosity Level: low + +# Preconditioner Information + Preconditioner Type: MueLu + Preconditioner Types: + + Ifpack2: + Overlap: 1 + Prec Type: ILUT + + MueLu: + Matrix: + PDE equations: 2 + Factories: + myLineDetectionFact: + factory: LineDetectionFactory + 'linedetection: orientation': coordinates + mySemiCoarsenPFact1: + factory: SemiCoarsenPFactory + 'semicoarsen: coarsen rate': 14 + UncoupledAggregationFact2: + factory: UncoupledAggregationFactory + 'aggregation: ordering': graph + 'aggregation: max selected neighbors': 0 + 'aggregation: min agg size': 3 + 'aggregation: phase3 avoid singletons': true + MyCoarseMap2: + factory: CoarseMapFactory + Aggregates: UncoupledAggregationFact2 + myTentativePFact2: + 'tentative: calculate qr': true + factory: TentativePFactory + Aggregates: UncoupledAggregationFact2 + CoarseMap: MyCoarseMap2 + mySaPFact2: + 'sa: eigenvalue estimate num iterations': 10 + 'sa: damping factor': 1.33333e+00 + factory: SaPFactory + P: myTentativePFact2 + myTransferCoordinatesFact: + factory: CoordinatesTransferFactory + CoarseMap: MyCoarseMap2 + Aggregates: UncoupledAggregationFact2 + myTogglePFact: + factory: TogglePFactory + 'semicoarsen: number of levels': 2 + TransferFactories: + P1: mySemiCoarsenPFact1 + P2: mySaPFact2 + Ptent1: mySemiCoarsenPFact1 + Ptent2: myTentativePFact2 + Nullspace1: mySemiCoarsenPFact1 + Nullspace2: myTentativePFact2 + myRestrictorFact: + factory: TransPFactory + P: myTogglePFact + myToggleTransferCoordinatesFact: + factory: ToggleCoordinatesTransferFactory + Chosen P: myTogglePFact + TransferFactories: + Coordinates1: mySemiCoarsenPFact1 + Coordinates2: myTransferCoordinatesFact + myRAPFact: + factory: RAPFactory + P: myTogglePFact + R: myRestrictorFact + TransferFactories: + For Coordinates: myToggleTransferCoordinatesFact + myRepartitionHeuristicFact: + factory: RepartitionHeuristicFactory + A: myRAPFact + 'repartition: min rows per proc': 3000 + 'repartition: max imbalance': 1.327e+00 + 'repartition: start level': 1 + myZoltanInterface: + factory: ZoltanInterface + A: myRAPFact + Coordinates: myToggleTransferCoordinatesFact + number of partitions: myRepartitionHeuristicFact + myRepartitionFact: + factory: RepartitionFactory + A: myRAPFact + Partition: myZoltanInterface + 'repartition: remap parts': true + number of partitions: myRepartitionHeuristicFact + myRebalanceProlongatorFact: + factory: RebalanceTransferFactory + type: Interpolation + P: myTogglePFact + Coordinates: myToggleTransferCoordinatesFact + Nullspace: myTogglePFact + myRebalanceRestrictionFact: + factory: RebalanceTransferFactory + type: Restriction + R: myRestrictorFact + myRebalanceAFact: + factory: RebalanceAcFactory + A: myRAPFact + TransferFactories: { } + mySmoother1: + factory: TrilinosSmoother + type: LINESMOOTHING_BANDEDRELAXATION + 'smoother: pre or post': both + ParameterList: + 'relaxation: type': Gauss-Seidel + 'relaxation: sweeps': 1 + 'relaxation: damping factor': 1.0 + mySmoother3: + factory: TrilinosSmoother + type: RELAXATION + 'smoother: pre or post': both + ParameterList: + 'relaxation: type': Gauss-Seidel + 'relaxation: sweeps': 1 + 'relaxation: damping factor': 1.0 + mySmoother4: + factory: TrilinosSmoother + type: RELAXATION + 'smoother: pre or post': pre + ParameterList: + 'relaxation: type': Gauss-Seidel + 'relaxation: sweeps': 4 + 'relaxation: damping factor': 1.0 + Hierarchy: + max levels: 7 + 'coarse: max size': 2000 + verbosity: None + Finest: + Smoother: mySmoother1 + CoarseSolver: mySmoother4 + P: myRebalanceProlongatorFact + Nullspace: myRebalanceProlongatorFact + CoarseNumZLayers: myLineDetectionFact + LineDetection_Layers: myLineDetectionFact + LineDetection_VertLineIds: myLineDetectionFact + A: myRebalanceAFact + Coordinates: myRebalanceProlongatorFact + Importer: myRepartitionFact + All: + startLevel: 1 + Smoother: mySmoother4 + CoarseSolver: mySmoother4 + P: myRebalanceProlongatorFact + Nullspace: myRebalanceProlongatorFact + CoarseNumZLayers: myLineDetectionFact + LineDetection_Layers: myLineDetectionFact + LineDetection_VertLineIds: myLineDetectionFact + A: myRebalanceAFact + Coordinates: myRebalanceProlongatorFact + Importer: myRepartitionFact + diff --git a/components/mpas-albany-landice/bld/namelist_files/albany_input.aisgis20km.yaml b/components/mpas-albany-landice/bld/namelist_files/albany_input.aisgis20km.yaml new file mode 100644 index 000000000000..589e163bba7f --- /dev/null +++ b/components/mpas-albany-landice/bld/namelist_files/albany_input.aisgis20km.yaml @@ -0,0 +1,231 @@ +%YAML 1.1 +--- +ANONYMOUS: + +# Discretization Description + Discretization: + #Exodus Output File Name: albany_output.exo + + Piro: +# Nonlinear Solver Information + NOX: + Nonlinear Solver: Line Search Based + Line Search: + Full Step: + Full Step: 1.0e+00 + Method: Backtrack + Solver Options: + Status Test Check Type: Minimal + Status Tests: + Test Type: Combo + Combo Type: OR + Number of Tests: 2 + Test 0: + Test Type: Combo + Combo Type: AND + Number of Tests: 2 + Test 0: + Test Type: NormF + Norm Type: Two Norm + Scale Type: Unscaled + Tolerance: 1.0e-03 + Test 1: + Test Type: RelativeNormF + Norm Type: Two Norm + Tolerance: 0.9999 + Test 1: + Test Type: MaxIters + Maximum Iterations: 100 + Printing: + Output Precision: 3 + Output Processor: 0 + Output Information: + Error: true + Warning: true + Outer Iteration: true + Parameters: false + Details: false + Linear Solver Details: false + Stepper Iteration: true + Stepper Details: true + Stepper Parameters: true + + Direction: + Method: Newton + Newton: + Forcing Term Method: Type 2 + Rescue Bad Newton Solve: true + Linear Solver: + Write Linear System: false + Tolerance: 1.0e-8 + + Stratimikos Linear Solver: + Stratimikos: + +# Linear Solver Information + Linear Solver Type: Belos + Linear Solver Types: + Belos: + Solver Type: Block GMRES + Solver Types: + Block GMRES: + Output Frequency: 20 + Output Style: 1 + Verbosity: 33 + Maximum Iterations: 200 + Block Size: 1 + Num Blocks: 200 + Flexible Gmres: false + VerboseObject: + Output File: none + Verbosity Level: low + +# Preconditioner Information + Preconditioner Type: MueLu + Preconditioner Types: + + Ifpack2: + Overlap: 1 + Prec Type: ILUT + + MueLu: + Matrix: + PDE equations: 2 + Factories: + myLineDetectionFact: + factory: LineDetectionFactory + 'linedetection: orientation': coordinates + mySemiCoarsenPFact1: + factory: SemiCoarsenPFactory + 'semicoarsen: coarsen rate': 14 + UncoupledAggregationFact2: + factory: UncoupledAggregationFactory + 'aggregation: ordering': graph + 'aggregation: max selected neighbors': 0 + 'aggregation: min agg size': 3 + 'aggregation: phase3 avoid singletons': true + MyCoarseMap2: + factory: CoarseMapFactory + Aggregates: UncoupledAggregationFact2 + myTentativePFact2: + 'tentative: calculate qr': true + factory: TentativePFactory + Aggregates: UncoupledAggregationFact2 + CoarseMap: MyCoarseMap2 + mySaPFact2: + 'sa: eigenvalue estimate num iterations': 10 + 'sa: damping factor': 1.33333e+00 + factory: SaPFactory + P: myTentativePFact2 + myTransferCoordinatesFact: + factory: CoordinatesTransferFactory + CoarseMap: MyCoarseMap2 + Aggregates: UncoupledAggregationFact2 + myTogglePFact: + factory: TogglePFactory + 'semicoarsen: number of levels': 2 + TransferFactories: + P1: mySemiCoarsenPFact1 + P2: mySaPFact2 + Ptent1: mySemiCoarsenPFact1 + Ptent2: myTentativePFact2 + Nullspace1: mySemiCoarsenPFact1 + Nullspace2: myTentativePFact2 + myRestrictorFact: + factory: TransPFactory + P: myTogglePFact + myToggleTransferCoordinatesFact: + factory: ToggleCoordinatesTransferFactory + Chosen P: myTogglePFact + TransferFactories: + Coordinates1: mySemiCoarsenPFact1 + Coordinates2: myTransferCoordinatesFact + myRAPFact: + factory: RAPFactory + P: myTogglePFact + R: myRestrictorFact + TransferFactories: + For Coordinates: myToggleTransferCoordinatesFact + myRepartitionHeuristicFact: + factory: RepartitionHeuristicFactory + A: myRAPFact + 'repartition: min rows per proc': 3000 + 'repartition: max imbalance': 1.327e+00 + 'repartition: start level': 1 + myZoltanInterface: + factory: ZoltanInterface + A: myRAPFact + Coordinates: myToggleTransferCoordinatesFact + number of partitions: myRepartitionHeuristicFact + myRepartitionFact: + factory: RepartitionFactory + A: myRAPFact + Partition: myZoltanInterface + 'repartition: remap parts': true + number of partitions: myRepartitionHeuristicFact + myRebalanceProlongatorFact: + factory: RebalanceTransferFactory + type: Interpolation + P: myTogglePFact + Coordinates: myToggleTransferCoordinatesFact + Nullspace: myTogglePFact + myRebalanceRestrictionFact: + factory: RebalanceTransferFactory + type: Restriction + R: myRestrictorFact + myRebalanceAFact: + factory: RebalanceAcFactory + A: myRAPFact + TransferFactories: { } + mySmoother1: + factory: TrilinosSmoother + type: LINESMOOTHING_BANDEDRELAXATION + 'smoother: pre or post': both + ParameterList: + 'relaxation: type': Gauss-Seidel + 'relaxation: sweeps': 1 + 'relaxation: damping factor': 1.0 + mySmoother3: + factory: TrilinosSmoother + type: RELAXATION + 'smoother: pre or post': both + ParameterList: + 'relaxation: type': Gauss-Seidel + 'relaxation: sweeps': 1 + 'relaxation: damping factor': 1.0 + mySmoother4: + factory: TrilinosSmoother + type: RELAXATION + 'smoother: pre or post': pre + ParameterList: + 'relaxation: type': Gauss-Seidel + 'relaxation: sweeps': 4 + 'relaxation: damping factor': 1.0 + Hierarchy: + max levels: 7 + 'coarse: max size': 2000 + verbosity: None + Finest: + Smoother: mySmoother1 + CoarseSolver: mySmoother4 + P: myRebalanceProlongatorFact + Nullspace: myRebalanceProlongatorFact + CoarseNumZLayers: myLineDetectionFact + LineDetection_Layers: myLineDetectionFact + LineDetection_VertLineIds: myLineDetectionFact + A: myRebalanceAFact + Coordinates: myRebalanceProlongatorFact + Importer: myRepartitionFact + All: + startLevel: 1 + Smoother: mySmoother4 + CoarseSolver: mySmoother4 + P: myRebalanceProlongatorFact + Nullspace: myRebalanceProlongatorFact + CoarseNumZLayers: myLineDetectionFact + LineDetection_Layers: myLineDetectionFact + LineDetection_VertLineIds: myLineDetectionFact + A: myRebalanceAFact + Coordinates: myRebalanceProlongatorFact + Importer: myRepartitionFact + diff --git a/components/mpas-albany-landice/bld/namelist_files/albany_input.gis_1to10km_r01.yaml b/components/mpas-albany-landice/bld/namelist_files/albany_input.gis_1to10km_r01.yaml new file mode 100644 index 000000000000..c1b2e310f323 --- /dev/null +++ b/components/mpas-albany-landice/bld/namelist_files/albany_input.gis_1to10km_r01.yaml @@ -0,0 +1,234 @@ +%YAML 1.1 +--- +ANONYMOUS: + + Problem: + Depth Integrated Model: true + +# Discretization Description + Discretization: + #Exodus Output File Name: albany_output.exo + + Piro: +# Nonlinear Solver Information + NOX: + Nonlinear Solver: Line Search Based + Line Search: + Full Step: + Full Step: 1.0e+00 + Method: Backtrack + Solver Options: + Status Test Check Type: Minimal + Status Tests: + Test Type: Combo + Combo Type: OR + Number of Tests: 2 + Test 0: + Test Type: Combo + Combo Type: AND + Number of Tests: 2 + Test 0: + Test Type: NormF + Norm Type: Two Norm + Scale Type: Unscaled + Tolerance: 1.0e-03 + Test 1: + Test Type: RelativeNormF + Norm Type: Two Norm + Tolerance: 0.9999 + Test 1: + Test Type: MaxIters + Maximum Iterations: 100 + Printing: + Output Precision: 3 + Output Processor: 0 + Output Information: + Error: true + Warning: true + Outer Iteration: true + Parameters: false + Details: false + Linear Solver Details: false + Stepper Iteration: true + Stepper Details: true + Stepper Parameters: true + + Direction: + Method: Newton + Newton: + Forcing Term Method: Type 2 + Rescue Bad Newton Solve: true + Linear Solver: + Write Linear System: false + Tolerance: 1.0e-8 + + Stratimikos Linear Solver: + Stratimikos: + +# Linear Solver Information + Linear Solver Type: Belos + Linear Solver Types: + Belos: + Solver Type: Block GMRES + Solver Types: + Block GMRES: + Output Frequency: 20 + Output Style: 1 + Verbosity: 33 + Maximum Iterations: 200 + Block Size: 1 + Num Blocks: 200 + Flexible Gmres: false + VerboseObject: + Output File: none + Verbosity Level: low + +# Preconditioner Information + Preconditioner Type: MueLu + Preconditioner Types: + + Ifpack2: + Overlap: 1 + Prec Type: ILUT + + MueLu: + Matrix: + PDE equations: 2 + Factories: + myLineDetectionFact: + factory: LineDetectionFactory + 'linedetection: orientation': coordinates + mySemiCoarsenPFact1: + factory: SemiCoarsenPFactory + 'semicoarsen: coarsen rate': 14 + UncoupledAggregationFact2: + factory: UncoupledAggregationFactory + 'aggregation: ordering': graph + 'aggregation: max selected neighbors': 0 + 'aggregation: min agg size': 3 + 'aggregation: phase3 avoid singletons': true + MyCoarseMap2: + factory: CoarseMapFactory + Aggregates: UncoupledAggregationFact2 + myTentativePFact2: + 'tentative: calculate qr': true + factory: TentativePFactory + Aggregates: UncoupledAggregationFact2 + CoarseMap: MyCoarseMap2 + mySaPFact2: + 'sa: eigenvalue estimate num iterations': 10 + 'sa: damping factor': 1.33333e+00 + factory: SaPFactory + P: myTentativePFact2 + myTransferCoordinatesFact: + factory: CoordinatesTransferFactory + CoarseMap: MyCoarseMap2 + Aggregates: UncoupledAggregationFact2 + myTogglePFact: + factory: TogglePFactory + 'semicoarsen: number of levels': 2 + TransferFactories: + P1: mySemiCoarsenPFact1 + P2: mySaPFact2 + Ptent1: mySemiCoarsenPFact1 + Ptent2: myTentativePFact2 + Nullspace1: mySemiCoarsenPFact1 + Nullspace2: myTentativePFact2 + myRestrictorFact: + factory: TransPFactory + P: myTogglePFact + myToggleTransferCoordinatesFact: + factory: ToggleCoordinatesTransferFactory + Chosen P: myTogglePFact + TransferFactories: + Coordinates1: mySemiCoarsenPFact1 + Coordinates2: myTransferCoordinatesFact + myRAPFact: + factory: RAPFactory + P: myTogglePFact + R: myRestrictorFact + TransferFactories: + For Coordinates: myToggleTransferCoordinatesFact + myRepartitionHeuristicFact: + factory: RepartitionHeuristicFactory + A: myRAPFact + 'repartition: min rows per proc': 3000 + 'repartition: max imbalance': 1.327e+00 + 'repartition: start level': 1 + myZoltanInterface: + factory: ZoltanInterface + A: myRAPFact + Coordinates: myToggleTransferCoordinatesFact + number of partitions: myRepartitionHeuristicFact + myRepartitionFact: + factory: RepartitionFactory + A: myRAPFact + Partition: myZoltanInterface + 'repartition: remap parts': true + number of partitions: myRepartitionHeuristicFact + myRebalanceProlongatorFact: + factory: RebalanceTransferFactory + type: Interpolation + P: myTogglePFact + Coordinates: myToggleTransferCoordinatesFact + Nullspace: myTogglePFact + myRebalanceRestrictionFact: + factory: RebalanceTransferFactory + type: Restriction + R: myRestrictorFact + myRebalanceAFact: + factory: RebalanceAcFactory + A: myRAPFact + TransferFactories: { } + mySmoother1: + factory: TrilinosSmoother + type: LINESMOOTHING_BANDEDRELAXATION + 'smoother: pre or post': both + ParameterList: + 'relaxation: type': Gauss-Seidel + 'relaxation: sweeps': 1 + 'relaxation: damping factor': 1.0 + mySmoother3: + factory: TrilinosSmoother + type: RELAXATION + 'smoother: pre or post': both + ParameterList: + 'relaxation: type': Gauss-Seidel + 'relaxation: sweeps': 1 + 'relaxation: damping factor': 1.0 + mySmoother4: + factory: TrilinosSmoother + type: RELAXATION + 'smoother: pre or post': pre + ParameterList: + 'relaxation: type': Gauss-Seidel + 'relaxation: sweeps': 4 + 'relaxation: damping factor': 1.0 + Hierarchy: + max levels: 7 + 'coarse: max size': 2000 + verbosity: None + Finest: + Smoother: mySmoother1 + CoarseSolver: mySmoother4 + P: myRebalanceProlongatorFact + Nullspace: myRebalanceProlongatorFact + CoarseNumZLayers: myLineDetectionFact + LineDetection_Layers: myLineDetectionFact + LineDetection_VertLineIds: myLineDetectionFact + A: myRebalanceAFact + Coordinates: myRebalanceProlongatorFact + Importer: myRepartitionFact + All: + startLevel: 1 + Smoother: mySmoother4 + CoarseSolver: mySmoother4 + P: myRebalanceProlongatorFact + Nullspace: myRebalanceProlongatorFact + CoarseNumZLayers: myLineDetectionFact + LineDetection_Layers: myLineDetectionFact + LineDetection_VertLineIds: myLineDetectionFact + A: myRebalanceAFact + Coordinates: myRebalanceProlongatorFact + Importer: myRepartitionFact + diff --git a/components/mpas-albany-landice/bld/namelist_files/albany_input.yaml b/components/mpas-albany-landice/bld/namelist_files/albany_input.gis_1to10km_r02.yaml similarity index 78% rename from components/mpas-albany-landice/bld/namelist_files/albany_input.yaml rename to components/mpas-albany-landice/bld/namelist_files/albany_input.gis_1to10km_r02.yaml index 478ed9dd6580..45539411756a 100644 --- a/components/mpas-albany-landice/bld/namelist_files/albany_input.yaml +++ b/components/mpas-albany-landice/bld/namelist_files/albany_input.gis_1to10km_r02.yaml @@ -1,20 +1,20 @@ %YAML 1.1 --- ANONYMOUS: - Build Type: Tpetra Problem: + Depth Integrated Model: true + Basal Cubature Degree: 4 LandIce Field Norm: sliding_velocity_basalside: Regularization Type: Given Value Regularization Value: 1.0e-4 LandIce BCs: BC 0: - Cubature Degree: 4 Basal Friction Coefficient: Type: Power Law Power Exponent: 1.0 - Mu Type: Field + Mu Type: Field Effective Pressure Type: Hydrostatic Computed At Nodes Zero Effective Pressure On Floating Ice At Nodes: true Zero Beta On Floating Ice: false @@ -22,26 +22,26 @@ ANONYMOUS: # Discretization Description Discretization: #Exodus Output File Name: albany_output.exo - - Piro: + + Piro: # Nonlinear Solver Information - NOX: + NOX: Nonlinear Solver: Line Search Based - Line Search: - Full Step: + Line Search: + Full Step: Full Step: 1.0e+00 Method: Backtrack - Solver Options: + Solver Options: Status Test Check Type: Minimal - Status Tests: + Status Tests: Test Type: Combo Combo Type: OR Number of Tests: 2 - Test 0: + Test 0: Test Type: Combo Combo Type: AND Number of Tests: 2 - Test 0: + Test 0: Test Type: NormF Norm Type: Two Norm Scale Type: Unscaled @@ -50,13 +50,13 @@ ANONYMOUS: Test Type: RelativeNormF Norm Type: Two Norm Tolerance: 0.9999 - Test 1: + Test 1: Test Type: MaxIters Maximum Iterations: 100 - Printing: + Printing: Output Precision: 3 Output Processor: 0 - Output Information: + Output Information: Error: true Warning: true Outer Iteration: true @@ -67,29 +67,21 @@ ANONYMOUS: Stepper Details: true Stepper Parameters: true - Direction: + Direction: Method: Newton - Newton: - Forcing Term Method: Type 2 + Newton: + Forcing Term Method: Type 2 Rescue Bad Newton Solve: true Linear Solver: Write Linear System: false Tolerance: 1.0e-8 - - Stratimikos Linear Solver: + + Stratimikos Linear Solver: Stratimikos: - + # Linear Solver Information Linear Solver Type: Belos - Linear Solver Types: - AztecOO: - Forward Solve: - AztecOO Settings: - Aztec Solver: GMRES - Convergence Test: r0 - Size of Krylov Subspace: 200 - Output Frequency: 20 - Max Iterations: 200 + Linear Solver Types: Belos: Solver Type: Block GMRES Solver Types: @@ -104,133 +96,133 @@ ANONYMOUS: VerboseObject: Output File: none Verbosity Level: low - + # Preconditioner Information Preconditioner Type: MueLu - Preconditioner Types: - - Ifpack2: + Preconditioner Types: + + Ifpack2: Overlap: 1 - Prec Type: ILUT - - MueLu: - Matrix: + Prec Type: ILUT + + MueLu: + Matrix: PDE equations: 2 - Factories: - myLineDetectionFact: + Factories: + myLineDetectionFact: factory: LineDetectionFactory 'linedetection: orientation': coordinates - mySemiCoarsenPFact1: + mySemiCoarsenPFact1: factory: SemiCoarsenPFactory 'semicoarsen: coarsen rate': 14 - UncoupledAggregationFact2: + UncoupledAggregationFact2: factory: UncoupledAggregationFactory 'aggregation: ordering': graph 'aggregation: max selected neighbors': 0 'aggregation: min agg size': 3 'aggregation: phase3 avoid singletons': true - MyCoarseMap2: + MyCoarseMap2: factory: CoarseMapFactory Aggregates: UncoupledAggregationFact2 - myTentativePFact2: + myTentativePFact2: 'tentative: calculate qr': true factory: TentativePFactory Aggregates: UncoupledAggregationFact2 CoarseMap: MyCoarseMap2 - mySaPFact2: + mySaPFact2: 'sa: eigenvalue estimate num iterations': 10 'sa: damping factor': 1.33333e+00 factory: SaPFactory P: myTentativePFact2 - myTransferCoordinatesFact: + myTransferCoordinatesFact: factory: CoordinatesTransferFactory CoarseMap: MyCoarseMap2 Aggregates: UncoupledAggregationFact2 - myTogglePFact: + myTogglePFact: factory: TogglePFactory 'semicoarsen: number of levels': 2 - TransferFactories: + TransferFactories: P1: mySemiCoarsenPFact1 P2: mySaPFact2 Ptent1: mySemiCoarsenPFact1 Ptent2: myTentativePFact2 Nullspace1: mySemiCoarsenPFact1 Nullspace2: myTentativePFact2 - myRestrictorFact: + myRestrictorFact: factory: TransPFactory P: myTogglePFact - myToggleTransferCoordinatesFact: + myToggleTransferCoordinatesFact: factory: ToggleCoordinatesTransferFactory Chosen P: myTogglePFact - TransferFactories: + TransferFactories: Coordinates1: mySemiCoarsenPFact1 Coordinates2: myTransferCoordinatesFact - myRAPFact: + myRAPFact: factory: RAPFactory P: myTogglePFact R: myRestrictorFact - TransferFactories: + TransferFactories: For Coordinates: myToggleTransferCoordinatesFact - myRepartitionHeuristicFact: + myRepartitionHeuristicFact: factory: RepartitionHeuristicFactory A: myRAPFact 'repartition: min rows per proc': 3000 'repartition: max imbalance': 1.327e+00 'repartition: start level': 1 - myZoltanInterface: + myZoltanInterface: factory: ZoltanInterface A: myRAPFact Coordinates: myToggleTransferCoordinatesFact number of partitions: myRepartitionHeuristicFact - myRepartitionFact: + myRepartitionFact: factory: RepartitionFactory A: myRAPFact Partition: myZoltanInterface 'repartition: remap parts': true number of partitions: myRepartitionHeuristicFact - myRebalanceProlongatorFact: + myRebalanceProlongatorFact: factory: RebalanceTransferFactory type: Interpolation P: myTogglePFact Coordinates: myToggleTransferCoordinatesFact Nullspace: myTogglePFact - myRebalanceRestrictionFact: + myRebalanceRestrictionFact: factory: RebalanceTransferFactory type: Restriction R: myRestrictorFact - myRebalanceAFact: + myRebalanceAFact: factory: RebalanceAcFactory A: myRAPFact TransferFactories: { } - mySmoother1: + mySmoother1: factory: TrilinosSmoother type: LINESMOOTHING_BANDEDRELAXATION 'smoother: pre or post': both - ParameterList: + ParameterList: 'relaxation: type': Gauss-Seidel 'relaxation: sweeps': 1 'relaxation: damping factor': 1.0 - mySmoother3: + mySmoother3: factory: TrilinosSmoother type: RELAXATION 'smoother: pre or post': both - ParameterList: + ParameterList: 'relaxation: type': Gauss-Seidel 'relaxation: sweeps': 1 'relaxation: damping factor': 1.0 - mySmoother4: + mySmoother4: factory: TrilinosSmoother type: RELAXATION 'smoother: pre or post': pre - ParameterList: + ParameterList: 'relaxation: type': Gauss-Seidel 'relaxation: sweeps': 4 'relaxation: damping factor': 1.0 - Hierarchy: + Hierarchy: max levels: 7 'coarse: max size': 2000 verbosity: None - Finest: + Finest: Smoother: mySmoother1 CoarseSolver: mySmoother4 P: myRebalanceProlongatorFact @@ -241,7 +233,7 @@ ANONYMOUS: A: myRebalanceAFact Coordinates: myRebalanceProlongatorFact Importer: myRepartitionFact - All: + All: startLevel: 1 Smoother: mySmoother4 CoarseSolver: mySmoother4 @@ -253,4 +245,3 @@ ANONYMOUS: A: myRebalanceAFact Coordinates: myRebalanceProlongatorFact Importer: myRepartitionFact - diff --git a/components/mpas-albany-landice/bld/namelist_files/albany_input.gis_20km_r01.yaml b/components/mpas-albany-landice/bld/namelist_files/albany_input.gis_20km_r01.yaml new file mode 100644 index 000000000000..589e163bba7f --- /dev/null +++ b/components/mpas-albany-landice/bld/namelist_files/albany_input.gis_20km_r01.yaml @@ -0,0 +1,231 @@ +%YAML 1.1 +--- +ANONYMOUS: + +# Discretization Description + Discretization: + #Exodus Output File Name: albany_output.exo + + Piro: +# Nonlinear Solver Information + NOX: + Nonlinear Solver: Line Search Based + Line Search: + Full Step: + Full Step: 1.0e+00 + Method: Backtrack + Solver Options: + Status Test Check Type: Minimal + Status Tests: + Test Type: Combo + Combo Type: OR + Number of Tests: 2 + Test 0: + Test Type: Combo + Combo Type: AND + Number of Tests: 2 + Test 0: + Test Type: NormF + Norm Type: Two Norm + Scale Type: Unscaled + Tolerance: 1.0e-03 + Test 1: + Test Type: RelativeNormF + Norm Type: Two Norm + Tolerance: 0.9999 + Test 1: + Test Type: MaxIters + Maximum Iterations: 100 + Printing: + Output Precision: 3 + Output Processor: 0 + Output Information: + Error: true + Warning: true + Outer Iteration: true + Parameters: false + Details: false + Linear Solver Details: false + Stepper Iteration: true + Stepper Details: true + Stepper Parameters: true + + Direction: + Method: Newton + Newton: + Forcing Term Method: Type 2 + Rescue Bad Newton Solve: true + Linear Solver: + Write Linear System: false + Tolerance: 1.0e-8 + + Stratimikos Linear Solver: + Stratimikos: + +# Linear Solver Information + Linear Solver Type: Belos + Linear Solver Types: + Belos: + Solver Type: Block GMRES + Solver Types: + Block GMRES: + Output Frequency: 20 + Output Style: 1 + Verbosity: 33 + Maximum Iterations: 200 + Block Size: 1 + Num Blocks: 200 + Flexible Gmres: false + VerboseObject: + Output File: none + Verbosity Level: low + +# Preconditioner Information + Preconditioner Type: MueLu + Preconditioner Types: + + Ifpack2: + Overlap: 1 + Prec Type: ILUT + + MueLu: + Matrix: + PDE equations: 2 + Factories: + myLineDetectionFact: + factory: LineDetectionFactory + 'linedetection: orientation': coordinates + mySemiCoarsenPFact1: + factory: SemiCoarsenPFactory + 'semicoarsen: coarsen rate': 14 + UncoupledAggregationFact2: + factory: UncoupledAggregationFactory + 'aggregation: ordering': graph + 'aggregation: max selected neighbors': 0 + 'aggregation: min agg size': 3 + 'aggregation: phase3 avoid singletons': true + MyCoarseMap2: + factory: CoarseMapFactory + Aggregates: UncoupledAggregationFact2 + myTentativePFact2: + 'tentative: calculate qr': true + factory: TentativePFactory + Aggregates: UncoupledAggregationFact2 + CoarseMap: MyCoarseMap2 + mySaPFact2: + 'sa: eigenvalue estimate num iterations': 10 + 'sa: damping factor': 1.33333e+00 + factory: SaPFactory + P: myTentativePFact2 + myTransferCoordinatesFact: + factory: CoordinatesTransferFactory + CoarseMap: MyCoarseMap2 + Aggregates: UncoupledAggregationFact2 + myTogglePFact: + factory: TogglePFactory + 'semicoarsen: number of levels': 2 + TransferFactories: + P1: mySemiCoarsenPFact1 + P2: mySaPFact2 + Ptent1: mySemiCoarsenPFact1 + Ptent2: myTentativePFact2 + Nullspace1: mySemiCoarsenPFact1 + Nullspace2: myTentativePFact2 + myRestrictorFact: + factory: TransPFactory + P: myTogglePFact + myToggleTransferCoordinatesFact: + factory: ToggleCoordinatesTransferFactory + Chosen P: myTogglePFact + TransferFactories: + Coordinates1: mySemiCoarsenPFact1 + Coordinates2: myTransferCoordinatesFact + myRAPFact: + factory: RAPFactory + P: myTogglePFact + R: myRestrictorFact + TransferFactories: + For Coordinates: myToggleTransferCoordinatesFact + myRepartitionHeuristicFact: + factory: RepartitionHeuristicFactory + A: myRAPFact + 'repartition: min rows per proc': 3000 + 'repartition: max imbalance': 1.327e+00 + 'repartition: start level': 1 + myZoltanInterface: + factory: ZoltanInterface + A: myRAPFact + Coordinates: myToggleTransferCoordinatesFact + number of partitions: myRepartitionHeuristicFact + myRepartitionFact: + factory: RepartitionFactory + A: myRAPFact + Partition: myZoltanInterface + 'repartition: remap parts': true + number of partitions: myRepartitionHeuristicFact + myRebalanceProlongatorFact: + factory: RebalanceTransferFactory + type: Interpolation + P: myTogglePFact + Coordinates: myToggleTransferCoordinatesFact + Nullspace: myTogglePFact + myRebalanceRestrictionFact: + factory: RebalanceTransferFactory + type: Restriction + R: myRestrictorFact + myRebalanceAFact: + factory: RebalanceAcFactory + A: myRAPFact + TransferFactories: { } + mySmoother1: + factory: TrilinosSmoother + type: LINESMOOTHING_BANDEDRELAXATION + 'smoother: pre or post': both + ParameterList: + 'relaxation: type': Gauss-Seidel + 'relaxation: sweeps': 1 + 'relaxation: damping factor': 1.0 + mySmoother3: + factory: TrilinosSmoother + type: RELAXATION + 'smoother: pre or post': both + ParameterList: + 'relaxation: type': Gauss-Seidel + 'relaxation: sweeps': 1 + 'relaxation: damping factor': 1.0 + mySmoother4: + factory: TrilinosSmoother + type: RELAXATION + 'smoother: pre or post': pre + ParameterList: + 'relaxation: type': Gauss-Seidel + 'relaxation: sweeps': 4 + 'relaxation: damping factor': 1.0 + Hierarchy: + max levels: 7 + 'coarse: max size': 2000 + verbosity: None + Finest: + Smoother: mySmoother1 + CoarseSolver: mySmoother4 + P: myRebalanceProlongatorFact + Nullspace: myRebalanceProlongatorFact + CoarseNumZLayers: myLineDetectionFact + LineDetection_Layers: myLineDetectionFact + LineDetection_VertLineIds: myLineDetectionFact + A: myRebalanceAFact + Coordinates: myRebalanceProlongatorFact + Importer: myRepartitionFact + All: + startLevel: 1 + Smoother: mySmoother4 + CoarseSolver: mySmoother4 + P: myRebalanceProlongatorFact + Nullspace: myRebalanceProlongatorFact + CoarseNumZLayers: myLineDetectionFact + LineDetection_Layers: myLineDetectionFact + LineDetection_VertLineIds: myLineDetectionFact + A: myRebalanceAFact + Coordinates: myRebalanceProlongatorFact + Importer: myRepartitionFact + diff --git a/components/mpas-albany-landice/bld/namelist_files/namelist_defaults_mali.xml b/components/mpas-albany-landice/bld/namelist_files/namelist_defaults_mali.xml index 5cebbf9cd136..8dc305533ca3 100644 --- a/components/mpas-albany-landice/bld/namelist_files/namelist_defaults_mali.xml +++ b/components/mpas-albany-landice/bld/namelist_files/namelist_defaults_mali.xml @@ -18,7 +18,7 @@ 'fo' -'none' +'fo' 3 0.25 .false. @@ -26,7 +26,7 @@ 'none' -'0002-00-00_00:00:00' +2 'mpas_to_grid.nc' 'grid_to_mpas.nc' @@ -44,8 +44,8 @@ 0.0 .true. .true. -.false. -.false. +.true. +.true. 100.0 1.0e6 1.0e6 @@ -67,7 +67,7 @@ .false. -'none' +'temperature' .true. 'file' 0.0 @@ -184,6 +184,7 @@ 0.1 0.04 0.01 +.true. .false. .false. 1.25 @@ -194,6 +195,7 @@ .true. 'none' 'file' +1 .true. diff --git a/components/mpas-albany-landice/bld/namelist_files/namelist_definition_mali.xml b/components/mpas-albany-landice/bld/namelist_files/namelist_definition_mali.xml index c04d52840a6c..e16e7042a2cb 100644 --- a/components/mpas-albany-landice/bld/namelist_files/namelist_definition_mali.xml +++ b/components/mpas-albany-landice/bld/namelist_files/namelist_definition_mali.xml @@ -194,11 +194,11 @@ Valid values: 'none', 'data', 'sealevelmodel' Default: Defined in namelist_defaults.xml - -Time interval at which the sea-level model is called by MALI. The interval has to be an even multiple of the option 'config_adaptive_timestep_force_interval +Time interval at which the sea-level model is called by MALI. Only integer years are currently supported. The user must set 'dt1' in namelist.sealevel to match this value. Note that the user needs to set config_adaptive_timestep_force_interval to divide evenly into config_slm_coupling_interval. Also, restart file output_interval needs to be a multiple of config_slm_coupling_interval. -Valid values: Any time interval of the format 'YYYY-MM-DD_HH:MM:SS' +Valid values: Any positive integer Default: Defined in namelist_defaults.xml @@ -1218,7 +1218,7 @@ Default: Defined in namelist_defaults.xml -Selection of the method for calculating the tangent component of slope at edges. 'from_vertex_barycentric' interpolates scalar values from cell centers to vertices using the barycentric interpolation routine in operators (mpas_cells_to_points_using_baryweights) and then calculates the slope between vertices. It works for obtuse triangles, but will not work correctly across the edges of periodic meshes. 'from_vertex_barycentric_kiteareas' interpolates scalar values from cell centers to vertices using barycentric interpolation based on kiterea values and then calculates the slope between vertices. It will work across the edges of periodic meshes, but will not work correctly for obtuse triangles. 'from_normal_slope' uses the vector operator mpas_tangential_vector_1d to calculate the tangent slopes from the normal slopes on the edges of the adjacent cells. It will work for any mesh configuration, but is the least accurate method. +Selection of the method for calculating the tangent component of slope at edges. 'from_vertex_barycentric' interpolates scalar values from cell centers to vertices using the barycentric interpolation routine in operators (mpas_cells_to_points_using_baryweights) and then calculates the slope between vertices. It works for obtuse triangles, but will not work correctly across the edges of periodic meshes. 'from_vertex_barycentric_kiteareas' interpolates scalar values from cell centers to vertices using barycentric interpolation based on kiterea values and then calculates the slope between vertices. It will work across the edges of periodic meshes, but will not work correctly for obtuse triangles. 'from_normal_slope' uses the vector operator mpas_tangential_vector_1d to calculate the tangent slopes from the normal slopes on the edges of the adjacent cells. It will work for any mesh configuration. 'from_normal_slope' uses a larger stencil, so may therefore produce a smoother 'gradMagPhiEdge' field. Detailed testing yielded nearly identical results between 'from_normal_slope' and 'from_vertex_barycentric' methods, but 'from_normal_slope' seemed to produce slightly more stable results at the grounding line. Valid values: 'from_vertex_barycentric', 'from_vertex_barycentric_kiteareas', 'from_normal_slope' Default: Defined in namelist_defaults.xml @@ -1320,6 +1320,14 @@ Valid values: positive real number Default: Defined in namelist_defaults.xml + +Option to use an altered ice thickness field called iceThicknessHydro that replaces local maxima/minima in upperSurface with a mean of the cells neighbors. This option has no significant effect on the behavior of the model but makes it more stable. + +Valid values: .true. or .false. +Default: Defined in namelist_defaults.xml + + activate channels in subglacial hydrology model @@ -1400,6 +1408,14 @@ Valid values: 'file', 'thermal', 'basal_heat' Default: Defined in namelist_defaults.xml + +number of iterations to smooth waterPressure over when calculating waterPressureSlopeNormal. Used only to keep channelPressureFreeze stable and will not affect other aspects of the model that rely on waterPressure. + +Valid values: positive integer or zero +Default: Defined in namelist_defaults.xml + + diff --git a/components/mpas-albany-landice/cime_config/buildnml b/components/mpas-albany-landice/cime_config/buildnml index 0a3b35df93eb..3b38ed39c438 100755 --- a/components/mpas-albany-landice/cime_config/buildnml +++ b/components/mpas-albany-landice/cime_config/buildnml @@ -62,16 +62,26 @@ def buildnml(case, caseroot, compname): grid_prefix += 'aisgis20km' decomp_date += '20190326' decomp_prefix += 'mpasli.graph.info.' - elif glc_grid == 'mpas.gis20km': - grid_date += '20210824' - grid_prefix += 'gis_20km_r01' - decomp_date += '150922' - decomp_prefix += 'mpasli.graph.info.' elif glc_grid == 'mpas.ais20km': grid_date += '150910' grid_prefix += 'ais20km' decomp_date += '150910' decomp_prefix += 'mpasli.graph.info.' + elif glc_grid == 'mpas.ais8to30km': + grid_date += '20221027' + grid_prefix += 'ais_8to30km' + decomp_date += '240507' + decomp_prefix += 'mpasli.graph.info.' + elif glc_grid == 'mpas.ais4to20km': + grid_date += '20240708' + grid_prefix += 'ais_4to20km' + decomp_date += '240507' + decomp_prefix += 'mpasli.graph.info.' + elif glc_grid == 'mpas.gis20km': + grid_date += '20210824' + grid_prefix += 'gis_20km_r01' + decomp_date += '150922' + decomp_prefix += 'mpasli.graph.info.' elif glc_grid == 'mpas.gis1to10km': grid_date += '20210824' grid_prefix += 'gis_1to10km_r01' @@ -219,25 +229,33 @@ def buildnml(case, caseroot, compname): lines.append(' ') lines.append(' ') lines.append(' ') + lines.append(' ') lines.append(' ') lines.append(' ') lines.append(' ') lines.append(' ') -# lines.append(' ') -# lines.append(' ') lines.append(' ') lines.append(' ') lines.append(' ') lines.append(' ') lines.append(' ') - lines.append(' ') + lines.append(' ') + lines.append(' ') + lines.append(' ') + lines.append(' ') + lines.append(' ') lines.append(' ') lines.append(' ') + lines.append(' ') lines.append(' ') lines.append(' ') lines.append(' ') lines.append(' ') lines.append(' ') + lines.append(' ') + lines.append(' ') + lines.append(' ') + lines.append(' ') lines.append('') lines.append('') lines.append('') @@ -253,22 +271,18 @@ def buildnml(case, caseroot, compname): lines.append(' filename_interval="0001-00-00_00:00:00"') lines.append(' clobber_mode="truncate"') lines.append(' packages="globalStatsAMPKG"') - lines.append(' output_interval="0000_01:00:00">') + lines.append(' output_interval="0000_00:00:01">') lines.append('') - lines.append(' ') - lines.append(' ') - lines.append(' ') - lines.append(' ') - lines.append(' ') - lines.append(' ') - lines.append(' ') - lines.append(' ') - lines.append(' ') - lines.append(' ') - lines.append(' ') - lines.append(' ') - lines.append(' ') + lines.append(' ') lines.append(' ') + lines.append(' ') + lines.append(' ') + lines.append(' ') + lines.append(' ') + lines.append(' ') + if mali_use_albany: + lines.append(' ') + lines.append('') lines.append('') lines.append(' @@ -869,7 +870,8 @@ - + + @@ -935,6 +937,7 @@ input_interval="initial_only" runtime_format="single_file"> + + + + + + + @@ -140,7 +150,9 @@ - + @@ -152,7 +164,9 @@ description="water layer thickness in subglacial till from previous time step" /> - + @@ -174,7 +188,9 @@ description="mask indicating how to handle fluxes on each edge: 0=calculate based on hydropotential gradient; 1=allow outflow based on hydropotential gradient, but no inflow (NOT YET IMPLEMENTED); 2=zero flux" /> - + @@ -196,14 +212,20 @@ description="hydropotential in subglacial hydrology system without water thickness contribution" /> + - + + - + + + + + - diff --git a/components/mpas-albany-landice/src/SeaLevelModel b/components/mpas-albany-landice/src/SeaLevelModel index 26c156da2191..5bb102d6750b 160000 --- a/components/mpas-albany-landice/src/SeaLevelModel +++ b/components/mpas-albany-landice/src/SeaLevelModel @@ -1 +1 @@ -Subproject commit 26c156da2191df360e1040e0141534178674fc82 +Subproject commit 5bb102d6750b1437f6a5305cdd244cbd3776c32b diff --git a/components/mpas-albany-landice/src/analysis_members/Registry_global_stats.xml b/components/mpas-albany-landice/src/analysis_members/Registry_global_stats.xml old mode 100644 new mode 100755 index 622d33933cc0..50ad79158354 --- a/components/mpas-albany-landice/src/analysis_members/Registry_global_stats.xml +++ b/components/mpas-albany-landice/src/analysis_members/Registry_global_stats.xml @@ -100,6 +100,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/components/mpas-albany-landice/src/analysis_members/mpas_li_global_stats.F b/components/mpas-albany-landice/src/analysis_members/mpas_li_global_stats.F old mode 100644 new mode 100755 index d7a8123bf371..10350fa9d235 --- a/components/mpas-albany-landice/src/analysis_members/mpas_li_global_stats.F +++ b/components/mpas-albany-landice/src/analysis_members/mpas_li_global_stats.F @@ -163,11 +163,13 @@ subroutine li_compute_global_stats(domain, memberName, timeLevel, err) type (mpas_pool_type), pointer :: globalStatsAM type (mpas_pool_type), pointer :: geometryPool type (mpas_pool_type), pointer :: velocityPool + type (mpas_pool_type), pointer :: hydroPool ! arrays, vars needed from other pools for calculations here real (kind=RKIND), pointer :: deltat real (kind=RKIND), dimension(:), pointer :: areaCell real (kind=RKIND), dimension(:), pointer :: dvEdge + real (kind=RKIND), dimension(:), pointer :: dcEdge real (kind=RKIND), dimension(:), pointer :: thickness real (kind=RKIND), dimension(:), pointer :: bedTopography real (kind=RKIND), dimension(:), pointer :: sfcMassBalApplied @@ -181,7 +183,18 @@ subroutine li_compute_global_stats(domain, memberName, timeLevel, err) real (kind=RKIND), dimension(:), pointer :: basalSpeed real (kind=RKIND), dimension(:), pointer :: fluxAcrossGroundingLine real (kind=RKIND), dimension(:), pointer :: groundedToFloatingThickness + + real (kind=RKIND), dimension(:), pointer :: waterThickness + real (kind=RKIND), dimension(:), pointer :: basalMeltInput + real (kind=RKIND), dimension(:), pointer :: externalWaterInput + real (kind=RKIND), dimension(:), pointer :: channelMelt + real (kind=RKIND), dimension(:), pointer :: waterFlux + real (kind=RKIND), dimension(:), pointer :: channelDischarge + real (kind=RKIND), dimension(:), pointer :: waterPressure + integer, dimension(:), pointer :: cellMask + integer, dimension(:), pointer :: hydroMarineMarginMask + integer, dimension(:), pointer :: hydroTerrestrialMarginMask integer, pointer :: nCellsSolve integer, pointer :: nEdgesSolve @@ -189,9 +202,11 @@ subroutine li_compute_global_stats(domain, memberName, timeLevel, err) real (kind=RKIND), pointer :: config_sea_level real (kind=RKIND), pointer :: rhoi ! config_ice_density real (kind=RKIND), pointer :: rhow ! config_ocean_density + real (kind=RKIND), pointer :: bedBumpMax ! config_SGH_bed_roughness_max + logical, pointer :: config_SGH ! Local counters - integer :: k, iCell, iEdge + integer :: k, iCell, iEdge, nCellsGrounded ! scalars to be calculated here from global reductions real (kind=RKIND), pointer :: totalIceArea, totalIceVolume @@ -211,6 +226,17 @@ subroutine li_compute_global_stats(domain, memberName, timeLevel, err) real (kind=RKIND), pointer :: groundingLineMigrationFlux real (kind=RKIND), pointer :: surfaceSpeedMax real (kind=RKIND), pointer :: basalSpeedMax + real (kind=RKIND), pointer :: totalSubglacialWaterVolume + real (kind=RKIND), pointer :: totalBasalMeltInput + real (kind=RKIND), pointer :: totalExternalWaterInput + real (kind=RKIND), pointer :: totalChannelMelt + real (kind=RKIND), pointer :: totalSubglacialLakeVolume + real (kind=RKIND), pointer :: totalSubglacialLakeArea + real (kind=RKIND), pointer :: totalDistWaterFluxMarineMargin + real (kind=RKIND), pointer :: totalDistWaterFluxTerrestrialMargin + real (kind=RKIND), pointer :: totalChnlWaterFluxMarineMargin + real (kind=RKIND), pointer :: totalChnlWaterFluxTerrestrialMargin + real (kind=RKIND), pointer :: avgFlotationFraction ! scalar reductions over all blocks on this processor real (kind=RKIND) :: blockSumIceArea, blockSumIceVolume @@ -227,11 +253,23 @@ subroutine li_compute_global_stats(domain, memberName, timeLevel, err) real (kind=RKIND) :: blockMaxBasalSpeed real (kind=RKIND) :: blockGLflux real (kind=RKIND) :: blockGLMigrationFlux + real (kind=RKIND) :: blockSumSubglacialWaterVolume + real (kind=RKIND) :: blockSumBasalMeltInput + real (kind=RKIND) :: blockSumExternalWaterInput + real (kind=RKIND) :: blockSumChannelMelt + real (kind=RKIND) :: blockSumLakeVolume + real (kind=RKIND) :: blockSumLakeArea + real (kind=RKIND) :: blockSumGLMeltFlux + real (kind=RKIND) :: blockSumTerrestrialMeltFlux + real (kind=RKIND) :: blockSumChannelGLMeltFlux + real (kind=RKIND) :: blockSumChannelTerrestrialMeltFlux + real (kind=RKIND) :: blockSumFlotationFraction ! Local variables for calculations + real (kind=RKIND) :: totalFlotationFraction ! variables for processing stats - integer, parameter :: kMaxVariables = 24 ! Increase if number of stats increase + integer, parameter :: kMaxVariables = 35 ! Increase if number of stats increase integer :: nVars real (kind=RKIND), dimension(kMaxVariables) :: reductions, sums, mins, maxes @@ -257,6 +295,17 @@ subroutine li_compute_global_stats(domain, memberName, timeLevel, err) blockSumFaceMeltingFlux = 0.0_RKIND blockGLflux = 0.0_RKIND blockGLMigrationFlux = 0.0_RKIND + blockSumSubglacialWaterVolume = 0.0_RKIND + blockSumBasalMeltInput = 0.0_RKIND + blockSumExternalWaterInput = 0.0_RKIND + blockSumChannelMelt = 0.0_RKIND + blockSumLakeVolume = 0.0_RKIND + blockSumLakeArea = 0.0_RKIND + blockSumGLMeltFlux = 0.0_RKIND + blockSumTerrestrialMeltFlux = 0.0_RKIND + blockSumChannelGLMeltFlux = 0.0_RKIND + blockSumChannelTerrestrialMeltFlux = 0.0_RKIND + blockSumFlotationFraction = 0.0_RKIND ! initialize max to 0, min to large number blockThickMin = 100000.0_RKIND @@ -268,6 +317,8 @@ subroutine li_compute_global_stats(domain, memberName, timeLevel, err) call mpas_pool_get_config(liConfigs, 'config_sea_level', config_sea_level) call mpas_pool_get_config(liConfigs, 'config_ice_density', rhoi) call mpas_pool_get_config(liConfigs, 'config_ocean_density', rhow) + call mpas_pool_get_config(liConfigs, 'config_SGH_bed_roughness_max', bedBumpMax) + call mpas_pool_get_config(liConfigs, 'config_SGH', config_SGH) ! loop over blocks block => domain % blocklist @@ -278,6 +329,7 @@ subroutine li_compute_global_stats(domain, memberName, timeLevel, err) call mpas_pool_get_subpool(block % structs, 'globalStatsAM', globalStatsAMPool) call mpas_pool_get_subpool(block % structs, 'geometry', geometryPool) call mpas_pool_get_subpool(block % structs, 'velocity', velocityPool) + call mpas_pool_get_subpool(block % structs, 'hydro', hydroPool) ! get values and arrays from standard pools call mpas_pool_get_dimension(block % dimensions, 'nCellsSolve', nCellsSolve) @@ -285,6 +337,7 @@ subroutine li_compute_global_stats(domain, memberName, timeLevel, err) call mpas_pool_get_array(meshPool, 'deltat', deltat) call mpas_pool_get_array(meshPool, 'areaCell', areaCell) call mpas_pool_get_array(meshPool, 'dvEdge', dvEdge) + call mpas_pool_get_array(meshPool, 'dcEdge', dcEdge) call mpas_pool_get_array(geometryPool, 'thickness', thickness) call mpas_pool_get_array(geometryPool, 'bedTopography', bedTopography) call mpas_pool_get_array(geometryPool, 'cellMask', cellMask) @@ -299,6 +352,17 @@ subroutine li_compute_global_stats(domain, memberName, timeLevel, err) call mpas_pool_get_array(velocityPool, 'surfaceSpeed', surfaceSpeed) call mpas_pool_get_array(velocityPool, 'basalSpeed', basalSpeed) call mpas_pool_get_array(velocityPool, 'fluxAcrossGroundingLine', fluxAcrossGroundingLine) + if (config_SGH) then + call mpas_pool_get_array(hydroPool, 'waterThickness', waterThickness) + call mpas_pool_get_array(hydroPool, 'basalMeltInput', basalMeltInput) + call mpas_pool_get_array(hydroPool, 'externalWaterInput', externalWaterInput) + call mpas_pool_get_array(hydroPool, 'channelMelt', channelMelt) + call mpas_pool_get_array(hydroPool, 'hydroMarineMarginMask', hydroMarineMarginMask) + call mpas_pool_get_array(hydroPool, 'hydroTerrestrialMarginMask', hydroTerrestrialMarginMask) + call mpas_pool_get_array(hydroPool, 'waterFlux', waterFlux) + call mpas_pool_get_array(hydroPool, 'channelDischarge', channelDischarge) + call mpas_pool_get_array(hydroPool, 'waterPressure', waterPressure) + endif ! loop over cells do iCell = 1,nCellsSolve @@ -314,11 +378,13 @@ subroutine li_compute_global_stats(domain, memberName, timeLevel, err) blockSumGroundedIceArea = blockSumGroundedIceArea + real(li_mask_is_grounded_ice_int(cellMask(iCell)),RKIND) & * areaCell(iCell) + blockSumGroundedIceVolume = blockSumGroundedIceVolume + real(li_mask_is_grounded_ice_int(cellMask(iCell)),RKIND) & * areaCell(iCell) * thickness(iCell) blockSumFloatingIceArea = blockSumFloatingIceArea + real(li_mask_is_floating_ice_int(cellMask(iCell)),RKIND) & * areaCell(iCell) + blockSumFloatingIceVolume = blockSumFloatingIceVolume + real(li_mask_is_floating_ice_int(cellMask(iCell)),RKIND) & * areaCell(iCell) * thickness(iCell) @@ -335,6 +401,7 @@ subroutine li_compute_global_stats(domain, memberName, timeLevel, err) blockSumGroundedSfcMassBal = blockSumGroundedSfcMassBal + areaCell(iCell) * groundedSfcMassBalApplied(iCell) * scyr blockSumFloatingSfcMassBal = blockSumFloatingSfcMassBal + & (sfcMassBalApplied(iCell) - groundedSfcMassBalApplied(iCell)) * areaCell(iCell) * scyr + ! BMB (kg yr-1) blockSumBasalMassBal = blockSumBasalMassBal + areaCell(iCell) * basalMassBalApplied(iCell) * scyr blockSumGroundedBasalMassBal = blockSumGroundedBasalMassBal + areaCell(iCell) * groundedBasalMassBalApplied(iCell) * scyr @@ -362,15 +429,66 @@ subroutine li_compute_global_stats(domain, memberName, timeLevel, err) blockGLMigrationFlux = blockGLMigrationFlux + groundedToFloatingThickness(iCell) * areaCell(iCell) & * rhoi / (deltat / scyr) ! convert from m to kg/yr + !! Subglacial Hydrology Calculations + if (config_SGH) then + + ! Subglacial Water Volume + blockSumSubglacialWaterVolume = blockSumSubglacialWaterVolume + waterThickness(iCell) * areaCell(iCell) + + ! Basal melt input + blockSumBasalMeltInput = blockSumBasalMeltInput + real(li_mask_is_grounded_ice_int(cellMask(iCell)),RKIND) * & + basalMeltInput(iCell) * areaCell(iCell) + + ! External water input + blockSumExternalWaterInput = blockSumExternalWaterInput + & + real(li_mask_is_grounded_ice_int(cellMask(iCell)),RKIND) * externalWaterInput(iCell) * areaCell(iCell) + + ! Lake Volume + if (waterThickness(iCell) > bedBumpMax) then + blockSumLakeVolume = blockSumLakeVolume + (waterThickness(iCell) - bedBumpMax) * areaCell(iCell) + endif + + ! Lake Area + if (waterThickness(iCell) > bedBumpMax) then + blockSumLakeArea = blockSumLakeArea + areaCell(iCell) + endif + + ! Area-weighted flotation fraction for grounded ice + if (li_mask_is_grounded_ice(cellMask(iCell))) then + blockSumFlotationFraction = blockSumFlotationFraction + ( waterPressure(iCell) / rhoi / gravity / thickness(iCell) ) * areaCell(iCell) + endif + endif + + end do ! end loop over cells ! Loop over edges do iEdge = 1, nEdgesSolve + ! Flux across GL, units = kg/yr blockGLflux = blockGLflux + fluxAcrossGroundingLine(iEdge) * dvEdge(iEdge) & * scyr * rhoi ! convert from m^2/s to kg/yr - end do ! end loop over edges + if (config_SGH) then + + ! Channel Melt + blockSumChannelMelt = blockSumChannelMelt + abs(channelMelt(iEdge) * dcEdge(iEdge)) + + ! Meltwater Flux across the grounding line + blockSumGLMeltFlux = blockSumGLMeltFlux + abs(hydroMarineMarginMask(iEdge) * waterFlux(iEdge) * dvEdge(iEdge) * rho_water) + + ! Meltwater Flux across terrestrial margins + blockSumTerrestrialMeltFlux = blockSumTerrestrialMeltFlux + abs(hydroTerrestrialMarginMask(iEdge) * waterFlux(iEdge) * dvEdge(iEdge) * rho_water) + + ! Meltwater Discharge in channels across grounding line + blockSumChannelGLMeltFlux = blockSumChannelGLMeltFlux + abs(hydroMarineMarginMask(iEdge) * channelDischarge(iEdge) * rho_water) + + ! Meltwater discharge in channels across terrestrial margin + blockSumChannelTerrestrialMeltFlux = blockSumChannelTerrestrialMeltFlux + abs( hydroTerrestrialMarginMask(iEdge) * channelDischarge(iEdge) * rho_water) + + endif ! is SGH is turned on + end do ! end loop over edges + block => block % next end do ! end loop over blocks @@ -409,7 +527,6 @@ subroutine li_compute_global_stats(domain, memberName, timeLevel, err) sums(7) = blockSumSfcMassBal sums(8) = blockSumGroundedSfcMassBal sums(9) = blockSumFloatingSfcMassBal - sums(10) = blockSumBasalMassBal sums(11) = blockSumGroundedBasalMassBal sums(12) = blockSumFloatingBasalMassBal @@ -418,7 +535,22 @@ subroutine li_compute_global_stats(domain, memberName, timeLevel, err) sums(15) = blockSumVAF sums(16) = blockGLflux sums(17) = blockGLMigrationflux - nVars = 17 + if (config_SGH) then + sums(18) = blockSumSubglacialWaterVolume + sums(19) = blockSumBasalMeltInput + sums(20) = blockSumExternalWaterInput + sums(21) = blockSumChannelMelt + sums(22) = blockSumLakeVolume + sums(23) = blockSumLakeArea + sums(24) = blockSumGLMeltFlux + sums(25) = blockSumTerrestrialMeltFlux + sums(26) = blockSumChannelGLMeltFlux + sums(27) = blockSumChannelTerrestrialMeltFlux + sums(28) = blockSumFlotationFraction + nVars = 28 + else + nVars = 17 + endif call mpas_dmpar_sum_real_array(dminfo, nVars, sums(1:nVars), reductions(1:nVars)) @@ -447,6 +579,19 @@ subroutine li_compute_global_stats(domain, memberName, timeLevel, err) call mpas_pool_get_array(globalStatsAMPool, 'totalFaceMeltingFlux', totalFaceMeltingFlux) call mpas_pool_get_array(globalStatsAMPool, 'groundingLineFlux', groundingLineFlux) call mpas_pool_get_array(globalStatsAMPool, 'groundingLineMigrationFlux', groundingLineMigrationFlux) + if (config_SGH) then + call mpas_pool_get_array(globalStatsAMPool, 'totalSubglacialWaterVolume', totalSubglacialWaterVolume) + call mpas_pool_get_array(globalStatsAMPool, 'totalBasalMeltInput', totalBasalMeltInput) + call mpas_pool_get_array(globalStatsAMPool, 'totalExternalWaterInput', totalExternalWaterInput) + call mpas_pool_get_array(globalStatsAMPool, 'totalChannelMelt', totalChannelMelt) + call mpas_pool_get_array(globalStatsAMPool, 'totalSubglacialLakeVolume', totalSubglacialLakeVolume) + call mpas_pool_get_array(globalStatsAMPool, 'totalSubglacialLakeArea', totalSubglacialLakeArea) + call mpas_pool_get_array(globalStatsAMPool, 'totalDistWaterFluxMarineMargin',totalDistWaterFluxMarineMargin) + call mpas_pool_get_array(globalStatsAMPool, 'totalDistWaterFluxTerrestrialMargin', totalDistWaterFluxTerrestrialMargin) + call mpas_pool_get_array(globalStatsAMPool, 'totalChnlWaterFluxMarineMargin',totalChnlWaterFluxMarineMargin) + call mpas_pool_get_array(globalStatsAMPool, 'totalChnlWaterFluxTerrestrialMargin', totalChnlWaterFluxTerrestrialMargin) + call mpas_pool_get_array(globalStatsAMPool, 'avgFlotationFraction', avgFlotationFraction) + endif totalIceArea = reductions(1) totalIceVolume = reductions(2) @@ -465,6 +610,19 @@ subroutine li_compute_global_stats(domain, memberName, timeLevel, err) volumeAboveFloatation = reductions(15) groundingLineFlux = reductions(16) groundingLineMigrationFlux = reductions(17) + if (config_SGH) then + totalSubglacialWaterVolume = reductions(18) + totalBasalMeltInput = reductions(19) + totalExternalWaterInput = reductions(20) + totalChannelMelt = reductions(21) + totalSubglacialLakeVolume = reductions(22) + totalSubglacialLakeArea = reductions(23) + totalDistWaterFluxMarineMargin = reductions(24) + totalDistWaterFluxTerrestrialMargin = reductions(25) + totalChnlWaterFluxMarineMargin = reductions(26) + totalChnlWaterFluxTerrestrialMargin = reductions(27) + totalFlotationFraction = reductions(28) + endif if (totalIceArea > 0.0_RKIND) then iceThicknessMean = totalIceVolume / totalIceArea @@ -473,16 +631,27 @@ subroutine li_compute_global_stats(domain, memberName, timeLevel, err) iceThicknessMean = 0.0_RKIND avgNetAccumulation = 0.0_RKIND endif + if (groundedIceArea > 0.0_RKIND) then avgGroundedBasalMelt = -1.0_RKIND * totalGroundedBasalMassBal / groundedIceArea / rhoi else avgGroundedBasalMelt = 0.0_RKIND endif + if (floatingIceArea > 0.0_RKIND) then avgSubshelfMelt = -1.0_RKIND * totalFloatingBasalMassBal / floatingIceArea / rhoi else avgSubshelfMelt = 0.0_RKIND endif + if (config_SGH) then + if (groundedIceArea > 0.0_RKIND) then + avgFlotationFraction = totalFlotationFraction / groundedIceArea + else + avgFlotationFraction = 0.0_RKIND + endif + endif + + block => block % next end do diff --git a/components/mpas-albany-landice/src/analysis_members/mpas_li_regional_stats.F b/components/mpas-albany-landice/src/analysis_members/mpas_li_regional_stats.F index 0f544b4b47a6..e18305ed51e0 100644 --- a/components/mpas-albany-landice/src/analysis_members/mpas_li_regional_stats.F +++ b/components/mpas-albany-landice/src/analysis_members/mpas_li_regional_stats.F @@ -164,12 +164,14 @@ subroutine li_compute_regional_stats(domain, memberName, timeLevel, err) type (mpas_pool_type), pointer :: geometryPool type (mpas_pool_type), pointer :: regionsPool type (mpas_pool_type), pointer :: velocityPool + type (mpas_pool_type), pointer :: hydroPool ! arrays, vars needed from other pools for calculations here real (kind=RKIND), pointer :: config_ice_density real (kind=RKIND), pointer :: deltat real (kind=RKIND), dimension(:), pointer :: areaCell real (kind=RKIND), dimension(:), pointer :: dvEdge + real (kind=RKIND), dimension(:), pointer :: dcEdge real (kind=RKIND), dimension(:), pointer :: thickness real (kind=RKIND), dimension(:), pointer :: bedTopography real (kind=RKIND), dimension(:), pointer :: sfcMassBalApplied @@ -185,15 +187,28 @@ subroutine li_compute_regional_stats(domain, memberName, timeLevel, err) real (kind=RKIND), dimension(:), pointer :: groundedToFloatingThickness real (kind=RKIND), dimension(:,:), pointer :: normalVelocity + real (kind=RKIND), dimension(:), pointer :: waterThickness + real (kind=RKIND), dimension(:), pointer :: basalMeltInput + real (kind=RKIND), dimension(:), pointer :: externalWaterInput + real (kind=RKIND), dimension(:), pointer :: channelMelt + real (kind=RKIND), dimension(:), pointer :: waterFlux + real (kind=RKIND), dimension(:), pointer :: channelDischarge + real (kind=RKIND), dimension(:), pointer :: waterPressure + ! config options needed real (kind=RKIND), pointer :: config_sea_level real (kind=RKIND), pointer :: rhoi ! config_ice_density real (kind=RKIND), pointer :: rhow ! config_ocean_density + real (kind=RKIND), pointer :: bedBumpMax ! config_SGH_bed_roughness_max + logical, pointer :: config_SGH integer, dimension(:,:), pointer :: regionCellMasks + integer, dimension(:,:), pointer :: regionEdgeMasks integer, dimension(:), pointer :: cellMask integer, dimension(:), pointer :: edgeMask integer, dimension(:,:), pointer :: cellsOnEdge + integer, dimension(:), pointer :: hydroMarineMarginMask + integer, dimension(:), pointer :: hydroTerrestrialMarginMask integer, pointer :: nRegions, nRegionGroups !, maxRegionsInGroup !! maxRegionsInGroup not needed / used yet integer, pointer :: nCellsSolve, nEdgesSolve, nVertLevels integer :: k, iCell, iEdge @@ -218,6 +233,17 @@ subroutine li_compute_regional_stats(domain, memberName, timeLevel, err) real (kind=RKIND), dimension(:), pointer :: regionalAvgSubshelfMelt real (kind=RKIND), dimension(:), pointer :: regionalSurfaceSpeedMax real (kind=RKIND), dimension(:), pointer :: regionalBasalSpeedMax + real (kind=RKIND), dimension(:), pointer :: regionalSumSubglacialWaterVolume + real (kind=RKIND), dimension(:), pointer :: regionalSumBasalMeltInput + real (kind=RKIND), dimension(:), pointer :: regionalSumExternalWaterInput + real (kind=RKIND), dimension(:), pointer :: regionalSumChannelMelt + real (kind=RKIND), dimension(:), pointer :: regionalSumSubglacialLakeVolume + real (kind=RKIND), dimension(:), pointer :: regionalSumSubglacialLakeArea + real (kind=RKIND), dimension(:), pointer :: regionalSumDistWaterFluxMarineMargin + real (kind=RKIND), dimension(:), pointer :: regionalSumDistWaterFluxTerrestrialMargin + real (kind=RKIND), dimension(:), pointer :: regionalSumChnlWaterFluxMarineMargin + real (kind=RKIND), dimension(:), pointer :: regionalSumChnlWaterFluxTerrestrialMargin + real (kind=RKIND), dimension(:), pointer :: regionalAvgFlotationFraction ! storage for sums over blocks real (kind=RKIND), dimension(:), allocatable :: blockSumRegionIceArea, blockSumRegionIceVolume @@ -234,12 +260,25 @@ subroutine li_compute_regional_stats(domain, memberName, timeLevel, err) real (kind=RKIND), dimension(:), allocatable :: blockRegionGLMigrationFlux real (kind=RKIND), dimension(:), allocatable :: blockRegionMaxSurfaceSpeed real (kind=RKIND), dimension(:), allocatable :: blockRegionMaxBasalSpeed + real (kind=RKIND), dimension(:), allocatable :: blockSumRegionSubglacialWaterVolume + real (kind=RKIND), dimension(:), allocatable :: blockSumRegionBasalMeltInput + real (kind=RKIND), dimension(:), allocatable :: blockSumRegionExternalWaterInput + real (kind=RKIND), dimension(:), allocatable :: blockSumRegionChannelMelt + real (kind=RKIND), dimension(:), allocatable :: blockSumRegionLakeVolume + real (kind=RKIND), dimension(:), allocatable :: blockSumRegionLakeArea + real (kind=RKIND), dimension(:), allocatable :: blockSumRegionGLMeltFlux + real (kind=RKIND), dimension(:), allocatable :: blockSumRegionTerrestrialMeltFlux + real (kind=RKIND), dimension(:), allocatable :: blockSumRegionChannelGLMeltFlux + real (kind=RKIND), dimension(:), allocatable :: blockSumRegionChannelTerrestrialMeltFlux + real (kind=RKIND), dimension(:), allocatable :: blockSumRegionFlotationFraction + ! local variable needed calculating numerator of regionalAvgFlotationFraction + real (kind=RKIND), dimension(:), allocatable:: regionalSumFlotationFraction ! local variables real (kind=RKIND) :: fluxSign ! variables for processing stats - integer, parameter :: kMaxVariables = 32 ! Increase if number of stats increase + integer, parameter :: kMaxVariables = 43 ! Increase if number of stats increase integer :: nVars real (kind=RKIND), dimension(kMaxVariables) :: reductions, sums, mins, maxes @@ -251,6 +290,8 @@ subroutine li_compute_regional_stats(domain, memberName, timeLevel, err) call mpas_pool_get_config(liConfigs, 'config_sea_level', config_sea_level) call mpas_pool_get_config(liConfigs, 'config_ice_density', rhoi) call mpas_pool_get_config(liConfigs, 'config_ocean_density', rhow) + call mpas_pool_get_config(liConfigs, 'config_SGH_bed_roughness_max', bedBumpMax) + call mpas_pool_get_config(liConfigs, 'config_SGH', config_SGH) ! loop over blocks block => domain % blocklist @@ -265,7 +306,8 @@ subroutine li_compute_regional_stats(domain, memberName, timeLevel, err) call mpas_pool_get_subpool(block % structs, 'geometry', geometryPool) call mpas_pool_get_subpool(block % structs, 'velocity', velocityPool) call mpas_pool_get_subpool(block % structs, 'regions', regionsPool) -! call mpas_pool_get_subpool(block % structs, 'regionalStatsAM', regionalStatsAMPool) + call mpas_pool_get_subpool(block % structs, 'hydro', hydroPool) +! call mpas_pool_get_subpool(block % structs, 'regionalStatsAM', regionalStatsAMPool) ! get values and arrays from standard pools call mpas_pool_get_config(liConfigs, 'config_ice_density', config_ice_density) @@ -292,10 +334,27 @@ subroutine li_compute_regional_stats(domain, memberName, timeLevel, err) call mpas_pool_get_array(velocityPool, 'basalSpeed', basalSpeed) call mpas_pool_get_array(velocityPool, 'fluxAcrossGroundingLine', fluxAcrossGroundingLine) call mpas_pool_get_array(velocityPool, 'normalVelocity', normalVelocity) + if (config_SGH) then + call mpas_pool_get_array(meshPool, 'dcEdge', dcEdge) + call mpas_pool_get_array(hydroPool, 'waterThickness', waterThickness) + call mpas_pool_get_array(hydroPool, 'basalMeltInput', basalMeltInput) + call mpas_pool_get_array(hydroPool, 'externalWaterInput', externalWaterInput) + call mpas_pool_get_array(hydroPool, 'channelMelt', channelMelt) + call mpas_pool_get_array(hydroPool, 'hydroMarineMarginMask', hydroMarineMarginMask) + call mpas_pool_get_array(hydroPool, 'hydroTerrestrialMarginMask', hydroTerrestrialMarginMask) + call mpas_pool_get_array(hydroPool, 'waterFlux', waterFlux) + call mpas_pool_get_array(hydroPool, 'channelDischarge', channelDischarge) + call mpas_pool_get_array(hydroPool, 'waterPressure', waterPressure) + endif ! get region cell masks from regionMasks.nc input file call mpas_pool_get_array(regionsPool, 'regionCellMasks', regionCellMasks) - + if (config_SGH) then + ! regionEdgeMasks is required if calculating regional stats with SGH, + ! in the fututre will probably be required for standalone regional stats + ! but this is used a stopgap to forestall backwards compatibility problems + call mpas_pool_get_array(regionsPool, 'regionEdgeMasks', regionEdgeMasks) + endif ! allocate & initialize sums over blocks to 0 allocate(blockSumRegionIceArea(nRegions)); allocate(blockSumRegionIceVolume(nRegions)) allocate(blockSumRegionVAF(nRegions)) @@ -310,6 +369,20 @@ subroutine li_compute_regional_stats(domain, memberName, timeLevel, err) allocate(blockSumRegionFaceMeltingFlux(nRegions)) allocate(blockSumRegionGLflux(nRegions)) allocate(blockRegionGLMigrationFlux(nRegions)) + if (config_SGH) then + allocate(blockSumRegionSubglacialWaterVolume(nRegions)) + allocate(blockSumRegionBasalMeltInput(nRegions)) + allocate(blockSumRegionExternalWaterInput(nRegions)) + allocate(blockSumRegionChannelMelt(nRegions)) + allocate(blockSumRegionLakeVolume(nRegions)) + allocate(blockSumRegionLakeArea(nRegions)) + allocate(blockSumRegionGLMeltFlux(nRegions)) + allocate(blockSumRegionTerrestrialMeltFlux(nRegions)) + allocate(blockSumRegionChannelGLMeltFlux(nRegions)) + allocate(blockSumRegionChannelTerrestrialMeltFlux(nRegions)) + allocate(blockSumRegionFlotationFraction(nRegions)) + allocate(regionalSumFlotationFraction(nRegions)) + endif blockSumRegionIceArea = 0.0_RKIND; blockSumRegionIceVolume = 0.0_RKIND blockSumRegionVAF = 0.0_RKIND @@ -324,6 +397,21 @@ subroutine li_compute_regional_stats(domain, memberName, timeLevel, err) blockSumRegionFaceMeltingFlux = 0.0_RKIND blockSumRegionGLflux = 0.0_RKIND blockRegionGLMigrationFlux = 0.0_RKIND + + if (config_SGH) then + blockSumRegionSubglacialWaterVolume = 0.0_RKIND + blockSumRegionBasalMeltInput = 0.0_RKIND + blockSumRegionExternalWaterInput = 0.0_RKIND + blockSumRegionChannelMelt = 0.0_RKIND + blockSumRegionLakeVolume = 0.0_RKIND + blockSumRegionLakeArea = 0.0_RKIND + blockSumRegionGLMeltFlux = 0.0_RKIND + blockSumRegionTerrestrialMeltFlux = 0.0_RKIND + blockSumRegionChannelGLMeltFlux = 0.0_RKIND + blockSumRegionChannelTerrestrialMeltFlux = 0.0_RKIND + blockSumRegionFlotationFraction = 0.0_RKIND + regionalSumFlotationFraction = 0.0_RKIND + endif do iCell = 1,nCellsSolve ! loop over cells ! do iGroup = 1,nRegionGroups ! loop over groups @@ -425,8 +513,45 @@ subroutine li_compute_regional_stats(domain, memberName, timeLevel, err) real(regionCellMasks(iRegion,iCell),RKIND) * & groundedToFloatingThickness(iCell) * areaCell(iCell) * rhoi / (deltat / scyr) + !! Subglacial Hydrology Calculations + if (config_SGH) then + + ! Subglacial Water Volume + blockSumRegionSubglacialWaterVolume(iRegion) = blockSumRegionSubglacialWaterVolume(iRegion) + & + (real(regionCellMasks(iRegion,iCell),RKIND) * waterThickness(iCell) * areaCell(iCell)) + + if (li_mask_is_grounded_ice(cellMask(iCell))) then + ! Basal melt input + blockSumRegionBasalMeltInput(iRegion) = blockSumRegionBasalMeltInput(iRegion) + & + (real(regionCellMasks(iRegion,iCell),RKIND) * basalMeltInput(iCell) * areaCell(iCell)) + endif + + ! External water input + blockSumRegionExternalWaterInput(iRegion) = blockSumRegionExternalWaterInput(iRegion) + & + (real(regionCellMasks(iRegion,iCell),RKIND) * & + real(li_mask_is_grounded_ice_int(cellMask(iCell)),RKIND) * & + externalWaterInput(iCell) * areaCell(iCell)) + + ! Lake Volume + if (waterThickness(iCell) > bedBumpMax) then + blockSumRegionLakeVolume(iRegion) = blockSumRegionLakeVolume(iRegion) + & + (real(regionCellMasks(iRegion,iCell),RKIND) * (waterThickness(iCell) - bedBumpMax) * areaCell(iCell)) + endif + + ! Lake Area + if (waterThickness(iCell) > bedBumpMax) then + blockSumRegionLakeArea(iRegion) = blockSumRegionLakeArea(iRegion) + & + (real(regionCellMasks(iRegion,iCell),RKIND) * areaCell(iCell)) + endif + + ! Area-weighted flotation fraction for grounded ice + if (li_mask_is_grounded_ice(cellMask(iCell))) then + blockSumRegionFlotationFraction(iRegion) = blockSumRegionFlotationFraction(iRegion) + & + (real(regionCellMasks(iRegion,iCell),RKIND) * & + ( waterPressure(iCell) / rhoi / gravity / thickness(iCell) ) * areaCell(iCell)) + endif + endif end do ! end loop over regions - ! end do ! end loop over groups end do ! end loop over cells @@ -450,6 +575,36 @@ subroutine li_compute_regional_stats(domain, memberName, timeLevel, err) end if ! if edge is on cell in region of interest end do ! end loop over regions end if ! if GL + + ! assign the SGH stats based on edge values using the regionEdgeMask + if (config_SGH) then + + do iRegion = 1,nRegions ! loop over regions + ! Channel Melt + blockSumRegionChannelMelt(iRegion) = blockSumRegionChannelMelt(iRegion) + & + (real(regionEdgeMasks(iRegion,iEdge),RKIND) * abs(channelMelt(iEdge) * dcEdge(iEdge))) + + ! Meltwater Flux across the grounding line + blockSumRegionGLMeltFlux(iRegion) = blockSumRegionGLMeltFlux(iRegion) + & + (real(regionEdgeMasks(iRegion,iEdge),RKIND) * & + abs(hydroMarineMarginMask(iEdge) * waterFlux(iEdge) * dvEdge(iEdge) * rho_water)) + + ! Meltwater Flux across terrestrial margins + blockSumRegionTerrestrialMeltFlux(iRegion) = blockSumRegionTerrestrialMeltFlux(iRegion) + & + (real(regionEdgeMasks(iRegion,iEdge),RKIND) * & + abs(hydroTerrestrialMarginMask(iEdge) * waterFlux(iEdge) * dvEdge(iEdge) * rho_water)) + + ! Meltwater Discharge in channels across grounding line + blockSumRegionChannelGLMeltFlux(iRegion) = blockSumRegionChannelGLMeltFlux(iRegion) + & + (real(regionEdgeMasks(iRegion,iEdge),RKIND) * & + abs(hydroMarineMarginMask(iEdge) * channelDischarge(iEdge) * rho_water)) + + ! Meltwater discharge in channels across terrestrial margin + blockSumRegionChannelTerrestrialMeltFlux(iRegion) = blockSumRegionChannelTerrestrialMeltFlux(iRegion) + & + (real(regionEdgeMasks(iRegion,iEdge),RKIND) * & + abs( hydroTerrestrialMarginMask(iEdge) * channelDischarge(iEdge) * rho_water)) + end do ! end loop over regions + endif ! if SGH is on end do ! end loop over edges block => block % next @@ -494,7 +649,22 @@ subroutine li_compute_regional_stats(domain, memberName, timeLevel, err) sums(15) = blockSumRegionVAF(iRegion) sums(16) = blockSumRegionGLflux(iRegion) sums(17) = blockRegionGLMigrationFlux(iRegion) - nVars = 17 + if (config_SGH) then + sums(18) = blockSumRegionSubglacialWaterVolume(iRegion) + sums(19) = blockSumRegionBasalMeltInput(iRegion) + sums(20) = blockSumRegionExternalWaterInput(iRegion) + sums(21) = blockSumRegionChannelMelt(iRegion) + sums(22) = blockSumRegionLakeVolume(iRegion) + sums(23) = blockSumRegionLakeArea(iRegion) + sums(24) = blockSumRegionGLMeltFlux(iRegion) + sums(25) = blockSumRegionTerrestrialMeltFlux(iRegion) + sums(26) = blockSumRegionChannelGLMeltFlux(iRegion) + sums(27) = blockSumRegionChannelTerrestrialMeltFlux(iRegion) + sums(28) = blockSumRegionFlotationFraction(iRegion) + nVars = 28 + else + nVars = 17 + endif call mpas_dmpar_sum_real_array(dminfo, nVars, sums(1:nVars), reductions(1:nVars)) @@ -526,6 +696,19 @@ subroutine li_compute_regional_stats(domain, memberName, timeLevel, err) call mpas_pool_get_array(regionalStatsAMPool, 'regionalSumGroundingLineFlux', regionalSumGroundingLineFlux) call mpas_pool_get_array(regionalStatsAMPool, 'regionalSumGroundingLineMigrationFlux', & regionalSumGroundingLineMigrationFlux) + if (config_SGH) then + call mpas_pool_get_array(regionalStatsAMPool, 'regionalSumSubglacialWaterVolume', regionalSumSubglacialWaterVolume) + call mpas_pool_get_array(regionalStatsAMPool, 'regionalSumBasalMeltInput', regionalSumBasalMeltInput) + call mpas_pool_get_array(regionalStatsAMPool, 'regionalSumExternalWaterInput', regionalSumExternalWaterInput) + call mpas_pool_get_array(regionalStatsAMPool, 'regionalSumChannelMelt', regionalSumChannelMelt) + call mpas_pool_get_array(regionalStatsAMPool, 'regionalSumSubglacialLakeVolume', regionalSumSubglacialLakeVolume) + call mpas_pool_get_array(regionalStatsAMPool, 'regionalSumSubglacialLakeArea', regionalSumSubglacialLakeArea) + call mpas_pool_get_array(regionalStatsAMPool, 'regionalSumDistWaterFluxMarineMargin',regionalSumDistWaterFluxMarineMargin) + call mpas_pool_get_array(regionalStatsAMPool, 'regionalSumDistWaterFluxTerrestrialMargin', regionalSumDistWaterFluxTerrestrialMargin) + call mpas_pool_get_array(regionalStatsAMPool, 'regionalSumChnlWaterFluxMarineMargin',regionalSumChnlWaterFluxMarineMargin) + call mpas_pool_get_array(regionalStatsAMPool, 'regionalSumChnlWaterFluxTerrestrialMargin', regionalSumChnlWaterFluxTerrestrialMargin) + call mpas_pool_get_array(regionalStatsAMPool, 'regionalAvgFlotationFraction', regionalAvgFlotationFraction) + endif regionalIceArea(iRegion) = reductions(1) regionalIceVolume(iRegion) = reductions(2) @@ -544,6 +727,19 @@ subroutine li_compute_regional_stats(domain, memberName, timeLevel, err) regionalVolumeAboveFloatation(iRegion) = reductions(15) regionalSumGroundingLineFlux(iRegion) = reductions(16) regionalSumGroundingLineMigrationFlux(iRegion) = reductions(17) + if (config_SGH) then + regionalSumSubglacialWaterVolume(iRegion) = reductions(18) + regionalSumBasalMeltInput(iRegion) = reductions(19) + regionalSumExternalWaterInput(iRegion) = reductions(20) + regionalSumChannelMelt(iRegion) = reductions(21) + regionalSumSubglacialLakeVolume(iRegion) = reductions(22) + regionalSumSubglacialLakeArea(iRegion) = reductions(23) + regionalSumDistWaterFluxMarineMargin(iRegion) = reductions(24) + regionalSumDistWaterFluxTerrestrialMargin(iRegion) = reductions(25) + regionalSumChnlWaterFluxMarineMargin(iRegion) = reductions(26) + regionalSumChnlWaterFluxTerrestrialMargin(iRegion) = reductions(27) + regionalSumFlotationFraction(iRegion) = reductions(28) + endif if (regionalIceArea(iRegion) > 0.0_RKIND) then regionalIceThicknessMean(iRegion) = regionalIceVolume(iRegion) / regionalIceArea(iRegion) @@ -565,6 +761,14 @@ subroutine li_compute_regional_stats(domain, memberName, timeLevel, err) regionalAvgSubshelfMelt(iRegion) = 0.0_RKIND endif + if (config_SGH) then + if (regionalGroundedIceArea(iRegion) > 0.0_RKIND) then + regionalAvgFlotationFraction(iRegion) = regionalSumFlotationFraction(iRegion) / regionalGroundedIceArea(iRegion) + else + regionalAvgFlotationFraction(iRegion) = 0.0_RKIND + endif + endif + block => block % next end do @@ -624,6 +828,21 @@ subroutine li_compute_regional_stats(domain, memberName, timeLevel, err) deallocate(blockSumRegionFaceMeltingFlux) deallocate(blockSumRegionGLflux) deallocate(blockRegionGLMigrationflux) + if (config_SGH) then + deallocate(blockSumRegionSubglacialWaterVolume) + deallocate(blockSumRegionBasalMeltInput) + deallocate(blockSumRegionExternalWaterInput) + deallocate(blockSumRegionChannelMelt) + deallocate(blockSumRegionLakeVolume) + deallocate(blockSumRegionLakeArea) + deallocate(blockSumRegionGLMeltFlux) + deallocate(blockSumRegionTerrestrialMeltFlux) + deallocate(blockSumRegionChannelGLMeltFlux) + deallocate(blockSumRegionChannelTerrestrialMeltFlux) + deallocate(blockSumRegionFlotationFraction) + ! local variable needed for calculating numerator of regionalAvgFlotationFraction + deallocate(regionalSumFlotationFraction) + endif end subroutine li_compute_regional_stats diff --git a/components/mpas-albany-landice/src/mode_forward/mpas_li_bedtopo.F b/components/mpas-albany-landice/src/mode_forward/mpas_li_bedtopo.F index 1cfbe6a8da70..51c9a8f69e23 100644 --- a/components/mpas-albany-landice/src/mode_forward/mpas_li_bedtopo.F +++ b/components/mpas-albany-landice/src/mode_forward/mpas_li_bedtopo.F @@ -53,7 +53,7 @@ module li_bedtopo !-------------------------------------------------------------------- ! sea-level model timestep - integer, save :: slmTimeStep + integer, save :: slmTimeStep, nglv_slm, norder_slm ! Interpolation weights variables integer, dimension(:), allocatable :: toRowValues, toColValues @@ -115,14 +115,20 @@ subroutine li_bedtopo_init(domain, err) !----------------------------------------------------------------- character (len=StrKIND), pointer :: config_uplift_method + integer :: err_tmp ! No init is needed. err = 0 call mpas_pool_get_config(liConfigs, 'config_uplift_method', config_uplift_method) if (trim(config_uplift_method)=='sealevelmodel') then - ! initialize the 1D sea-level model - call slmodel_init(domain, err) + ! initialize the 1D sea-level model if fresh start + call slmodel_init(domain, err_tmp) + err = ior(err, err_tmp) + + if (err /= 0) then + call mpas_log_write('Error in li_bedtopo_init', MPAS_LOG_ERR) + endif endif !-------------------------------------------------------------------- @@ -362,9 +368,9 @@ end subroutine li_bedtopo_finalize subroutine slmodel_init(domain, err) #ifdef USE_SEALEVELMODEL + use mpas_timekeeping use sl_model_mod !< this is part of the SLM code use sl_io_mod !< this is part of the SLM code - use user_specs_mod, only: nglv !< this is part of the SLM code #endif !----------------------------------------------------------------- ! input variables @@ -386,21 +392,24 @@ subroutine slmodel_init(domain, err) !----------------------------------------------------------------- #ifdef USE_SEALEVELMODEL - character (len=StrKIND), pointer :: config_slm_coupling_interval + logical, pointer :: config_do_restart type (mpas_pool_type), pointer :: meshPool !< mesh information type (mpas_pool_type), pointer :: geometryPool real (kind=RKIND), dimension(:), pointer :: thickness, bedTopography real (kind=RKIND), dimension(:), allocatable :: meshMask - real (kind=RKIND), dimension(nglv,2*nglv) :: ismIceload, ismBedtopo, ismMask - real (kind=RKIND), dimension(nglv*2*nglv) :: thicknessSLgrid1D - real (kind=RKIND), dimension(nglv*2*nglv) :: bedtopoSLgrid1D - real (kind=RKIND), dimension(nglv*2*nglv) :: maskSLgrid1D - integer :: slm_coupling_interval + real (kind=RKIND), dimension(:,:), allocatable :: ismIceload, ismBedtopo, ismMask + real (kind=RKIND), dimension(:), allocatable :: thicknessSLgrid1D + real (kind=RKIND), dimension(:), allocatable :: bedtopoSLgrid1D + real (kind=RKIND), dimension(:), allocatable :: maskSLgrid1D integer :: err_tmp - integer :: unit_num_slm ! SLM variable - integer :: itersl, dtime ! SLM variable - real :: starttime ! SLM variable + integer :: unit_num_slm ! SLM variable + integer :: itersl, dtime ! SLM variable + real :: starttime ! SLM variable integer, dimension(:), pointer :: cellMask ! integer bitmask for cells + integer, pointer :: config_slm_coupling_interval + type (MPAS_TimeInterval_type) :: slm_coupling_interval + character (len=StrKIND), pointer :: simulationStartTime + type (MPAS_Time_type) :: simulationStartTime_timeType ! MPI variables integer, dimension(:), pointer :: indexToCellID @@ -409,12 +418,29 @@ subroutine slmodel_init(domain, err) err = 0 err_tmp = 0 + call mpas_pool_get_subpool(domain % blocklist % structs, 'mesh', meshPool) + + ! Set up the alarm for the coupling time interval + call mpas_pool_get_config(liConfigs, 'config_slm_coupling_interval', config_slm_coupling_interval) + call mpas_set_timeInterval(slm_coupling_interval, YY=config_slm_coupling_interval, ierr=err_tmp) + err = ior(err,err_tmp) + call mpas_pool_get_array(meshPool, 'simulationStartTime', simulationStartTime) + call mpas_set_time(simulationStartTime_timeType, dateTimeString=simulationStartTime, ierr=err_tmp) + err = ior(err,err_tmp) + call mpas_add_clock_alarm(domain%clock, 'slmCouplingInterval', alarmTime=simulationStartTime_timeType, & + alarmTimeInterval=slm_coupling_interval, ierr=err_tmp) + err = ior(err,err_tmp) + if (mpas_is_alarm_ringing(domain%clock, 'slmCouplingInterval', ierr=err_tmp)) then + err = ior(err, err_tmp) + call mpas_reset_clock_alarm(domain%clock, 'slmCouplingInterval', ierr=err_tmp) + err = ior(err, err_tmp) + endif + ! initialize interpolation call interpolate_init(domain, err_tmp) err = ior(err, err_tmp) ! Set needed variables for using MPI - call mpas_pool_get_subpool(domain % blocklist % structs, 'mesh', meshPool) call mpas_pool_get_dimension(meshPool, 'nCells', nCellsAll) call mpas_pool_get_dimension(meshPool, 'nCellsSolve', nCellsOwned) call mpas_pool_get_array(meshPool, 'indexToCellID', indexToCellID) @@ -431,11 +457,29 @@ subroutine slmodel_init(domain, err) ! Gather nCellsOwned call MPI_GATHER( nCellsOwned, 1, MPI_INTEGER, nCellsPerProc, 1, MPI_INTEGER, & - 0, domain % dminfo % comm, err_tmp) + 0, domain % dminfo % comm, err_tmp) err = ior(err, err_tmp) - ! Set Displacement variable for GATHERV command if (curProc.eq.0) then + ! First, set SLM unit number to the MALI output log file unit + unit_num_slm = domain % logInfo % outputLog % unitNum + call sl_set_unit_num(unit_num_slm) + + call sl_drive_readnl(itersl, dtime, starttime) !SLM subroutine + + ! First, check consistency in coupling interval set up in MALI and SLM + call check_SLM_coupling_interval(dtime, meshPool, err_tmp) + err = ior(err, err_tmp) + if (err /= 0) then + call mpas_log_write("Error occurred in check_SLM_coupling_interval.", MPAS_LOG_ERR) + endif + + ! check the number of points on the SLM Gauss-Legendre grid + call sl_get_model_res(norder_slm, nglv_slm) + call mpas_log_write("Solving the SLM upto $i order and degrees of Spherical Harmonics", intArgs=(/norder_slm/)) + call mpas_log_write("Number of Gauss-Legendre latitudinal nodes in the SLM grid is $i", intArgs=(/nglv_slm/)) + + ! Set Displacement variable for GATHERV command nCellsGlobal = sum(nCellsPerProc) allocate(indexToCellIDGathered(nCellsGlobal)) nCellsDisplacement(1) = 0 @@ -451,89 +495,101 @@ subroutine slmodel_init(domain, err) ! Gather indexToCellID call MPI_GATHERV( indexToCellID, nCellsOwned, MPI_INTEGER, indexToCellIDGathered, & - nCellsPerProc, nCellsDisplacement, MPI_INTEGER, 0, domain % dminfo % comm, err_tmp) + nCellsPerProc, nCellsDisplacement, MPI_INTEGER, 0, domain % dminfo % comm, err_tmp) err = ior(err, err_tmp) - call mpas_pool_get_subpool(domain % blocklist % structs, 'geometry', geometryPool) - call mpas_pool_get_array(geometryPool, 'thickness', thickness) - call mpas_pool_get_array(geometryPool, 'bedTopography', bedTopography) - call mpas_pool_get_array(geometryPool, 'cellMask', cellMask) + ! check if the run is a restart or not + call mpas_pool_get_config(liConfigs, 'config_do_restart', config_do_restart) + if (config_do_restart) then - if (curProc.eq.0) then - allocate(globalArrayThickness(nCellsGlobal), gatheredArrayThickness(nCellsGlobal)) - allocate(globalArrayBedTopography(nCellsGlobal), gatheredArrayBedTopography(nCellsGlobal)) - allocate(meshMask(nCellsGlobal)) - ismIceload(:,:) = 0.0 - ismBedtopo(:,:) = 0.0 - ismMask(:,:) = 0.0 - bedtopoSLgrid1D(:) = 0.0 - thicknessSLgrid1D(:) = 0.0 - maskSLgrid1D(:) = 0.0 - else - ! Intel requires these be allocated even though they are not meaningful on the non-destination procs - allocate(globalArrayThickness(1), gatheredArrayThickness(1)) - allocate(globalArrayBedTopography(1), gatheredArrayBedTopography(1)) - allocate(meshMask(1)) - endif + call find_slm_restart_timestep(meshPool, slmTimeStep, err_tmp) + err = ior(err, err_tmp) - ! Gather only the nCellsOwned from thickness and bedtopo (does not include Halos) - call MPI_GATHERV((thickness*real(li_mask_is_grounded_ice_int(cellMask),RKIND)), & - nCellsOwned, MPI_DOUBLE, gatheredArrayThickness, nCellsPerProc, & - nCellsDisplacement, MPI_DOUBLE, 0, domain % dminfo % comm, err_tmp) - err = ior(err, err_tmp) - call MPI_GATHERV(bedTopography, nCellsOwned, MPI_DOUBLE, gatheredArrayBedTopography, nCellsPerProc, & - nCellsDisplacement, MPI_DOUBLE, 0, domain % dminfo % comm, err_tmp) - err = ior(err, err_tmp) + ! Note: no need to call slmodel_solve on init of a restart. + ! If this time level happens to be a coupling interval, SLM would have been solved already + ! in the previous run that generated the restart file. + ! While it would not hurt (other than unneeded execution time) to call SLM again if the + ! restart time level happens to be a coupling interval, if the restart time is in between + ! coupling intervals calling SLM here will make things out of sync. - if (curProc.eq.0) then + else - ! First, check consistency in coupling interval set up in MALI and SLM - err = 0 - call mpas_pool_get_config(liConfigs, 'config_slm_coupling_interval', config_slm_coupling_interval) - read(config_slm_coupling_interval(1:4),*) slm_coupling_interval - call sl_drive_readnl(itersl, dtime, starttime) !SLM subroutine - if (slm_coupling_interval .NE. dtime) then - call mpas_log_write("The coupling interval in MALI and SLM settings are inconsistent", & - MPAS_LOG_ERR) - err = ior(err,1) + call mpas_pool_get_subpool(domain % blocklist % structs, 'geometry', geometryPool) + call mpas_pool_get_array(geometryPool, 'thickness', thickness) + call mpas_pool_get_array(geometryPool, 'bedTopography', bedTopography) + call mpas_pool_get_array(geometryPool, 'cellMask', cellMask) + + if (curProc.eq.0) then + ! allocate and initialize the SLM-related variables used in this module + allocate(globalArrayThickness(nCellsGlobal), gatheredArrayThickness(nCellsGlobal)) + allocate(globalArrayBedTopography(nCellsGlobal), gatheredArrayBedTopography(nCellsGlobal)) + allocate(meshMask(nCellsGlobal)) + allocate(ismIceload(nglv_slm,2*nglv_slm), ismBedtopo(nglv_slm,2*nglv_slm), ismMask(nglv_slm,2*nglv_slm)) + allocate(bedtopoSLgrid1D(nglv_slm*2*nglv_slm), thicknessSLgrid1D(nglv_slm*2*nglv_slm), maskSLgrid1D(nglv_slm*2*nglv_slm)) + ismIceload(:,:) = 0.0 + ismBedtopo(:,:) = 0.0 + ismMask(:,:) = 0.0 + bedtopoSLgrid1D(:) = 0.0 + thicknessSLgrid1D(:) = 0.0 + maskSLgrid1D(:) = 0.0 + call mpas_log_write("Allocating SLM variables in MALI, nglv is $i", intArgs=(/nglv_slm/)) + else + ! Intel requires these be allocated even though they are not meaningful on the non-destination procs + allocate(globalArrayThickness(1), gatheredArrayThickness(1)) + allocate(globalArrayBedTopography(1), gatheredArrayBedTopography(1)) + allocate(meshMask(1)) endif - ! Rearrange data into CellID order - do iCell = 1,nCellsGlobal - globalArrayThickness(indexToCellIDGathered(iCell)) = gatheredArrayThickness(iCell) - globalArrayBedTopography(indexToCellIDGathered(iCell)) = gatheredArrayBedTopography(iCell) - meshMask(indexToCellIDGathered(iCell)) = 1 - enddo - ! interpolate thickness, bedTopograpy, mesh mask to the Gaussian grid - call interpolate(toColValues, toRowValues, toSvalues, globalArrayThickness, thicknessSLgrid1D) - call interpolate(toColValues, toRowValues, toSvalues, globalArrayBedTopography, bedtopoSLgrid1D) - call interpolate(toColValues, toRowValues, toSvalues, meshMask, maskSLgrid1D) + ! Gather only the nCellsOwned from thickness and bedtopo (does not include Halos) + call MPI_GATHERV((thickness*real(li_mask_is_grounded_ice_int(cellMask),RKIND)), & + nCellsOwned, MPI_DOUBLE, gatheredArrayThickness, nCellsPerProc, & + nCellsDisplacement, MPI_DOUBLE, 0, domain % dminfo % comm, err_tmp) + err = ior(err, err_tmp) + call MPI_GATHERV(bedTopography, nCellsOwned, MPI_DOUBLE, gatheredArrayBedTopography, nCellsPerProc, & + nCellsDisplacement, MPI_DOUBLE, 0, domain % dminfo % comm, err_tmp) + err = ior(err, err_tmp) - ! reformat the interpolated data - ismIceload = reshape(thicknessSLgrid1D, [nglv,2*nglv]) - ismBedtopo = reshape(bedtopoSLgrid1D, [nglv,2*nglv]) - ismMask = reshape(maskSLgrid1D, [nglv,2*nglv]) + if (curProc.eq.0) then + ! Rearrange data into CellID order + do iCell = 1,nCellsGlobal + globalArrayThickness(indexToCellIDGathered(iCell)) = gatheredArrayThickness(iCell) + globalArrayBedTopography(indexToCellIDGathered(iCell)) = gatheredArrayBedTopography(iCell) + meshMask(indexToCellIDGathered(iCell)) = 1 + enddo - ! initialize coupling time step number. initial time is 0 - slmTimeStep = 0 + ! interpolate thickness, bedTopograpy, mesh mask to the Gaussian grid + call interpolate(toColValues, toRowValues, toSvalues, globalArrayThickness, thicknessSLgrid1D) + call interpolate(toColValues, toRowValues, toSvalues, globalArrayBedTopography, bedtopoSLgrid1D) + call interpolate(toColValues, toRowValues, toSvalues, meshMask, maskSLgrid1D) + + ! reformat the interpolated data + ismIceload = reshape(thicknessSLgrid1D, [nglv_slm,2*nglv_slm]) + ismBedtopo = reshape(bedtopoSLgrid1D, [nglv_slm,2*nglv_slm]) + ismMask = reshape(maskSLgrid1D, [nglv_slm,2*nglv_slm]) + + ! initialize coupling time step number. initial time is 0 + slmTimeStep = 0 + + ! series of calling SLM routines + if (err == 0) then + call sl_call_readnl + call sl_timewindow(slmTimeStep) + call sl_allocate_and_initialize_array + call sl_solver_checkpoint(itersl, dtime) + call sl_solver_init(itersl, starttime, ismIceload, ismBedtopo, ismMask) + call sl_deallocate_array + endif + + deallocate(ismIceload, ismBedtopo, ismMask) + deallocate(bedtopoSLgrid1D, thicknessSLgrid1D, maskSLgrid1D) + endif + deallocate(globalArrayThickness) + deallocate(gatheredArrayThickness) + deallocate(globalArrayBedTopography) + deallocate(gatheredArrayBedTopography) + deallocate(meshMask) - ! set SLM unit number to the MALI output log file unit - unit_num_slm = domain % logInfo % outputLog % unitNum - - ! series of calling SLM routines - call sl_set_unit_num(unit_num_slm) - call sl_call_readnl - call sl_solver_checkpoint(itersl, dtime) - call sl_timewindow(slmTimeStep) - call sl_solver_init(itersl, starttime, ismIceload, ismBedtopo, ismMask) - call sl_deallocate_array - - endif - deallocate(globalArrayThickness) - deallocate(gatheredArrayThickness) - deallocate(globalArrayBedTopography) - deallocate(gatheredArrayBedTopography) - deallocate(meshMask) + endif ! endif restart or not # else call mpas_log_write("The sea-level model needs to be included in the compilation with 'SLM=true'", & @@ -568,7 +624,6 @@ subroutine slmodel_solve(slmTimeStep, domain) #ifdef USE_SEALEVELMODEL use sl_model_mod !< this is part of the SLM code use sl_io_mod !< this is part of the SLM code - use user_specs_mod, only: nglv, dt1 !< this is part of the SLM code #endif !----------------------------------------------------------------- ! input variables @@ -598,17 +653,17 @@ subroutine slmodel_solve(slmTimeStep, domain) real (kind=RKIND), dimension(:), pointer :: bedTopography, thickness real (kind=RKIND), dimension(:), pointer :: bedTopographyChange real (kind=RKIND), dimension(:), allocatable :: meshMask - real (kind=RKIND), dimension(nglv,2*nglv) :: ismIceload, ismMask - real (kind=RKIND), dimension(nglv,2*nglv) :: slmSLchange - real (kind=RKIND), dimension(nglv*2*nglv) :: slChangeSLgrid1D - real (kind=RKIND), dimension(nglv*2*nglv) :: thicknessSLgrid1D - real (kind=RKIND), dimension(nglv*2*nglv) :: maskSLgrid1D + real (kind=RKIND), dimension(:,:), allocatable :: ismIceload, ismMask + real (kind=RKIND), dimension(:,:), allocatable :: slmSLchange + real (kind=RKIND), dimension(:), allocatable :: slChangeSLgrid1D + real (kind=RKIND), dimension(:), allocatable :: thicknessSLgrid1D + real (kind=RKIND), dimension(:), allocatable :: maskSLgrid1D integer, dimension(:), pointer :: cellMask integer :: err, err_tmp - integer :: itersl, dtime ! SLM variable - real :: starttime ! SLM variable + integer :: itersl, dtime ! SLM variable + real :: starttime ! SLM variable err = 0 err_tmp = 0 @@ -626,9 +681,14 @@ subroutine slmodel_solve(slmTimeStep, domain) err = ior(err, err_tmp) if (curProc.eq.0) then + ! call the SLM modules to initialize arrays and their dimensions + call sl_drive_readnl(itersl, dtime, starttime) + ! allocate and initialize the SLM-related variables used in this module allocate(globalArrayThickness(nCellsGlobal), gatheredArrayThickness(nCellsGlobal)) allocate(globalArrayTopoChange(nCellsGlobal), gatheredArrayTopoChange(nCellsGlobal)) allocate(meshMask(nCellsGlobal)) + allocate(ismIceload(nglv_slm,2*nglv_slm), ismMask(nglv_slm,2*nglv_slm), slmSLchange(nglv_slm,2*nglv_slm)) + allocate(slChangeSLgrid1D(nglv_slm*2*nglv_slm), thicknessSLgrid1D(nglv_slm*2*nglv_slm), maskSLgrid1D(nglv_slm*2*nglv_slm)) ismIceload(:,:) = 0.0 ismMask(:,:) = 0.0 slmSLchange(:,:) = 0.0 @@ -661,19 +721,19 @@ subroutine slmodel_solve(slmTimeStep, domain) call interpolate(toColValues, toRowValues, toSvalues, meshMask, maskSLgrid1D) ! reformat the interpolated data - ismIceload = reshape(thicknessSLgrid1D, [nglv,2*nglv]) - ismMask = reshape(maskSLgrid1D, [nglv,2*nglv]) + ismIceload = reshape(thicknessSLgrid1D, [nglv_slm,2*nglv_slm]) + ismMask = reshape(maskSLgrid1D, [nglv_slm,2*nglv_slm]) ! series of calling SLM routines - call sl_drive_readnl(itersl, dtime, starttime) call sl_call_readnl - call sl_solver_checkpoint(itersl, dtime) call sl_timewindow(slmTimeStep) + call sl_allocate_and_initialize_array + call sl_solver_checkpoint(itersl, dtime) call sl_solver(itersl, slmTimeStep, dtime, starttime, ismIceload, ismMask, slmSLchange) call sl_deallocate_array ! reshape 2D array SLM output into 1D array - slChangeSLgrid1D = reshape(slmSLchange, [nglv*2*nglv]) + slChangeSLgrid1D = reshape(slmSLchange, [nglv_slm*2*nglv_slm]) ! interpolate sea-level change from GL grid to MALI mesh. ! note: in the static sea-level theory, sea level and topography are globally defined !> @@ -686,6 +746,8 @@ subroutine slmodel_solve(slmTimeStep, domain) gatheredArrayTopoChange(iCell) = globalArrayTopoChange(indexToCellIDGathered(iCell)) enddo + deallocate(ismIceload, ismMask, slmSLchange) + deallocate(slChangeSLgrid1D, thicknessSLgrid1D, maskSLgrid1D) endif ! scatter output sea-level changes to processors @@ -948,6 +1010,170 @@ subroutine check(status, err) end subroutine check +!*********************************************************************** +! +! routine check_SLM_coupling_interval +! +!> \brief Perform various checks on the SLM coupling interval setting +!> \author Matt Hoffman +!> \date Feb 2024 +!> \details +!> This routine checks that the SLM coupling interval is an even multiple +!> of the adaptive timestep force inverval and divides evenly into the +!> restart interval. It also checks that the coupling interval in the MALI +!> matches the value in the SLM namelist. +! +!----------------------------------------------------------------------- + + subroutine check_SLM_coupling_interval(slm_dt1, meshPool, err) + + use mpas_timekeeping + use mpas_stream_manager + use mpas_derived_types, only : MPAS_STREAM_PROPERTY_RECORD_INTV + + integer, intent (in) :: slm_dt1 + type (mpas_pool_type), intent(in) :: meshPool !< mesh information + integer, intent(out) :: err + + ! local variables + integer, pointer :: config_slm_coupling_interval + logical, pointer :: config_adaptive_timestep + character (len=StrKIND), pointer :: config_adaptive_timestep_force_interval, config_dt + type (MPAS_TimeInterval_Type) :: coupling_interval, force_interval, dt_interval, zero_interval + type (MPAS_Time_Type) :: start_time + character (len=StrKIND), pointer :: simulationStartTime + integer :: YYYY, MM, DD, H, M, S ! time components + integer (kind=I8KIND) :: n_intervals + type (MPAS_TimeInterval_type) :: remainder + integer :: err_tmp + + err = 0 + err_tmp = 0 + + call mpas_log_write("") + call mpas_log_write("-- Checking consistency of config_slm_coupling_interval and other settings --") + + ! First, check consistency in coupling interval set up in MALI and SLM + call mpas_pool_get_config(liConfigs, "config_slm_coupling_interval", config_slm_coupling_interval) + if (config_slm_coupling_interval == slm_dt1) then + call mpas_log_write("The coupling interval in MALI ($i yr) and SLM ($i yr) are consistent - check passes", & + intArgs=(/config_slm_coupling_interval, slm_dt1/)) + else + call mpas_log_write("The coupling interval in MALI ($i yr) and SLM ($i yr) are inconsistent", MPAS_LOG_ERR, & + intArgs=(/config_slm_coupling_interval, slm_dt1/)) + err = ior(err, 1) + endif + + ! define zero interval for comparing against below + call mpas_set_timeInterval(zero_interval, dt = 0.0_RKIND) + ! get start time as a reference time + call mpas_pool_get_array(meshPool, 'simulationStartTime', simulationStartTime) + call mpas_set_time(start_time, dateTimeString=simulationStartTime) + ! define SLM coupling interval as a timeInterval type + call mpas_set_timeInterval(coupling_interval, YY=config_slm_coupling_interval, MM=0, DD=0, H=0, M=0, S=0, ierr=err_tmp) + err = ior(err, err_tmp) + + call mpas_pool_get_config(liConfigs, "config_adaptive_timestep", config_adaptive_timestep) + if (config_adaptive_timestep) then + ! for adaptive dt, check that config_adaptive_timestep_force_interval divides evenly into config_slm_coupling_interval + call mpas_pool_get_config(liConfigs, "config_adaptive_timestep_force_interval", config_adaptive_timestep_force_interval) + call mpas_set_timeInterval(force_interval, timeString=config_adaptive_timestep_force_interval, ierr=err_tmp) + err = ior(err, err_tmp) + call mpas_interval_division(start_time, coupling_interval, force_interval, n_intervals, remainder) + if (remainder .EQ. zero_interval) then + call mpas_log_write("config_adaptive_timestep_force_interval divides into config_slm_coupling_interval $i times " // & + "with no remainder - check passes", intArgs=(/int(n_intervals)/)) + else + call mpas_log_write("config_adaptive_timestep_force_interval divides into config_slm_coupling_interval $i times " // & + "with nonzero remainder", MPAS_LOG_ERR, intArgs=(/int(n_intervals)/)) + err = ior(err, 1) + endif + else + ! For fixed dt, check that dt divides evenly into config_slm_coupling_interval + call mpas_pool_get_config(liConfigs, "config_dt", config_dt) + call mpas_set_timeInterval(dt_interval, timeString=config_dt, ierr=err_tmp) + err = ior(err, err_tmp) + call mpas_interval_division(start_time, coupling_interval, dt_interval, n_intervals, remainder) + if (remainder .EQ. zero_interval) then + call mpas_log_write("config_dt divides into config_slm_coupling_interval $i times " // & + "with no remainder - check passes", intArgs=(/int(n_intervals)/)) + else + call mpas_log_write("config_dt divides into config_slm_coupling_interval $i times " // & + "with nonzero remainder", MPAS_LOG_ERR, intArgs=(/int(n_intervals)/)) + err = ior(err, 1) + endif + endif + + ! No need to compare restart interval and coupling interval because restarts with SLM are supported for + ! any restart interval now + + call mpas_log_write("") + + !-------------------------------------------------------------------- + end subroutine check_SLM_coupling_interval + + +!*********************************************************************** +! +! routine find_slm_restart_timestep +! +!> \brief Perform various checks on the SLM coupling interval setting +!> \author Matt Hoffman +!> \date Feb 2024 +!> \details +!> This routine checks that the SLM coupling interval is an even multiple +!> of the adaptive timestep force inverval and divides evenly into the +!> restart interval. It also checks that the coupling interval in the MALI +!> matches the value in the SLM namelist. +! +!----------------------------------------------------------------------- + + subroutine find_slm_restart_timestep(meshPool, slmTimeStep, err) + + use mpas_timekeeping + + type (mpas_pool_type), intent(in) :: meshPool !< mesh information + integer, intent(out) :: slmTimeStep + integer, intent(out) :: err + + ! local vars + integer, pointer :: config_slm_coupling_interval + character (len=StrKIND), pointer :: xtime, simulationStartTime + type (MPAS_TimeInterval_Type) :: coupling_interval + type (MPAS_Time_Type) :: start_time, curr_time + integer (kind=I8KIND) :: n_intervals + type (MPAS_TimeInterval_type) :: remainder + character (len=StrKIND) :: remainder_string + integer :: err_tmp + + err = 0 + err_tmp = 0 + + call mpas_pool_get_config(liConfigs, "config_slm_coupling_interval", config_slm_coupling_interval) + ! define SLM coupling interval as a timeInterval type + call mpas_set_timeInterval(coupling_interval, YY=config_slm_coupling_interval, MM=0, DD=0, H=0, M=0, S=0, ierr=err_tmp) + err = ior(err, err_tmp) + + call mpas_pool_get_array(meshPool, 'simulationStartTime', simulationStartTime) + call mpas_pool_get_array(meshPool, 'xtime', xtime) + call mpas_set_time(start_time, dateTimeString=simulationStartTime, ierr=err_tmp) + err = ior(err, err_tmp) + call mpas_set_time(curr_time, dateTimeString=xtime, ierr=err_tmp) + err = ior(err, err_tmp) + + call mpas_interval_division(start_time, curr_time - start_time, coupling_interval, n_intervals, remainder) + slmTimeStep = int(n_intervals) + call mpas_get_timeInterval(remainder, start_time, timeString=remainder_string, ierr=err_tmp) + err = ior(err, err_tmp) + call mpas_log_write("SLM Restart: Using SLM time level $i because config_slm_coupling_interval divides into " // & + "elapsed time that many times ", intArgs=(/int(slmTimeStep)/)) + call mpas_log_write(" That calculation implies it has been " // trim(remainder_string) // " since last SLM coupling. " // & + "If that interval seems wrong, there may be an error in your configuration.") + call mpas_log_write("") + + !-------------------------------------------------------------------- + end subroutine find_slm_restart_timestep + !*********************************************************************** end module li_bedtopo diff --git a/components/mpas-albany-landice/src/mode_forward/mpas_li_calving.F b/components/mpas-albany-landice/src/mode_forward/mpas_li_calving.F index 304ed0b0349c..a460c3224a0e 100644 --- a/components/mpas-albany-landice/src/mode_forward/mpas_li_calving.F +++ b/components/mpas-albany-landice/src/mode_forward/mpas_li_calving.F @@ -45,7 +45,8 @@ module li_calving !-------------------------------------------------------------------- public :: li_calve_ice, li_restore_calving_front, li_apply_front_ablation_velocity, & - li_calculate_damage, li_finalize_damage_after_advection, li_flood_fill + li_calculate_damage, li_finalize_damage_after_advection, li_flood_fill, & + li_remove_icebergs !-------------------------------------------------------------------- ! @@ -305,6 +306,12 @@ subroutine li_calve_ice(domain, err, solveVeloAfterCalving) endif + call mpas_pool_get_subpool(domain % blocklist % structs, 'geometry', geometryPool) + call mpas_pool_get_subpool(domain % blocklist % structs, 'mesh', meshPool) + call mpas_pool_get_subpool(domain % blocklist % structs, 'velocity', velocityPool) + + call li_calculate_mask(meshPool, velocityPool, geometryPool, err_tmp) + ! Consider mask calving as a possible additional step ! Mask calving can occur by itself or in conjunction with a physical calving law if (config_apply_calving_mask) then @@ -312,14 +319,24 @@ subroutine li_calve_ice(domain, err, solveVeloAfterCalving) err = ior(err, err_tmp) endif + call li_calculate_mask(meshPool, velocityPool, geometryPool, err_tmp) + + call remove_small_islands(domain, err_tmp) + + call li_calculate_mask(meshPool, velocityPool, geometryPool, err_tmp) + ! now also remove any icebergs - call remove_icebergs(domain) + call li_remove_icebergs(domain) - ! Final operations after calving has been applied. + call li_calculate_mask(meshPool, velocityPool, geometryPool, err_tmp) + + ! Final operations after calving has been applied, including removal + ! of small islands block => domain % blocklist do while (associated(block)) call mpas_pool_get_subpool(block % structs, 'geometry', geometryPool) call mpas_pool_get_subpool(block % structs, 'mesh', meshPool) + call mpas_pool_get_subpool(block % structs, 'velocity', velocityPool) call mpas_pool_get_array(geometryPool, 'thickness', thickness) call mpas_pool_get_array(geometryPool, 'calvingThickness', calvingThickness) call mpas_pool_get_dimension(meshPool, 'nCells', nCells) @@ -348,7 +365,6 @@ subroutine li_calve_ice(domain, err, solveVeloAfterCalving) endif ! config_print_calving_info ! Update mask and geometry - call mpas_pool_get_subpool(block % structs, 'velocity', velocityPool) call li_calculate_mask(meshPool, velocityPool, geometryPool, err_tmp) err = ior(err, err_tmp) call li_update_geometry(geometryPool) @@ -927,8 +943,6 @@ subroutine thickness_calving(domain, calvingFraction, err) ! === apply calving === thickness(:) = thickness(:) - calvingThickness(:) - call remove_small_islands(meshPool, geometryPool) - block => block % next enddo @@ -1003,8 +1017,6 @@ subroutine floating_calving(domain, calvingFraction, err) ! === apply calving === thickness(:) = thickness(:) - calvingThickness(:) - call remove_small_islands(meshPool, geometryPool) - block => block % next enddo @@ -1015,20 +1027,21 @@ end subroutine floating_calving ! routine remove_small_islands ! !> \brief Remove very small islands that lead to velocity solver problems -!> \author Matthew Hoffman -!> \date Summer 2018 +!> \author Matthew Hoffman, Trevor Hillebrand +!> \date Summer 2018, re-written Apr 2024 !> \details This routine finds and eliminates very small islands that lead to !> unrealistic velocities in the Albany velocity solver. Specifically, this -!> finds one- and two-cell masses of ice that are surrounded by open ocean -!> and eliminates them by sending them to the calving flux. +!> finds one- and two-cell masses of grounded ice that are surrounded by dynamic +!> floating ice ice shelves ≥1 cell wide. It eliminates the dynamic cells +!> (both grounded and floating) in these islands by sending them to the calving +!> flux and then cleans up stranded non-dynamic cells using a flood-fill routine. !----------------------------------------------------------------------- - subroutine remove_small_islands(meshPool, geometryPool) - type (mpas_pool_type), pointer, intent(in) :: meshPool !< Input: Mesh pool - type (mpas_pool_type), pointer, intent(inout) :: geometryPool !< Input: Geometry pool - + subroutine remove_small_islands(domain, err) + type (domain_type), intent(inout) :: domain !< Input/Output: domain object + integer, intent(inout) :: err + type (mpas_pool_type), pointer :: scratchPool, meshPool, geometryPool, velocityPool logical, pointer :: config_remove_small_islands - real(kind=RKIND), pointer :: config_sea_level real (kind=RKIND), dimension(:), pointer :: calvingThickness ! thickness of ice that calves (computed in this subroutine) real (kind=RKIND), dimension(:), pointer :: calvingThicknessFromThreshold ! thickness of ice that calves (computed in this subroutine) real (kind=RKIND), dimension(:), pointer :: thickness @@ -1036,73 +1049,204 @@ subroutine remove_small_islands(meshPool, geometryPool) integer, dimension(:), pointer :: cellMask integer, dimension(:,:), pointer :: cellsOnCell ! list of cells that neighbor each cell integer, dimension(:), pointer :: nEdgesOnCell ! number of cells that border each cell - integer, pointer :: nCellsSolve - integer :: iCell, jCell, n, nIceNeighbors, nIceNeighbors2, neighborWithIce - integer :: nOpenOceanNeighbors, nOpenOceanNeighbors2 + integer, pointer :: nCells, maxEdges + logical :: removeIsland + integer :: iCell, jCell, kCell, m, n, count + integer :: nIslandCellsLocal, nIslandCellsGlobal + integer :: nGroundedNeighbors, nGroundedNeighborsJCell + integer, dimension(:), allocatable :: connectedCellsList + integer, dimension(:), allocatable :: islandMask + type (field1dInteger), pointer :: seedMaskField + type (field1dInteger), pointer :: growMaskField + integer, dimension(:), pointer :: seedMask, growMask !masks to pass to flood-fill routine call mpas_pool_get_config(liConfigs, 'config_remove_small_islands', config_remove_small_islands) if (.not. config_remove_small_islands) then return ! skip this entire routine if disabled endif - call mpas_pool_get_config(liConfigs, 'config_sea_level', config_sea_level) - call mpas_pool_get_dimension(meshPool, 'nCellsSolve', nCellsSolve) + call mpas_pool_get_subpool(domain % blocklist % structs, 'scratch', scratchPool) + call mpas_pool_get_subpool(domain % blocklist % structs, 'mesh', meshPool) + call mpas_pool_get_subpool(domain % blocklist % structs, 'geometry', geometryPool) + call mpas_pool_get_subpool(domain % blocklist % structs, 'velocity', velocityPool) + + call mpas_pool_get_dimension(meshPool, 'nCells', nCells) + call mpas_pool_get_dimension(meshPool, 'maxEdges', maxEdges) call mpas_pool_get_array(meshPool, 'cellsOnCell', cellsOnCell) call mpas_pool_get_array(meshPool, 'nEdgesOnCell', nEdgesOnCell) call mpas_pool_get_array(geometryPool, 'calvingThickness', calvingThickness) call mpas_pool_get_array(geometryPool, 'calvingThicknessFromThreshold', calvingThicknessFromThreshold) call mpas_pool_get_array(geometryPool, 'thickness', thickness) call mpas_pool_get_array(geometryPool, 'cellMask', cellMask) - call mpas_pool_get_array(geometryPool, 'bedTopography', bedTopography) - do iCell = 1, nCellsSolve - if (li_mask_is_ice(cellMask(iCell))) then ! might as well do for both grounded or floating - ! (1 or 2 cell floating masses are icebergs) - nIceNeighbors = 0 - nOpenOceanNeighbors = 0 + allocate(connectedCellsList((maxEdges+1)**2), & + islandMask(nCells+1)) + + islandMask(:) = 0 + nIslandCellsLocal = 0 + nIslandCellsGlobal = 0 + ! Allocate scratch fields for flood-fill + call mpas_pool_get_field(scratchPool, 'seedMask', seedMaskField) + call mpas_allocate_scratch_field(seedMaskField, single_block_in = .true.) + seedMask => seedMaskField % array + seedMask(:) = 0 + + call mpas_pool_get_field(scratchPool, 'growMask', growMaskField) + call mpas_allocate_scratch_field(growMaskField, single_block_in = .true.) + growMask => growMaskField % array + growMask(:) = 0 + + ! Phase 1: Loop over cells to find one- and two-cell regions of + ! grounded ice that are not dynamically connected to other grounded + ! regions, which are "islands" that potentially need to be removed. + ! In this first phase we identify islands that meet these + ! criteria. In phase 2 below we check if islands are dynamically + ! connected to more extensive floating ice, which will disqualify + ! them for removal to avoid removing pinning points from ice + ! shelves, for example. + do iCell = 1, nCells + if (li_mask_is_grounded_ice(cellMask(iCell))) then + islandMask(iCell) = 1 ! Potentially an island. Further evaluated below. + nGroundedNeighbors = 0 + ! Count grounded neighbors do n = 1, nEdgesOnCell(iCell) jCell = cellsOnCell(n, iCell) - if (li_mask_is_ice(cellMask(jCell))) then - nIceNeighbors = nIceNeighbors + 1 - neighborWithIce = jCell + if (li_mask_is_grounded_ice(cellMask(jCell))) then + nGroundedNeighbors = nGroundedNeighbors + 1 endif - if (.not. li_mask_is_ice(cellMask(jCell)) .and. bedTopography(jCell) < config_sea_level) then - nOpenOceanNeighbors = nOpenOceanNeighbors + 1 + nGroundedNeighborsJCell = 0 + ! If the neighbor contains dynamic ice, check whether + ! it has other grounded neighbors. If it does, then we + ! will not consider this an island. + if (li_mask_is_dynamic_ice(cellMask(jCell))) then + do m = 1, nEdgesOnCell(jCell) + kCell = cellsOnCell(m, jCell) + if (li_mask_is_grounded_ice(cellMask(kCell))) then + nGroundedNeighborsJCell = nGroundedNeighborsJCell + 1 + endif + enddo + endif + ! Two checks that a grounded cell is NOT a 1 or 2 cell island: + ! 1. If a grounded cell has more than 1 grounded neighbor, it is not an island + ! This is the nGroundedNeighbors criterion. It gets re-evaluated with every + ! neighbor each time through the loop. It may not trigger on early checks + ! but it will trigger eventually if this cell has more than 1 grounded neighbor. + ! 2. If its dynamic neighbors have other grounded neighbors, then we do not + ! consider it an island. This is the nGroundedNeighborsJCell criterion. + ! Any grounded cells that survive these two checks are considered islands + ! and are further evaluated in the next phase. + if ( (nGroundedNeighborsJCell > 1) .or. & + (nGroundedNeighbors > 1) ) then + islandMask(iCell) = 0 + exit endif enddo - if ((nIceNeighbors == 0) .and. (nOpenOceanNeighbors == nEdgesOnCell(iCell))) then - ! If this is a single cell of ice surrounded by open ocean, kill this location - calvingThickness(iCell) = calvingThickness(iCell) + thickness(iCell) - calvingThicknessFromThreshold(iCell) = calvingThicknessFromThreshold(iCell) + thickness(iCell) - thickness(iCell) = 0.0_RKIND - elseif (nIceNeighbors == 1) then - ! check if this neighbor has any additional neighbors with ice - nIceNeighbors2 = 0 - nOpenOceanNeighbors2 = 0 - do n = 1, nEdgesOnCell(neighborWithIce) - jCell = cellsOnCell(n, neighborWithIce) - if (li_mask_is_ice(cellMask(jCell))) then - nIceNeighbors2 = nIceNeighbors2 + 1 - endif - if (.not. li_mask_is_ice(cellMask(jCell)) .and. bedTopography(jCell) < config_sea_level) then - nOpenOceanNeighbors2 = nOpenOceanNeighbors2 + 1 + endif + enddo + + ! Phase 2: Determine whether to remove each island based on if it is + ! dynamically connected to other regions. For each cell in islandMask, + ! first make a list of its dynamic neighbors. If the grounded island + ! cell has a grounded neighbor, add that neighbor's dynamic neighbors + ! to the list. Then, check that all the dynamic neighbors of the cells + ! in the list are also in the list. If so, then this is considered an + ! isolated island and is removed. If not, then it is dynamically connected + ! to other regions, so we leave it alone. + do iCell = 1, nCells + connectedCellsList(:) = -1 + if (islandMask(iCell) == 1) then + removeIsland = .true. ! evalulated and updated below + ! Make a list of the grounded island cell and its + ! dynamic neighbors. + count = 1 + connectedCellsList(count) = iCell + do n = 1, nEdgesOnCell(iCell) + jCell = cellsOnCell(n, iCell) + if (li_mask_is_dynamic_ice(cellMask(jCell))) then + count = count + 1 + connectedCellsList(count) = jCell + endif + ! If there is a grounded neighbor, list its dynamic neighbors as well + if (li_mask_is_grounded_ice(cellMask(jCell))) then + do m = 1, nEdgesOnCell(jCell) + kCell = cellsOnCell(m, jCell) + if (li_mask_is_dynamic_ice(cellMask(kCell))) then + count = count + 1 + connectedCellsList(count) = kCell + endif + enddo + endif + enddo + ! Check that all the dynamic neighbors of neighbors are + ! in the list. If not, then do not remove the island. + do n = 1, (maxEdges+1)**2 + if (connectedCellsList(n) == -1) then + exit ! We've reached the end of the list. + endif + jCell = connectedCellsList(n) + do m = 1, nEdgesOnCell(jCell) + kCell = cellsOnCell(m, jCell) + if ( li_mask_is_dynamic_ice(cellMask(kCell)) .and. & + (.not. any(connectedCellsList == kCell)) ) then + removeIsland = .false. + exit endif enddo - if ((nIceNeighbors2 == 1) .and. (nOpenOceanNeighbors2 == nEdgesOnCell(iCell)-1)) then - ! <- only neighbor with ice must have been iCell - ! kill both cells + enddo + ! Actually remove island + if ( removeIsland ) then + nIslandCellsLocal = nIslandCellsLocal + count + ! Note: nIslandCellsLocal may be inaccurate as neighbors or neighbors of neighbors to iCell + ! may get tallied multiple times from different members of islandMask. However, we only need + ! to know if nIslandCells>0, so this is ok. If we ever need an accurate value of nIslandCells, + ! some additional steps must be taken to avoid potential double counting. + do n = 1, count + calvingThickness(connectedCellsList(n)) = calvingThickness(connectedCellsList(n)) + & + thickness(connectedCellsList(n)) + calvingThicknessFromThreshold(connectedCellsList(n)) = & + calvingThicknessFromThreshold(connectedCellsList(n)) + thickness(connectedCellsList(n)) + thickness(connectedCellsList(n)) = 0.0_RKIND + ! No need to evaluate any cells in this list again. + if (islandMask(connectedCellsList(n)) == 1) islandMask(connectedCellsList(n)) = 0 + enddo + endif + endif + enddo + + call mpas_timer_start("halo updates") + call mpas_dmpar_field_halo_exch(domain, 'thickness') + call mpas_dmpar_field_halo_exch(domain, 'calvingThickness') + call mpas_timer_stop("halo updates") + call li_calculate_mask(meshPool, velocityPool, geometryPool, err) + + call mpas_dmpar_sum_int(domain % dminfo, nIslandCellsLocal, nIslandCellsGlobal) + + if ( nIslandCellsGlobal > 0 ) then + ! Clean up by removing non-dynamic ice that may have been left behind + ! after islands where removed. + where (li_mask_is_grounded_ice(cellMask)) + seedMask = 1 + end where + + where (li_mask_is_ice(cellMask)) + growMask = 1 + end where + + call mpas_log_write("***Cleaning up stranded cells after removing small islands***") + call li_flood_fill(seedMask, growMask, domain) + do iCell = 1, nCells + if (li_mask_is_floating_ice(cellMask(iCell)) .and. seedMask(iCell) == 0) then calvingThickness(iCell) = calvingThickness(iCell) + thickness(iCell) calvingThicknessFromThreshold(iCell) = calvingThicknessFromThreshold(iCell) + thickness(iCell) thickness(iCell) = 0.0_RKIND - calvingThickness(neighborWithIce) = calvingThickness(neighborWithIce) + thickness(neighborWithIce) - calvingThicknessFromThreshold(neighborWithIce) = calvingThicknessFromThreshold(neighborWithIce) + thickness(neighborWithIce) - thickness(neighborWithIce) = 0.0_RKIND - endif - - endif ! check on nIceNeighbors - - endif ! check if iCell has ice - end do ! loop over cells + endif + enddo + call mpas_log_write("***Finished cleaning up after removing small islands***") + endif + deallocate(connectedCellsList, & + islandMask) + call mpas_deallocate_scratch_field(seedMaskField, single_block_in=.true.) + call mpas_deallocate_scratch_field(growMaskField, single_block_in=.true.) end subroutine remove_small_islands @@ -1180,8 +1324,6 @@ subroutine topographic_calving(domain, calvingFraction, err) ! === apply calving === thickness(:) = thickness(:) - calvingThickness(:) - call remove_small_islands(meshPool, geometryPool) - block => block % next enddo @@ -1412,8 +1554,6 @@ subroutine eigencalving(domain, err) enddo ! TODO: global reduce & reporting on amount of calving generated in this step - call remove_small_islands(meshPool, geometryPool) - block => block % next enddo @@ -1596,8 +1736,6 @@ subroutine specified_calving_velocity(domain, err) enddo ! TODO: global reduce & reporting on amount of calving generated in this step - call remove_small_islands(meshPool, geometryPool) - block => block % next enddo @@ -1985,8 +2123,6 @@ subroutine von_Mises_calving(domain, err) call li_calculate_mask(meshPool, velocityPool, geometryPool, err_tmp) err = ior(err, err_tmp) - call remove_small_islands(meshPool, geometryPool) - block => block % next enddo ! associated(block) @@ -2256,7 +2392,6 @@ subroutine ismip6_retreat(domain, err) ! update mask call li_calculate_mask(meshPool, velocityPool, geometryPool, err_tmp) err = ior(err, err_tmp) - call remove_small_islands(meshPool, geometryPool) deallocate(submergedArea) @@ -3326,8 +3461,6 @@ subroutine damage_calving(domain, err) enddo ! TODO: global reduce & reporting on amount of calving generated in this step - call remove_small_islands(meshPool, geometryPool) - block => block % next enddo @@ -3986,8 +4119,6 @@ subroutine mask_calving(domain, err) call li_calculate_mask(meshPool, velocityPool, geometryPool, err_tmp) err = ior(err, err_tmp) - call remove_small_islands(meshPool, geometryPool) - block => block % next enddo @@ -4078,7 +4209,7 @@ subroutine calculate_calving_front_mask(meshPool, geometryPool, calvingFrontMask end subroutine calculate_calving_front_mask - subroutine remove_icebergs(domain) + subroutine li_remove_icebergs(domain) !----------------------------------------------------------------- ! input/output variables !----------------------------------------------------------------- @@ -4232,7 +4363,7 @@ subroutine remove_icebergs(domain) call mpas_deallocate_scratch_field(growMaskField, single_block_in=.false.) call mpas_log_write("Iceberg-detection flood-fill complete. Removed $i iceberg cells.", intArgs=(/globalIcebergCellCount/)) call mpas_timer_stop("iceberg detection") - end subroutine remove_icebergs + end subroutine li_remove_icebergs !||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ! diff --git a/components/mpas-albany-landice/src/mode_forward/mpas_li_core.F b/components/mpas-albany-landice/src/mode_forward/mpas_li_core.F index 10ee1e94b305..0e6ff08df22d 100644 --- a/components/mpas-albany-landice/src/mode_forward/mpas_li_core.F +++ b/components/mpas-albany-landice/src/mode_forward/mpas_li_core.F @@ -338,8 +338,8 @@ function li_core_init(domain, startTimeStamp) result(err) ! === call li_velocity_external_write_albany_mesh(domain) - call mpas_dmpar_max_int(domain % dminfo, err, globalErr) ! Find out if any blocks got an error - if (globalErr > 0) then + call mpas_dmpar_max_int(domain % dminfo, abs(err), globalErr) ! Find out if any blocks got an error + if (globalErr /= 0) then call mpas_log_write("An error has occurred in li_core_init. Aborting...", MPAS_LOG_CRIT) endif @@ -1025,6 +1025,10 @@ subroutine landice_init_block(block, dminfo, err) err = ior(err, err_tmp) call mpas_timer_stop("initialize velocity") + ! SIA and hydro need these weights initialized for some options + call li_init_barycentric_weights_vertex(block, err_tmp) + err = ior(err, err_tmp) + ! Higher-order velo solvers needs vertex-to-cell interp routine initialized if ( (trim(config_velocity_solver) == 'L1L2') .or. & (trim(config_velocity_solver) == 'FO') .or. & @@ -1105,13 +1109,12 @@ subroutine li_simulation_clock_init(core_clock, configs, ierr) type (MPAS_Time_Type) :: startTime, stopTime, alarmStartTime type (MPAS_TimeInterval_type) :: runDuration, timeStep, alarmTimeStep type (MPAS_TimeInterval_type) :: adaptDtForceInterval - type (MPAS_TimeInterval_type) :: slm_coupling_interval character (len=StrKIND), pointer :: config_start_time, config_run_duration, config_stop_time, & config_output_interval, config_restart_interval ! MPAS standard configs character (len=StrKIND), pointer :: config_dt ! MPAS LI-specific config option character (len=StrKIND), pointer :: config_adaptive_timestep_force_interval ! MPAS LI-specific config option character (len=StrKIND), pointer :: config_restart_timestamp_name - character (len=StrKIND), pointer :: config_uplift_method, config_slm_coupling_interval + integer, pointer :: config_slm_coupling_interval character (len=StrKIND) :: restartTimeStamp !< string to be read from file integer, pointer :: config_year_digits integer :: err_tmp @@ -1130,7 +1133,6 @@ subroutine li_simulation_clock_init(core_clock, configs, ierr) call mpas_pool_get_config(configs, 'config_stop_time', config_stop_time) call mpas_pool_get_config(configs, 'config_restart_timestamp_name', config_restart_timestamp_name) call mpas_pool_get_config(configs, 'config_adaptive_timestep_force_interval', config_adaptive_timestep_force_interval) - call mpas_pool_get_config(configs, 'config_uplift_method', config_uplift_method) call mpas_pool_get_config(configs, 'config_slm_coupling_interval', config_slm_coupling_interval) @@ -1195,22 +1197,8 @@ subroutine li_simulation_clock_init(core_clock, configs, ierr) endif ierr = ior(ierr, err_tmp) - ! Set up the coupling time interval if MALI is coupled to sea-level model - if (trim(config_uplift_method) == "sealevelmodel") then - call mpas_set_timeInterval(slm_coupling_interval, timeString=config_slm_coupling_interval, ierr=err_tmp) - ierr = ior(ierr,err_tmp) - call mpas_add_clock_alarm(core_clock, 'slmCouplingInterval', alarmTime=startTime, & - alarmTimeInterval=slm_coupling_interval, ierr=err_tmp) - ierr = ior(ierr,err_tmp) - if (mpas_is_alarm_ringing(core_clock, 'slmCouplingInterval', ierr=err_tmp)) then - ierr = ior(ierr, err_tmp) - call mpas_reset_clock_alarm(core_clock, 'slmCouplingInterval', ierr=err_tmp) - ierr = ior(ierr, err_tmp) - endif - endif - ! === error check - if (ierr > 0) then + if (ierr /= 0) then call mpas_log_write("An error has occurred in li_simulation_clock_init.", MPAS_LOG_ERR) endif diff --git a/components/mpas-albany-landice/src/mode_forward/mpas_li_sia.F b/components/mpas-albany-landice/src/mode_forward/mpas_li_sia.F index 17649f9dcfc7..753edd8631a8 100644 --- a/components/mpas-albany-landice/src/mode_forward/mpas_li_sia.F +++ b/components/mpas-albany-landice/src/mode_forward/mpas_li_sia.F @@ -154,53 +154,9 @@ subroutine li_sia_block_init(block, err) ! local variables ! !----------------------------------------------------------------- - type (mpas_pool_type), pointer :: meshPool - type (mpas_pool_type), pointer :: scratchPool - integer :: iCell, iLevel, i, iVertex, err_tmp - integer, pointer :: nVertices - character (len=StrKIND), pointer :: config_sia_tangent_slope_calculation - integer, dimension(:,:), pointer :: baryCellsOnVertex - real (kind=RKIND), dimension(:,:), pointer :: baryWeightsOnVertex - real (kind=RKIND), dimension(:), pointer :: xVertex, yVertex, zVertex - type (field1dInteger), pointer :: vertexIndicesField ! No block init needed. err = 0 - err_tmp = 0 - - call mpas_pool_get_subpool(block % structs, 'mesh', meshPool) - call mpas_pool_get_subpool(block % structs, 'scratch', scratchPool) - call mpas_pool_get_array(meshPool, 'baryCellsOnVertex', baryCellsOnVertex) - call mpas_pool_get_array(meshPool, 'baryWeightsOnVertex', baryWeightsOnVertex) - call mpas_pool_get_array(meshPool, 'xVertex', xVertex) - call mpas_pool_get_array(meshPool, 'yVertex', yVertex) - call mpas_pool_get_array(meshPool, 'zVertex', zVertex) - call mpas_pool_get_config(liConfigs, 'config_sia_tangent_slope_calculation', config_sia_tangent_slope_calculation) - call mpas_pool_get_field(scratchPool, 'vertexIndices', vertexIndicesField) - call mpas_pool_get_dimension(meshPool, 'nVertices', nVertices) - - ! The SIA solver may need to setup these weights for calculating upperSurfaceVertex - if (trim(config_sia_tangent_slope_calculation) == 'from_vertex_barycentric') then - call mpas_allocate_scratch_field(vertexIndicesField, .true.) - do iVertex = 1, nVertices - vertexIndicesField % array(iVertex) = iVertex - enddo - call mpas_calculate_barycentric_weights_for_points(meshPool, & - xVertex(1:nVertices), yVertex(1:nVertices), zVertex(1:nVertices), & - vertexIndicesField % array(1:nVertices), & - baryCellsOnVertex(:, 1:nVertices), baryWeightsOnVertex(:, 1:nVertices), err_tmp) - ! TODO: Until framework can handle periodic meshs gracefully, this will return an error - ! for periodic meshes. This error means that the velocity solver will be very wrong across - ! the periodicity, but it will be fine everywhere else. For now, just print a warning but - ! don't make this a fatal error. - !err = ior(err, err_tmp) - if (err_tmp > 0) then - call mpas_log_write("The 'from_vertex_barycentric' option for 'config_sia_tangent_slope_calculation' " & - // "does NOT work across the periodicity in periodic meshes. However, it does work within the interior " & - // "of the mesh.", MPAS_LOG_WARN) - endif - call mpas_deallocate_scratch_field(vertexIndicesField, .true.) - endif ! === error check if (err > 0) then diff --git a/components/mpas-albany-landice/src/mode_forward/mpas_li_subglacial_hydro.F b/components/mpas-albany-landice/src/mode_forward/mpas_li_subglacial_hydro.F index ad3642622e1f..b722459761eb 100644 --- a/components/mpas-albany-landice/src/mode_forward/mpas_li_subglacial_hydro.F +++ b/components/mpas-albany-landice/src/mode_forward/mpas_li_subglacial_hydro.F @@ -56,7 +56,8 @@ module li_subglacial_hydro ! Private module variables ! !-------------------------------------------------------------------- - + ! Minimum gradMagPhiBaseEdge and gradMagPhiEdge allowed before all dependent variables are zeroed out + real(kind=RKIND), parameter :: SMALL_GRADPHI = 1.0e-6_RKIND !*********************************************************************** contains @@ -105,9 +106,11 @@ subroutine li_SGH_init(domain, err) real (kind=RKIND), dimension(:), pointer :: waterPressure real (kind=RKIND), dimension(:), pointer :: thickness real (kind=RKIND), dimension(:), pointer :: bedTopography + real (kind=RKIND), dimension(:), pointer :: iceThicknessHydro integer, dimension(:), pointer :: cellMask real (kind=RKIND), pointer :: tillMax real (kind=RKIND), pointer :: rhoi, rhoo + logical, pointer :: config_do_restart real (kind=RKIND), pointer :: config_sea_level integer, pointer :: config_num_halos integer :: err_tmp @@ -138,6 +141,7 @@ subroutine li_SGH_init(domain, err) err = ior(err, 1) endif + call mpas_pool_get_config(liConfigs, 'config_do_restart', config_do_restart) call mpas_pool_get_config(liConfigs, 'config_SGH_till_max', tillMax) call mpas_pool_get_config(liConfigs, 'config_ice_density', rhoi) call mpas_pool_get_config(liConfigs, 'config_ocean_density', rhoo) @@ -152,9 +156,16 @@ subroutine li_SGH_init(domain, err) call mpas_pool_get_array(hydroPool, 'deltatSGH', deltatSGH) - ! Until init is done properly, make this tiny. It will be updated at the end of the first subcycle. - ! TODO: Set time step appropriately on first subcycle of init - deltatSGH = 1.0e-4_RKIND ! in seconds + if (.not. config_do_restart) then + ! On cold start, set initial timestep to a small value. + ! On a restart we will use the value from the last subcycle of the previous + ! master timestep to make restarts BFB. + ! Note the value here is only used for the first update of thetill model; + ! the sheet and channel models calculate the adaptive timestep, but that is not + ! available for the till model as the code is currently organized. + ! TODO: Move till update until after adaptive timestep has been set + deltatSGH = 1.0e-4_RKIND ! in seconds + endif ! Mask needs to be initialized for pressure calcs to be correct call li_calculate_mask(meshPool, velocityPool, geometryPool, err_tmp) @@ -170,10 +181,28 @@ subroutine li_SGH_init(domain, err) tillWaterThickness = max(0.0_RKIND, tillWaterThickness) tillWaterThickness = min(tillMax, tillWaterThickness) - call mpas_pool_get_array(hydroPool, 'waterPressure', waterPressure) call mpas_pool_get_array(geometryPool, 'thickness', thickness) + call mpas_pool_get_array(hydroPool, 'iceThicknessHydro', iceThicknessHydro) + call calc_iceThicknessHydro(block, err_tmp) !adjust ice thickness along boundaries + err = ior(err,err_tmp) + block => block % next + end do + + !update halo for iceThicknessHydro + call mpas_timer_start("halo updates") + call mpas_dmpar_field_halo_exch(domain, 'iceThicknessHydro') + call mpas_timer_stop("halo updates") + + block => domain % blocklist + do while (associated(block)) + call mpas_pool_get_subpool(block % structs, 'hydro', hydroPool) + call mpas_pool_get_subpool(block % structs, 'geometry', geometryPool) + + call mpas_pool_get_array(hydroPool, 'waterPressure', waterPressure) + call mpas_pool_get_array(hydroPool, 'iceThicknessHydro', iceThicknessHydro) + waterPressure = max(0.0_RKIND, waterPressure) - waterPressure = min(waterPressure, rhoi * gravity * thickness) + waterPressure = min(waterPressure, rhoi * gravity * iceThicknessHydro) ! set pressure correctly under floating ice and open ocean call mpas_pool_get_array(geometryPool, 'cellMask', cellMask) call mpas_pool_get_array(geometryPool, 'bedTopography', bedTopography) @@ -186,9 +215,18 @@ subroutine li_SGH_init(domain, err) call calc_pressure_diag_vars(block, err_tmp) err = ior(err, err_tmp) + !smooth water pressure for calculation of waterPressureSlopeNormal + call calc_waterPressureSmooth(block, err_tmp) + err = ior(err,err_tmp) + block => block % next end do + !updates halos for waterPressureSmooth + call mpas_timer_start("halo updates") + call mpas_dmpar_field_halo_exch(domain, 'waterPressureSmooth') + call mpas_timer_stop("halo updates") + ! === error check if (err > 0) then call mpas_log_write("An error has occurred in li_SGH_init.", MPAS_LOG_ERR) @@ -259,6 +297,7 @@ subroutine li_SGH_solve(domain, err) real (kind=RKIND), dimension(:), pointer :: waterThicknessTendency real (kind=RKIND), dimension(:), pointer :: divergenceChannel real (kind=RKIND), dimension(:), pointer :: channelAreaChangeCell + real (kind=RKIND), dimension(:), pointer :: channelMeltInputCell real (kind=RKIND), dimension(:), pointer :: dvEdge real (kind=RKIND), dimension(:), pointer :: areaCell real (kind=RKIND), dimension(:), pointer :: waterVelocity @@ -281,8 +320,6 @@ subroutine li_SGH_solve(domain, err) integer :: numSubCycles ! number of subcycles integer :: err_tmp - - err = 0 err_tmp = 0 @@ -314,12 +351,20 @@ subroutine li_SGH_solve(domain, err) call mpas_pool_get_array(velocityPool, 'flowParamA', flowParamA) call mpas_pool_get_array(geometryPool, 'thickness', thickness) + call calc_iceThicknessHydro(block, err_tmp) + err = ior(err, err_tmp) + call li_calculate_flowParamA(meshPool, temperature, thickness, flowParamA, err_tmp) err = ior(err, err_tmp) block => block % next end do + !update halo for iceThicknessHydro + call mpas_timer_start("halo updates") + call mpas_dmpar_field_halo_exch(domain, 'iceThicknessHydro') + call mpas_timer_stop("halo updates") + ! initialize while loop call mpas_pool_get_subpool(domain % blocklist % structs, 'mesh', meshPool) ! can get from any block call mpas_pool_get_array(meshPool, 'deltat', masterDeltat) @@ -464,6 +509,8 @@ subroutine li_SGH_solve(domain, err) call mpas_timer_start("halo updates") call mpas_dmpar_field_halo_exch(domain, 'channelChangeRate') call mpas_dmpar_field_halo_exch(domain, 'channelDischarge') + call mpas_dmpar_field_halo_exch(domain, 'channelMelt') + call mpas_dmpar_field_halo_exch(domain, 'channelPressureFreeze') call mpas_timer_stop("halo updates") endif @@ -534,24 +581,23 @@ subroutine li_SGH_solve(domain, err) call mpas_timer_start("halo updates") call mpas_dmpar_field_halo_exch(domain, 'divergenceChannel') call mpas_dmpar_field_halo_exch(domain, 'channelAreaChangeCell') + call mpas_dmpar_field_halo_exch(domain, 'channelMeltInputCell') call mpas_dmpar_field_halo_exch(domain, 'channelArea') call mpas_timer_stop("halo updates") endif - ! ============= - ! Calculate pressure field + ! Calculate total grounding line discharges ! ============= block => domain % blocklist do while (associated(block)) - call calc_pressure(block, err_tmp) + call calc_gl_totals(block, err_tmp) err = ior(err, err_tmp) block => block % next end do - ! ============= ! Update water layer thickness ! ============= @@ -570,12 +616,16 @@ subroutine li_SGH_solve(domain, err) call mpas_pool_get_array(hydroPool, 'divergence', divergence) call mpas_pool_get_array(hydroPool, 'divergenceChannel', divergenceChannel) call mpas_pool_get_array(hydroPool, 'channelAreaChangeCell', channelAreaChangeCell) + call mpas_pool_get_array(hydroPool, 'channelMeltInputCell', channelMeltInputCell) call mpas_pool_get_array(geometryPool, 'cellMask', cellMask) waterThicknessOld = waterThickness - waterThickness = waterThicknessOld + deltatSGH * ( (basalMeltInput + externalWaterInput) / rho_water - divergence & + waterThickness = waterThicknessOld + deltatSGH * ( & + (basalMeltInput + externalWaterInput) / rho_water & + + channelMeltInputCell & + - divergence & - divergenceChannel - channelAreaChangeCell & - - (Wtill - WtillOld) / deltatSGH) + - (Wtill - WtillOld) / deltatSGH ) waterThickness = waterThickness * li_mask_is_grounded_ice_int(cellMask) ! zero in non-grounded locations waterThickness = max(0.0_RKIND, waterThickness) divergence = divergence * li_mask_is_grounded_ice_int(cellMask) ! zero in non-grounded locations for more convenient viz @@ -584,6 +634,41 @@ subroutine li_SGH_solve(domain, err) block => block % next end do + ! ============= + ! Calculate pressure field + ! ============= + ! Note: In Bueler and van Pelt, pressure is updated before waterThickness + ! (step vii on page 1625). It does not matter which order they are calculated + ! because the update calculations are formulated on intermediate variables + ! such that neither depend directly on the other in the actual update. + ! However, calc_pressure also calculates the full hydropotential (including + ! the water thickness elevation head) which *is* a direct function of water thickness, + ! making the ordering of that calculation important. + ! Because the pressure variables calculated here are meant to be used on the + ! following timestep (forward Euler), the full hydropotential should be using + ! the updated waterThickness, not the old one. To achieve that, calc_pressure + ! is called here, after waterThickness has been updated. + ! Note that the full hydropotential is only used by the channel model, so this + ! ordering choice is only needed to support channels. Without it, runs with + ! channels would use an out of date waterThickness in the hydropotential and + ! do not restart correctly due to the order of operations mismatch. + block => domain % blocklist + do while (associated(block)) + + call calc_pressure(block, err_tmp) + err = ior(err, err_tmp) + + call calc_waterPressureSmooth(block, err_tmp) !compute smoothed version of waterPressure + err = ior(err,err_tmp) + + block => block % next + end do + + !updates halos for waterPressure + call mpas_timer_start("halo updates") + call mpas_dmpar_field_halo_exch(domain, 'waterPressureSmooth') + call mpas_timer_stop("halo updates") + ! ============= ! ============= @@ -714,6 +799,7 @@ subroutine calc_edge_quantities(block, err) real (kind=RKIND), dimension(:), pointer :: hydropotentialBase real (kind=RKIND), dimension(:), pointer :: hydropotential real (kind=RKIND), dimension(:), pointer :: hydropotentialBaseVertex + real (kind=RKIND), dimension(:), pointer :: hydropotentialVertex real (kind=RKIND), dimension(:), pointer :: waterPressure real (kind=RKIND), dimension(:), pointer :: waterThicknessEdge real (kind=RKIND), dimension(:), pointer :: waterThicknessEdgeUpwind @@ -722,6 +808,8 @@ subroutine calc_edge_quantities(block, err) real (kind=RKIND), dimension(:), pointer :: hydropotentialSlopeNormal real (kind=RKIND), dimension(:), pointer :: waterPressureSlopeNormal real (kind=RKIND), dimension(:), pointer :: hydropotentialBaseSlopeTangent + real (kind=RKIND), dimension(:), pointer :: hydropotentialSlopeTangent + real (kind=RKIND), dimension(:), pointer :: gradMagPhiBaseEdge real (kind=RKIND), dimension(:), pointer :: gradMagPhiEdge real (kind=RKIND), dimension(:), pointer :: effectiveConducEdge real (kind=RKIND), dimension(:), pointer :: diffusivity @@ -731,12 +819,14 @@ subroutine calc_edge_quantities(block, err) real (kind=RKIND), dimension(:), pointer :: waterFlux real (kind=RKIND), dimension(:), pointer :: waterFluxAdvec real (kind=RKIND), dimension(:), pointer :: waterFluxDiffu - integer, dimension(:), pointer :: waterFluxMask + real (kind=RKIND), dimension(:), pointer :: waterPressureSmooth integer, dimension(:), pointer :: hydroMarineMarginMask + integer, dimension(:), pointer :: waterFluxMask integer, dimension(:,:), pointer :: edgeSignOnCell integer, dimension(:), pointer :: cellMask integer, dimension(:), pointer :: edgeMask integer, dimension(:,:), pointer :: cellsOnEdge + integer, dimension(:,:), pointer :: edgesOnCell integer, dimension(:,:), pointer :: verticesOnEdge integer, dimension(:,:), pointer :: baryCellsOnVertex real (kind=RKIND), dimension(:,:), pointer :: baryWeightsOnVertex @@ -752,14 +842,15 @@ subroutine calc_edge_quantities(block, err) integer, pointer :: nCells integer, pointer :: nVertices integer :: iEdge, cell1, cell2 + integer :: i, j, iVertex, iCell real (kind=RKIND) :: velSign integer :: numGroundedCells + real(kind=RKIND), parameter :: SMALL_CONDUC = 1.0e-30_RKIND integer :: err_tmp - + err = 0 err_tmp = 0 - ! Get pools things call mpas_pool_get_subpool(block % structs, 'mesh', meshPool) call mpas_pool_get_subpool(block % structs, 'hydro', hydroPool) @@ -777,7 +868,7 @@ subroutine calc_edge_quantities(block, err) call mpas_pool_get_config(liConfigs, 'config_SGH_tangent_slope_calculation', config_SGH_tangent_slope_calculation) call mpas_pool_get_config(liConfigs, 'config_sea_level', config_sea_level) call mpas_pool_get_config(liConfigs, 'config_ocean_density', rhoo) - + call mpas_pool_get_array(hydroPool, 'waterThickness', waterThickness) call mpas_pool_get_array(hydroPool, 'waterPressure', waterPressure) call mpas_pool_get_array(hydroPool, 'hydropotentialBase', hydropotentialBase) @@ -792,8 +883,11 @@ subroutine calc_edge_quantities(block, err) call mpas_pool_get_array(meshPool, 'dcEdge', dcEdge) call mpas_pool_get_array(geometryPool, 'cellMask', cellMask) call mpas_pool_get_array(meshPool, 'cellsOnEdge', cellsOnEdge) + call mpas_pool_get_array(meshPool, 'edgesOnCell', edgesOnCell) call mpas_pool_get_array(meshPool, 'edgeSignOnCell', edgeSignOnCell) call mpas_pool_get_array(hydroPool, 'hydropotentialBaseSlopeTangent', hydropotentialBaseSlopeTangent) + call mpas_pool_get_array(hydroPool, 'hydropotentialSlopeTangent', hydropotentialSlopeTangent) + call mpas_pool_get_array(hydroPool, 'gradMagPhiBaseEdge', gradMagPhiBaseEdge) call mpas_pool_get_array(hydroPool, 'gradMagPhiEdge', gradMagPhiEdge) call mpas_pool_get_array(hydroPool, 'effectiveConducEdge', effectiveConducEdge) call mpas_pool_get_array(hydroPool, 'diffusivity', diffusivity) @@ -804,8 +898,8 @@ subroutine calc_edge_quantities(block, err) call mpas_pool_get_array(hydroPool, 'waterFluxMask', waterFluxMask) call mpas_pool_get_array(hydroPool, 'hydroMarineMarginMask', hydroMarineMarginMask) call mpas_pool_get_array(geometryPool, 'edgeMask', edgeMask) - - + call mpas_pool_get_array(hydroPool, 'waterPressureSmooth', waterPressureSmooth) + do iEdge = 1, nEdges cell1 = cellsOnEdge(1, iEdge) cell2 = cellsOnEdge(2, iEdge) @@ -822,15 +916,33 @@ subroutine calc_edge_quantities(block, err) hydropotentialBaseSlopeNormal(iEdge) = (hydropotentialBase(cell2) - hydropotentialBase(cell1)) / dcEdge(iEdge) hydropotentialSlopeNormal(iEdge) = (hydropotential(cell2) - hydropotential(cell1)) / dcEdge(iEdge) - waterPressureSlopeNormal(iEdge) = (waterPressure(cell2) - waterPressure(cell1)) / dcEdge(iEdge) + + waterPressureSlopeNormal(iEdge) = (waterPressureSmooth(cell2) - waterPressureSmooth(cell1)) / dcEdge(iEdge) + end do + + ! At boundaries of hydro domain, disallow inflow. Allow outflow if hydropotential gradient requires it. + do iEdge = 1, nEdges + if ( (li_mask_is_margin(edgeMask(iEdge)) .and. li_mask_is_grounded_ice(edgeMask(iEdge))) .or. & + (hydroMarineMarginMask(iEdge)==1)) then + cell1 = cellsOnEdge(1, iEdge) + cell2 = cellsOnEdge(2, iEdge) + if (li_mask_is_grounded_ice(cellMask(cell1))) then ! cell2 is the cell outside the hydro domain + hydropotentialBaseSlopeNormal(iEdge) = min(0.0_RKIND, hydropotentialBaseSlopeNormal(iEdge)) + hydropotentialSlopeNormal(iEdge) = min(0.0_RKIND, hydropotentialSlopeNormal(iEdge)) + else ! cell1 is the cell outside the hydro domain + hydropotentialBaseSlopeNormal(iEdge) = max(0.0_RKIND, hydropotentialBaseSlopeNormal(iEdge)) + hydropotentialSlopeNormal(iEdge) = max(0.0_RKIND, hydropotentialSlopeNormal(iEdge)) + endif ! which cell is icefree + endif ! if edge of grounded ice end do ! At terrestrial margin, ignore the downslope bed topography gradient. Including it can lead to unrealistically large ! hydropotential gradients and unstable channel growth. ! We also want to do this at marine margins because otherwise the offshore topography can create a barrier to flow, ! but that is unrealistic. - ! So for all boundaries of the hydro system, the hydropotential at the margin should be determined by the geometry - ! at the edge of the cell in a 1-sided sense + ! So for all boundaries of the hydro system where outflow is occuring, + ! the hydropotential at the margin should be determined by the geometry + ! at the edge of the cell in a 1-sided sense. do iEdge = 1, nEdges if ( (li_mask_is_margin(edgeMask(iEdge)) .and. li_mask_is_grounded_ice(edgeMask(iEdge))) .or. & (hydroMarineMarginMask(iEdge)==1)) then @@ -854,41 +966,23 @@ subroutine calc_edge_quantities(block, err) endif ! if edge of grounded ice end do - ! Disallow flow from ocean to glacier, or land to glacier, - ! which can occur under some circumstances - ! For ocean this is invalid because ocean water has a different density! - ! For land this would only happen if there is a supply of water, which is not currently handled. - ! Do this by simply zeroing the hydropotential gradient in those cases. - ! (Do this step only after the other hydropotential special cases are treated above.) + ! zero gradients at edges that are marked as no flux. These should be applied at boundaries of the mesh. do iEdge = 1, nEdges - ! Find edges along GL or margin to check for 'backwards' flow - if ((hydroMarineMarginMask(iEdge)==1) .or. & - li_mask_is_margin(edgeMask(iEdge)) ) then - ! Now check if flow is backwards - cell1 = cellsOnEdge(1, iEdge) - cell2 = cellsOnEdge(2, iEdge) - if (hydropotentialBaseSlopeNormal(iEdge) > 0.0_RKIND) then - ! flow is from cell2 to cell1 - if (.not. li_mask_is_grounded_ice(cellMask(cell2))) then - hydropotentialBaseSlopeNormal(iEdge) = 0.0_RKIND - hydropotentialSlopeNormal(iEdge) = 0.0_RKIND - endif - elseif (hydropotentialBaseSlopeNormal(iEdge) < 0.0_RKIND) then - ! flow is from cell1 to cell2 - if (.not. li_mask_is_grounded_ice(cellMask(cell1))) then - hydropotentialBaseSlopeNormal(iEdge) = 0.0_RKIND - hydropotentialSlopeNormal(iEdge) = 0.0_RKIND - endif - endif - endif ! GL edge or grounded margin + if (waterFluxMask(iEdge) == 2) then + hydropotentialBaseSlopeNormal(iEdge) = 0.0_RKIND + hydropotentialSlopeNormal(iEdge) = 0.0_RKIND + waterPressureSlopeNormal(iEdge) = 0.0_RKIND + endif end do - - ! Calculate tangent slope of hydropotentialBase - three possible methods to consider + ! Calculate tangent slope of hydropotential and hydropotentialBase - three possible methods to consider ! Calculate hydropotentialBaseVertex if needed call mpas_pool_get_array(hydroPool, 'hydropotentialBaseVertex', hydropotentialBaseVertex) ! < this array could be protected by logic if desired + ! calculate hydropotentialVertex if needed + call mpas_pool_get_array(hydroPool, 'hydropotentialVertex', hydropotentialVertex) + ! < this array could be protected by logic if desired select case (trim(config_SGH_tangent_slope_calculation)) case ('from_vertex_barycentric') call mpas_pool_get_array(meshPool, 'baryCellsOnVertex', baryCellsOnVertex) @@ -896,52 +990,100 @@ subroutine calc_edge_quantities(block, err) call mpas_cells_to_points_using_baryweights(meshPool, baryCellsOnVertex(:, 1:nVertices), & baryWeightsOnVertex(:, 1:nVertices), hydropotentialBase, hydropotentialBaseVertex(1:nVertices), err_tmp) err = ior(err, err_tmp) + call mpas_cells_to_points_using_baryweights(meshPool, baryCellsOnVertex(:, 1:nVertices), & + baryWeightsOnVertex(:, 1:nVertices), hydropotential, hydropotentialVertex(1:nVertices), err_tmp) case ('from_vertex_barycentric_kiteareas') call li_cells_to_vertices_1dfield_using_kiteAreas(meshPool, hydropotentialBase, hydropotentialBaseVertex) + call li_cells_to_vertices_1dfield_using_kiteAreas(meshPool, hydropotential, hydropotentialVertex) end select ! Now perform tangent slope calculation based on method chosen + ! For the two vertex based methods, edges with vertices on the boundary of the mesh will have invalid values + ! For the normal slope method, any edges on cells that are at the edge of the mesh will have + ! contaminated values. + call mpas_pool_get_array(meshPool, 'dvEdge', dvEdge) + call mpas_pool_get_array(meshPool, 'verticesOnEdge', verticesOnEdge) select case (trim(config_SGH_tangent_slope_calculation)) case ('from_vertex_barycentric', 'from_vertex_barycentric_kiteareas') - call mpas_pool_get_array(geometryPool, 'edgeMask', edgeMask) - call mpas_pool_get_array(meshPool, 'dvEdge', dvEdge) - call mpas_pool_get_array(meshPool, 'verticesOnEdge', verticesOnEdge) do iEdge = 1, nEdges ! Only calculate slope for edges that have ice on at least one side. if ( li_mask_is_ice(edgeMask(iEdge)) ) then hydropotentialBaseSlopeTangent(iEdge) = ( hydropotentialBaseVertex(verticesOnEdge(1,iEdge)) - & hydropotentialBaseVertex(verticesOnEdge(2,iEdge)) ) / dvEdge(iEdge) + hydropotentialSlopeTangent(iEdge) = ( hydropotentialVertex(verticesOnEdge(1,iEdge)) - & + hydropotentialVertex(verticesOnEdge(2,iEdge)) ) / dvEdge(iEdge) else hydropotentialBaseSlopeTangent(iEdge) = 0.0_RKIND + hydropotentialSlopeTangent(iEdge) = 0.0_RKIND endif + ! zero tangent slope at waterFluxMask==2 + if (waterFluxMask(iEdge) == 2) then + hydropotentialBaseSlopeTangent(iEdge) = 0.0_RKIND + hydropotentialSlopeTangent(iEdge) = 0.0_RKIND + endif end do ! edges case ('from_normal_slope') + ! Do first with hydropotentialBase call mpas_tangential_vector_1d(hydropotentialBaseSlopeNormal, meshPool, & - includeHalo=.false., tangentialVector=hydropotentialBaseSlopeTangent) + includeHalo=.false., tangentialVector=hydropotentialBaseSlopeTangent) + ! Repeat for full hydropotential + call mpas_tangential_vector_1d(hydropotentialSlopeNormal, meshPool, & + includeHalo=.false., tangentialVector=hydropotentialSlopeTangent) + ! ensure that edges that don't have ice on at least one side have tangent slope set to zero + do iEdge = 1, nEdges + if ( .not. li_mask_is_ice(edgeMask(iEdge)) ) then + hydropotentialBaseSlopeTangent(iEdge) = 0.0_RKIND + hydropotentialSlopeTangent(iEdge) = 0.0_RKIND + endif + if (waterFluxMask(iEdge) == 2) then + hydropotentialBaseSlopeTangent(iEdge) = 0.0_RKIND + hydropotentialSlopeTangent(iEdge) = 0.0_RKIND + endif + + end do ! edges case default call mpas_log_write('Invalid value for config_SGH_tangent_slope_calculation.', MPAS_LOG_ERR) err = 1 end select ! calculate magnitude of gradient of Phi - gradMagPhiEdge = sqrt(hydropotentialBaseSlopeNormal**2 + hydropotentialBaseSlopeTangent**2) + gradMagPhiEdge = sqrt(hydropotentialSlopeNormal**2 + hydropotentialSlopeTangent**2) + + ! calculate magnitude of gradient of hydropotentialBase + gradMagPhiBaseEdge = sqrt(hydropotentialBaseSlopeNormal**2 +& + hydropotentialBaseSlopeTangent**2) ! calculate effective conductivity on edges if (conduc_coeff_drowned > 0.0_RKIND) then ! Use a thickness weighted conductivity coeff. when water thickness exceeds bump height do iEdge = 1, nEdges - conduc_coeff_wtd = (conduc_coeff * min(waterThicknessEdge(iEdge), bedRoughMax) + & - conduc_coeff_drowned * max(waterThicknessEdge(iEdge) - bedRoughMax, 0.0_RKIND)) / & - (waterThicknessEdge(iEdge) + 1.0e-16_RKIND) ! Regularization only applies where value doesn't matter - effectiveConducEdge(iEdge) = conduc_coeff_wtd * waterThicknessEdge(iEdge)**(alpha-1.0_RKIND) * & - (gradMagPhiEdge(iEdge)+1.0e-30_RKIND)**(beta - 2.0_RKIND) ! small value used for regularization + if (gradMagPhiBaseEdge(iEdge) < SMALL_GRADPHI) then + effectiveConducEdge(iEdge) = 0.0_RKIND + else + conduc_coeff_wtd = (conduc_coeff * min(waterThicknessEdge(iEdge), bedRoughMax) + & + conduc_coeff_drowned * max(waterThicknessEdge(iEdge) - bedRoughMax, 0.0_RKIND)) / & + (waterThicknessEdge(iEdge) + 1.0e-16_RKIND) ! Regularization only applies where value doesn't matter + + effectiveConducEdge(iEdge) = conduc_coeff_wtd * waterThicknessEdge(iEdge)**(alpha-1.0_RKIND) * & + gradMagPhiBaseEdge(iEdge)**(beta - 2.0_RKIND) + endif end do else - ! Just use a single conductivity coeff. - effectiveConducEdge(:) = conduc_coeff * waterThicknessEdge(:)**(alpha-1.0_RKIND) *& - (gradMagPhiEdge(:)+1.0e-30_RKIND)**(beta - 2.0_RKIND) ! small value used for regularization + do iEdge = 1, nEdges + ! Just use a single conductivity coeff. + if (gradMagPhiBaseEdge(iEdge) < SMALL_GRADPHI) then + effectiveConducEdge(iEdge) = 0.0_RKIND + else + effectiveConducEdge(iEdge) = conduc_coeff * waterThicknessEdge(iEdge)**(alpha-1.0_RKIND) *& + gradMagPhiBaseEdge(iEdge)**(beta - 2.0_RKIND) + endif + enddo endif + where (effectiveConducEdge < SMALL_CONDUC) + effectiveConducEdge = 0.0_RKIND + end where + ! calculate diffusivity on edges diffusivity(:) = rho_water * gravity * effectiveConducEdge(:) * waterThicknessEdge(:) @@ -957,13 +1099,19 @@ subroutine calc_edge_quantities(block, err) waterFluxAdvec(iEdge) = waterVelocity(iEdge) * waterThicknessEdgeUpwind(iEdge) ! diffusive flux - ! Note: At the GL, the water thickness for one cell will be 0, meaning a large gradient. However, the - ! diffusivity uses a one sided water thickness. It's unclear what really happens to lakes at the GL/margin. - waterFluxDiffu(iEdge) = -1.0_RKIND * diffusivity(iEdge) * (waterThickness(cell2) - waterThickness(cell1)) & + ! Note: Water thickness at the GL is undefined. I don't think we want to assume it's 0, and + ! we also don't want to assume it's the ocean water column height, because that would imply + ! a diffusive flux inward, which is undesirable. So disabling diffusion at the GL. + if (hydroMarineMarginMask(iEdge) == 1) then + diffusivity(iEdge) = 0.0_RKIND + waterFluxDiffu(iEdge) = 0.0_RKIND + else + waterFluxDiffu(iEdge) = -1.0_RKIND * diffusivity(iEdge) * (waterThickness(cell2) - waterThickness(cell1)) & / dcEdge(iEdge) - !endif + endif end do where (waterFluxMask == 2) + diffusivity = 0.0_RKIND waterFluxAdvec = 0.0_RKIND waterFluxDiffu = 0.0_RKIND waterVelocity = 0.0_RKIND @@ -1098,31 +1246,43 @@ subroutine check_timestep(domain, timeLeft, numSubCycles, err) call mpas_pool_get_array(meshPool, 'dcEdge', dcEdge) call mpas_pool_get_array(meshPool, 'indexToEdgeID', indexToEdgeID) - ! Calculate advective CFL-limited time step - dtSGHadvecBlock = 0.5_RKIND * minval(dcEdge(1:nEdgesSolve) / (abs(waterVelocity(1:nEdgesSolve)) & - + 1.0e-12_RKIND)) ! regularize - dtSGHadvecProc = min(dtSGHadvecProc, dtSGHadvecBlock) + dtSGHadvecBlock = bigNumber + dtSGHdiffuBlock = bigNumber + dtSGHpressureBlock = bigNumber + dtSGHadvecChanBlock = bigNumber + dtSGHdiffuChanBlock = bigNumber - ! Calculate diffusive CFL-limited time step - dtSGHdiffuBlock = 0.25_RKIND * minval(dcEdge(1:nEdgesSolve)**2 / (diffusivity(1:nEdgesSolve) + 1.0e-12_RKIND)) - dtSGHdiffuProc = min(dtSGHdiffuProc, dtSGHdiffuBlock) + do iEdge = 1, nEdgesSolve + ! Calculate advective CFL-limited time step + if (abs(waterVelocity(iEdge)) > 0.0) then + dtSGHadvecBlock = min(dtSGHadvecBlock, 0.5_RKIND * dcEdge(iEdge) / abs(waterVelocity(iEdge))) + endif - ! Calculate pressure limited time step - dtSGHpressureBlock = 1.0_RKIND * minval(porosity * dcEdge(1:nEdgesSolve)**2 & - / (2.0_RKIND * diffusivity(1:nEdgesSolve) + 1.0e-12_RKIND)) - dtSGHpressureProc = min(dtSGHpressureProc, dtSGHpressureBlock) + if (diffusivity(iEdge) > 0.0) then + ! Calculate diffusive CFL-limited time step + dtSGHdiffuBlock = min(dtSGHdiffuBlock, 0.25_RKIND * dcEdge(iEdge)**2 / diffusivity(iEdge)) + ! Calculate pressure limited time step + dtSGHpressureBlock = min(dtSGHpressureBlock, 1.0_RKIND * porosity * dcEdge(iEdge)**2 & + / (2.0_RKIND * diffusivity(iEdge))) + endif - if (config_SGH_chnl_active) then - ! Calculate channel advection limited time step - dtSGHadvecChanBlock = 0.5_RKIND * minval(dcEdge(1:nEdgesSolve) / (abs(channelVelocity(1:nEdgesSolve)) & - + 1.0e-12_RKIND)) - ! regularize - dtSGHadvecChanProc = min(dtSGHadvecChanProc, dtSGHadvecChanBlock) - ! Calculate channel diffusion limited time step - dtSGHdiffuChanBlock = 0.25_RKIND * minval(dcEdge(1:nEdgesSolve)**2 / (channelDiffusivity(1:nEdgesSolve) + & - 1.0e-12_RKIND)) - dtSGHdiffuChanProc = min(dtSGHdiffuChanProc, dtSGHdiffuChanBlock) - endif + if (config_SGH_chnl_active) then + if (abs(channelVelocity(iEdge)) > 0.0) then + ! Calculate channel advection limited time step + dtSGHadvecChanBlock = min(dtSGHadvecChanBlock, 0.5_RKIND * dcEdge(iEdge) / (abs(channelVelocity(iEdge)))) + endif + ! Calculate channel diffusion limited time step + if (channelDiffusivity(iEdge) > 0.0) then + dtSGHdiffuChanBlock = min(dtSGHdiffuChanBlock, 0.25_RKIND * dcEdge(iEdge)**2 / channelDiffusivity(iEdge)) + endif + endif + enddo + + dtSGHadvecProc = min(dtSGHadvecProc, dtSGHadvecBlock) + dtSGHdiffuProc = min(dtSGHdiffuProc, dtSGHdiffuBlock) + dtSGHpressureProc = min(dtSGHpressureProc, dtSGHpressureBlock) + dtSGHadvecChanProc = min(dtSGHadvecChanProc, dtSGHadvecChanBlock) + dtSGHdiffuChanProc = min(dtSGHdiffuChanProc, dtSGHdiffuChanBlock) ! Master deltat is needed below, so grab it in this block loop call mpas_pool_get_array(meshPool, 'deltat', deltat) @@ -1370,6 +1530,7 @@ subroutine calc_pressure(block, err) real (kind=RKIND), dimension(:), pointer :: divergenceChannel real (kind=RKIND), dimension(:), pointer :: channelAreaChangeCell real (kind=RKIND), dimension(:), pointer :: bedTopography + real (kind=RKIND), dimension(:), pointer :: iceThicknessHydro integer, dimension(:), pointer :: hydroMarineMarginMask integer, dimension(:), pointer :: cellMask integer, dimension(:), pointer :: nEdgesOnCell @@ -1436,6 +1597,7 @@ subroutine calc_pressure(block, err) call mpas_pool_get_array(geometryPool, 'thickness', thickness) call mpas_pool_get_array(geometryPool, 'cellMask', cellMask) call mpas_pool_get_array(geometryPool, 'bedTopography', bedTopography) + call mpas_pool_get_array(hydroPool, 'iceThicknessHydro', iceThicknessHydro) openingRate(:) = bedRough * basalSpeed(:) * (bedRoughMax - waterThickness(:)) !openingRate(:) = bedRough * basalSpeed(:) * (bedRoughMax - waterThickness(:)) + & @@ -1456,7 +1618,7 @@ subroutine calc_pressure(block, err) case ('cavity') where (li_mask_is_floating_ice(cellMask)) - waterPressure = rhoi * gravity * thickness + waterPressure = rhoi * gravity * iceThicknessHydro elsewhere (.not. li_mask_is_ice(cellMask)) waterPressure = 0.0_RKIND elsewhere @@ -1466,11 +1628,11 @@ subroutine calc_pressure(block, err) case ('overburden') where (li_mask_is_floating_ice(cellMask)) - waterPressure = rhoi * gravity * thickness + waterPressure = rhoi * gravity * iceThicknessHydro elsewhere (.not. li_mask_is_ice(cellMask)) waterPressure = 0.0_RKIND elsewhere - waterPressure = rhoi * gravity * thickness + waterPressure = rhoi * gravity * iceThicknessHydro end where case default @@ -1479,8 +1641,8 @@ subroutine calc_pressure(block, err) end select waterPressure = max(0.0_RKIND, waterPressure) - waterPressure = min(waterPressure, rhoi * gravity * thickness) - + waterPressure = min(waterPressure, rhoi * gravity * iceThicknessHydro) + do iCell = 1, nCells if ( li_mask_is_floating_ice(cellMask(iCell)) .or. & ((.not. li_mask_is_ice(cellMask(iCell))) .and. (bedTopography(iCell) < config_sea_level) ) ) then @@ -1528,7 +1690,6 @@ subroutine calc_pressure_diag_vars(block, err) !----------------------------------------------------------------- ! input variables !----------------------------------------------------------------- - !----------------------------------------------------------------- ! input/output variables !----------------------------------------------------------------- @@ -1546,13 +1707,13 @@ subroutine calc_pressure_diag_vars(block, err) type (mpas_pool_type), pointer :: geometryPool type (mpas_pool_type), pointer :: hydroPool real (kind=RKIND), pointer :: rhoi, rhoo - real (kind=RKIND), dimension(:), pointer :: thickness real (kind=RKIND), dimension(:), pointer :: waterPressure real (kind=RKIND), dimension(:), pointer :: bedTopography real (kind=RKIND), dimension(:), pointer :: hydropotentialBase real (kind=RKIND), dimension(:), pointer :: waterThickness real (kind=RKIND), dimension(:), pointer :: hydropotential real (kind=RKIND), dimension(:), pointer :: effectivePressure + real (kind=RKIND), dimension(:), pointer :: iceThicknessHydro integer, dimension(:), pointer :: cellMask real (kind=RKIND), pointer :: config_sea_level @@ -1567,20 +1728,20 @@ subroutine calc_pressure_diag_vars(block, err) call mpas_pool_get_config(liConfigs, 'config_ocean_density', rhoo) call mpas_pool_get_array(hydroPool, 'effectivePressure', effectivePressure) - call mpas_pool_get_array(geometryPool, 'thickness', thickness) call mpas_pool_get_array(hydroPool, 'waterPressure', waterPressure) call mpas_pool_get_array(geometryPool, 'bedTopography', bedTopography) call mpas_pool_get_array(hydroPool, 'hydropotentialBase', hydropotentialBase) call mpas_pool_get_array(hydroPool, 'waterThickness', waterThickness) call mpas_pool_get_array(hydroPool, 'hydropotential', hydropotential) + call mpas_pool_get_array(hydroPool, 'iceThicknessHydro', iceThicknessHydro) call mpas_pool_get_array(geometryPool, 'cellMask', cellMask) - effectivePressure = rhoi * gravity * thickness - waterPressure + effectivePressure = rhoi * gravity * iceThicknessHydro - waterPressure ! < this should evalute to 0 for floating ice if Pw set correctly there. where (.not. li_mask_is_grounded_ice(cellmask)) effectivePressure = 0.0_RKIND ! zero effective pressure where no ice to avoid confusion end where - + hydropotentialBase = rho_water * gravity * bedTopography + waterPressure ! This is still correct under ice shelves/open ocean because waterPressure has been set appropriately there already. ! Note this leads to a nonuniform hydropotential at sea level that is a function of the ocean depth. @@ -1626,7 +1787,6 @@ subroutine update_channel(block, err) ! local variables !----------------------------------------------------------------- ! Pools pointers -!! type (mpas_pool_type), pointer :: geometryPool type (mpas_pool_type), pointer :: hydroPool type (mpas_pool_type), pointer :: meshPool type (mpas_pool_type), pointer :: velocityPool @@ -1638,7 +1798,6 @@ subroutine update_channel(block, err) real (kind=RKIND), pointer :: rhoi real (kind=RKIND), pointer :: config_SGH_incipient_channel_width logical, pointer :: config_SGH_include_pressure_melt - real (kind=RKIND), dimension(:), pointer :: channelArea real (kind=RKIND), dimension(:), pointer :: channelMelt real (kind=RKIND), dimension(:), pointer :: channelPressureFreeze @@ -1646,7 +1805,7 @@ subroutine update_channel(block, err) real (kind=RKIND), dimension(:), pointer :: channelVelocity real (kind=RKIND), dimension(:), pointer :: gradMagPhiEdge real (kind=RKIND), dimension(:), pointer :: waterFlux - real (kind=RKIND), dimension(:), pointer :: hydropotentialBaseSlopeNormal + real (kind=RKIND), dimension(:), pointer :: hydropotentialSlopeNormal real (kind=RKIND), dimension(:), pointer :: waterPressureSlopeNormal real (kind=RKIND), dimension(:), pointer :: channelOpeningRate real (kind=RKIND), dimension(:), pointer :: channelClosingRate @@ -1661,20 +1820,16 @@ subroutine update_channel(block, err) real (kind=RKIND), dimension(:,:), pointer :: flowParamA integer, dimension(:,:), pointer :: cellsOnEdge integer, pointer :: nVertLevels - integer, pointer :: nEdgesSolve integer :: iEdge, cell1, cell2 - err = 0 ! Get pools things call mpas_pool_get_subpool(block % structs, 'hydro', hydroPool) -! call mpas_pool_get_subpool(block % structs, 'geometry', geometryPool) call mpas_pool_get_subpool(block % structs, 'mesh', meshPool) call mpas_pool_get_subpool(block % structs, 'velocity', velocityPool) call mpas_pool_get_subpool(block % structs, 'geometry', geometryPool) - call mpas_pool_get_config(liConfigs, 'config_ice_density', rhoi) call mpas_pool_get_config(liConfigs, 'config_SGH_chnl_conduc_coeff', Kc) call mpas_pool_get_config(liConfigs, 'config_SGH_chnl_alpha', alpha_c) @@ -1682,17 +1837,15 @@ subroutine update_channel(block, err) call mpas_pool_get_config(liConfigs, 'config_SGH_chnl_creep_coefficient', creep_coeff) call mpas_pool_get_config(liConfigs, 'config_SGH_incipient_channel_width', config_SGH_incipient_channel_width) call mpas_pool_get_config(liConfigs, 'config_SGH_include_pressure_melt', config_SGH_include_pressure_melt) - - call mpas_pool_get_dimension(meshPool, 'nEdgesSolve', nEdgesSolve) call mpas_pool_get_dimension(meshPool, 'nVertLevels', nVertLevels) - + call mpas_pool_get_dimension(meshPool, 'nEdgesSolve', nEdgesSolve) call mpas_pool_get_array(hydroPool, 'channelArea', channelArea) call mpas_pool_get_array(hydroPool, 'channelMelt', channelMelt) call mpas_pool_get_array(hydroPool, 'channelPressureFreeze', channelPressureFreeze) call mpas_pool_get_array(hydroPool, 'channelDischarge', channelDischarge) call mpas_pool_get_array(hydroPool, 'channelVelocity', channelVelocity) call mpas_pool_get_array(hydroPool, 'gradMagPhiEdge', gradMagPhiEdge) - call mpas_pool_get_array(hydroPool, 'hydropotentialBaseSlopeNormal', hydropotentialBaseSlopeNormal) + call mpas_pool_get_array(hydroPool, 'hydropotentialSlopeNormal', hydropotentialSlopeNormal) call mpas_pool_get_array(hydroPool, 'waterPressureSlopeNormal', waterPressureSlopeNormal) call mpas_pool_get_array(hydroPool, 'waterFlux', waterFlux) call mpas_pool_get_array(hydroPool, 'channelOpeningRate', channelOpeningRate) @@ -1707,14 +1860,13 @@ subroutine update_channel(block, err) call mpas_pool_get_array(hydroPool, 'hydroMarineMarginMask', hydroMarineMarginMask) call mpas_pool_get_array(hydroPool, 'channelDiffusivity', channelDiffusivity) call mpas_pool_get_array(geometryPool, 'edgeMask', edgeMask) - ! Calculate terms needed for opening (melt) rate - where(gradMagPhiEdge < 0.01_RKIND) + where(gradMagPhiEdge < SMALL_GRADPHI) channelDischarge(:) = 0.0_RKIND elsewhere channelDischarge = -1.0_RKIND * Kc * channelArea**alpha_c * gradMagPhiEdge**(beta_c - 2.0_RKIND) * & - hydropotentialBaseSlopeNormal + hydropotentialSlopeNormal end where where (waterFluxMask == 2) @@ -1739,15 +1891,15 @@ subroutine update_channel(block, err) channelVelocity = channelDischarge / (channelArea + 1.0e-12_RKIND) ! diffusivity used only to limit channel dt right now - where(gradMagPhiEdge < 0.01_RKIND) + where(gradMagPhiEdge < SMALL_GRADPHI) channelDiffusivity = 0.0_RKIND elsewhere channelDiffusivity = abs(rho_water * gravity * channelArea * & Kc * channelArea**(alpha_c - 1.0_RKIND) * gradMagPhiEdge**(beta_c - 2.0_RKIND)) end where - channelMelt = (abs(channelDischarge * hydropotentialBaseSlopeNormal) & ! channel dissipation - + abs(waterFlux * hydropotentialBaseSlopeNormal * config_SGH_incipient_channel_width) & !some sheet dissipation + channelMelt = (abs(channelDischarge * hydropotentialSlopeNormal) & ! channel dissipation + + abs(waterFlux * hydropotentialSlopeNormal * config_SGH_incipient_channel_width) & !some sheet dissipation ) / latent_heat_ice channelPressureFreeze = -1.0_RKIND * iceMeltingPointPressureDependence * cp_freshwater * rho_water * & (channelDischarge + waterFlux * config_SGH_incipient_channel_width) & @@ -1775,6 +1927,7 @@ subroutine update_channel(block, err) channelOpeningRate = 0.0_RKIND channelClosingRate = 0.0_RKIND end where + channelChangeRate = channelOpeningRate - channelClosingRate !-------------------------------------------------------------------- @@ -1816,9 +1969,11 @@ subroutine evolve_channel(block, err) type (mpas_pool_type), pointer :: meshPool real (kind=RKIND), dimension(:), pointer :: channelArea real (kind=RKIND), dimension(:), pointer :: channelDischarge + real (kind=RKIND), dimension(:), pointer :: channelMelt, channelPressureFreeze real (kind=RKIND), dimension(:), pointer :: channelChangeRate real (kind=RKIND), dimension(:), pointer :: divergenceChannel real (kind=RKIND), dimension(:), pointer :: channelAreaChangeCell + real (kind=RKIND), dimension(:), pointer :: channelMeltInputCell real (kind=RKIND), pointer :: deltatSGH integer, dimension(:), pointer :: nEdgesOnCell integer, dimension(:,:), pointer :: edgesOnCell @@ -1834,9 +1989,12 @@ subroutine evolve_channel(block, err) call mpas_pool_get_array(hydroPool, 'deltatSGH', deltatSGH) call mpas_pool_get_array(hydroPool, 'channelArea', channelArea) call mpas_pool_get_array(hydroPool, 'channelDischarge', channelDischarge) + call mpas_pool_get_array(hydroPool, 'channelMelt', channelMelt) + call mpas_pool_get_array(hydroPool, 'channelPressureFreeze', channelPressureFreeze) call mpas_pool_get_array(hydroPool, 'channelChangeRate', channelChangeRate) call mpas_pool_get_array(hydroPool, 'divergenceChannel', divergenceChannel) call mpas_pool_get_array(hydroPool, 'channelAreaChangeCell', channelAreaChangeCell) + call mpas_pool_get_array(hydroPool, 'channelMeltInputCell', channelMeltInputCell) call mpas_pool_get_dimension(meshPool, 'nCellsSolve', nCellsSolve) call mpas_pool_get_array(meshPool, 'nEdgesOnCell', nEdgesOnCell) call mpas_pool_get_array(meshPool, 'edgesOnCell', edgesOnCell) @@ -1848,6 +2006,7 @@ subroutine evolve_channel(block, err) ! Calculate flux divergence on cells and channel area change on cells divergenceChannel(:) = 0.0_RKIND ! zero div before accumulating channelAreaChangeCell(:) = 0.0_RKIND ! zero before accumulating + channelMeltInputCell(:) = 0.0_RKIND ! zero before accumulating ! loop over locally owned cells do iCell = 1, nCellsSolve ! TODO: could limit to grounded cells only @@ -1856,12 +2015,15 @@ subroutine evolve_channel(block, err) iEdge = edgesOnCell(iEdgeOnCell, iCell) ! add on advective & diffusive fluxes divergenceChannel(iCell) = divergenceChannel(iCell) - channelDischarge(iEdge) * edgeSignOnCell(iEdgeOnCell, iCell) - channelAreaChangeCell(iCell) = channelChangeRate(iEdge) * dcEdge(iEdge) * 0.5_RKIND + channelAreaChangeCell(iCell) = channelChangeRate(iEdge) * dcEdge(iEdge) * 0.5_RKIND + channelAreaChangeCell(iCell) ! < only half of channel is in this cell + channelMeltInputCell(iCell) = 0.5_RKIND * (channelMelt(iEdge) - channelPressureFreeze(iEdge)) * dcEdge(iEdge) / rho_water + channelMeltInputCell(iCell) end do ! edges + end do ! cells divergenceChannel(1:nCellsSolve) = divergenceChannel(1:nCellsSolve) / areaCell(1:nCellsSolve) channelAreaChangeCell(1:nCellsSolve) = channelAreaChangeCell(1:nCellsSolve) / areaCell(1:nCellsSolve) + channelMeltInputCell(1:nCellsSolve) = channelMeltInputCell(1:nCellsSolve) / areaCell(1:nCellsSolve) ! Now update channel area channelArea = channelChangeRate * deltatSGH + channelArea @@ -2047,9 +2209,9 @@ subroutine ocean_connection_N(domain) type (block_type), pointer :: block type (mpas_pool_type), pointer :: hydroPool type (mpas_pool_type), pointer :: geometryPool - real (kind=RKIND), dimension(:), pointer :: thickness real (kind=RKIND), dimension(:), pointer :: bedTopography real (kind=RKIND), dimension(:), pointer :: effectivePressure + real (kind=RKIND), dimension(:), pointer :: thickness real (kind=RKIND), pointer :: rhoi, rhoo ! Calculate N assuming perfect ocean connection @@ -2061,9 +2223,10 @@ subroutine ocean_connection_N(domain) do while (associated(block)) call mpas_pool_get_subpool(block % structs, 'geometry', geometryPool) call mpas_pool_get_subpool(block % structs, 'hydro', hydroPool) - call mpas_pool_get_array(geometryPool, 'thickness', thickness) call mpas_pool_get_array(geometryPool, 'bedTopography', bedTopography) call mpas_pool_get_array(hydroPool, 'effectivePressure', effectivePressure) + call mpas_pool_get_array(hydroPool, 'thickness', thickness) + effectivePressure = rhoi * gravity * thickness - rhoi * gravity * max(0.0_RKIND, -1.0_RKIND * rhoo/rhoi * bedTopography) effectivePressure = max(effectivePressure, 0.0_RKIND) ! This is just to zero out N in the open ocean to avoid confusion @@ -2082,7 +2245,8 @@ end subroutine ocean_connection_N !> \author Matt Hoffman !> \date 24 October 2022 !> \details -!> This routine calculates a mask of the boundaries of the active hydrology domain +!> This routine calculates a mask of the boundaries of the active hydrology domain. +!> If there is no waterFluxMask set around domain boundaries, then calc_hydro_mask creates one. !----------------------------------------------------------------------- subroutine calc_hydro_mask(domain) @@ -2108,11 +2272,15 @@ subroutine calc_hydro_mask(domain) type (mpas_pool_type), pointer :: meshPool real (kind=RKIND), dimension(:), pointer :: bedTopography integer, dimension(:), pointer :: hydroMarineMarginMask + integer, dimension(:), pointer :: hydroTerrestrialMarginMask integer, dimension(:,:), pointer :: cellsOnEdge integer, dimension(:), pointer :: cellMask + integer, dimension(:), pointer :: waterFluxMask integer, pointer :: nEdgesSolve + integer, pointer :: nCells integer :: cell1, cell2, iEdge real (kind=RKIND), pointer :: config_sea_level + integer :: wfmWarning call mpas_pool_get_config(liConfigs, 'config_sea_level', config_sea_level) @@ -2124,33 +2292,400 @@ subroutine calc_hydro_mask(domain) call mpas_pool_get_array(geometryPool, 'bedTopography', bedTopography) call mpas_pool_get_array(geometryPool, 'cellMask', cellMask) call mpas_pool_get_array(hydroPool, 'hydroMarineMarginMask', hydroMarineMarginMask) + call mpas_pool_get_array(hydroPool, 'hydroTerrestrialMarginMask', hydroTerrestrialMarginMask) + call mpas_pool_get_array(hydroPool, 'waterFluxMask', waterFluxMask) call mpas_pool_get_array(meshPool, 'cellsOnEdge', cellsOnEdge) call mpas_pool_get_dimension(meshPool, 'nEdgesSolve', nEdgesSolve) + call mpas_pool_get_dimension(meshPool, 'nCells', nCells) hydroMarineMarginMask(:) = 0 + hydroTerrestrialMarginMask(:) = 0 + wfmWarning = 0 + do iEdge = 1, nEdgesSolve cell1 = cellsOnEdge(1, iEdge) cell2 = cellsOnEdge(2, iEdge) - ! We are looking for edges with 1 edge grounded ice and the other edge floating ice or open ocean + + !ensure no-flow conditions on edges of domain if not set up + !in input file + if ( ((cell1 == nCells + 1) .or. (cell2 == nCells +1 )) & + .and. (waterFluxMask(iEdge) .ne. 2)) then + waterFluxMask(iEdge) = 2 + wfmWarning = 1 + endif + + ! hydroMarineMarginMask: We are looking for edges with 1 edge grounded ice and the other edge floating ice or open ocean + ! Exclude no-flow boundaries if ( (li_mask_is_grounded_ice(cellMask(cell1))) .and. & (li_mask_is_floating_ice(cellMask(cell2)) .or. & - ((bedTopography(cell2) < config_sea_level) .and. (.not. li_mask_is_ice(cellMask(cell2)))) ) ) then + ((bedTopography(cell2) < config_sea_level) .and. (.not. li_mask_is_ice(cellMask(cell2)))) ) & + .and. (waterFluxMask(iEdge) .ne. 2) ) then hydroMarineMarginMask(iEdge) = 1 elseif ( (li_mask_is_grounded_ice(cellMask(cell2))) .and. & (li_mask_is_floating_ice(cellMask(cell1)) .or. & - ((bedTopography(cell1) < config_sea_level) .and. (.not. li_mask_is_ice(cellMask(cell1)))) ) ) then + ((bedTopography(cell1) < config_sea_level) .and. (.not. li_mask_is_ice(cellMask(cell1)))) ) & + .and. (waterFluxMask(iEdge) .ne. 2) ) then hydroMarineMarginMask(iEdge) = 1 endif + + ! hydroTerrestrialMarginMask: Look for edges with 1 cell on grounding ice and the other cell on land without ice + ! Exclude no-flow boundaries + if ((li_mask_is_grounded_ice(cellMask(cell1))) .and. ( .not. li_mask_is_ice(cellMask(cell2))) & + .and. (bedTopography(cell2) >= config_sea_level) & + .and. (waterFluxMask(iEdge) .ne. 2) ) then + hydroTerrestrialMarginMask(iEdge) = 1 + elseif ((li_mask_is_grounded_ice(cellMask(cell2))) .and. ( .not. li_mask_is_ice(cellMask(cell1))) & + .and. (bedTopography(cell1) >= config_sea_level) & + .and. (waterFluxMask(iEdge) .ne. 2) ) then + hydroTerrestrialMarginMask(iEdge) = 1 + endif enddo block => block % next end do + if (wfmWarning == 1) then + call mpas_log_write('Changing waterFluxMask to enforce no-flow conditions at domain boundaries', MPAS_LOG_WARN) + endif call mpas_timer_start("halo updates") call mpas_dmpar_field_halo_exch(domain, 'hydroMarineMarginMask') + call mpas_dmpar_field_halo_exch(domain, 'hydroTerrestrialMarginMask') + call mpas_dmpar_field_halo_exch(domain, 'waterFluxMask') call mpas_timer_stop("halo updates") !-------------------------------------------------------------------- end subroutine calc_hydro_mask + + +!*********************************************************************** +! +! routine calc_iceThicknessHydro +! +!> \brief Calculate version of ice thickness used by hydrology model +!> \author Alex Hager +!> \date 7 June 2023 +!> \details +!> This routine calculates a modified ice thickness that is altered to +!> avoid local minima in hydropotential +!----------------------------------------------------------------------- + subroutine calc_iceThicknessHydro(block, err) + + !----------------------------------------------------------------- + ! input variables + !----------------------------------------------------------------- + + !----------------------------------------------------------------- + ! input/output variables + !----------------------------------------------------------------- + type (block_type), intent(inout) :: block !< Input/Output: block object + + !----------------------------------------------------------------- + ! output variables + !----------------------------------------------------------------- + integer, intent(out) :: err !< Output: error flag + + !----------------------------------------------------------------- + ! local variables + !----------------------------------------------------------------- + ! Pools pointers + type (mpas_pool_type), pointer :: geometryPool + type (mpas_pool_type), pointer :: hydroPool + type (mpas_pool_type), pointer :: meshPool + real (kind=RKIND), dimension(:), pointer :: thickness + real (kind=RKIND), dimension(:), pointer :: bedTopography + real (kind=RKIND), dimension(:), pointer :: iceThicknessHydro + real (kind=RKIND), dimension(:), pointer :: upperSurface + integer, dimension(:,:), pointer :: cellsOnCell + integer, dimension(:), pointer :: cellMask + real (kind=RKIND), dimension(:), pointer :: areaCell + integer, pointer :: nCells + integer, dimension(:), pointer :: nEdgesOnCell + integer :: iCell + integer :: jCell + integer :: iNeighbor + real (kind=RKIND) :: maxNeighborHeight + real (kind=RKIND) :: minNeighborHeight + real (kind=RKIND) :: meanNeighborHeight + real (kind=RKIND) :: totalNeighborHeight + real (kind=RKIND) :: totalArea + real (kind=RKIND), parameter :: bigValue = 1.0e6_RKIND + real (kind=RKIND), parameter :: bigNegativeValue = -1.0e6_RKIND + logical, pointer :: config_SGH_use_iceThicknessHydro + err = 0 + + ! Get pools things + call mpas_pool_get_subpool(block % structs, 'hydro', hydroPool) + call mpas_pool_get_subpool(block % structs, 'geometry', geometryPool) + call mpas_pool_get_subpool(block % structs, 'mesh', meshPool) + + call mpas_pool_get_array(geometryPool, 'thickness', thickness) + call mpas_pool_get_array(geometryPool, 'bedTopography', bedTopography) + call mpas_pool_get_array(geometryPool, 'cellMask', cellMask) + call mpas_pool_get_array(hydroPool, 'iceThicknessHydro', iceThicknessHydro) + call mpas_pool_get_array(geometryPool, 'upperSurface', upperSurface) + call mpas_pool_get_array(meshPool, 'nEdgesOnCell', nEdgesOnCell) + call mpas_pool_get_dimension(meshPool, 'nCells', nCells) + call mpas_pool_get_array(meshPool, 'cellsOnCell', cellsOnCell) + call mpas_pool_get_array(meshPool, 'nEdgesOnCell', nEdgesOnCell) + call mpas_pool_get_array(meshPool, 'areaCell', areaCell) + call mpas_pool_get_config(liConfigs, 'config_SGH_use_iceThicknessHydro', config_SGH_use_iceThicknessHydro) + + iceThicknessHydro = thickness + + !iceThicknessHydro is equivalent to thickness if + !config_SGH_use_iceThicknessHydro is false. Default is to alter + !ice thickness + + if (config_SGH_use_iceThicknessHydro) then + do iCell = 1, nCells + + if (li_mask_is_grounded_ice(cellMask(iCell))) then !identify grounded ice + + maxNeighborHeight = bigNegativeValue !initialize + minNeighborHeight = bigValue + + totalNeighborHeight = 0.0_RKIND + totalArea = 0.0_RKIND + + do jCell = 1, nEdgesOnCell(iCell) + + iNeighbor = cellsOnCell(jCell,iCell) + + !Only include neighbor cell in averaging if it contains grounded ice + if ((li_mask_is_grounded_ice(cellMask(iNeighbor)))) then + + minNeighborHeight = min(minNeighborHeight, upperSurface(iNeighbor)) + + maxNeighborHeight = max(maxNeighborHeight, upperSurface(iNeighbor)) + + totalNeighborHeight = totalNeighborHeight + upperSurface(iNeighbor)*areaCell(iNeighbor) + + totalArea = totalArea + areaCell(iNeighbor) + + endif + end do + + if ((totalNeighborHeight == 0.0_RKIND) .or. (totalArea == 0.0_RKIND)) then + meanNeighborHeight = upperSurface(iCell) !no smoothing in single-cell islands + else + meanNeighborHeight = totalNeighborHeight / totalArea !area-weighted average height + endif + + !only adjust surface elevation if cell is local minimum or + !maximum + if ((upperSurface(iCell) < minNeighborHeight) & + .and. (minNeighborHeight < bigValue)) then + + iceThicknessHydro(iCell) = meanNeighborHeight - bedTopography(iCell) + + elseif ((upperSurface(iCell) > maxNeighborHeight) & + .and. (maxNeighborHeight > bigNegativeValue)) then + + iceThicknessHydro(iCell) = meanNeighborHeight - bedTopography(iCell) + + endif + + !avoid negatives, default to original thickness + if (iceThicknessHydro(iCell) < 0.0_RKIND) then + iceThicknessHydro(iCell) = thickness(iCell) + endif + endif + enddo + endif + + end subroutine calc_iceThicknessHydro + +!*********************************************************************** +! +! routine calc_gl_total +! +!> \brief Calculate total grounding line discharge on +! adjacent ocean cell +!> \author Alex Hager +!> \date 27 March 2024 +!> \details Find the total amount of freshwater entering the first ocean cell from the grounding line. +!----------------------------------------------------------------------- + subroutine calc_gl_totals(block, err) + !----------------------------------------------------------------- + ! input variables + !----------------------------------------------------------------- + + !----------------------------------------------------------------- + ! input/output variables + !----------------------------------------------------------------- + type (block_type), intent(inout) :: block !< Input/Output: block object + + !----------------------------------------------------------------- + ! output variables + !----------------------------------------------------------------- + integer, intent(out) :: err !< Output: error flag + + !----------------------------------------------------------------- + ! local variables + !----------------------------------------------------------------- + type (mpas_pool_type), pointer :: hydroPool + type (mpas_pool_type), pointer :: geometryPool + type (mpas_pool_type), pointer :: meshPool + + real (kind=RKIND), dimension(:), pointer :: distGroundingLineDischargeCell + real (kind=RKIND), dimension(:), pointer :: chnlGroundingLineDischargeCell + real (kind=RKIND), dimension(:), pointer :: totalGroundingLineDischargeCell + real (kind=RKIND), dimension(:), pointer :: channelDischarge + real (kind=RKIND), dimension(:), pointer :: waterFlux + real (kind=RKIND), dimension(:), pointer :: dvEdge + integer iEdge, cell1, cell2 + integer, pointer :: nEdgesSolve + integer, dimension(:,:), pointer :: cellsOnEdge + integer, dimension(:), pointer :: hydroMarineMarginMask + integer, dimension(:), pointer :: cellMask + real (kind=RKIND) :: distGroundingLineDischargeEdge + real (kind=RKIND) :: chnlGroundingLineDischargeEdge + real (kind=RKIND) :: totalGroundingLineDischargeEdge + + call mpas_pool_get_subpool(block % structs, 'hydro', hydroPool) + call mpas_pool_get_subpool(block % structs, 'geometry', geometryPool) + call mpas_pool_get_subpool(block % structs, 'mesh', meshPool) + + call mpas_pool_get_array(hydroPool, 'distGroundingLineDischargeCell', distGroundingLineDischargeCell) + call mpas_pool_get_array(hydroPool, 'chnlGroundingLineDischargeCell', chnlGroundingLineDischargeCell) + call mpas_pool_get_array(hydroPool, 'totalGroundingLineDischargeCell', totalGroundingLineDischargeCell) + call mpas_pool_get_array(hydroPool, 'channelDischarge', channelDischarge) + call mpas_pool_get_array(hydroPool, 'waterFlux', waterFlux) + call mpas_pool_get_array(meshPool, 'dvEdge', dvEdge) + call mpas_pool_get_dimension(meshPool, 'nEdgesSolve', nEdgesSolve) + call mpas_pool_get_array(meshPool, 'cellsOnEdge', cellsOnEdge) + call mpas_pool_get_array(hydroPool, 'hydroMarineMarginMask', hydroMarineMarginMask) + call mpas_pool_get_array(geometryPool, 'cellMask', cellMask) + + distGroundingLineDischargeCell(:) = 0.0_RKIND + chnlGroundingLineDischargeCell(:) = 0.0_RKIND + totalGroundingLineDischargeCell(:) = 0.0_RKIND + + do iEdge = 1, nEdgesSolve + + if (hydroMarineMarginMask(iEdge) == 1) then + + cell1 = cellsOnEdge(1, iEdge) + cell2 = cellsOnEdge(2, iEdge) + + !calculate totals at each grounding line edge + distGroundingLineDischargeEdge = abs(waterFlux(iEdge) * dvEdge(iEdge)) + chnlGroundingLineDischargeEdge = abs(channelDischarge(iEdge)) + totalGroundingLineDischargeEdge = distGroundingLineDischargeEdge + chnlGroundingLineDischargeEdge + + !Assign sum of edge totals to adjacent ungrounded cell + if (li_mask_is_grounded_ice(cellMask(cell1))) then + distGroundingLineDischargeCell(cell2) = distGroundingLineDischargeCell(cell2) + distGroundingLineDischargeEdge + chnlGroundingLineDischargeCell(cell2) = chnlGroundingLineDischargeCell(cell2) + chnlGroundingLineDischargeEdge + totalGroundingLineDischargeCell(cell2) = totalGroundingLineDischargeCell(cell2) + totalGroundingLineDischargeEdge + elseif (li_mask_is_grounded_ice(cellMask(cell2))) then + distGroundingLineDischargeCell(cell1) = distGroundingLineDischargeCell(cell1) + distGroundingLineDischargeEdge + chnlGroundingLineDischargeCell(cell1) = chnlGroundingLineDischargeCell(cell1) + chnlGroundingLineDischargeEdge + totalGroundingLineDischargeCell(cell1) = totalGroundingLineDischargeCell(cell1) + totalGroundingLineDischargeEdge + endif + endif + enddo + end subroutine calc_gl_totals + +!*********************************************************************** +! +! routine calc_waterPressureSmooth +! +!> \brief Calculate smoothed version of waterPressure used for calculation +!> of waterPressureSlopeNormal +!> \author Alex Hager +!> \date 29 February 2024 +!> \details Creates a smoothed version of waterPressure, called waterPressureSmooth, +!> that is used for calculation of waterPressureSlopeNormal. +!> This is necessary to increase stability with channelPressureFreeze +!> with spatially variable bedTopography and upperSurface. waterPressureSmooth +!> an area-weighted average of the current cells and its neighbors. Possible to +!> perform multiple iterations of smoothing by adjusting +!> config_SGH_iter_smooth_waterPressureSlopeNormal +!----------------------------------------------------------------------- + subroutine calc_waterPressureSmooth(block,err) + !----------------------------------------------------------------- + ! input variables + !----------------------------------------------------------------- + + !----------------------------------------------------------------- + ! input/output variables + !----------------------------------------------------------------- + type (block_type), intent(inout) :: block !< Input/Output: block object + + !----------------------------------------------------------------- + ! output variables + !----------------------------------------------------------------- + integer, intent(out) :: err !< Output: error flag + + !----------------------------------------------------------------- + ! local variables + !----------------------------------------------------------------- + + type (mpas_pool_type), pointer :: meshPool + type (mpas_pool_type), pointer :: geometryPool + type (mpas_pool_type), pointer :: hydroPool + real (kind=RKIND), dimension(:), pointer :: bedTopography + real (kind=RKIND), dimension(:), pointer :: waterPressure + real (kind=RKIND), dimension(:), pointer :: waterPressureSmooth + real (kind=RKIND), dimension(:), pointer :: areaCell + real (kind=RKIND), dimension(:), allocatable :: pressureField + real(kind=RKIND) :: totalPressure + real(kind=RKIND) :: totalArea + integer, dimension(:), pointer :: cellMask + integer, dimension(:,:), pointer :: cellsOnCell + integer, dimension(:), pointer :: nEdgesOnCell + integer, pointer :: nTimesSmooth + integer, pointer :: nCells + integer :: iCell, jEdge + integer :: iNeighbor + integer :: iter + + err = 0 + + ! Get pools things + call mpas_pool_get_subpool(block % structs, 'mesh', meshPool) + call mpas_pool_get_subpool(block % structs, 'hydro', hydroPool) + call mpas_pool_get_subpool(block % structs, 'geometry', geometryPool) + call mpas_pool_get_dimension(meshPool, 'nCells', nCells) + call mpas_pool_get_config(liConfigs, 'config_SGH_iter_smooth_waterPressureSlopeNormal', nTimesSmooth) + call mpas_pool_get_array(hydroPool, 'waterPressure', waterPressure) + call mpas_pool_get_array(hydroPool, 'waterPressureSmooth', waterPressureSmooth) + call mpas_pool_get_array(geometryPool, 'cellMask', cellMask) + call mpas_pool_get_array(meshPool, 'cellsOnCell', cellsOnCell) + call mpas_pool_get_array(meshPool, 'nEdgesOnCell', nEdgesOnCell) + call mpas_pool_get_array(meshPool, 'areaCell', areaCell) + allocate(pressureField(nCells+1)) + + waterPressureSmooth = waterPressure + pressureField = waterPressure + + do iter = 1, nTimesSmooth !May need to iterate to smooth properly + + do iCell = 1, nCells + if (li_mask_is_grounded_ice(cellMask(iCell))) then !smooth over all grounded cells + + totalPressure = pressureField(iCell)*areaCell(iCell) + totalArea = areaCell(iCell) + + do jEdge = 1, nEdgesOnCell(iCell) + iNeighbor = cellsOnCell(jEdge,iCell) + + if ((li_mask_is_grounded_ice(cellMask(iNeighbor)))) then !only include GROUNDED neighboring cells in smoothing + + totalPressure = totalPressure + pressureField(iNeighbor)*areaCell(iNeighbor) + + totalArea = totalArea + areaCell(iNeighbor) + endif + end do + + waterPressureSmooth(iCell) = totalPressure / totalArea !area-weighted average pressure + endif + end do + pressureField = waterPressureSmooth + end do + + deallocate(pressureField) + end subroutine calc_waterPressureSmooth end module li_subglacial_hydro diff --git a/components/mpas-albany-landice/src/mode_forward/mpas_li_thermal.F b/components/mpas-albany-landice/src/mode_forward/mpas_li_thermal.F index 4ef8ae672b8c..acc5048e3a4e 100644 --- a/components/mpas-albany-landice/src/mode_forward/mpas_li_thermal.F +++ b/components/mpas-albany-landice/src/mode_forward/mpas_li_thermal.F @@ -70,7 +70,7 @@ module li_thermal ! Note: kelvin_to_celsius = 273.15 (perhaps it should be called celsius_to_kelvin?) real (kind=RKIND), parameter :: & - maxtempThreshold = 100._RKIND + kelvin_to_celsius, & + maxtempThreshold = 1e-6_RKIND + kelvin_to_celsius, & mintempThreshold = -100._RKIND + kelvin_to_celsius !*********************************************************************** @@ -792,8 +792,9 @@ subroutine li_thermal_solver(domain, err) call mpas_pool_get_array(meshPool, 'deltat', deltat) if (deltat <= 0.0_RKIND) then + err = ior(err, 1) call mpas_log_write('li_thermal_solver was called with invalid deltat = $r', MPAS_LOG_ERR, realArgs=(/deltat/)) - call mpas_log_write("An error has occurred in li_thermal. Aborting...", MPAS_LOG_CRIT) + return endif @@ -1305,25 +1306,25 @@ subroutine li_thermal_solver(domain, err) mintemp = minval(temperature(:,iCell)) if (maxtemp > maxtempThreshold) then - call mpas_log_write('maxtemp > maxtempThreshold: indexToCellID=$i, maxtemp = $r', intArgs=(/indexToCellID(iCell)/), & + err = ior(err, 1) + call mpas_log_write('maxtemp > maxtempThreshold: indexToCellID=$i, maxtemp = $r', MPAS_LOG_ERR, intArgs=(/indexToCellID(iCell)/), & realArgs=(/maxtemp/)) - call mpas_log_write('thickness = $r', realArgs=(/thickness(iCell)/)) - call mpas_log_write('temperature:') + call mpas_log_write(' thickness = $r', MPAS_LOG_ERR, realArgs=(/thickness(iCell)/)) + call mpas_log_write(' temperature:', MPAS_LOG_ERR) do k = 1, nVertLevels - call mpas_log_write('$i $r', intArgs=(/k/), realArgs=(/temperature(k,iCell)/)) + call mpas_log_write(' $i $r', MPAS_LOG_ERR, intArgs=(/k/), realArgs=(/temperature(k,iCell)/)) enddo - call mpas_log_write("An error has occurred in li_thermal. Aborting...", MPAS_LOG_CRIT) endif if (mintemp < mintempThreshold) then - call mpas_log_write('mintemp < mintempThreshold: indexToCellID=$i, mintemp = $r', intArgs=(/indexToCellID(iCell)/), & + err = ior(err, 1) + call mpas_log_write('mintemp < mintempThreshold: indexToCellID=$i, mintemp = $r', MPAS_LOG_ERR, intArgs=(/indexToCellID(iCell)/), & realArgs=(/mintemp/)) - call mpas_log_write('thickness = $r', realArgs=(/thickness(iCell)/)) - call mpas_log_write('temperature:') + call mpas_log_write(' thickness = $r', MPAS_LOG_ERR, realArgs=(/thickness(iCell)/)) + call mpas_log_write(' temperature:', MPAS_LOG_ERR) do k = 1, nVertLevels - call mpas_log_write('$i $r', intArgs=(/k/), realArgs=(/temperature(k,iCell)/)) + call mpas_log_write(' $i $r', MPAS_LOG_ERR, intArgs=(/k/), realArgs=(/temperature(k,iCell)/)) enddo - call mpas_log_write("An error has occurred in li_thermal. Aborting...", MPAS_LOG_CRIT) endif enddo ! iCell @@ -2840,15 +2841,21 @@ subroutine basal_melt_grounded_ice(& ! to the form as Eqn (66) in Aschwanden and others (2012) "An ! enthalpy formulation for glaciers and ice sheets". An extra ! term (1-w) would be more accurate. - basalWaterThickness(iCell) = basalWaterThickness(iCell) - deltat*groundedBasalMassBal(iCell) - ! TZ: allow basalWaterThickness freely accumulate here. Change it to something else for difference cases - if (basalWaterThickness(iCell) < 0.0_RKIND) then - basalWaterThickness(iCell) = 0.0_RKIND - endif else ! temperature solver groundedBasalMassBal(iCell) = -netBasalFlux / (latent_heat_ice * rhoi) ! m/s endif + ! Update basal water thickness based on melting or freezing (same for enthalpy or temperature) + if (groundedBasalMassBal(iCell) > 0.0) then + ! for freezing conditions, limit positive BMB to the available basal water + groundedBasalMassBal(iCell) = min(groundedBasalMassBal(iCell), basalWaterThickness(iCell) / deltat) + endif + basalWaterThickness(iCell) = basalWaterThickness(iCell) - deltat*groundedBasalMassBal(iCell) + + ! negative water thickness should not occur, but if round off leads to it, set back to zero + if (basalWaterThickness(iCell) < 0.0_RKIND) then + basalWaterThickness(iCell) = 0.0_RKIND + endif endif ! ice is present and grounded diff --git a/components/mpas-albany-landice/src/mode_forward/mpas_li_time_integration_fe_rk.F b/components/mpas-albany-landice/src/mode_forward/mpas_li_time_integration_fe_rk.F index 6ca13f8deb0d..e4c58cc42b11 100644 --- a/components/mpas-albany-landice/src/mode_forward/mpas_li_time_integration_fe_rk.F +++ b/components/mpas-albany-landice/src/mode_forward/mpas_li_time_integration_fe_rk.F @@ -29,7 +29,9 @@ module li_time_integration_fe_rk use mpas_log use li_advection - use li_calving, only: li_calve_ice, li_restore_calving_front, li_calculate_damage, li_finalize_damage_after_advection + use li_calving, only: li_calve_ice, li_restore_calving_front, & + li_remove_icebergs, li_calculate_damage, & + li_finalize_damage_after_advection use li_thermal, only: li_thermal_solver, li_enthalpy_to_temperature_kelvin use li_iceshelf_melt use li_diagnostic_vars @@ -481,6 +483,11 @@ subroutine li_time_integrator_forwardeuler_rungekutta(domain, err) call li_restore_calving_front(domain, err_tmp) err = ior(err, err_tmp) endif + ! We need to remove icebergs between RK stages because the + ! main calving routine is not called until after the RK loop. + ! This frequently results in icebergs that causes intermediate + ! RK stage velocity solves to fail. + call li_remove_icebergs(domain) call li_velocity_solve(domain, solveVelo=.true., err=err_tmp) err = ior(err, err_tmp) diff --git a/components/mpas-albany-landice/src/shared/mpas_li_mask.F b/components/mpas-albany-landice/src/shared/mpas_li_mask.F index 673ed8186e47..64050cb83adf 100644 --- a/components/mpas-albany-landice/src/shared/mpas_li_mask.F +++ b/components/mpas-albany-landice/src/shared/mpas_li_mask.F @@ -45,6 +45,7 @@ module li_mask integer, parameter :: li_mask_ValueAlbanyMarginNeighbor = 128 ! This the first cell beyond the last active albany cell integer, parameter :: li_mask_ValueGroundingLine = 256 !< This is grounded cell that has a floating neighbor, or vertex/edge on that boundary + integer, parameter :: li_mask_ValueDomainBoundary = 512 !-------------------------------------------------------------------- ! @@ -143,7 +144,18 @@ module li_mask module procedure li_mask_is_grounding_line_logout_0d end interface - !-------------------------------------------------------------------- + + interface li_mask_is_boundary + module procedure li_mask_is_boundary_logout_1d + module procedure li_mask_is_boundary_logout_0d + end interface + + + interface li_mask_is_boundary_int + module procedure li_mask_is_boundary_intout_1d + module procedure li_mask_is_boundary_intout_0d + end interface +!-------------------------------------------------------------------- ! ! Private module variables ! @@ -294,10 +306,10 @@ subroutine li_calculate_mask(meshPool, velocityPool, geometryPool, err) logical :: isMargin logical :: isAlbanyMarginNeighbor logical :: aCellOnVertexHasIce, aCellOnVertexHasNoIce, aCellOnVertexHasDynamicIce, aCellOnVertexHasNoDynamicIce, & - aCellOnVertexIsFloating, aCellOnVertexIsFloatingAndDynamic, aCellOnVertexIsAlbanyActive + aCellOnVertexIsFloating, aCellOnVertexIsFloatingAndDynamic, aCellOnVertexIsAlbanyActive, aCellOnVertexIsDomainBoundary logical :: aCellOnVertexIsGrounded logical :: aCellOnEdgeHasIce, aCellOnEdgeHasNoIce, aCellOnEdgeHasDynamicIce, aCellOnEdgeHasNoDynamicIce, & - aCellOnEdgeIsFloating, aCellOnEdgeIsFloatingAndDynamic + aCellOnEdgeIsFloating, aCellOnEdgeIsFloatingAndDynamic, aCellOnEdgeIsDomainBoundary logical :: aCellOnEdgeIsGrounded logical :: aCellOnEdgeIsOpenOcean integer :: numCellsOnVertex @@ -473,6 +485,16 @@ subroutine li_calculate_mask(meshPool, velocityPool, geometryPool, err) endif enddo + !identify domain boundaries + do i=1,nCells + do j=1,nEdgesOnCell(i) + iCellNeighbor = cellsOnCell(j,i) + if (iCellNeighbor == nCells+1) then + cellMask(i) = ior(cellMask(i), li_mask_ValueDomainBoundary) + endif + enddo + enddo + !call mpas_timer_stop('calculate mask cell') ! ==== @@ -503,6 +525,7 @@ subroutine li_calculate_mask(meshPool, velocityPool, geometryPool, err) aCellOnVertexIsFloating = .false. aCellOnVertexIsGrounded = .false. aCellOnVertexIsFloatingAndDynamic = .false. + aCellOnVertexIsDomainBoundary = .false. do j = 1, vertexDegree ! vertexDegree is usually 3 (e.g. CVT mesh) but could be something else (e.g. 4 for quad mesh) iCell = cellsOnVertex(j,i) aCellOnVertexHasIce = (aCellOnVertexHasIce .or. li_mask_is_ice(cellMask(iCell))) @@ -514,7 +537,9 @@ subroutine li_calculate_mask(meshPool, velocityPool, geometryPool, err) (li_mask_is_floating_ice(cellMask(iCell)) .and. & li_mask_is_dynamic_ice(cellMask(iCell))) ) aCellOnVertexIsGrounded = (aCellOnVertexIsGrounded .or. li_mask_is_grounded_ice(cellMask(iCell))) + aCellOnVertexIsDomainBoundary = (aCellOnVertexIsDomainBoundary .or. li_mask_is_boundary(cellMask(iCell))) end do + if (aCellOnVertexHasIce) then vertexMask(i) = ior(vertexMask(i), li_mask_ValueIce) endif @@ -535,6 +560,9 @@ subroutine li_calculate_mask(meshPool, velocityPool, geometryPool, err) vertexMask(i) = ior(vertexMask(i), li_mask_ValueDynamicMargin) ! vertex with both 1+ dynamic ice cell(s) and 1+ non-dynamic cell(s) as neighbors endif + if (aCellOnVertexIsDomainBoundary) then + vertexMask(i) = ior(vertexMask(i), li_mask_ValueDomainBoundary) + endif end do @@ -607,6 +635,7 @@ subroutine li_calculate_mask(meshPool, velocityPool, geometryPool, err) aCellOnEdgeIsGrounded = .false. aCellOnEdgeIsOpenOcean = .false. aCellOnEdgeIsFloatingAndDynamic = .false. + aCellOnEdgeIsDomainBoundary = .false. do j = 1, 2 iCell = cellsOnEdge(j,i) aCellOnEdgeHasIce = (aCellOnEdgeHasIce .or. li_mask_is_ice(cellMask(iCell))) @@ -620,6 +649,7 @@ subroutine li_calculate_mask(meshPool, velocityPool, geometryPool, err) aCellOnEdgeIsGrounded = (aCellOnEdgeIsGrounded .or. li_mask_is_grounded_ice(cellMask(iCell))) aCellOnEdgeIsOpenOcean = aCellOnEdgeIsOpenOcean .or. & ((bedTopography(iCell) < config_sea_level) .and. (.not. li_mask_is_ice(cellMask(iCell)))) + aCellOnEdgeIsDomainBoundary = (aCellOnEdgeIsDomainBoundary .or. li_mask_is_boundary(cellMask(iCell))) end do if (aCellOnEdgeHasIce) then edgeMask(i) = ior(edgeMask(i), li_mask_ValueIce) @@ -641,6 +671,9 @@ subroutine li_calculate_mask(meshPool, velocityPool, geometryPool, err) if (aCellOnEdgeHasDynamicIce .and. aCellOnEdgeHasNoDynamicIce) then edgeMask(i) = ior(edgeMask(i), li_mask_ValueDynamicMargin) endif + if (aCellOnEdgeIsDomainBoundary) then + edgeMask(i) = ior(edgeMask(i), li_mask_ValueDomainBoundary) + endif end do !call mpas_timer_stop('calculate mask edge') @@ -905,8 +938,35 @@ function li_mask_is_initial_ice_logout_0d(mask) li_mask_is_initial_ice_logout_0d = (iand(mask, li_mask_ValueInitialIceExtent) == li_mask_ValueInitialIceExtent) end function li_mask_is_initial_ice_logout_0d + ! -- Functions that check for domain boundary -- + function li_mask_is_boundary_logout_1d(mask) + integer, dimension(:), intent(in) :: mask + logical, dimension(size(mask)) :: li_mask_is_boundary_logout_1d + + li_mask_is_boundary_logout_1d = (iand(mask, li_mask_ValueDomainBoundary) == li_mask_ValueDomainBoundary) + end function li_mask_is_boundary_logout_1d + + function li_mask_is_boundary_logout_0d(mask) + integer, intent(in) :: mask + logical :: li_mask_is_boundary_logout_0d + + li_mask_is_boundary_logout_0d = (iand(mask, li_mask_ValueDomainBoundary) == li_mask_ValueDomainBoundary) + end function li_mask_is_boundary_logout_0d + function li_mask_is_boundary_intout_1d(mask) + integer, dimension(:), intent(in) :: mask + integer, dimension(size(mask)) :: li_mask_is_boundary_intout_1d + + li_mask_is_boundary_intout_1d = iand(mask, li_mask_ValueDomainBoundary) / li_mask_ValueDomainBoundary + end function li_mask_is_boundary_intout_1d + + function li_mask_is_boundary_intout_0d(mask) + integer, intent(in) :: mask + integer :: li_mask_is_boundary_intout_0d + + li_mask_is_boundary_intout_0d = iand(mask, li_mask_ValueDomainBoundary) / li_mask_ValueDomainBoundary + end function li_mask_is_boundary_intout_0d !*********************************************************************** ! Private subroutines: !*********************************************************************** diff --git a/components/mpas-albany-landice/src/shared/mpas_li_setup.F b/components/mpas-albany-landice/src/shared/mpas_li_setup.F index e231b4733bbd..a77178001e3c 100644 --- a/components/mpas-albany-landice/src/shared/mpas_li_setup.F +++ b/components/mpas-albany-landice/src/shared/mpas_li_setup.F @@ -53,7 +53,8 @@ module li_setup li_interpolate_vertex_to_cell_2d, & li_cells_to_vertices_1dfield_using_kiteAreas, & li_calculate_layerThickness, & - li_compute_gradient_2d + li_compute_gradient_2d, & + li_init_barycentric_weights_vertex !-------------------------------------------------------------------- @@ -817,6 +818,109 @@ subroutine li_compute_gradient_2d(& end subroutine li_compute_gradient_2d +!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +! +! routine li_init_barycentric_weights_vertex +! +!> \brief compute barycentric weights for interpolating cells to vertices +!> \author Matt Hoffman +!> \date May 2023 +!> \details +!> This routine uses a framework routine to compute the barycentric +!> weights for interpolating from cells to vertices +! +!----------------------------------------------------------------------- + + subroutine li_init_barycentric_weights_vertex(block, err) + + use mpas_geometry_utils, only: mpas_calculate_barycentric_weights_for_points + + !----------------------------------------------------------------- + ! input variables + !----------------------------------------------------------------- + + !----------------------------------------------------------------- + ! input/output variables + !----------------------------------------------------------------- + type (block_type), intent(inout) :: & + block !< Input/Output: block object + + !----------------------------------------------------------------- + ! output variables + !----------------------------------------------------------------- + integer, intent(out) :: err !< Output: error flag + + !----------------------------------------------------------------- + ! local variables + !----------------------------------------------------------------- + type (mpas_pool_type), pointer :: meshPool + type (mpas_pool_type), pointer :: scratchPool + integer :: iCell, iLevel, i, iVertex, err_tmp + integer, pointer :: nVertices + character (len=StrKIND), pointer :: config_velocity_solver + character (len=StrKIND), pointer :: config_sia_tangent_slope_calculation + logical, pointer :: config_SGH + character (len=StrKIND), pointer :: config_SGH_tangent_slope_calculation + integer, dimension(:,:), pointer :: baryCellsOnVertex + real (kind=RKIND), dimension(:,:), pointer :: baryWeightsOnVertex + real (kind=RKIND), dimension(:), pointer :: xVertex, yVertex, zVertex + type (field1dInteger), pointer :: vertexIndicesField + + ! No block init needed. + err = 0 + err_tmp = 0 + + call mpas_pool_get_subpool(block % structs, 'mesh', meshPool) + call mpas_pool_get_subpool(block % structs, 'scratch', scratchPool) + call mpas_pool_get_array(meshPool, 'baryCellsOnVertex', baryCellsOnVertex) + call mpas_pool_get_array(meshPool, 'baryWeightsOnVertex', baryWeightsOnVertex) + call mpas_pool_get_array(meshPool, 'xVertex', xVertex) + call mpas_pool_get_array(meshPool, 'yVertex', yVertex) + call mpas_pool_get_array(meshPool, 'zVertex', zVertex) + call mpas_pool_get_config(liConfigs, 'config_velocity_solver', config_velocity_solver) + call mpas_pool_get_config(liConfigs, 'config_sia_tangent_slope_calculation', config_sia_tangent_slope_calculation) + call mpas_pool_get_config(liConfigs, 'config_SGH', config_SGH) + call mpas_pool_get_config(liConfigs, 'config_SGH_tangent_slope_calculation', config_SGH_tangent_slope_calculation) + call mpas_pool_get_field(scratchPool, 'vertexIndices', vertexIndicesField) + call mpas_pool_get_dimension(meshPool, 'nVertices', nVertices) + + if ( & + (trim(config_velocity_solver) == 'sia' .and. & + trim(config_sia_tangent_slope_calculation) == 'from_vertex_barycentric') & + .or. & + (config_SGH .and. trim(config_SGH_tangent_slope_calculation) == 'from_vertex_barycentric')) then + + call mpas_allocate_scratch_field(vertexIndicesField, .true.) + do iVertex = 1, nVertices + vertexIndicesField % array(iVertex) = iVertex + enddo + call mpas_calculate_barycentric_weights_for_points(meshPool, & + xVertex(1:nVertices), yVertex(1:nVertices), zVertex(1:nVertices), & + vertexIndicesField % array(1:nVertices), & + baryCellsOnVertex(:, 1:nVertices), baryWeightsOnVertex(:, 1:nVertices), err_tmp) + ! TODO: Until framework can handle periodic meshs gracefully, this will return an error + ! for periodic meshes. This error means that the velocity solver will be very wrong across + ! the periodicity, but it will be fine everywhere else. For now, just print a warning but + ! don't make this a fatal error. + !err = ior(err, err_tmp) + if (err_tmp > 0) then + call mpas_log_write("The 'from_vertex_barycentric' option for 'config_sia_tangent_slope_calculation' " & + // "'config_SGH_tangent_slope_calculation' " & + // "does NOT work across the periodicity in periodic meshes. However, it does work within the interior " & + // "of the mesh.", MPAS_LOG_WARN) + endif + call mpas_deallocate_scratch_field(vertexIndicesField, .true.) + + endif + + ! === error check + if (err > 0) then + call mpas_log_write("An error has occurred in li_init_barycentric_weights_vertex", MPAS_LOG_ERR) + endif + + end subroutine li_init_barycentric_weights_vertex + + !*********************************************************************** !*********************************************************************** ! Private subroutines: diff --git a/components/mpas-framework/src/framework/mpas_stream_manager.F b/components/mpas-framework/src/framework/mpas_stream_manager.F index 9f9b46adae54..fd393908a7de 100644 --- a/components/mpas-framework/src/framework/mpas_stream_manager.F +++ b/components/mpas-framework/src/framework/mpas_stream_manager.F @@ -146,7 +146,7 @@ end subroutine seed_random if (err_local /= MPAS_STREAM_LIST_NOERR) then if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR STREAM_ERROR_WRITE('Problems while creating stream list') - return + return end if ! @@ -156,7 +156,7 @@ end subroutine seed_random if (err_local /= MPAS_STREAM_LIST_NOERR) then if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR STREAM_ERROR_WRITE('Problems while creating input alarm list') - return + return end if ! @@ -166,7 +166,7 @@ end subroutine seed_random if (err_local /= MPAS_STREAM_LIST_NOERR) then if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR STREAM_ERROR_WRITE('Problems while creating output alarm list') - return + return end if ! @@ -204,7 +204,7 @@ subroutine MPAS_stream_mgr_finalize(manager, ierr)!{{{ threadNum = mpas_threading_get_thread_num() - STREAM_DEBUG_WRITE('-- Called MPAS_stream_mgr_finalize()') + STREAM_DEBUG_WRITE('-- Called MPAS_stream_mgr_finalize()') if (present(ierr)) ierr = MPAS_STREAM_MGR_NOERR @@ -264,16 +264,16 @@ end subroutine MPAS_stream_mgr_finalize!}}} !> \author Michael Duda, Doug Jacobsen !> \date 13 June 2014 !> \details - !> Creates a new stream within the stream manager. The "direction" - !> argument may be either MPAS_STREAM_INPUT, MPAS_STREAM_OUTPUT, - !> MPAS_STREAM_INPUT_OUTPUT, or MPAS_STREAM_NONE. The "filename" argument - !> is the template of the filenames that are associated with the stream. - !> Knowing the interval between files, and - !> the filename template, a "referenceTime" argument must be provided to - !> specify the first timestamp appearing in any of the files associated with - !> the stream, thereby determining where the "file breaks" will occur between - !> timestamps. If no "referenceTime" is specified, the start time of the - !> clock associated with the stream handler will be used as the reference + !> Creates a new stream within the stream manager. The "direction" + !> argument may be either MPAS_STREAM_INPUT, MPAS_STREAM_OUTPUT, + !> MPAS_STREAM_INPUT_OUTPUT, or MPAS_STREAM_NONE. The "filename" argument + !> is the template of the filenames that are associated with the stream. + !> Knowing the interval between files, and + !> the filename template, a "referenceTime" argument must be provided to + !> specify the first timestamp appearing in any of the files associated with + !> the stream, thereby determining where the "file breaks" will occur between + !> timestamps. If no "referenceTime" is specified, the start time of the + !> clock associated with the stream handler will be used as the reference !> time. Additionally, the interval between records in the file may be !> specified using the optional "recordInterval" argument; if this argument !> is not supplied, the stream manager will assume that this interval is @@ -284,8 +284,8 @@ end subroutine MPAS_stream_mgr_finalize!}}} !> MPAS_IO_DOUBLE_PRECISION, or MPAS_IO_NATIVE_PRECISION; if this argument is !> not supplied, native precision is assumed. !> The optional argument clobberMode determines how the stream manager will - !> deal with existing files; possible options include MPAS_STREAM_CLOBBER_NEVER, - !> MPAS_STREAM_CLOBBER_APPEND, MPAS_STREAM_CLOBBER_TRUNCATE, + !> deal with existing files; possible options include MPAS_STREAM_CLOBBER_NEVER, + !> MPAS_STREAM_CLOBBER_APPEND, MPAS_STREAM_CLOBBER_TRUNCATE, !> and MPAS_STREAM_CLOBBER_OVERWRITE. The default behavior is to never modify !> existing files (MPAS_STREAM_CLOBBER_NEVER). !> The optional argument ioType specifies the I/O type to use for the @@ -398,14 +398,14 @@ subroutine MPAS_stream_mgr_create_stream(manager, streamID, direction, filename, if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR STREAM_ERROR_WRITE('Problems while creating input alarm list') deallocate(new_stream) - return + return end if call MPAS_stream_list_create(new_stream % alarmList_out, ierr=err_local) if (err_local /= MPAS_STREAM_LIST_NOERR) then if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR STREAM_ERROR_WRITE('Problems while creating output alarm list') deallocate(new_stream) - return + return end if call mpas_pool_create_pool(new_stream % att_pool) call mpas_pool_clone_pool(manager % defaultAtts, new_stream % att_pool) @@ -424,7 +424,7 @@ subroutine MPAS_stream_mgr_create_stream(manager, streamID, direction, filename, STREAM_ERROR_WRITE('Problems while adding stream to list') return end if - + manager % numStreams = manager % numStreams + 1 end if @@ -635,7 +635,7 @@ subroutine MPAS_stream_mgr_destroy_stream(manager, streamID, ierr)!{{{ deallocate(stream % stream) end if deallocate(stream) - + manager % numStreams = manager % numStreams - 1 end if @@ -649,8 +649,8 @@ end subroutine MPAS_stream_mgr_destroy_stream!}}} !> \author Michael Duda !> \date 22 August 2014 !> \details - !> Returns a pointer to the clock associated with the stream manager, - !> in which any stream alarms should be defined before being added to + !> Returns a pointer to the clock associated with the stream manager, + !> in which any stream alarms should be defined before being added to !> the stream manager via the MPAS_stream_mgr_add_alarm() routine. ! !----------------------------------------------------------------------- @@ -1072,7 +1072,7 @@ end subroutine MPAS_stream_mgr_add_stream_fields!}}} ! !----------------------------------------------------------------------- subroutine MPAS_stream_mgr_remove_field(manager, streamID, fieldName, ierr)!{{{ - + implicit none character (len=*), parameter :: sub = 'MPAS_stream_mgr_remove_field' @@ -1232,7 +1232,7 @@ subroutine MPAS_stream_mgr_add_alarm(manager, streamID, alarmID, direction, ierr ! if ( threadNum == 0 ) then if (direction == MPAS_STREAM_INPUT .or. direction == MPAS_STREAM_INPUT_OUTPUT) then - + ! If alarm is not already defined, we need to create a new alarm node nullify(new_alarm) if (.not. MPAS_stream_list_query(manager % alarms_in, alarmID, new_alarm, ierr=err_local)) then @@ -1242,10 +1242,10 @@ subroutine MPAS_stream_mgr_add_alarm(manager, streamID, alarmID, direction, ierr if (err_local /= MPAS_STREAM_LIST_NOERR) then if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR STREAM_ERROR_WRITE('Problems while creating stream list for alarm') - return + return end if nullify(new_alarm % next) - + call MPAS_stream_list_insert(manager % alarms_in, new_alarm, ierr=err_local) if (err_local /= MPAS_STREAM_LIST_NOERR) then if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR @@ -1253,7 +1253,7 @@ subroutine MPAS_stream_mgr_add_alarm(manager, streamID, alarmID, direction, ierr return end if end if - + ! Add specified stream to alarm node stream list allocate(new_xref) new_xref % name = streamID @@ -1264,7 +1264,7 @@ subroutine MPAS_stream_mgr_add_alarm(manager, streamID, alarmID, direction, ierr STREAM_ERROR_WRITE('Problems while adding stream to alarm stream list') return end if - + ! Add alarm to stream alarm list allocate(new_xref) new_xref % name = alarmID @@ -1276,9 +1276,9 @@ subroutine MPAS_stream_mgr_add_alarm(manager, streamID, alarmID, direction, ierr return end if end if - + if (direction == MPAS_STREAM_OUTPUT .or. direction == MPAS_STREAM_INPUT_OUTPUT) then - + ! If alarm is not already defined, we need to create a new alarm node nullify(new_alarm) if (.not. MPAS_stream_list_query(manager % alarms_out, alarmID, new_alarm, ierr=err_local)) then @@ -1288,10 +1288,10 @@ subroutine MPAS_stream_mgr_add_alarm(manager, streamID, alarmID, direction, ierr if (err_local /= MPAS_STREAM_LIST_NOERR) then if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR STREAM_ERROR_WRITE('Problems while creating stream list for alarm') - return + return end if nullify(new_alarm % next) - + call MPAS_stream_list_insert(manager % alarms_out, new_alarm, ierr=err_local) if (err_local /= MPAS_STREAM_LIST_NOERR) then if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR @@ -1299,7 +1299,7 @@ subroutine MPAS_stream_mgr_add_alarm(manager, streamID, alarmID, direction, ierr return end if end if - + ! Add specified stream to alarm node stream list allocate(new_xref) new_xref % name = streamID @@ -1310,7 +1310,7 @@ subroutine MPAS_stream_mgr_add_alarm(manager, streamID, alarmID, direction, ierr STREAM_ERROR_WRITE('Problems while adding stream to alarm stream list') return end if - + ! Add alarm to stream alarm list allocate(new_xref) new_xref % name = alarmID @@ -1399,7 +1399,7 @@ subroutine MPAS_stream_mgr_remove_alarm(manager, streamID, alarmID, direction, i STREAM_ERROR_WRITE('Output alarm '//trim(alarmID)//' does not exist on stream '//trim(streamID)) end if return - end if + end if if (.not. associated(streamNode)) then if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR STREAM_ERROR_WRITE('Alarm '//trim(alarmID)//' does not have stream '//trim(streamID)//' on its stream list.') @@ -1433,7 +1433,7 @@ end subroutine MPAS_stream_mgr_remove_alarm!}}} !> Resets all alarms used by the stream manager. If the optional argument !> 'streamID' is provided, only alarms associated with streams that match !> the 'streamID' regular expression will be - !> reset. If the optional 'direction' argument is provided, only alarms + !> reset. If the optional 'direction' argument is provided, only alarms !> associated with that direction will be reset. ! !----------------------------------------------------------------------- @@ -1453,7 +1453,7 @@ subroutine MPAS_stream_mgr_reset_alarms(manager, streamID, direction, ierr)!{{{ logical :: resetAlarms threadNum = mpas_threading_get_thread_num() - + if (present(streamID)) then STREAM_DEBUG_WRITE('-- Called MPAS_stream_mgr_reset_alarms() for stream ' // trim(streamID)) else @@ -1486,7 +1486,7 @@ subroutine MPAS_stream_mgr_reset_alarms(manager, streamID, direction, ierr)!{{{ alarm_cursor => stream % alarmList_in % head do while (associated(alarm_cursor)) if (mpas_is_alarm_ringing(manager % streamClock, alarm_cursor % name, ierr=local_ierr)) then - call mpas_reset_clock_alarm(manager % streamClock, alarm_cursor % name, ierr=local_ierr) + call mpas_reset_clock_alarm(manager % streamClock, alarm_cursor % name, ierr=local_ierr) end if alarm_cursor => alarm_cursor % next end do @@ -1496,7 +1496,7 @@ subroutine MPAS_stream_mgr_reset_alarms(manager, streamID, direction, ierr)!{{{ alarm_cursor => stream % alarmList_out % head do while (associated(alarm_cursor)) if (mpas_is_alarm_ringing(manager % streamClock, alarm_cursor % name, ierr=local_ierr)) then - call mpas_reset_clock_alarm(manager % streamClock, alarm_cursor % name, ierr=local_ierr) + call mpas_reset_clock_alarm(manager % streamClock, alarm_cursor % name, ierr=local_ierr) end if alarm_cursor => alarm_cursor % next end do @@ -1514,7 +1514,7 @@ subroutine MPAS_stream_mgr_reset_alarms(manager, streamID, direction, ierr)!{{{ alarm_cursor => manager % alarms_in % head do while (associated(alarm_cursor)) if (mpas_is_alarm_ringing(manager % streamClock, alarm_cursor % name, ierr=local_ierr)) then - call mpas_reset_clock_alarm(manager % streamClock, alarm_cursor % name, ierr=local_ierr) + call mpas_reset_clock_alarm(manager % streamClock, alarm_cursor % name, ierr=local_ierr) end if alarm_cursor => alarm_cursor % next end do @@ -1525,7 +1525,7 @@ subroutine MPAS_stream_mgr_reset_alarms(manager, streamID, direction, ierr)!{{{ alarm_cursor => manager % alarms_out % head do while (associated(alarm_cursor)) if (mpas_is_alarm_ringing(manager % streamClock, alarm_cursor % name, ierr=local_ierr)) then - call mpas_reset_clock_alarm(manager % streamClock, alarm_cursor % name, ierr=local_ierr) + call mpas_reset_clock_alarm(manager % streamClock, alarm_cursor % name, ierr=local_ierr) end if alarm_cursor => alarm_cursor % next end do @@ -1543,10 +1543,10 @@ end subroutine MPAS_stream_mgr_reset_alarms!}}} !> \author Michael Duda !> \date 30 September 2014 !> \details - !> Tests whether any I/O alarms in a stream manager are ringing; if the optional - !> 'streamID' argument is given, only alarms for that stream are tested; if - !> the optional argument 'direction' is given, only alarms for the specified - !> direction are tested. If any of the tested alarms is ringing, the function + !> Tests whether any I/O alarms in a stream manager are ringing; if the optional + !> 'streamID' argument is given, only alarms for that stream are tested; if + !> the optional argument 'direction' is given, only alarms for the specified + !> direction are tested. If any of the tested alarms is ringing, the function !> returns .true.; otherwise, it returns .false.. !> Note: This function doesn't support streamID regular expressions ! @@ -1566,7 +1566,7 @@ logical function MPAS_stream_mgr_ringing_alarms(manager, streamID, direction, ie integer :: local_ierr, threadNum threadNum = mpas_threading_get_thread_num() - + STREAM_DEBUG_WRITE('-- Called MPAS_stream_mgr_ringing_alarms()') MPAS_stream_mgr_ringing_alarms = .false. @@ -1784,7 +1784,7 @@ subroutine MPAS_stream_mgr_set_property_int(manager, streamID, propertyName, pro if ( .not. setProperties ) then STREAM_ERROR_WRITE('No stream matching '//trim(streamID)//' exists in call to MPAS_stream_mgr_set_property().') if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR - return + return end if @@ -1848,7 +1848,7 @@ subroutine MPAS_stream_mgr_set_property_char(manager, streamID, propertyName, pr call mpas_set_time(stream_cursor % referenceTime, dateTimeString=propertyValue) case (MPAS_STREAM_PROPERTY_RECORD_INTV) - + ! The interval between records may not have been allocated if the optional recordInterval ! argument was not provided when the stream was created if (.not. associated(stream_cursor % recordInterval)) then @@ -1869,7 +1869,7 @@ subroutine MPAS_stream_mgr_set_property_char(manager, streamID, propertyName, pr if ( .not. setProperties ) then STREAM_ERROR_WRITE('No stream matching '//trim(streamID)//' exists in call to MPAS_stream_mgr_set_property().') if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR - return + return end if @@ -1945,7 +1945,7 @@ subroutine MPAS_stream_mgr_set_property_logical(manager, streamID, propertyName, if ( .not. setProperties ) then STREAM_ERROR_WRITE('No stream matching '//trim(streamID)//' exists in call to MPAS_stream_mgr_set_property().') if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR - return + return end if @@ -1990,7 +1990,7 @@ subroutine MPAS_stream_mgr_get_property_int(manager, streamID, propertyName, pro if (.not. MPAS_stream_list_query(manager % streams, streamID, stream_cursor, ierr=err_local)) then STREAM_ERROR_WRITE('Stream '//trim(streamID)//' does not exist in call to MPAS_stream_mgr_get_property().') if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR - return + return end if ! @@ -2057,7 +2057,7 @@ subroutine MPAS_stream_mgr_get_property_char(manager, streamID, propertyName, pr if (.not. MPAS_stream_list_query(manager % streams, streamID, stream_cursor, ierr=err_local)) then STREAM_ERROR_WRITE('Stream '//trim(streamID)//' does not exist in call to MPAS_stream_mgr_get_property().') if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR - return + return end if ! @@ -2081,9 +2081,9 @@ subroutine MPAS_stream_mgr_get_property_char(manager, streamID, propertyName, pr ! assume that the interval is the shortest interval between alarms on the stream; since ! recordInterval is only used for reading, use the input alarm list in this check. if (.not. associated(stream_cursor % recordInterval)) then - + ! - ! If no direction is specified, return the read interval, since this was the only historic + ! If no direction is specified, return the read interval, since this was the only historic ! use of the recordInterval for a stream. ! if (present(direction)) then @@ -2164,7 +2164,7 @@ subroutine MPAS_stream_mgr_get_property_logical(manager, streamID, propertyName, if (.not. MPAS_stream_list_query(manager % streams, streamID, stream_cursor, ierr=err_local)) then STREAM_ERROR_WRITE('Stream '//trim(streamID)//' does not exist in call to MPAS_stream_mgr_get_property().') if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR - return + return end if ! @@ -2245,14 +2245,14 @@ subroutine MPAS_stream_mgr_add_pkg(manager, streamID, packageName, ierr)!{{{ ! ! Add package to the packages pool for the stream ! - call mpas_pool_add_package(stream_cursor % pkg_pool, packageName, package) + call mpas_pool_add_package(stream_cursor % pkg_pool, packageName, package) end do if ( .not. addedPackages ) then STREAM_ERROR_WRITE('No stream matching '//trim(streamID)//' exists in call to MPAS_stream_mgr_add_pkg().') if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR - return + return end if @@ -2310,7 +2310,7 @@ subroutine MPAS_stream_mgr_remove_pkg(manager, streamID, packageName, ierr)!{{{ if ( .not. removedPackage ) then STREAM_ERROR_WRITE('No stream matching '//trim(streamID)//' exists in call to MPAS_stream_mgr_remove_pkg().') if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR - return + return end if @@ -2374,7 +2374,7 @@ subroutine MPAS_stream_mgr_add_att_int(manager, attName, attVal, streamID, ierr) if (mpas_pool_config_type(att_pool, attName) /= MPAS_POOL_FATAL) then STREAM_ERROR_WRITE('Attribute '//trim(attName)//' in stream '//trim(stream_cursor % name)//' is not of type integer.') if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR - return + return end if call mpas_pool_add_config(att_pool, attName, attVal) else @@ -2385,7 +2385,7 @@ subroutine MPAS_stream_mgr_add_att_int(manager, attName, attVal, streamID, ierr) if ( .not. addedAttribute ) then STREAM_ERROR_WRITE('No stream matching '//trim(streamID)//' exists in call to MPAS_stream_mgr_add_att().') if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR - return + return end if else @@ -2403,7 +2403,7 @@ subroutine MPAS_stream_mgr_add_att_int(manager, attName, attVal, streamID, ierr) if (mpas_pool_config_type(att_pool, attName) /= MPAS_POOL_FATAL) then STREAM_ERROR_WRITE('Attribute '//trim(attName)//' in streamManager is not of type integer.') if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR - return + return end if call mpas_pool_add_config(att_pool, attName, attVal) else @@ -2473,7 +2473,7 @@ subroutine MPAS_stream_mgr_add_att_real(manager, attName, attVal, streamID, ierr if (mpas_pool_config_type(att_pool, attName) /= MPAS_POOL_FATAL) then STREAM_ERROR_WRITE('Attribute '//trim(attName)//' in stream '//trim(stream_cursor % name)//' is not of type real.') if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR - return + return end if call mpas_pool_add_config(att_pool, attName, attVal) else @@ -2484,7 +2484,7 @@ subroutine MPAS_stream_mgr_add_att_real(manager, attName, attVal, streamID, ierr if ( .not. addedAttribute ) then STREAM_ERROR_WRITE('No stream matching '//trim(streamID)//' exists in call to MPAS_stream_mgr_add_att().') if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR - return + return end if else @@ -2503,7 +2503,7 @@ subroutine MPAS_stream_mgr_add_att_real(manager, attName, attVal, streamID, ierr if (mpas_pool_config_type(att_pool, attName) /= MPAS_POOL_FATAL) then STREAM_ERROR_WRITE('Attribute '//trim(attName)//' in streamManager is not of type real.') if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR - return + return end if call mpas_pool_add_config(att_pool, attName, attVal) else @@ -2573,7 +2573,7 @@ subroutine MPAS_stream_mgr_add_att_char(manager, attName, attVal, streamID, ierr if (mpas_pool_config_type(att_pool, attName) /= MPAS_POOL_FATAL) then STREAM_ERROR_WRITE('Attribute '//trim(attName)//' in stream '//trim(stream_cursor % name)//' is not of type character.') if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR - return + return end if call mpas_pool_add_config(att_pool, attName, attVal) else @@ -2584,7 +2584,7 @@ subroutine MPAS_stream_mgr_add_att_char(manager, attName, attVal, streamID, ierr if ( .not. addedAttribute ) then STREAM_ERROR_WRITE('No stream matching '//trim(streamID)//' exists in call to MPAS_stream_mgr_add_att().') if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR - return + return end if else @@ -2603,7 +2603,7 @@ subroutine MPAS_stream_mgr_add_att_char(manager, attName, attVal, streamID, ierr if (mpas_pool_config_type(att_pool, attName) /= MPAS_POOL_FATAL) then STREAM_ERROR_WRITE('Attribute '//trim(attName)//' in streamManager is not of type character.') if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR - return + return end if call mpas_pool_add_config(att_pool, attName, attVal) else @@ -2673,7 +2673,7 @@ subroutine MPAS_stream_mgr_add_att_logical(manager, attName, attVal, streamID, i if (mpas_pool_config_type(att_pool, attName) /= MPAS_POOL_FATAL) then STREAM_ERROR_WRITE('Attribute '//trim(attName)//' in stream '//trim(stream_cursor % name)//' is not of type logical.') if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR - return + return end if call mpas_pool_add_config(att_pool, attName, attVal) else @@ -2684,7 +2684,7 @@ subroutine MPAS_stream_mgr_add_att_logical(manager, attName, attVal, streamID, i if ( .not. addedAttribute ) then STREAM_ERROR_WRITE('No stream matching '//trim(streamID)//' exists in call to MPAS_stream_mgr_add_att().') if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR - return + return end if else @@ -2703,7 +2703,7 @@ subroutine MPAS_stream_mgr_add_att_logical(manager, attName, attVal, streamID, i if (mpas_pool_config_type(att_pool, attName) /= MPAS_POOL_FATAL) then STREAM_ERROR_WRITE('Attribute '//trim(attName)//' in streamManger is not of type logical.') if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR - return + return end if call mpas_pool_add_config(att_pool, attName, attVal) else @@ -2727,11 +2727,11 @@ end subroutine MPAS_stream_mgr_add_att_logical!}}} !> stream is only written if any of its alarms are ringing. !> The "timeLevel" argument optionally specifies, for fields with multiple !> time levels, the time level from which fields should be written. - !> The "mgLevel" argument optionally specifies, for fields that exist for + !> The "mgLevel" argument optionally specifies, for fields that exist for !> multiple grid levels, the grid level from which fields should be written. - !> The "forceWriteNow" argument optionally specifies that all streams -- or - !> the stream specified by the "streamID" argument -- should be written by - !> the call regardless of whether any alarms associated with the stream(s) + !> The "forceWriteNow" argument optionally specifies that all streams -- or + !> the stream specified by the "streamID" argument -- should be written by + !> the call regardless of whether any alarms associated with the stream(s) !> are ringing. The "writeTime" argument optionally specifies a time stamp !> to be used for expanding a filename template, when it is not passed in, !> the current time of the streamManager's clock is used to expand filename @@ -2824,7 +2824,7 @@ subroutine MPAS_stream_mgr_write(manager, streamID, timeLevel, mgLevel, forceWri if ( .not. wroteStreams ) then STREAM_ERROR_WRITE('No output stream matching '//trim(streamID)//' exists in call to MPAS_stream_mgr_write().') if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR - return + return end if else nullify(stream_cursor) @@ -2872,11 +2872,11 @@ end subroutine MPAS_stream_mgr_write !}}} !> stream is only written if any of its alarms are ringing. !> The "timeLevel" argument optionally specifies, for fields with multiple !> time levels, the time level from which fields should be written. - !> The "mgLevel" argument optionally specifies, for fields that exist for + !> The "mgLevel" argument optionally specifies, for fields that exist for !> multiple grid levels, the grid level from which fields should be written. - !> The "forceWriteNow" argument optionally specifies that all streams -- or - !> the stream specified by the "streamID" argument -- should be written by - !> the call regardless of whether any alarms associated with the stream(s) + !> The "forceWriteNow" argument optionally specifies that all streams -- or + !> the stream specified by the "streamID" argument -- should be written by + !> the call regardless of whether any alarms associated with the stream(s) !> are ringing. The "writeTime" argument optionally specifies a time stamp !> to be used for expanding a filename template, when it is not passed in, !> the current time of the streamManager's clock is used to expand filename @@ -3006,7 +3006,7 @@ subroutine MPAS_stream_mgr_block_write(manager, writeBlock, streamID, timeLevel, if ( .not. wroteStreams ) then STREAM_ERROR_WRITE('No output stream matching '//trim(streamID)//' exists in call to MPAS_stream_mgr_block_write().') if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR - return + return end if else nullify(stream_cursor) @@ -3048,7 +3048,7 @@ subroutine MPAS_stream_mgr_block_write(manager, writeBlock, streamID, timeLevel, call mpas_dmpar_finalize(debugContext % dminfo) deallocate(debugContext % dminfo) - deallocate(debugContext) + deallocate(debugContext) end if call mpas_threading_barrier() @@ -3180,7 +3180,7 @@ subroutine write_stream(manager, stream, blockID, timeLevel, mgLevel, forceWrite ! Based on clobber_mode, determine if it matters if the file exists or not. if ( stream % clobber_mode == MPAS_STREAM_CLOBBER_OVERWRITE .or. stream % clobber_mode == MPAS_STREAM_CLOBBER_APPEND ) then STREAM_DEBUG_WRITE(' -- Cobber mode is overwrite or append...') - + ! Check if the file exists if (manager % ioContext % dminfo % my_proc_id == IO_NODE) then inquire(file=trim(stream % filename), exist=recordSeek) @@ -3217,12 +3217,12 @@ subroutine write_stream(manager, stream, blockID, timeLevel, mgLevel, forceWrite if ( recordSeek ) then STREAM_DEBUG_WRITE(' -- File exists on disk: ' // trim(stream % filename)) call mpas_get_time(writeTime, dateTimeString=now_string) - + ! Look for exact record (in the case of overwriting) ! This also gets the number of records in the file. stream % nRecords = MPAS_seekStream(stream % stream, now_string, MPAS_STREAM_EXACT_TIME, actualWhen, maxRecords, local_ierr) STREAM_DEBUG_WRITE(' -- Seeked record is: $i with current records equal to $i and an error of $i' COMMA intArgs=(/stream % nRecords COMMA maxRecords COMMA local_ierr/)) - + if ( stream % nRecords == 0 ) then ! If we didn't find an exact time, set record to point to the end of the file. ! This might result in non-monotonic timestamps in the output file. @@ -3266,7 +3266,7 @@ subroutine write_stream(manager, stream, blockID, timeLevel, mgLevel, forceWrite ! Based on clobber_mode, determine if it matters if the file exists or not. if ( stream % clobber_mode == MPAS_STREAM_CLOBBER_OVERWRITE .or. stream % clobber_mode == MPAS_STREAM_CLOBBER_APPEND ) then STREAM_DEBUG_WRITE(' -- Cobber mode is overwrite or append...') - + ! Check if the file exists if (manager % ioContext % dminfo % my_proc_id == IO_NODE) then inquire(file=trim(stream % filename), exist=recordSeek) @@ -3305,12 +3305,12 @@ subroutine write_stream(manager, stream, blockID, timeLevel, mgLevel, forceWrite if ( recordSeek ) then STREAM_DEBUG_WRITE(' -- File exists on disk: ' // trim(stream % filename)) call mpas_get_time(writeTime, dateTimeString=now_string) - + ! Look for exact record (in the case of overwriting) ! This also gets the number of records in the file. stream % nRecords = MPAS_seekStream(stream % stream, now_string, MPAS_STREAM_EXACT_TIME, actualWhen, maxRecords, local_ierr) STREAM_DEBUG_WRITE(' -- Seeked record is: $i with current records equal to $i and an error of $i' COMMA intArgs=(/stream % nRecords COMMA maxRecords COMMA local_ierr/)) - + if ( stream % nRecords == 0 ) then ! If we didn't find an exact time, set record to point to the end of the file. ! This might result in non-monotonic timestamps in the output file. @@ -3330,12 +3330,12 @@ subroutine write_stream(manager, stream, blockID, timeLevel, mgLevel, forceWrite stream % nRecords = stream % nRecords + 1 if ( stream % clobber_mode == MPAS_STREAM_CLOBBER_OVERWRITE .or. stream % clobber_mode == MPAS_STREAM_CLOBBER_APPEND ) then call mpas_get_time(writeTime, dateTimeString=now_string) - + ! Look for exact record (in the case of overwriting) ! This also gets the number of records in the file. tempRecord = MPAS_seekStream(stream % stream, now_string, MPAS_STREAM_EXACT_TIME, actualWhen, maxRecords, local_ierr) STREAM_DEBUG_WRITE(' -- Seeked record is: $i with current records equal to $i and an error of $i' COMMA intArgs=(/tempRecord COMMA maxRecords COMMA local_ierr/)) - + if ( tempRecord /= 0 .and. stream % nRecords < maxRecords ) then ! If we found an exact result ! This might result in non-monotonic timestamps in the output file. @@ -3375,9 +3375,9 @@ subroutine write_stream(manager, stream, blockID, timeLevel, mgLevel, forceWrite call prewrite_reindex(manager % allFields, stream % field_pool) end if - ! + ! ! Write the stream - ! + ! STREAM_DEBUG_WRITE(' -- Writing stream ' // trim(stream % name)) call MPAS_writeStream(stream % stream, stream % nRecords, & useMissingValMask, ierr=local_ierr) @@ -3398,10 +3398,9 @@ subroutine write_stream(manager, stream, blockID, timeLevel, mgLevel, forceWrite ! write(err_string,'(a,i4,a)') 'Writing to stream '''//trim(stream % name)//''' would overwrite record ', & stream % nRecords, ' in file '''//trim(stream % filename)//''',' - STREAM_ERROR_WRITE(trim(err_string)) + STREAM_WARNING_WRITE(trim(err_string)) write(err_string,'(a)') ' but clobber_mode is set to ''append''.' - STREAM_ERROR_WRITE(trim(err_string)) - ierr = MPAS_STREAM_MGR_ERR_CLOBBER_REC + STREAM_WARNING_WRITE(trim(err_string)) else ierr = MPAS_STREAM_MGR_ERROR end if @@ -3433,16 +3432,16 @@ end subroutine write_stream !}}} !> is only read if any of its alarms are ringing. !> The "timeLevel" argument optionally specifies, for fields with multiple !> time levels, the time level into which fields should be read. - !> The "mgLevel" argument optionally specifies, for fields that exist for + !> The "mgLevel" argument optionally specifies, for fields that exist for !> multiple grid levels, the grid level into which fields should be read. !> The "when" argument optionally specifies the timestamp from which fields !> are to be read. !> The "whence" argument optionally specifies the method for determining !> the timestamp to read from in case an exact match is not found for the !> read timestamp, which is the current time unless the optional "when" - !> argument is given; possible values are MPAS_STREAM_EXACT_TIME, - !> MPAS_STREAM_NEAREST, MPAS_STREAM_LATEST_BEFORE, - !> MPAS_STREAM_LATEST_STRICTLY_BEFORE, MPAS_STREAM_EARLIEST_AFTER, or + !> argument is given; possible values are MPAS_STREAM_EXACT_TIME, + !> MPAS_STREAM_NEAREST, MPAS_STREAM_LATEST_BEFORE, + !> MPAS_STREAM_LATEST_STRICTLY_BEFORE, MPAS_STREAM_EARLIEST_AFTER, or !> MPAS_STREAM_EARLIEST_STRICTLY_AFTER. !> The optional output argument "saveActualWhen" will save the actual time read !> from a stream in case an exact match for the "when" time is not found, @@ -3484,7 +3483,7 @@ subroutine MPAS_stream_mgr_read(manager, streamID, timeLevel, mgLevel, rightNow, integer :: local_whence integer :: local_ierr integer :: temp_ierr - type (MPAS_Time_type) :: now_time + type (MPAS_Time_type) :: now_time character (len=StrKIND) :: actualWhen_local logical :: local_saveActualWhen logical :: local_readInputOutputStreams @@ -3555,7 +3554,7 @@ subroutine MPAS_stream_mgr_read(manager, streamID, timeLevel, mgLevel, rightNow, nullify(stream_cursor) do while (MPAS_stream_list_query(manager % streams, streamID, stream_cursor, ierr=ierr)) STREAM_DEBUG_WRITE('-- Handling read of stream '//trim(stream_cursor % name)) - + ! Verify that the stream is an input stream if (local_readInputOutputStreams) then if (stream_cursor % direction == MPAS_STREAM_INPUT .or. stream_cursor % direction == MPAS_STREAM_INPUT_OUTPUT) then @@ -3590,7 +3589,7 @@ subroutine MPAS_stream_mgr_read(manager, streamID, timeLevel, mgLevel, rightNow, STREAM_ERROR_WRITE(' strictly INPUT direction were requested by this call.') endif if (present(ierr)) ierr = MPAS_STREAM_MGR_ERROR - return + return end if else ! try to read any stream of input direction nullify(stream_cursor) @@ -3631,7 +3630,7 @@ subroutine MPAS_stream_mgr_read(manager, streamID, timeLevel, mgLevel, rightNow, local_ierr = MPAS_STREAM_MGR_ERROR end if end if - + stream_cursor => stream_cursor % next end do end if @@ -3747,7 +3746,7 @@ subroutine read_stream(manager, stream, timeLevel, mgLevel, forceReadNow, when, if ( stream % filename_interval /= 'none' ) then call mpas_set_time(now_time, dateTimeString=when, ierr=local_ierr) call mpas_set_timeInterval(filename_interval, timeString=stream % filename_interval) - + call mpas_build_stream_filename(stream % referenceTime, now_time, filename_interval, stream % filename_template, blockID_local, temp_filename, ierr=local_ierr) else call mpas_expand_string(when, blockID_local, stream % filename_template, temp_filename) @@ -3916,7 +3915,7 @@ subroutine read_stream(manager, stream, timeLevel, mgLevel, forceReadNow, when, call mpas_get_time(filenameTime, dateTimeString=test_when) call mpas_set_timeInterval(filename_interval, timeString=stream % filename_interval) - + call mpas_build_stream_filename(stream % referenceTime, filenameTime, filename_interval, stream % filename_template, blockID_local, test_filename, ierr=local_ierr) STREAM_DEBUG_WRITE(' --- Retesting filename is ' // trim(test_filename)) @@ -4031,9 +4030,9 @@ subroutine read_stream(manager, stream, timeLevel, mgLevel, forceReadNow, when, stream % timeLevel = timeLevel end if - ! + ! ! Read the stream - ! + ! call MPAS_readStream(stream % stream, stream % nRecords, ierr=local_ierr) if (local_ierr /= MPAS_STREAM_NOERR) then ierr = MPAS_STREAM_MGR_ERROR @@ -4068,13 +4067,13 @@ end subroutine read_stream !}}} !----------------------------------------------------------------------- ! routine MPAS_stream_mesg ! - !> \brief Write an error message (if the level requires it) to + !> \brief Write an error message (if the level requires it) to !> \author Michael Duda, Doug Jacobsen !> \date 07/16/2014 - !> \details Using the input error level, + !> \details Using the input error level, !----------------------------------------------------------------------- subroutine MPAS_stream_mesg(level, mesg)!{{{ - + use mpas_dmpar implicit none @@ -4171,7 +4170,7 @@ end subroutine mpas_get_stream_filename !}}} !> \brief Construct the filename that contains a specific time in a stream !> \author Michael Duda, Doug Jacobsen !> \date 21 August 2014 - !> \details + !> \details !> Given a filename template and the information necessary to determine the time !> in the stream that matches a time available in any of the files associated with !> the stream, returns a specific filename that should contain that time. @@ -4182,7 +4181,7 @@ end subroutine mpas_get_stream_filename !}}} !> !> This is a low level subroutine to complement the !> mpas_get_stream_Filename routine - !> + !> !> Return error codes: !> 0 no error !----------------------------------------------------------------------- @@ -4229,7 +4228,7 @@ subroutine mpas_build_stream_filename(ref_time, when, filename_interval, filenam call mpas_get_timeInterval(intv, timeString=temp_string) STREAM_DEBUG_WRITE(' ** intv is: ' // trim(temp_string)) - call mpas_interval_division(ref_time, intv, filename_interval, nrecs, rem) + call mpas_interval_division(ref_time, intv, filename_interval, nrecs, rem) ! STREAM_DEBUG_WRITE(' ** Divisions are: $i' COMMA intArgs=(/nrecs/)) @@ -4260,7 +4259,7 @@ end subroutine mpas_build_stream_filename !}}} !> \brief This is a utility routine to build a stream type from a pool representing a stream. !> \author Michael Duda, Doug Jacobsen !> \date 07/23/2014 - !> \details + !> \details !> This routine will take as input a pool representing a stream. !> It will then generate a stream type based on this pool, and return that. !----------------------------------------------------------------------- @@ -4465,8 +4464,8 @@ end subroutine build_stream !}}} !> \brief Updates the time level for fields in a stream !> \author Michael Duda, Doug Jacobsen !> \date 07/23/2014 - !> \details - !> For an existing stream, updates the time levels for all fields in + !> \details + !> For an existing stream, updates the time levels for all fields in !> the stream so that subsequent reads/writes of the stream will read !> from / write to the specified time level. !----------------------------------------------------------------------- @@ -4581,7 +4580,7 @@ end subroutine update_stream !}}} !> \brief Checks whether a stream has any active packages (or none at all) !> \author Michael Duda !> \date 23 September 2014 - !> \details + !> \details !> This function determines whether a stream has any active packages !> associated with it. If the stream has at least one active package, !> or no packages at all, the function returns true; else, if all packages @@ -4630,32 +4629,32 @@ end function stream_active_pkg_check !}}} !> \brief Parses a semi-colon-separated list of package names, indicating whether any are active !> \author Michael Duda !> \date 19 March 2015 - !> \details - !> This function determines whether any of the named strings in + !> \details + !> This function determines whether any of the named strings in !> the semi-colon-separated list provided in the 'packages' argument are - !> active. + !> active. !> If any of the packages does not exist in the package pool, the optional - !> argument ierr is set to a non-zero value; otherwise, if all packages exist, + !> argument ierr is set to a non-zero value; otherwise, if all packages exist, !> ierr will be set to zero upon return. ! !----------------------------------------------------------------------- logical function parse_package_list(package_pool, packages, ierr) result(active) - + implicit none - + type (mpas_pool_type), intent(in) :: package_pool character (len=*), intent(in) :: packages integer, intent(out), optional :: ierr - + integer :: i, j, slen integer :: err_level logical, pointer :: pkg_val - - + + if (present(ierr)) ierr = 0 - + slen = len_trim(packages) - + ! ! No packages @@ -4664,7 +4663,7 @@ logical function parse_package_list(package_pool, packages, ierr) result(active) active = .true. return end if - + active = .false. err_level = mpas_pool_get_error_level() @@ -4870,8 +4869,8 @@ end subroutine exch_all_halos !}}} !> \brief Determines whether a dimension represents a decomposed dimension or not !> \author Michael Duda !> \date 24 September 2014 - !> \details - !> This function determines whether the name of the input argument is + !> \details + !> This function determines whether the name of the input argument is !> a decompsed dimension or not. Currently in MPAS, the only decomposed !> dimensions are: !> nCells @@ -4906,8 +4905,8 @@ end function is_decomposed_dim !}}} !> \brief Reindex connectivity fields from local to global index space. !> \author Doug Jacobsen, Michael Duda !> \date 24 September 2014 - !> \details - !> For any connectivity fields contained in the stream to be written, + !> \details + !> For any connectivity fields contained in the stream to be written, !> whose fields include those in the streamFields pool, save the locally !> indexed fields in module variables *_save, and allocate new arrays for !> the fields, which are set to contain global indices. @@ -5203,12 +5202,12 @@ end subroutine prewrite_reindex !}}} !> \brief Reindex connectivity fields from global to local index space. !> \author Doug Jacobsen, Michael Duda !> \date 24 September 2014 - !> \details - !> For any connectivity fields contained in the stream to be written, + !> \details + !> For any connectivity fields contained in the stream to be written, !> whose fields include those in the streamFields pool, restore the locally !> indexed fields from module variables *_save. !> This routine should be called immediately after a write of a stream. - !> + !> !> NB: Even if the write of a stream fails, it is important to stil call !> this routine to reset the connectivity fields to contain local indices. ! @@ -5247,35 +5246,35 @@ subroutine postwrite_reindex(allFields, streamFields) !{{{ if (associated(cellsOnCell_save)) then cellsOnCell_ptr => cellsOnCell_save call mpas_pool_get_field(allFields, 'cellsOnCell', cellsOnCell) - end if + end if if (associated(edgesOnCell_save)) then edgesOnCell_ptr => edgesOnCell_save call mpas_pool_get_field(allFields, 'edgesOnCell', edgesOnCell) - end if + end if if (associated(verticesOnCell_save)) then verticesOnCell_ptr => verticesOnCell_save call mpas_pool_get_field(allFields, 'verticesOnCell', verticesOnCell) - end if + end if if (associated(cellsOnEdge_save)) then cellsOnEdge_ptr => cellsOnEdge_save call mpas_pool_get_field(allFields, 'cellsOnEdge', cellsOnEdge) - end if + end if if (associated(verticesOnEdge_save)) then verticesOnEdge_ptr => verticesOnEdge_save call mpas_pool_get_field(allFields, 'verticesOnEdge', verticesOnEdge) - end if + end if if (associated(edgesOnEdge_save)) then edgesOnEdge_ptr => edgesOnEdge_save call mpas_pool_get_field(allFields, 'edgesOnEdge', edgesOnEdge) - end if + end if if (associated(cellsOnVertex_save)) then cellsOnVertex_ptr => cellsOnVertex_save call mpas_pool_get_field(allFields, 'cellsOnVertex', cellsOnVertex) - end if + end if if (associated(edgesOnVertex_save)) then edgesOnVertex_ptr => edgesOnVertex_save call mpas_pool_get_field(allFields, 'edgesOnVertex', edgesOnVertex) - end if + end if ! ! Reset indices for connectivity arrays from global to local index space @@ -5378,8 +5377,8 @@ end subroutine postwrite_reindex !}}} !> \brief Reindex connectivity fields from global to local index space. !> \author Doug Jacobsen, Michael Duda !> \date 24 September 2014 - !> \details - !> For any connectivity fields contained in the stream that was read, + !> \details + !> For any connectivity fields contained in the stream that was read, !> whose fields include those in the streamFields pool, convert the !> globally indexed connectivity fields in the stream to local index space. !> This routine should be called immediately after a read of a stream. @@ -5606,13 +5605,13 @@ end subroutine postread_reindex !}}} !> \author Doug Jacobsen, Michael Duda !> \date 03/03/2015 !> \details - !> If the optional 'streamID' argument is provided, this routine resets - !> the iterator within a stream manager so that streams may subsequently - !> be iterated over using the MPAS_stream_mgr_get_next_stream function. + !> If the optional 'streamID' argument is provided, this routine resets + !> the iterator within a stream manager so that streams may subsequently + !> be iterated over using the MPAS_stream_mgr_get_next_stream function. !> !> If an optional stream name is provided via the 'streamID' argument, this - !> routine will reset the iterator for fields within the specified stream, - !> which may subsequently iterated over using the + !> routine will reset the iterator for fields within the specified stream, + !> which may subsequently iterated over using the !> MPAS_stream_mgr_get_next_field() routine. !> !> NOTE: This routine does not support regular expressions for StreamID @@ -5772,7 +5771,7 @@ end function MPAS_stream_mgr_get_next_stream !}}} !> the stream manager. !> !> This function returns .TRUE. if the stream contains another field, - !> whether active or not, in which case the output argument fieldName + !> whether active or not, in which case the output argument fieldName !> provides the name of this field, and .FALSE. otherwise. If a field name !> is returned, the optional logical argument isActive may be used to !> determine whether the field is currently active in the stream. @@ -5828,7 +5827,7 @@ logical function MPAS_stream_mgr_get_next_field(manager, streamID, fieldName, is else isActive = .true. end if - + call mpas_pool_set_error_level(err_level) end if @@ -5864,7 +5863,7 @@ logical function MPAS_stream_mgr_stream_exists(manager, streamID) result(validSt return end function MPAS_stream_mgr_stream_exists!}}} - + end module mpas_stream_manager @@ -5967,7 +5966,7 @@ subroutine stream_mgr_create_stream_c(manager_c, streamID_c, direction_c, filena end if STREAM_DEBUG_WRITE('Creating stream from c...') - + ! ! For immutable streams, the stream should have already been defined at this point, and ! all we need to do is update the stream's filename template; diff --git a/components/mpas-ocean/bld/build-namelist b/components/mpas-ocean/bld/build-namelist index 6e63d8f9c11c..460b9ecda428 100755 --- a/components/mpas-ocean/bld/build-namelist +++ b/components/mpas-ocean/bld/build-namelist @@ -54,6 +54,9 @@ OPTIONS -ocn_ismf variable for defining how the ocn model will handle ice shelf melt fluxes Options are: none, data, internal, coupled + -ocn_sgr variable for defining how the ocn model will handle subglacial + runoff + Options are: none, data -decomp_prefix decomp_prefix variable -date_stamp date_stamp variable -cfg_grid Directory containing MPASO configuration scripts. @@ -111,6 +114,7 @@ my %opts = ( help => 0, ocn_forcing => undef, ocn_iceberg => undef, ocn_ismf => undef, + ocn_sgr => undef, decomp_prefix => undef, date_stamp => undef, ocn_bgc => undef, @@ -137,6 +141,7 @@ GetOptions( "ocn_forcing=s" => \$opts{'ocn_forcing'}, "ocn_iceberg=s" => \$opts{'ocn_iceberg'}, "ocn_ismf=s" => \$opts{'ocn_ismf'}, + "ocn_sgr=s" => \$opts{'ocn_sgr'}, "decomp_prefix=s" => \$opts{'decomp_prefix'}, "date_stamp=s" => \$opts{'date_stamp'}, "ocn_bgc=s" => \$opts{'ocn_bgc'}, @@ -180,6 +185,7 @@ my $OCN_GRID = $opts{'ocn_grid'}; my $OCN_FORCING = $opts{'ocn_forcing'}; my $OCN_ICEBERG = $opts{'ocn_iceberg'}; my $OCN_ISMF = $opts{'ocn_ismf'}; +my $OCN_SGR = $opts{'ocn_sgr'}; my $decomp_prefix = $opts{'decomp_prefix'}; my $date_stamp = $opts{'date_stamp'}; my $ocn_bgc = $opts{'ocn_bgc'}; @@ -702,6 +708,18 @@ add_default($nl, 'config_use_bulk_wind_stress'); add_default($nl, 'config_use_bulk_thickness_flux'); add_default($nl, 'config_flux_attenuation_coefficient'); add_default($nl, 'config_flux_attenuation_coefficient_runoff'); +if ($OCN_SGR eq 'data') { + add_default($nl, 'config_subglacial_runoff_mode', 'val'=>"data"); +} else { + add_default($nl, 'config_subglacial_runoff_mode'); +} +add_default($nl, 'config_flux_attenuation_coefficient_subglacial_runoff'); +add_default($nl, 'config_sgr_flux_vertical_location'); +add_default($nl, 'config_use_sgr_opt_kpp'); +add_default($nl, 'config_use_sgr_opt_temp_prescribed'); +add_default($nl, 'config_use_sgr_opt_salt_prescribed'); +add_default($nl, 'config_sgr_temperature_prescribed'); +add_default($nl, 'config_sgr_salinity_prescribed'); ############################ # Namelist group: coupling # diff --git a/components/mpas-ocean/bld/build-namelist-section b/components/mpas-ocean/bld/build-namelist-section index cae11d395c9f..c5dad5d935a9 100644 --- a/components/mpas-ocean/bld/build-namelist-section +++ b/components/mpas-ocean/bld/build-namelist-section @@ -224,6 +224,14 @@ add_default($nl, 'config_use_bulk_wind_stress'); add_default($nl, 'config_use_bulk_thickness_flux'); add_default($nl, 'config_flux_attenuation_coefficient'); add_default($nl, 'config_flux_attenuation_coefficient_runoff'); +add_default($nl, 'config_subglacial_runoff_mode'); +add_default($nl, 'config_flux_attenuation_coefficient_subglacial_runoff'); +add_default($nl, 'config_sgr_flux_vertical_location'); +add_default($nl, 'config_use_sgr_opt_kpp'); +add_default($nl, 'config_use_sgr_opt_temp_prescribed'); +add_default($nl, 'config_use_sgr_opt_salt_prescribed'); +add_default($nl, 'config_sgr_temperature_prescribed'); +add_default($nl, 'config_sgr_salinity_prescribed'); ############################ # Namelist group: coupling # diff --git a/components/mpas-ocean/bld/namelist_files/namelist_defaults_mpaso.xml b/components/mpas-ocean/bld/namelist_files/namelist_defaults_mpaso.xml index d4a1487ba161..fd2785616655 100644 --- a/components/mpas-ocean/bld/namelist_files/namelist_defaults_mpaso.xml +++ b/components/mpas-ocean/bld/namelist_files/namelist_defaults_mpaso.xml @@ -342,6 +342,14 @@ .true. 0.001 10.0 +'off' +0.001 +'bottom' +.true. +.false. +.false. +0.0 +0.0 .false. @@ -1112,6 +1120,7 @@ .false. +.true. '0000-00-00_01:00:00' 'eddyProductVariablesOutput' .true. diff --git a/components/mpas-ocean/bld/namelist_files/namelist_definition_mpaso.xml b/components/mpas-ocean/bld/namelist_files/namelist_definition_mpaso.xml index 6ebd149d17ac..bea1e98d9de8 100644 --- a/components/mpas-ocean/bld/namelist_files/namelist_definition_mpaso.xml +++ b/components/mpas-ocean/bld/namelist_files/namelist_definition_mpaso.xml @@ -1188,6 +1188,70 @@ Valid values: Any positive real number. Default: Defined in namelist_defaults.xml + +Selects the mode in which subglacial runoff fluxes are implemented. + +Valid values: 'off', 'data' +Default: Defined in namelist_defaults.xml + + + +The length scale of exponential decay of subglacial runoff, used when config_sgr_flux_vertical_location is 'top' or 'bottom'. Fluxes are multiplied by $e^{z/\gamma}$, where this coefficient is $\gamma$. + +Valid values: Any positive real number. +Default: Defined in namelist_defaults.xml + + + +Selects the vertical location where subglacial runoff is fluxed. + +Valid values: 'top','uniform', 'bottom' +Default: Defined in namelist_defaults.xml + + + +If true, include subglacial runoff (sgr) contribution in kpp calculation. + +Valid values: .true. or .false. +Default: Defined in namelist_defaults.xml + + + +If true, subglacial runoff temperature is set to config_sgr_temperature_prescribed. If false, the temperature is set to local freezing point. + +Valid values: .true. or .false. +Default: Defined in namelist_defaults.xml + + + +If true, subglacial runoff salinity is set to config_sgr_salinity_prescribed. If false, the salinity is set to 0 PSU. + +Valid values: .true. or .false. +Default: Defined in namelist_defaults.xml + + + +Prescribed subglacial runoff temperature value, applied when config_use_sgr_opt_temp_prescribed = .true. + +Valid values: Any real number. +Default: Defined in namelist_defaults.xml + + + +Prescribed subglacial runoff salinity value, applied when config_use_sgr_opt_salt_prescribed = .true. + +Valid values: Any positive real number +Default: Defined in namelist_defaults.xml + + diff --git a/components/mpas-ocean/cime_config/buildnml b/components/mpas-ocean/cime_config/buildnml index 4c7ed2c0a311..8f5193c334be 100755 --- a/components/mpas-ocean/cime_config/buildnml +++ b/components/mpas-ocean/cime_config/buildnml @@ -35,6 +35,7 @@ def buildnml(case, caseroot, compname): ocn_forcing = case.get_value("MPASO_FORCING") ocn_iceberg = case.get_value("MPASO_ICEBERG") ocn_ismf = case.get_value("MPASO_ISMF") + ocn_sgr = case.get_value("MPASO_SGR") ocn_bgc = case.get_value("MPASO_BGC") ocn_wave = case.get_value("MPASO_WAVE") ocn_tidal_mixing = case.get_value("MPASO_TIDAL_MIXING") @@ -76,6 +77,7 @@ def buildnml(case, caseroot, compname): analysis_mask_file = '' eco_forcing_file = '' u_tidal_rms_file = '' + data_sgr_file = '' if ocn_grid == 'oEC60to30v3': decomp_date = '230424' @@ -140,6 +142,8 @@ def buildnml(case, caseroot, compname): data_ismf_file = 'prescribed_ismf_paolo2023.oQU240wLI.20240404.nc' if ocn_tidal_mixing == 'true': u_tidal_rms_file = 'velocityTidalRMS_CATS2008.oQU240wLI.20240221.nc' + if ocn_sgr == 'data': + data_sgr_file = 'DSGR.massFlux.MALI.out2055.oQU240wLI.20240328.nc' elif ocn_grid == 'oQU120': decomp_date = '230424' @@ -277,6 +281,8 @@ def buildnml(case, caseroot, compname): data_ismf_file = 'prescribed_ismf_adusumilli2020.SOwISC12to60E2r4.230516.nc' if ocn_tidal_mixing == 'true': u_tidal_rms_file = 'velocityTidalRMS_CATS2008.SOwISC12to60E2r4.20210114.nc' + if ocn_sgr == 'data': + data_sgr_file = 'DSGR.massFlux.MALI.out2055.SOwISC12to60E2r4.20240328.nc' elif ocn_grid == 'FRISwISC08to60E3r1': decomp_date = '20230913' # changed to date of partiotions in ../files_for_e3sm/assembled_files/inputdata/ocn/mpas-o/FRISwISC08to60E3r1/partitions @@ -352,6 +358,8 @@ def buildnml(case, caseroot, compname): data_ismf_file = 'prescribed_ismf_adusumilli2020.ECwISC30to60E2r1.230429.nc' if ocn_tidal_mixing == 'true': u_tidal_rms_file = 'velocityTidalRMS_CATS2008.ECwISC30to60E2r1.20240221.nc' + if ocn_sgr == 'data': + data_sgr_file = 'DSGR.massFlux.MALI.out2055.ECwISC30to60E2r1.20240328.nc' elif ocn_grid == 'IcoswISC30E3r5': decomp_date = '20231120' @@ -371,6 +379,8 @@ def buildnml(case, caseroot, compname): data_ismf_file = 'prescribed_ismf_paolo2023.IcoswISC30E3r5.20240227.nc' if ocn_tidal_mixing == 'true': u_tidal_rms_file = 'velocityTidalRMS_CATS2008.IcoswISC30E3r5.20231120.nc' + if ocn_sgr == 'data': + data_sgr_file = 'DSGR.massFlux.MALI.out2055.IcoswISC30E3r5.20240328.nc' elif ocn_grid == 'IcosXISC30E3r7': decomp_date = '20240314' @@ -396,7 +406,6 @@ def buildnml(case, caseroot, compname): if ocn_ismf == 'data': data_ismf_file = 'prescribed_ismf_paolo2023.RRSwISC6to18E3r5.20240327.nc' - #-------------------------------------------------------------------- # Set OCN_FORCING = datm_forced_restoring if restoring file is available #-------------------------------------------------------------------- @@ -436,6 +445,9 @@ def buildnml(case, caseroot, compname): if u_tidal_rms_file != '': input_list.write("u_tidal_rms = {}/ocn/mpas-o/{}/{}\n".format(din_loc_root, ocn_mask, u_tidal_rms_file)) + if data_sgr_file != '': + input_list.write("subglacial_runoff = {}/ocn/mpas-o/{}/{}\n".format(din_loc_root, ocn_mask, data_sgr_file)) + #-------------------------------------------------------------------- # Invoke mpas build-namelist - output will go in $CASEBUILD/mpasoconf #-------------------------------------------------------------------- @@ -495,6 +507,7 @@ def buildnml(case, caseroot, compname): sysmod += " -ocn_forcing '{}'".format(ocn_forcing) sysmod += " -ocn_iceberg '{}'".format(ocn_iceberg) sysmod += " -ocn_ismf '{}'".format(ocn_ismf) + sysmod += " -ocn_sgr '{}'".format(ocn_sgr) sysmod += " -ocn_bgc '{}'".format(ocn_bgc) sysmod += " -ocn_wave '{}'".format(ocn_wave) sysmod += " -ocn_tidal_mixing '{}'".format(ocn_tidal_mixing) @@ -702,6 +715,19 @@ def buildnml(case, caseroot, compname): lines.append('') lines.append('') + if data_sgr_file != '': + lines.append('') + lines.append('') + lines.append(' ') + lines.append('') + lines.append('') + if analysis_mask_file != '': lines.append('') lines.append('') lines.append('') + lines.append('') lines.append('') lines.append('') lines.append('') lines.append('') lines.append('') lines.append('') + lines.append('') lines.append('') lines.append('') lines.append('') @@ -1183,6 +1211,7 @@ def buildnml(case, caseroot, compname): lines.append('') lines.append('') lines.append('') + lines.append('') lines.append('') lines.append('') lines.append('') @@ -1331,6 +1360,7 @@ def buildnml(case, caseroot, compname): lines.append(' ') lines.append(' ') lines.append(' ') + lines.append(' ') lines.append(' ') lines.append(' ') lines.append(' ') @@ -1533,6 +1563,7 @@ def buildnml(case, caseroot, compname): lines.append(' ') lines.append(' ') + lines.append(' ') lines.append(' ') lines.append(' ') lines.append(' ') @@ -1598,6 +1629,7 @@ def buildnml(case, caseroot, compname): lines.append(' ') lines.append(' ') + lines.append(' ') lines.append(' ') lines.append(' ') lines.append(' ') @@ -1812,6 +1844,7 @@ def buildnml(case, caseroot, compname): lines.append(' ') lines.append(' ') lines.append(' ') + lines.append(' ') lines.append(' ') lines.append(' ') lines.append(' ') diff --git a/components/mpas-ocean/cime_config/config_component.xml b/components/mpas-ocean/cime_config/config_component.xml index e95b63682d95..83b4501ee5e5 100644 --- a/components/mpas-ocean/cime_config/config_component.xml +++ b/components/mpas-ocean/cime_config/config_component.xml @@ -39,6 +39,19 @@ Option to describe the MPASO prescribed tidal mixing + + char + none,data + none + + none + data + + case_comp + env_case.xml + Option to describe how MPASO will handle subglacial runoff fluxes + + char false,true diff --git a/components/mpas-ocean/cime_config/config_compsets.xml b/components/mpas-ocean/cime_config/config_compsets.xml index 448aa7a82b57..be36f0103472 100644 --- a/components/mpas-ocean/cime_config/config_compsets.xml +++ b/components/mpas-ocean/cime_config/config_compsets.xml @@ -37,6 +37,11 @@ 2000_DATM%NYF_SLND_MPASSI_MPASO%PISMFDATMFORCED_DROF%NYFAIS45_SGLC_SWAV + + GMPAS-NYF-PISMF-DSGR + 2000_DATM%NYF_SLND_MPASSI_MPASO%PISMFDATMFORCEDDSGR_DROF%NYFAIS45_SGLC_SWAV + + GMPAS-NYF-DISMF 2000_DATM%NYF_SLND_MPASSI_MPASO%DISMFDATMFORCED_DROF%NYFAIS45_SGLC_SWAV @@ -87,6 +92,16 @@ 2000_DATM%JRA-1p5_SLND_MPASSI%DIB_MPASO%IBPISMFDATMFORCED_DROF%JRA-1p5-AIS0ROF_SGLC_SWAV + + GMPAS-JRA1p5-DIB-PISMF-DSGR + 2000_DATM%JRA-1p5_SLND_MPASSI%DIB_MPASO%IBPISMFDATMFORCEDDSGR_DROF%JRA-1p5-AIS0ROF_SGLC_SWAV + + + + GMPAS-JRA1p5-DIB-PISMF-DSGR-TMIX + 2000_DATM%JRA-1p5_SLND_MPASSI%DIB_MPASO%IBPISMFDATMFORCEDDSGRTMIX_DROF%JRA-1p5-AIS0ROF_SGLC_SWAV + + GMPAS-JRA1p5-DIB-DISMF 2000_DATM%JRA-1p5_SLND_MPASSI%DIB_MPASO%IBDISMFDATMFORCED_DROF%JRA-1p5-AIS0ROF_SGLC_SWAV diff --git a/components/mpas-ocean/driver/ocn_comp_mct.F b/components/mpas-ocean/driver/ocn_comp_mct.F index bd425e7e806a..d1b140563bb7 100644 --- a/components/mpas-ocean/driver/ocn_comp_mct.F +++ b/components/mpas-ocean/driver/ocn_comp_mct.F @@ -2952,6 +2952,8 @@ subroutine ocn_export_mct(o2x_o, errorCode) !{{{ block_ptr => block_ptr % next end do + errorCode = 0 + !----------------------------------------------------------------------- !EOC @@ -3936,7 +3938,6 @@ subroutine ocn_import_moab( Eclock, errorCode)!{{{ call mpas_dmpar_exch_halo_field(iceFluxDMSPField) endif endif - endif !----------------------------------------------------------------------- !EOC diff --git a/components/mpas-ocean/src/Registry.xml b/components/mpas-ocean/src/Registry.xml index be50e9ccd9ee..2a21e22f40d2 100644 --- a/components/mpas-ocean/src/Registry.xml +++ b/components/mpas-ocean/src/Registry.xml @@ -702,6 +702,39 @@ description="The length scale of exponential decay of river runoff. Fluxes are multiplied by $e^{z/\gamma}$, where this coefficient is $\gamma$." possible_values="Any positive real number." /> + + + + + + + + + + @@ -2233,6 +2267,7 @@ + @@ -3351,6 +3386,10 @@ + + + @@ -3764,6 +3811,10 @@ description="Fresh water flux from river runoff at cell centers from coupler. Positive into the ocean." packages="thicknessBulkPKG" /> + + @@ -145,6 +149,10 @@ description="Fresh water flux from river runoff from coupler. Positive into the ocean." packages="thicknessBulkPKG" /> + @@ -194,6 +202,11 @@ + + + + @@ -302,6 +317,7 @@ + @@ -343,12 +359,14 @@ + + @@ -358,6 +376,7 @@ + diff --git a/components/mpas-ocean/src/analysis_members/mpas_ocn_conservation_check.F b/components/mpas-ocean/src/analysis_members/mpas_ocn_conservation_check.F index bdd07e799b5d..beed937d6767 100644 --- a/components/mpas-ocean/src/analysis_members/mpas_ocn_conservation_check.F +++ b/components/mpas-ocean/src/analysis_members/mpas_ocn_conservation_check.F @@ -28,6 +28,7 @@ module ocn_conservation_check use ocn_constants use ocn_config + use ocn_mesh implicit none private @@ -427,6 +428,7 @@ subroutine energy_conservation(domain, err) accumulatedEvapTemperatureFlux, & accumulatedSeaIceTemperatureFlux, & accumulatedRiverRunoffTemperatureFlux, & + accumulatedSubglacialRunoffTemperatureFlux, & accumulatedIcebergTemperatureFlux real(kind=RKIND), dimension(:), allocatable :: & @@ -463,7 +465,8 @@ subroutine energy_conservation(domain, err) real(kind=RKIND), dimension(:,:), pointer :: & - activeTracersSurfaceFluxRunoff + activeTracersSurfaceFluxRunoff, & + activeTracersSurfaceFluxSubglacialRunoff type (MPAS_timeInterval_type) :: & timeStepESMF @@ -480,7 +483,7 @@ subroutine energy_conservation(domain, err) ierr integer, parameter :: & - nSums = 19 + nSums = 20 character(len=160) :: & m @@ -513,6 +516,7 @@ subroutine energy_conservation(domain, err) call MPAS_pool_get_array(conservationCheckEnergyAMPool, "accumulatedEvapTemperatureFlux", accumulatedEvapTemperatureFlux) call MPAS_pool_get_array(conservationCheckEnergyAMPool, "accumulatedSeaIceTemperatureFlux", accumulatedSeaIceTemperatureFlux) call MPAS_pool_get_array(conservationCheckEnergyAMPool, "accumulatedRiverRunoffTemperatureFlux", accumulatedRiverRunoffTemperatureFlux) + call MPAS_pool_get_array(conservationCheckEnergyAMPool, "accumulatedSubglacialRunoffTemperatureFlux", accumulatedSubglacialRunoffTemperatureFlux) call MPAS_pool_get_array(conservationCheckEnergyAMPool, "accumulatedIcebergTemperatureFlux", accumulatedIcebergTemperatureFlux) !------------------------------------------------------------- @@ -556,6 +560,7 @@ subroutine energy_conservation(domain, err) call mpas_pool_get_subpool(forcingPool, 'tracersSurfaceFlux',tracersSurfaceFluxPool) call mpas_pool_get_dimension(tracersSurfaceFluxPool, 'index_temperatureSurfaceFlux', index_temperature_flux) call mpas_pool_get_array(tracersSurfaceFluxPool, 'activeTracersSurfaceFluxRunoff', activeTracersSurfaceFluxRunoff) + call mpas_pool_get_array(tracersSurfaceFluxPool, 'activeTracersSurfaceFluxSubglacialRunoff', activeTracersSurfaceFluxSubglacialRunoff) call mpas_pool_get_array(statePool, 'accumulatedFrazilIceMass', accumulatedFrazilIceMassNew, 2) call mpas_pool_get_array(statePool, 'accumulatedFrazilIceMass', accumulatedFrazilIceMassOld, 1) @@ -581,6 +586,11 @@ subroutine energy_conservation(domain, err) sumArray(14) = sumArray(14) + areaCell(iCell) * activeTracersSurfaceFluxRunoff(index_temperature_flux,iCell) sumArray(15) = sumArray(15) + areaCell(iCell) * icebergTemperatureFlux(iCell) + ! subglacial river runoff temperature flux + if (trim(config_subglacial_runoff_mode) == 'data') then + sumArray(20) = sumArray(20) + areaCell(iCell) * activeTracersSurfaceFluxSubglacialRunoff(index_temperature_flux,iCell) + end if + enddo ! iCell if (config_use_frazil_ice_formation) then @@ -634,6 +644,9 @@ subroutine energy_conservation(domain, err) accumulatedLandIceHeatFlux = accumulatedLandIceHeatFlux + sumArrayOut(17) accumulatedLandIceFrazilHeatFlux = accumulatedLandIceFrazilHeatFlux + sumArrayOut(18) accumulatedRemovedIceRunoffHeatFlux = accumulatedRemovedIceRunoffHeatFlux + sumArrayOut(19) + if (trim(config_subglacial_runoff_mode) == 'data') then + accumulatedSubglacialRunoffTemperatureFlux = accumulatedSubglacialRunoffTemperatureFlux + sumArrayOut(20) + end if ! cleanup deallocate(sumArray) @@ -663,6 +676,9 @@ subroutine energy_conservation(domain, err) accumulatedEvapTemperatureFlux = accumulatedEvapTemperatureFlux /accumulatedFluxCounter accumulatedSeaIceTemperatureFlux = accumulatedSeaIceTemperatureFlux /accumulatedFluxCounter accumulatedRiverRunoffTemperatureFlux = accumulatedRiverRunoffTemperatureFlux /accumulatedFluxCounter + if (trim(config_subglacial_runoff_mode) == 'data') then + accumulatedSubglacialRunoffTemperatureFlux = accumulatedSubglacialRunoffTemperatureFlux /accumulatedFluxCounter + end if accumulatedIcebergTemperatureFlux = accumulatedIcebergTemperatureFlux /accumulatedFluxCounter accumulatedLandIceFrazilHeatFlux = accumulatedLandIceFrazilHeatFlux /accumulatedFluxCounter accumulatedRemovedIceRunoffHeatFlux = accumulatedRemovedIceRunoffHeatFlux /accumulatedFluxCounter @@ -699,6 +715,9 @@ subroutine energy_conservation(domain, err) + accumulatedRiverRunoffTemperatureFlux *rho_sw*cp_sw & + accumulatedIcebergTemperatureFlux*rho_sw*cp_sw ! note, accumulatedLandIceFrazilHeatFlux not added because already in accumulatedFrazilHeatFlux + if (trim(config_subglacial_runoff_mode) == 'data') then + netEnergyFlux = netEnergyFlux + accumulatedSubglacialRunoffTemperatureFlux * rho_sw*cp_sw + end if ! compute the final energy error call MPAS_pool_get_array(conservationCheckEnergyAMPool, "absoluteEnergyError", absoluteEnergyError) @@ -760,6 +779,9 @@ subroutine energy_conservation(domain, err) v=accumulatedEvapTemperatureFlux *rho_sw*cp_sw; write(m,"('EvapTemperatureFlux ',es16.8,' ',f16.8)") v,v/A; call mpas_log_write(m); s=s+v v=accumulatedSeaIceTemperatureFlux *rho_sw*cp_sw; write(m,"('SeaIceTemperatureFlux ',es16.8,' ',f16.8)") v,v/A; call mpas_log_write(m); s=s+v v=accumulatedRiverRunoffTemperatureFlux*rho_sw*cp_sw; write(m,"('RiverRunoffTempFlux ',es16.8,' ',f16.8)") v,v/A; call mpas_log_write(m); s=s+v +if (trim(config_subglacial_runoff_mode) == 'data') then + v=accumulatedSubglacialRunoffTemperatureFlux*rho_sw*cp_sw; write(m,"('SubglacialRunoffTempFlux ',es16.8,' ',f16.8)") v,v/A; call mpas_log_write(m); s=s+v +end if v=accumulatedIcebergTemperatureFlux*rho_sw*cp_sw; write(m,"('IcebergTemperatureFlux ',es16.8,' ',f16.8)") v,v/A; call mpas_log_write(m); s=s+v write(m,"('SUM IMPLICIT HEAT FLUXES ',es16.8,' hh20temp ',f16.8,es16.8)") s, s/A; call mpas_log_write(m) s = s + explicitHeatFluxSum @@ -828,6 +850,7 @@ subroutine mass_conservation(domain, err) accumulatedEvaporationFlux, & accumulatedSeaIceFlux, & accumulatedRiverRunoffFlux, & + accumulatedSubglacialRunoffFlux, & accumulatedIceRunoffFlux, & accumulatedRemovedRiverRunoffFlux, & accumulatedRemovedIceRunoffFlux, & @@ -852,6 +875,7 @@ subroutine mass_conservation(domain, err) evaporationFlux, & seaIceFreshwaterFlux, & riverRunoffFlux, & + subglacialRunoffFlux, & iceRunoffFlux, & removedRiverRunoffFlux, & removedIceRunoffFlux, & @@ -877,7 +901,7 @@ subroutine mass_conservation(domain, err) iCell, ierr, k integer, parameter :: & - nSums = 12 + nSums = 13 integer, dimension(:), pointer :: minLevelCell, maxLevelCell @@ -900,6 +924,7 @@ subroutine mass_conservation(domain, err) call MPAS_pool_get_array(conservationCheckMassAMPool, "accumulatedEvaporationFlux", accumulatedEvaporationFlux) call MPAS_pool_get_array(conservationCheckMassAMPool, "accumulatedSeaIceFlux", accumulatedSeaIceFlux) call MPAS_pool_get_array(conservationCheckMassAMPool, "accumulatedRiverRunoffFlux", accumulatedRiverRunoffFlux) + call MPAS_pool_get_array(conservationCheckMassAMPool, "accumulatedSubglacialRunoffFlux", accumulatedSubglacialRunoffFlux) call MPAS_pool_get_array(conservationCheckMassAMPool, "accumulatedIceRunoffFlux", accumulatedIceRunoffFlux) call MPAS_pool_get_array(conservationCheckMassAMPool, "accumulatedRemovedRiverRunoffFlux",accumulatedRemovedRiverRunoffFlux) call MPAS_pool_get_array(conservationCheckMassAMPool, "accumulatedRemovedIceRunoffFlux", accumulatedRemovedIceRunoffFlux) @@ -937,6 +962,7 @@ subroutine mass_conservation(domain, err) call mpas_pool_get_array(forcingPool, 'evaporationFlux', evaporationFlux) call mpas_pool_get_array(forcingPool, 'seaIceFreshWaterFlux', seaIceFreshwaterFlux) call mpas_pool_get_array(forcingPool, 'riverRunoffFlux', riverRunoffFlux) + call mpas_pool_get_array(forcingPool, 'subglacialRunoffFlux', subglacialRunoffFlux) call mpas_pool_get_array(forcingPool, 'iceRunoffFlux', iceRunoffFlux) call mpas_pool_get_array(forcingPool, 'removedRiverRunoffFlux', removedRiverRunoffFlux) call mpas_pool_get_array(forcingPool, 'removedIceRunoffFlux', removedIceRunoffFlux) @@ -956,6 +982,9 @@ subroutine mass_conservation(domain, err) sumArray( 7) = sumArray( 7) + areaCell(iCell) * removedRiverRunoffFlux(iCell) sumArray( 8) = sumArray( 8) + areaCell(iCell) * removedIceRunoffFlux(iCell) sumArray( 9) = sumArray( 9) + areaCell(iCell) * icebergFreshwaterFlux(iCell) + if (trim(config_subglacial_runoff_mode) == 'data') then + sumArray(13) = sumArray(13) + areaCell(iCell) * subglacialRunoffFlux(iCell) + end if enddo if (config_use_frazil_ice_formation) then @@ -1002,6 +1031,9 @@ subroutine mass_conservation(domain, err) accumulatedFrazilFlux = accumulatedFrazilFlux + sumArrayOut(10) accumulatedLandIceFlux = accumulatedLandIceFlux + sumArrayOut(11) accumulatedLandIceFrazilFlux = accumulatedLandIceFrazilFlux + sumArrayOut(12) + if (trim(config_subglacial_runoff_mode) == 'data') then + accumulatedSubglacialRunoffFlux = accumulatedSubglacialRunoffFlux + sumArrayOut(13) + end if ! cleanup deallocate(sumArray) @@ -1021,6 +1053,9 @@ subroutine mass_conservation(domain, err) accumulatedEvaporationFlux = accumulatedEvaporationFlux /accumulatedFluxCounter accumulatedSeaIceFlux = accumulatedSeaIceFlux /accumulatedFluxCounter accumulatedRiverRunoffFlux = accumulatedRiverRunoffFlux /accumulatedFluxCounter + if (trim(config_subglacial_runoff_mode) == 'data') then + accumulatedSubglacialRunoffFlux = accumulatedSubglacialRunoffFlux /accumulatedFluxCounter + end if accumulatedIceRunoffFlux = accumulatedIceRunoffFlux /accumulatedFluxCounter accumulatedRemovedRiverRunoffFlux = accumulatedRemovedRiverRunoffFlux /accumulatedFluxCounter accumulatedRemovedIceRunoffFlux = accumulatedRemovedIceRunoffFlux /accumulatedFluxCounter @@ -1054,6 +1089,9 @@ subroutine mass_conservation(domain, err) + accumulatedFrazilFlux & + accumulatedLandIceFlux ! note, accumulatedLandIceFrazilFlux not added because already in accumulatedFrazilFlux + if (trim(config_subglacial_runoff_mode) == 'data') then + netMassFlux = netMassFlux + accumulatedSubglacialRunoffFlux + end if ! compute the final mass error call MPAS_pool_get_array(conservationCheckMassAMPool, "absoluteMassError", absoluteMassError) @@ -1083,6 +1121,10 @@ subroutine mass_conservation(domain, err) v=accumulatedIcebergFlux ; write(m,"('icebergFreshwaterFlux ',es16.8,' x2o_Fioi_bergw wberg ',f16.8)") v,v*c; call mpas_log_write(m); s=s+v v=accumulatedEvaporationFlux ; write(m,"('evaporationFlux ',es16.8,' x2o_Foxx_evap wevap ',f16.8)") v,v*c; call mpas_log_write(m); s=s+v v=accumulatedRiverRunoffFlux ; write(m,"('riverRunoffFlux ',es16.8,' x2o_Foxx_rofl wrunoff ',f16.8)") v,v*c; call mpas_log_write(m); s=s+v +if (trim(config_subglacial_runoff_mode) == 'data') then + v=accumulatedSubglacialRunoffFlux ; write(m,"('subglacialRunoffFlux ',es16.8,' x2o_Foxx_rofl wsgr ',f16.8)") v,v*c; call mpas_log_write(m); s=s+v +end if + if (landIceFreshwaterFluxesOn) then v=accumulatedRemovedRiverRunoffFlux; write(m,"('removedRiverRunoffFlux ',es16.8,' wrunoff ',f16.8)") v,v*c; call mpas_log_write(m); v=accumulatedRiverRunoffFlux+accumulatedRemovedRiverRunoffFlux; @@ -1150,7 +1192,8 @@ subroutine salt_conservation(domain, err) conservationCheckSaltAMPool, & meshPool, & statePool, & - forcingPool + forcingPool, & + tracersSurfaceFluxPool real(kind=RKIND), pointer :: & initialSalt, & @@ -1160,9 +1203,13 @@ subroutine salt_conservation(domain, err) absoluteSaltError, & relativeSaltError + real(kind=RKIND), dimension(:,:), pointer :: & + activeTracersSurfaceFluxSubglacialRunoff + real(kind=RKIND), pointer :: & accumulatedSeaIceSalinityFlux, & - accumulatedFrazilSalinityFlux + accumulatedFrazilSalinityFlux, & + accumulatedSubglacialRunoffSalinityFlux ! accumulatedLandIceFrazilSalinityFlux is not present because it is always 0 real(kind=RKIND), dimension(:), allocatable :: & @@ -1184,14 +1231,15 @@ subroutine salt_conservation(domain, err) dt, dtAvg, v, A, s, c integer, pointer :: & - nCellsSolve + nCellsSolve, & + index_salinity_flux integer :: & iCell, & ierr integer, parameter :: & - nSums = 3 + nSums = 4 logical, pointer :: & activeTracersBulkRestoringPKG @@ -1209,6 +1257,7 @@ subroutine salt_conservation(domain, err) call MPAS_pool_get_array(conservationCheckSaltAMPool, "accumulatedSeaIceSalinityFlux", accumulatedSeaIceSalinityFlux) call MPAS_pool_get_array(conservationCheckSaltAMPool, "accumulatedFrazilSalinityFlux", accumulatedFrazilSalinityFlux) + call MPAS_pool_get_array(conservationCheckSaltAMPool, "accumulatedSubglacialRunoffSalinityFlux", accumulatedSubglacialRunoffSalinityFlux) !------------------------------------------------------------- ! Net salt flux to ice @@ -1234,12 +1283,23 @@ subroutine salt_conservation(domain, err) call mpas_pool_get_array(forcingPool, 'seaIceSalinityFlux', seaIceSalinityFlux) call mpas_pool_get_array(statePool, 'accumulatedFrazilIceSalinity', accumulatedFrazilIceSalinityOld, 1) call mpas_pool_get_array(statePool, 'accumulatedFrazilIceSalinity', accumulatedFrazilIceSalinityNew, 2) + call mpas_pool_get_subpool(forcingPool, 'tracersSurfaceFlux',tracersSurfaceFluxPool) + call mpas_pool_get_array(tracersSurfaceFluxPool, 'activeTracersSurfaceFluxSubglacialRunoff', activeTracersSurfaceFluxSubglacialRunoff) + call mpas_pool_get_dimension(tracersSurfaceFluxPool, 'index_salinitySurfaceFlux', index_salinity_flux) + + do iCell = 1, nCellsSolve ! salt flux to ocean sumArray(1) = sumArray(1) + areaCell(iCell) * seaIceSalinityFlux(iCell) enddo ! iCell + ! subglacial runoff + if (trim(config_subglacial_runoff_mode) == 'data') then + do iCell = 1, nCellsSolve + sumArray(4) = sumArray(4) + areaCell(iCell) * activeTracersSurfaceFluxSubglacialRunoff(index_salinity_flux,iCell) + enddo ! iCell + end if if (config_use_frazil_ice_formation) then do iCell = 1, nCellsSolve @@ -1265,6 +1325,9 @@ subroutine salt_conservation(domain, err) ! accumulate fluxes accumulatedSeaIceSalinityFlux = accumulatedSeaIceSalinityFlux + sumArrayOut(1) accumulatedFrazilSalinityFlux = accumulatedFrazilSalinityFlux + sumArrayOut(2) + if (trim(config_subglacial_runoff_mode) == 'data') then + accumulatedSubglacialRunoffSalinityFlux = accumulatedSubglacialRunoffSalinityFlux + sumArrayOut(4) + end if ! cleanup deallocate(sumArray) @@ -1281,6 +1344,9 @@ subroutine salt_conservation(domain, err) ! Average the fluxes accumulatedSeaIceSalinityFlux = accumulatedSeaIceSalinityFlux /accumulatedFluxCounter accumulatedFrazilSalinityFlux = accumulatedFrazilSalinityFlux /accumulatedFluxCounter + if (trim(config_subglacial_runoff_mode) == 'data') then + accumulatedSubglacialRunoffSalinityFlux = accumulatedSubglacialRunoffSalinityFlux /accumulatedFluxCounter + end if ! get initial salt content call MPAS_pool_get_array(conservationCheckSaltAMPool, "initialSalt", initialSalt) @@ -1299,6 +1365,10 @@ subroutine salt_conservation(domain, err) netSaltFlux = accumulatedSeaIceSalinityFlux & + accumulatedFrazilSalinityFlux + if (trim(config_subglacial_runoff_mode) == 'data') then + netSaltFlux = netSaltFlux + accumulatedSubglacialRunoffSalinityFlux + end if + ! compute the final salt error call MPAS_pool_get_array(conservationCheckSaltAMPool, "absoluteSaltError", absoluteSaltError) call MPAS_pool_get_array(conservationCheckSaltAMPool, "relativeSaltError", relativeSaltError) @@ -1327,6 +1397,10 @@ subroutine salt_conservation(domain, err) .and.config_frazil_under_land_ice) then v=0; write(m,"('LandIceFrazilSalinityFlux',es16.8,' (already in wmelt, do not sum) ',f16.8)") v,v*c; call mpas_log_write(m); !no sum: s=s+v end if +if (trim(config_subglacial_runoff_mode) == 'data') then + v=accumulatedSubglacialRunoffSalinityFlux ; write(m,"('SubglacialRunoffSalinityFlux ',es16.8,' x2o_Fioi_salt salt ',f16.8)") v,v*c; call mpas_log_write(m); s=s+v +end if + write(m,"('SUM VOLUME FLUXES ',es16.8,' ',f16.8,es16.8)") s, s*c; call mpas_log_write(m) call mpas_log_write(' ') @@ -1523,11 +1597,11 @@ subroutine carbon_conservation(domain, err) block => domain % blocklist do while (associated(block)) call MPAS_pool_get_dimension(block % dimensions, "nCellsSolve", nCellsSolve) - + call MPAS_pool_get_subpool(block % structs, "mesh", meshPool) call MPAS_pool_get_subpool(block % structs, "forcing", forcingPool) call MPAS_pool_get_subpool(block % structs, "state", statePool) - + call MPAS_pool_get_array(meshPool, "areaCell", areaCell) call mpas_pool_get_array(meshPool, 'maxLevelCell', maxLevelCell) @@ -1594,7 +1668,7 @@ subroutine carbon_conservation(domain, err) + ecosysTracersSurfaceFlux(index_spCFlux, iCell) & + ecosysTracersSurfaceFlux(index_diatCFlux, iCell) & + ecosysTracersSurfaceFlux(index_diazCFlux, iCell)) - + do k = 1, maxLevelCell(iCell) sumArray(4) = sumArray(4) + areaCell(iCell) * ( & ecosysTracersTend(index_DICTend, k, iCell) & @@ -1645,7 +1719,7 @@ subroutine carbon_conservation(domain, err) !------------------------------------------------------------- if (MPAS_stream_mgr_ringing_alarms(domain % streamManager, "conservationCheckOutput", ierr=ierr)) then - + ! Average the fluxes accumulatedCarbonSourceSink = accumulatedCarbonSourceSink /accumulatedFluxCounter accumulatedCarbonSedimentFlux = accumulatedCarbonSedimentFlux /accumulatedFluxCounter @@ -1657,7 +1731,7 @@ subroutine carbon_conservation(domain, err) ! get initial carbon call MPAS_pool_get_array(conservationCheckCarbonAMPool, "initialCarbon", initialCarbon) - + ! get final carbon call MPAS_pool_get_array(conservationCheckCarbonAMPool, "finalCarbon", finalCarbon) call compute_total_carbon(domain, finalCarbon) @@ -1694,13 +1768,13 @@ subroutine carbon_conservation(domain, err) relativeCarbonErrorBounds = & relativeCarbonErrorStepBounds*relativeCarbonErrorBoundsFac*totalTimeSteps relativeCarbonErrorPerTimeStep = relativeCarbonError/accumulatedFluxCounter - + !------------------------------------------------------------- ! Output to log file !------------------------------------------------------------- if (config_AM_conservationCheck_write_to_logfile) then - + call mpas_log_write('') call mpas_log_write('----------------------------------------------------------') call mpas_log_write('CARBON CONSERVATION CHECK') @@ -1731,7 +1805,7 @@ subroutine carbon_conservation(domain, err) v=accumulatedIceOceanInorganicCarbonFlux*mmol_to_kg_C write(m,"('Ice-Ocean Inorganic Flux ',es16.8,' ',f16.8)") v,v*c call mpas_log_write(m) - write(m,"('SUM FLUXES (surf + sed) ',es16.8,' ',f16.8,es16.8)") s, s*c; + write(m,"('SUM FLUXES (surf + sed) ',es16.8,' ',f16.8,es16.8)") s, s*c; call mpas_log_write(m) call mpas_log_write(' ') @@ -1751,24 +1825,24 @@ subroutine carbon_conservation(domain, err) write(m,"('Carbon change ', 3es16.8)") & carbonChange*mmol_to_kg_C, & carbonChange*mmol_to_kg_C/dtAvg, & - carbonChange*mmol_to_kg_C/dtAvg*c + carbonChange*mmol_to_kg_C/dtAvg*c call mpas_log_write(m) write(m,"('Net carbon flux ', 3es16.8)") & netCarbonFlux*mmol_to_kg_C*dtAvg, & netCarbonFlux*mmol_to_kg_C, & - netCarbonFlux*mmol_to_kg_C*c + netCarbonFlux*mmol_to_kg_C*c call mpas_log_write(m) write(m,"('Absolute carbon error ', 3es16.8)") & absoluteCarbonError*mmol_to_kg_C, & absoluteCarbonError*mmol_to_kg_C/dtAvg, & - absoluteCarbonError*mmol_to_kg_C/dtAvg*c + absoluteCarbonError*mmol_to_kg_C/dtAvg*c call mpas_log_write(m) call mpas_log_write(' ') write(m,"('RELATIVE CARBON ERROR =', es16.8)") & relativeCarbonError call mpas_log_write(m) call mpas_log_write(' ') - + write(m,"('Relative carbon error per timestep = ', es16.8)") & relativeCarbonErrorPerTimeStep call mpas_log_write(m) @@ -1814,7 +1888,7 @@ subroutine carbon_conservation(domain, err) endif end subroutine carbon_conservation - + !*********************************************************************** ! ! routine compute_total_energy @@ -2190,7 +2264,7 @@ subroutine compute_total_carbon(domain, totalCarbon) call MPAS_dmpar_sum_real(domain % dminfo, carbon, totalCarbon) end subroutine compute_total_carbon - + !*********************************************************************** ! ! routine reset_accumulated_variables @@ -2232,6 +2306,7 @@ subroutine reset_accumulated_variables(domain) accumulatedEvapTemperatureFlux, & accumulatedSeaIceTemperatureFlux, & accumulatedRiverRunoffTemperatureFlux, & + accumulatedSubglacialRunoffTemperatureFlux, & accumulatedIcebergTemperatureFlux real(kind=RKIND), pointer :: & @@ -2240,6 +2315,7 @@ subroutine reset_accumulated_variables(domain) accumulatedEvaporationFlux, & accumulatedSeaIceFlux, & accumulatedRiverRunoffFlux, & + accumulatedSubglacialRunoffFlux, & accumulatedIceRunoffFlux, & accumulatedRemovedRiverRunoffFlux, & accumulatedRemovedIceRunoffFlux, & @@ -2250,7 +2326,8 @@ subroutine reset_accumulated_variables(domain) real(kind=RKIND), pointer :: & accumulatedSeaIceSalinityFlux, & - accumulatedFrazilSalinityFlux + accumulatedFrazilSalinityFlux, & + accumulatedSubglacialRunoffSalinityFlux real(kind=RKIND), pointer :: & accumulatedCarbonSourceSink, & @@ -2280,6 +2357,7 @@ subroutine reset_accumulated_variables(domain) call MPAS_pool_get_array(conservationCheckEnergyAMPool, "accumulatedEvapTemperatureFlux", accumulatedEvapTemperatureFlux) call MPAS_pool_get_array(conservationCheckEnergyAMPool, "accumulatedSeaIceTemperatureFlux", accumulatedSeaIceTemperatureFlux) call MPAS_pool_get_array(conservationCheckEnergyAMPool, "accumulatedRiverRunoffTemperatureFlux", accumulatedRiverRunoffTemperatureFlux) + call MPAS_pool_get_array(conservationCheckEnergyAMPool, "accumulatedSubglacialRunoffTemperatureFlux", accumulatedSubglacialRunoffTemperatureFlux) call MPAS_pool_get_array(conservationCheckEnergyAMPool, "accumulatedIcebergTemperatureFlux", accumulatedIcebergTemperatureFlux) accumulatedFluxCounter = 0 @@ -2298,6 +2376,9 @@ subroutine reset_accumulated_variables(domain) accumulatedEvapTemperatureFlux = 0.0_RKIND accumulatedSeaIceTemperatureFlux = 0.0_RKIND accumulatedRiverRunoffTemperatureFlux = 0.0_RKIND + if (trim(config_subglacial_runoff_mode) == 'data') then + accumulatedSubglacialRunoffTemperatureFlux = 0.0_RKIND + end if accumulatedIcebergTemperatureFlux = 0.0_RKIND accumulatedLandIceFrazilHeatFlux = 0.0_RKIND accumulatedRemovedIceRunoffHeatFlux = 0.0_RKIND @@ -2310,6 +2391,7 @@ subroutine reset_accumulated_variables(domain) call MPAS_pool_get_array(conservationCheckMassAMPool, "accumulatedEvaporationFlux", accumulatedEvaporationFlux) call MPAS_pool_get_array(conservationCheckMassAMPool, "accumulatedSeaIceFlux", accumulatedSeaIceFlux) call MPAS_pool_get_array(conservationCheckMassAMPool, "accumulatedRiverRunoffFlux", accumulatedRiverRunoffFlux) + call MPAS_pool_get_array(conservationCheckMassAMPool, "accumulatedSubglacialRunoffFlux", accumulatedSubglacialRunoffFlux) call MPAS_pool_get_array(conservationCheckMassAMPool, "accumulatedIceRunoffFlux", accumulatedIceRunoffFlux) call MPAS_pool_get_array(conservationCheckMassAMPool, "accumulatedRemovedRiverRunoffFlux",accumulatedRemovedRiverRunoffFlux) call MPAS_pool_get_array(conservationCheckMassAMPool, "accumulatedRemovedIceRunoffFlux", accumulatedRemovedIceRunoffFlux) @@ -2323,6 +2405,9 @@ subroutine reset_accumulated_variables(domain) accumulatedEvaporationFlux = 0.0_RKIND accumulatedSeaIceFlux = 0.0_RKIND accumulatedRiverRunoffFlux = 0.0_RKIND + if (trim(config_subglacial_runoff_mode) == 'data') then + accumulatedSubglacialRunoffFlux = 0.0_RKIND + end if accumulatedIceRunoffFlux = 0.0_RKIND accumulatedRemovedRiverRunoffFlux = 0.0_RKIND accumulatedRemovedIceRunoffFlux = 0.0_RKIND @@ -2336,9 +2421,13 @@ subroutine reset_accumulated_variables(domain) call MPAS_pool_get_array(conservationCheckSaltAMPool, "accumulatedSeaIceSalinityFlux", accumulatedSeaIceSalinityFlux) call MPAS_pool_get_array(conservationCheckSaltAMPool, "accumulatedFrazilSalinityFlux", accumulatedFrazilSalinityFlux) + call MPAS_pool_get_array(conservationCheckSaltAMPool, "accumulatedSubglacialRunoffSalinityFlux", accumulatedSubglacialRunoffSalinityFlux) accumulatedSeaIceSalinityFlux = 0.0_RKIND accumulatedFrazilSalinityFlux = 0.0_RKIND + if (trim(config_subglacial_runoff_mode) == 'data') then + accumulatedSubglacialRunoffSalinityFlux = 0.0_RKIND + end if call MPAS_pool_get_subpool(domain % blocklist % structs, "conservationCheckCarbonAM", conservationCheckCarbonAMPool) diff --git a/components/mpas-ocean/src/driver/mpas_ocn_core_interface.F b/components/mpas-ocean/src/driver/mpas_ocn_core_interface.F index 7d9eb083f907..6d542fb0c3f3 100644 --- a/components/mpas-ocean/src/driver/mpas_ocn_core_interface.F +++ b/components/mpas-ocean/src/driver/mpas_ocn_core_interface.F @@ -123,6 +123,7 @@ function ocn_setup_packages(configPool, packagePool, iocontext) result(ierr)!{{{ logical, pointer :: dataLandIceFluxesPKGActive logical, pointer :: landIceFluxesPKGActive logical, pointer :: landIceCouplingPKGActive + logical, pointer :: dataSubglacialRunoffFluxPKGActive logical, pointer :: thicknessBulkPKGActive logical, pointer :: frazilIceActive logical, pointer :: tidalForcingActive @@ -186,6 +187,7 @@ function ocn_setup_packages(configPool, packagePool, iocontext) result(ierr)!{{{ logical, pointer :: config_use_bulk_thickness_flux logical, pointer :: config_compute_active_tracer_budgets character (len=StrKIND), pointer :: config_land_ice_flux_mode + character (len=StrKIND), pointer :: config_subglacial_runoff_mode type (mpas_pool_iterator_type) :: groupItr character (len=StrKIND) :: tracerGroupName, configName, packageName @@ -319,6 +321,15 @@ function ocn_setup_packages(configPool, packagePool, iocontext) result(ierr)!{{{ landIceCouplingPKGActive = .true. end if + ! + ! test for use of subglacial runoff flux, dataSubglacialRunoffFluxPKGActive + ! + call mpas_pool_get_package(packagePool, 'dataSubglacialRunoffFluxPKGActive', dataSubglacialRunoffFluxPKGActive) + call mpas_pool_get_config(configPool, 'config_subglacial_runoff_mode', config_subglacial_runoff_mode) + if ( trim(config_subglacial_runoff_mode) == 'data' ) then + dataSubglacialRunoffFluxPKGActive = .true. + end if + ! ! test for use of frazil ice formation, frazilIceActive ! diff --git a/components/mpas-ocean/src/mode_init/mpas_ocn_init_vertical_grids.F b/components/mpas-ocean/src/mode_init/mpas_ocn_init_vertical_grids.F index 5c0ac5a0e114..d84291ed376b 100644 --- a/components/mpas-ocean/src/mode_init/mpas_ocn_init_vertical_grids.F +++ b/components/mpas-ocean/src/mode_init/mpas_ocn_init_vertical_grids.F @@ -1480,6 +1480,7 @@ subroutine ocn_init_vertical_grid_with_max_rx1(domain, iErr) call mpas_pool_get_dimension(meshPool, 'nCellsSolve', nCellsSolve) call mpas_pool_get_array(meshPool, 'nEdgesOnCell', nEdgesOnCell) call mpas_pool_get_array(meshPool, 'cellsOnCell', cellsOnCell) + call mpas_pool_get_array(meshPool, 'bottomDepth', bottomDepth) ! Fill bathymetry holes, i.e. single cells that are deeper than all neighbors. ! These cells can collect tracer extrema and are not able to use @@ -1497,6 +1498,9 @@ subroutine ocn_init_vertical_grid_with_max_rx1(domain, iErr) if (maxLevelCell(iCell) > maxLevelNeighbors) then maxLevelCell(iCell) = maxLevelNeighbors + if (smoothingMask(iCell) == 0) then + bottomDepth(iCell) = refBottomDepth(maxLevelNeighbors) + end if end if end do diff --git a/components/mpas-ocean/src/shared/mpas_ocn_diagnostics.F b/components/mpas-ocean/src/shared/mpas_ocn_diagnostics.F index 52ef08267fc1..a2d6586a7d63 100644 --- a/components/mpas-ocean/src/shared/mpas_ocn_diagnostics.F +++ b/components/mpas-ocean/src/shared/mpas_ocn_diagnostics.F @@ -218,6 +218,7 @@ subroutine ocn_diagnostic_solve(dt, statePool, forcingPool, meshPool, verticalMe !! tracersSurfaceValue calc :: minLevelCell (mesh array) !! normalVelocitySurfaceLayer calc :: minLevelEdgeBot (mesh array) !! surfaceFluxAttenuationCoefficientRunoff :: layerThickEdgeFlux (diagnostics array) + !! surfaceFluxAttenuationCoefficientSubglacialRunoff :: layerThickEdgeFlux (diagnostics array) !! ocn_diagnostic_solve_ssh :: ssh, (not on device) !! landIceDraft (not on device) @@ -457,6 +458,11 @@ subroutine ocn_diagnostic_solve(dt, statePool, forcingPool, meshPool, verticalMe indexSurfaceLayerDepth, normalVelocitySurfaceLayer, & sfcFlxAttCoeff, surfaceFluxAttenuationCoefficientRunoff) + if (trim(config_subglacial_runoff_mode) == 'data') then + ! outputs: surfaceFluxAttenuationCoefficientSubglacialRunoff + call ocn_diagnostic_solve_surfaceLayer_subglacialRunoff(surfaceFluxAttenuationCoefficientSubglacialRunoff) + end if + end if ! full_compute ! @@ -522,6 +528,11 @@ subroutine ocn_diagnostic_solve(dt, statePool, forcingPool, meshPool, verticalMe !! normalVelocitySurfaceLayer, (diagnostics array) !! surfaceFluxAttenuationCoefficient, ???? !! surfaceFluxAttenuationCoefficientRunoff (diagnostics array) + !! surfaceFluxAttenuationCoefficientSubglacialRunoff :: tracersSurfaceLayerValue, (diagnostics array) + !! indexSurfaceLayerDepth, (diagnostics array) + !! normalVelocitySurfaceLayer, (diagnostics array) + !! surfaceFluxAttenuationCoefficient, ???? + !! surfaceFluxAttenuationCoefficientSubglacialRunoff (diagnostics array) !! ocn_diagnostic_solve_ssh :: pressureAdjustedSSH, (diagnostics array) !! gradSSH (diagnostics array) @@ -558,6 +569,10 @@ subroutine ocn_diagnostic_solve(dt, statePool, forcingPool, meshPool, verticalMe ! !$acc normalVelocitySurfaceLayer, & ! !$acc sfcFlxAttCoeff, & ! !$acc surfaceFluxAttenuationCoefficientRunoff) +! if (trim(config_subglacial_runoff_mode) == 'data') then +! !$acc update host(surfaceFluxAttenuationCoefficientSubglacialRunoff) +! end if + ! end if ! full_compute ! !$acc exit data delete (atmosphericPressure, seaIcePressure) @@ -1902,6 +1917,69 @@ subroutine ocn_diagnostic_solve_surfaceLayer(layerThickness, & end subroutine ocn_diagnostic_solve_surfaceLayer !}}} +!*********************************************************************** +! +! routine ocn_diagnostic_solve_surfaceLayer_subglacialRunoff +! +!> \brief Computes diagnostic subglacialRunoff variables for surface layer +!> \author Irena Vankova +!> \date July 2024 +!> \details +! +!----------------------------------------------------------------------- + + subroutine ocn_diagnostic_solve_surfaceLayer_subglacialRunoff(surfaceFluxAttenuationCoefficientSubglacialRunoff)!{{{ + + !----------------------------------------------------------------- + ! input variables + !----------------------------------------------------------------- + + !----------------------------------------------------------------- + ! output variables + !----------------------------------------------------------------- + + real (kind=RKIND), dimension(:), intent(out) :: & + surfaceFluxAttenuationCoefficientSubglacialRunoff !< [out] sfc flx attenuation + + !----------------------------------------------------------------- + ! local variables + !----------------------------------------------------------------- + + integer :: & + nCells, &! num of cells + iCell ! loop indices for cell + + ! End preamble + !----------------------------------------------------------------- + ! Begin code + + ! compute the attenuation coefficient for subglacial runoff surface fluxes + + nCells = nCellsHalo( 1 ) + +#ifdef MPAS_OPENACC + !$acc parallel loop & + !$acc present(surfaceFluxAttenuationCoefficientSubglacialRunoff) +#else + !$omp parallel + !$omp do schedule(runtime) +#endif + do iCell = 1, nCells + surfaceFluxAttenuationCoefficientSubglacialRunoff(iCell) = & + config_flux_attenuation_coefficient_subglacial_runoff + end do +#ifndef MPAS_OPENACC + !$omp end do + !$omp end parallel +#endif + + !-------------------------------------------------------------------- + + end subroutine ocn_diagnostic_solve_surfaceLayer_subglacialRunoff !}}} + +!*********************************************************************** + + !*********************************************************************** ! ! routine ocn_diagnostic_solve_GMvel @@ -3275,15 +3353,18 @@ subroutine ocn_compute_KPP_input_fields(statePool, forcingPool, & !----------------------------------------------------------------- integer :: & - iCell, iEdge, i, &! loop indices for cell, edge, neighbors - kmin, &! topmost active cell index - nCells, &! number of cells - err, &! local error code - timeLevel ! time level for state variables (default 1) + iCell, iEdge, i, k, &! loop indices for cell, edge, neighbors + kmin, &! topmost active cell index + nCells, &! number of cells + err, &! local error code + timeLevel ! time level for state variables (default 1) real (kind=RKIND) :: & fracAbsorbed, &! fraction of sfc flux absorbed fracAbsorbedRunoff, &! same for runoff + fracAbsorbedSubglacialRunoff, &! same for subglacial runoff + zTop,zBot, &! temporary variables + transmissionCoeffTop,transmissionCoeffBot, &! temporary variables sumSurfaceStressSquared ! sum of sfc stress squared ! pointers for variable/pool retrievals @@ -3299,6 +3380,7 @@ subroutine ocn_compute_KPP_input_fields(statePool, forcingPool, & penetrativeTemperatureFlux, &! various sfc flux components surfaceThicknessFlux, & surfaceThicknessFluxRunoff, & + surfaceThicknessFluxSubglacialRunoff, & rainTemperatureFlux, & evapTemperatureFlux, & icebergTemperatureFlux, & @@ -3311,6 +3393,7 @@ subroutine ocn_compute_KPP_input_fields(statePool, forcingPool, & normalVelocity, &! normal velocity activeTracersSurfaceFlux, &! sfc flux of active tracers (T,S) activeTracersSurfaceFluxRunoff, &! flx of tracers in runoff + activeTracersSurfaceFluxSubglacialRunoff, &! flx of tracers in subglacial runoff nonLocalSurfaceTracerFlux ! non-local flux of tracers real (kind=RKIND), dimension(:,:,:), pointer :: & @@ -3374,11 +3457,16 @@ subroutine ocn_compute_KPP_input_fields(statePool, forcingPool, & call mpas_pool_get_array(tracersSurfaceFluxPool, & 'activeTracersSurfaceFluxRunoff', & activeTracersSurfaceFluxRunoff) + call mpas_pool_get_array(tracersSurfaceFluxPool, & + 'activeTracersSurfaceFluxSubglacialRunoff', & + activeTracersSurfaceFluxSubglacialRunoff) call mpas_pool_get_array(forcingPool, 'surfaceThicknessFlux', & surfaceThicknessFlux) call mpas_pool_get_array(forcingPool, 'surfaceThicknessFluxRunoff', & surfaceThicknessFluxRunoff) + call mpas_pool_get_array(forcingPool, 'surfaceThicknessFluxSubglacialRunoff', & + surfaceThicknessFluxSubglacialRunoff) call mpas_pool_get_array(forcingPool, 'penetrativeTemperatureFlux', & penetrativeTemperatureFlux) call mpas_pool_get_array(forcingPool, 'surfaceStress', & @@ -3451,7 +3539,7 @@ subroutine ocn_compute_KPP_input_fields(statePool, forcingPool, & !$omp parallel !$omp do schedule(runtime) & - !$omp private(kmin, fracAbsorbed, fracAbsorbedRunoff, & + !$omp private(kmin, fracAbsorbed, fracAbsorbedRunoff, fracAbsorbedSubglacialRunoff, & !$omp sumSurfaceStressSquared, i, iEdge) do iCell = 1, nCells @@ -3465,6 +3553,37 @@ subroutine ocn_compute_KPP_input_fields(statePool, forcingPool, & - exp( max(-100.0_RKIND, & -layerThickness(kmin, iCell)/ & config_flux_attenuation_coefficient_runoff)) + if (trim(config_subglacial_runoff_mode) == 'data') then + if (config_use_sgr_opt_kpp) then + if ( trim(config_sgr_flux_vertical_location) == 'top' ) then + fracAbsorbedSubglacialRunoff = 1.0_RKIND & + - exp( max(-100.0_RKIND, & + -layerThickness(kmin, iCell)/ & + config_flux_attenuation_coefficient_subglacial_runoff)) + else if ( trim(config_sgr_flux_vertical_location) == 'uniform' ) then + ! calculate total thickness into variable zTop + zTop = 0.0_RKIND + do k = minLevelCell(iCell), maxLevelCell(iCell) + zTop = zTop + layerThickness(k,iCell) + end do + ! distribute flux evenly throughout water column + fracAbsorbedSubglacialRunoff = layerThickness(kmin, iCell) / zTop + else if ( trim(config_sgr_flux_vertical_location) == 'bottom' ) then + zTop = 0.0_RKIND + do k = maxLevelCell(iCell), minLevelCell(iCell), -1 + zBot = zTop - layerThickness(k,iCell) + if (k == minLevelCell(iCell)) then + transmissionCoeffTop = exp( max(zTop / config_flux_attenuation_coefficient_runoff, -100.0_RKIND) ) + transmissionCoeffBot = exp( max(zBot / config_flux_attenuation_coefficient_runoff, -100.0_RKIND) ) + fracAbsorbedSubglacialRunoff = transmissionCoeffTop - transmissionCoeffBot + end if + zTop = zBot + end do + end if + else + fracAbsorbedSubglacialRunoff = 0.0_RKIND + end if + end if ! Store the total tracer flux below in ! nonLocalSurfaceTemperatureFlux for use in the CVMix nonlocal @@ -3480,6 +3599,11 @@ subroutine ocn_compute_KPP_input_fields(statePool, forcingPool, & icebergTemperatureFlux(iCell)) & - fracAbsorbedRunoff* & activeTracersSurfaceFluxRunoff(indexTempFlux,iCell) + if (trim(config_subglacial_runoff_mode) == 'data') then + nonLocalSurfaceTracerFlux(indexTempFlux, iCell) = nonLocalSurfaceTracerFlux(indexTempFlux, iCell) & + - fracAbsorbedSubglacialRunoff* & + activeTracersSurfaceFluxSubglacialRunoff(indexTempFlux,iCell) + end if nonLocalSurfaceTracerFlux(indexSaltFlux,iCell) = & activeTracersSurfaceFlux(indexSaltFlux,iCell) & @@ -3487,6 +3611,11 @@ subroutine ocn_compute_KPP_input_fields(statePool, forcingPool, & activeTracers(indexSaltFlux,kmin,iCell) & - fracAbsorbedRunoff*surfaceThicknessFluxRunoff(iCell)* & activeTracers(indexSaltFlux,kmin,iCell) + if (trim(config_subglacial_runoff_mode) == 'data') then + nonLocalSurfaceTracerFlux(indexSaltFlux,iCell) = nonLocalSurfaceTracerFlux(indexSaltFlux,iCell) & + - fracAbsorbedSubglacialRunoff*surfaceThicknessFluxSubglacialRunoff(iCell)* & + activeTracers(indexSaltFlux,kmin,iCell) + end if surfaceBuoyancyForcing(iCell) = & thermalExpansionCoeff(kmin,iCell)* & @@ -4428,6 +4557,21 @@ subroutine ocn_validate_state(domain, timeLevel)!{{{ call ocn_write_field_statistics(debugUnit, fieldName, minValue, maxValue) end if + if (trim(config_subglacial_runoff_mode) == 'data') then + ! Test subglacialRunoffFlux + fieldName = 'subglacialRunoffFlux' + minValue = HUGE(minValue) + maxValue = -HUGE(maxValue) + call mpas_pool_get_array(forcingPool, fieldName, real1DArr) + if ( associated(real1DArr) ) then + do iCell = 1, nCellsSolve + minValue = min( minValue, real1DArr(iCell) ) + maxValue = max( maxValue, real1DArr(iCell) ) + end do + call ocn_write_field_statistics(debugUnit, fieldName, minValue, maxValue) + end if + end if + ! Test seaIceSalinityFlux fieldName = 'seaIceSalinityFlux' minValue = HUGE(minValue) @@ -4598,6 +4742,12 @@ subroutine ocn_diagnostics_init(domain, err)!{{{ call ocn_diagnostics_variables_init(domain, jenkinsOn, & hollandJenkinsOn, err) + if ( trim(config_sgr_flux_vertical_location) /= 'top' .and. & + trim(config_sgr_flux_vertical_location) /= 'uniform' .and. & + trim(config_sgr_flux_vertical_location) /= 'bottom' ) then + call mpas_log_write("config_sgr_flux_vertical_location not one of 'bottom', 'uniform', 'top'.", MPAS_LOG_CRIT) + end if + end subroutine ocn_diagnostics_init!}}} !*********************************************************************** diff --git a/components/mpas-ocean/src/shared/mpas_ocn_diagnostics_variables.F b/components/mpas-ocean/src/shared/mpas_ocn_diagnostics_variables.F index 30a62f68c8b9..38f32f88e17c 100644 --- a/components/mpas-ocean/src/shared/mpas_ocn_diagnostics_variables.F +++ b/components/mpas-ocean/src/shared/mpas_ocn_diagnostics_variables.F @@ -85,6 +85,7 @@ module ocn_diagnostics_variables real (kind=RKIND), dimension(:), pointer :: sfcFlxAttCoeff real (kind=RKIND), dimension(:), pointer :: surfaceFluxAttenuationCoefficientRunoff + real (kind=RKIND), dimension(:), pointer :: surfaceFluxAttenuationCoefficientSubglacialRunoff real (kind=RKIND), dimension(:), pointer :: landIceFrictionVelocity real (kind=RKIND), dimension(:), pointer :: velocityTidalRMS @@ -680,6 +681,9 @@ subroutine ocn_diagnostics_variables_init(domain, jenkinsOn, hollandJenkinsOn, e call mpas_pool_get_array(diagnosticsPool, & 'surfaceFluxAttenuationCoefficientRunoff', & surfaceFluxAttenuationCoefficientRunoff) + call mpas_pool_get_array(diagnosticsPool, & + 'surfaceFluxAttenuationCoefficientSubglacialRunoff', & + surfaceFluxAttenuationCoefficientSubglacialRunoff) call mpas_pool_get_array(diagnosticsPool, & 'boundaryLayerDepth', & boundaryLayerDepth) @@ -964,7 +968,8 @@ subroutine ocn_diagnostics_variables_init(domain, jenkinsOn, hollandJenkinsOn, e !$acc Time_bnds, & !$acc simulationStartTime, & !$acc boundaryLayerDepthSmooth, & - !$acc surfaceFluxAttenuationCoefficientRunoff & + !$acc surfaceFluxAttenuationCoefficientRunoff, & + !$acc surfaceFluxAttenuationCoefficientSubglacialRunoff & !$acc ) end subroutine ocn_diagnostics_variables_init!}}} @@ -1223,7 +1228,8 @@ subroutine ocn_diagnostics_variables_destroy(err) !{{{ !$acc Time_bnds, & !$acc simulationStartTime, & !$acc boundaryLayerDepthSmooth, & - !$acc surfaceFluxAttenuationCoefficientRunoff & + !$acc surfaceFluxAttenuationCoefficientRunoff, & + !$acc surfaceFluxAttenuationCoefficientSubglacialRunoff & !$acc ) ! Nullify pointers @@ -1425,7 +1431,8 @@ subroutine ocn_diagnostics_variables_destroy(err) !{{{ Time_bnds, & simulationStartTime, & boundaryLayerDepthSmooth, & - surfaceFluxAttenuationCoefficientRunoff) + surfaceFluxAttenuationCoefficientRunoff, & + surfaceFluxAttenuationCoefficientSubglacialRunoff) end subroutine ocn_diagnostics_variables_destroy!}}} diff --git a/components/mpas-ocean/src/shared/mpas_ocn_forcing.F b/components/mpas-ocean/src/shared/mpas_ocn_forcing.F index 99a674cd45fa..5cfce4c4e690 100644 --- a/components/mpas-ocean/src/shared/mpas_ocn_forcing.F +++ b/components/mpas-ocean/src/shared/mpas_ocn_forcing.F @@ -27,6 +27,7 @@ module ocn_forcing use mpas_dmpar use ocn_constants use ocn_diagnostics_variables + use ocn_config implicit none private @@ -122,7 +123,7 @@ subroutine ocn_forcing_build_fraction_absorbed_array(meshPool, statePool, forcin real (kind=RKIND) :: zTop, zBot, transmissionCoeffTop, transmissionCoeffBot - real (kind=RKIND), dimension(:,:), pointer :: layerThickness, fractionAbsorbed, fractionAbsorbedRunoff + real (kind=RKIND), dimension(:,:), pointer :: layerThickness, fractionAbsorbed, fractionAbsorbedRunoff, fractionAbsorbedSubglacialRunoff integer :: iCell, k, timeLevel, nCells @@ -147,6 +148,7 @@ subroutine ocn_forcing_build_fraction_absorbed_array(meshPool, statePool, forcin call mpas_pool_get_array(forcingPool, 'fractionAbsorbed', fractionAbsorbed) call mpas_pool_get_array(forcingPool, 'fractionAbsorbedRunoff', fractionAbsorbedRunoff) + call mpas_pool_get_array(forcingPool, 'fractionAbsorbedSubglacialRunoff', fractionAbsorbedSubglacialRunoff) nCells = nCellsArray( 2 ) @@ -180,6 +182,48 @@ subroutine ocn_forcing_build_fraction_absorbed_array(meshPool, statePool, forcin end do end do +! now do subglacial runoff separately + if ( trim(config_subglacial_runoff_mode) == 'data' ) then + if ( trim(config_sgr_flux_vertical_location) == 'top' ) then + do iCell = 1, nCells + zTop = 0.0_RKIND + transmissionCoeffTop = ocn_forcing_transmission(zTop, surfaceFluxAttenuationCoefficientSubglacialRunoff(iCell)) + do k = minLevelCell(iCell), maxLevelCell(iCell) + zBot = zTop - layerThickness(k,iCell) + transmissionCoeffBot = ocn_forcing_transmission(zBot, surfaceFluxAttenuationCoefficientSubglacialRunoff(iCell)) + fractionAbsorbedSubglacialRunoff(k, iCell) = transmissionCoeffTop - transmissionCoeffBot + zTop = zBot + transmissionCoeffTop = transmissionCoeffBot + end do + end do + else if ( trim(config_sgr_flux_vertical_location) == 'uniform' ) then + do iCell = 1, nCells + ! calculate total thickness + zTop = 0.0_RKIND + do k = minLevelCell(iCell), maxLevelCell(iCell) + zTop = zTop + layerThickness(k,iCell) + end do + ! distribute flux evenly throughout water column + zBot = 0.0_RKIND + do k = minLevelCell(iCell), maxLevelCell(iCell) + fractionAbsorbedSubglacialRunoff(k, iCell) = layerThickness(k,iCell) / zTop + end do + end do + else if ( trim(config_sgr_flux_vertical_location) == 'bottom' ) then + do iCell = 1, nCells + zTop = 0.0_RKIND + transmissionCoeffTop = ocn_forcing_transmission(zTop, surfaceFluxAttenuationCoefficientSubglacialRunoff(iCell)) + do k = maxLevelCell(iCell), minLevelCell(iCell), -1 + zBot = zTop - layerThickness(k,iCell) + transmissionCoeffBot = ocn_forcing_transmission(zBot, surfaceFluxAttenuationCoefficientSubglacialRunoff(iCell)) + fractionAbsorbedSubglacialRunoff(k, iCell) = transmissionCoeffTop - transmissionCoeffBot + zTop = zBot + transmissionCoeffTop = transmissionCoeffBot + end do + end do + end if + end if + end subroutine ocn_forcing_build_fraction_absorbed_array!}}} !*********************************************************************** diff --git a/components/mpas-ocean/src/shared/mpas_ocn_surface_bulk_forcing.F b/components/mpas-ocean/src/shared/mpas_ocn_surface_bulk_forcing.F index e28c8f1e5819..11d70ae9c40d 100644 --- a/components/mpas-ocean/src/shared/mpas_ocn_surface_bulk_forcing.F +++ b/components/mpas-ocean/src/shared/mpas_ocn_surface_bulk_forcing.F @@ -49,7 +49,10 @@ module ocn_surface_bulk_forcing public :: ocn_surface_bulk_forcing_tracers, & ocn_surface_bulk_forcing_vel, & ocn_surface_bulk_forcing_thick, & - ocn_surface_bulk_forcing_init + ocn_surface_bulk_forcing_init, & + ocn_surface_bulk_forcing_tracers_subglacial_runoff, & + ocn_surface_bulk_forcing_thick_subglacial_runoff + !-------------------------------------------------------------------- ! @@ -128,6 +131,63 @@ subroutine ocn_surface_bulk_forcing_tracers(meshPool, groupName, forcingPool, tr end subroutine ocn_surface_bulk_forcing_tracers!}}} +!*********************************************************************** +! +! routine ocn_surface_bulk_forcing_tracers_subglacial_runoff +! +!> \brief Determines the tracers forcing array used for the bulk forcing. +!> \author Irena Vankova +!> \date July 2024 +!> \details +!> This routine computes the tracers forcing arrays used later in MPAS. +! +!----------------------------------------------------------------------- + + subroutine ocn_surface_bulk_forcing_tracers_subglacial_runoff(meshPool, groupName, forcingPool, & + tracersSurfaceFluxSubglacialRunoff, err)!{{{ + + !----------------------------------------------------------------- + ! + ! input variables + ! + !----------------------------------------------------------------- + type (mpas_pool_type), intent(in) :: meshPool !< Input: mesh information + character (len=*) :: groupName !< Input: Name of tracer group + + !----------------------------------------------------------------- + ! + ! input/output variables + ! + !----------------------------------------------------------------- + type (mpas_pool_type), intent(inout) :: forcingPool !< Input: Forcing information + real (kind=RKIND), dimension(:,:), intent(inout) :: & + tracersSurfaceFluxSubglacialRunoff !< Input/Output: Surface flux for tracer group due to subglacial runoff + + !----------------------------------------------------------------- + ! + ! output variables + ! + !----------------------------------------------------------------- + + integer, intent(out) :: err !< Output: Error flag + + !----------------------------------------------------------------- + ! + ! local variables + ! + !----------------------------------------------------------------- + + err = 0 + + call mpas_timer_start("bulk_" // trim(groupName)) + if ( trim(groupName) == 'activeTracers' ) then + call ocn_surface_bulk_forcing_active_tracers_subglacial_runoff(meshPool, forcingPool, & + tracersSurfaceFluxSubglacialRunoff, err) + end if + call mpas_timer_stop("bulk_" // trim(groupName)) + + end subroutine ocn_surface_bulk_forcing_tracers_subglacial_runoff!}}} + !*********************************************************************** ! ! routine ocn_surface_bulk_forcing_vel @@ -333,8 +393,10 @@ subroutine ocn_surface_bulk_forcing_thick(forcingPool, surfaceThicknessFlux, sur !$acc riverRunoffFlux, iceRunoffFlux, rainFlux) !$acc parallel loop & - !$acc present(surfaceThicknessFlux, surfaceThicknessFluxRunoff, evaporationFlux, snowFlux, & - !$acc seaIceFreshWaterFlux, icebergFreshWaterFlux, riverRunoffFlux, iceRunoffFlux, rainFlux) + !$acc present(surfaceThicknessFlux, surfaceThicknessFluxRunoff, & + !$acc evaporationFlux, snowFlux, & + !$acc seaIceFreshWaterFlux, icebergFreshWaterFlux, riverRunoffFlux, & + !$acc iceRunoffFlux, rainFlux) #else !$omp parallel !$omp do schedule(runtime) @@ -358,6 +420,85 @@ subroutine ocn_surface_bulk_forcing_thick(forcingPool, surfaceThicknessFlux, sur end subroutine ocn_surface_bulk_forcing_thick!}}} +!*********************************************************************** +! +! routine ocn_surface_bulk_forcing_thick_subglacial_runoff +! +!> \brief Determines the thickness forcing array used for the bulk forcing. +!> \author Irena Vankova +!> \date July 2024 +!> \details +!> This routine computes the thickness forcing arrays used later in MPAS. +! +!----------------------------------------------------------------------- + + subroutine ocn_surface_bulk_forcing_thick_subglacial_runoff(forcingPool, surfaceThicknessFluxSubglacialRunoff, err)!{{{ + + !----------------------------------------------------------------- + ! + ! input/output variables + ! + !----------------------------------------------------------------- + type (mpas_pool_type), intent(inout) :: forcingPool !< Input: Forcing information + real (kind=RKIND), dimension(:), intent(inout) :: & + surfaceThicknessFluxSubglacialRunoff !< Input/Output: Array for surface thickness flux due to subglacial runoff + + !----------------------------------------------------------------- + ! + ! output variables + ! + !----------------------------------------------------------------- + + integer, intent(out) :: err !< Output: Error flag + + !----------------------------------------------------------------- + ! + ! local variables + ! + !----------------------------------------------------------------- + + integer :: iCell, nCells + + real (kind=RKIND), dimension(:), pointer :: subglacialRunoffFlux + + err = 0 + + if (bulkThicknessFluxOff) return + + call mpas_timer_start("bulk_thick", .false.) + + call mpas_pool_get_array(forcingPool, 'subglacialRunoffFlux', subglacialRunoffFlux) + + nCells = nCellsHalo( 2 ) + + ! Build surface fluxes at cell centers + +#ifdef MPAS_OPENACC + !$acc enter data copyin(subglacialRunoffFlux) + + !$acc parallel loop & + !$acc present(surfaceThicknessFluxSubglacialRunoff, subglacialRunoffFlux) +#else + !$omp parallel + !$omp do schedule(runtime) +#endif + do iCell = 1, nCells + surfaceThicknessFluxSubglacialRunoff(iCell) = subglacialRunoffFlux(iCell) / rho_sw + end do +#ifndef MPAS_OPENACC + !$omp end do + !$omp end parallel +#endif + +#ifdef MPAS_OPENACC + !$acc exit data delete(subglacialRunoffFlux) +#endif + + call mpas_timer_stop("bulk_thick") + + end subroutine ocn_surface_bulk_forcing_thick_subglacial_runoff!}}} + + !*********************************************************************** ! ! routine ocn_surface_bulk_forcing_init @@ -470,6 +611,7 @@ subroutine ocn_surface_bulk_forcing_active_tracers(meshPool, forcingPool, tracer real (kind=RKIND), dimension(:), pointer :: rainTemperatureFlux, evapTemperatureFlux, & seaIceTemperatureFlux, icebergTemperatureFlux, & totalFreshWaterTemperatureFlux + real (kind=RKIND), dimension(:), pointer :: landIcePressure real (kind=RKIND) :: requiredSalt, allowedSalt, surfaceTemperatureFluxWithoutRunoff err = 0 @@ -505,6 +647,8 @@ subroutine ocn_surface_bulk_forcing_active_tracers(meshPool, forcingPool, tracer call mpas_pool_get_array(forcingPool, 'riverRunoffFlux', riverRunoffFlux) call mpas_pool_get_array(forcingPool, 'penetrativeTemperatureFlux', penetrativeTemperatureFlux) + call mpas_pool_get_array(forcingPool, 'landIcePressure', landIcePressure) + call mpas_pool_get_array(forcingPool, 'rainTemperatureFlux', rainTemperatureFlux) call mpas_pool_get_array(forcingPool, 'evapTemperatureFlux', evapTemperatureFlux) call mpas_pool_get_array(forcingPool, 'seaIceTemperatureFlux', seaIceTemperatureFlux) @@ -565,7 +709,7 @@ subroutine ocn_surface_bulk_forcing_active_tracers(meshPool, forcingPool, tracer * max(tracerGroup(index_temperature_flux,minLevelCell(iCell),iCell), 0.0_RKIND) / rho_sw ! Accumulate fluxes that use the freezing point -! mrp performance note: should call ocn_freezing_temperature just once here +! mrp performance note: should call ocn_freezing_temperature just once here seaIceTemperatureFlux(iCell) = seaIceFreshWaterFlux(iCell) * & ocn_freezing_temperature( tracerGroup(index_salinity_flux, minLevelCell(iCell), iCell), pressure=0.0_RKIND, & inLandIceCavity=.false.) / rho_sw @@ -579,7 +723,7 @@ subroutine ocn_surface_bulk_forcing_active_tracers(meshPool, forcingPool, tracer tracersSurfaceFlux(index_temperature_flux, iCell) = tracersSurfaceFlux(index_temperature_flux, iCell) & + surfaceTemperatureFluxWithoutRunoff - ! add runoff contribution for sending through coupler + ! add river runoff contribution for sending through coupler totalFreshWaterTemperatureFlux(iCell) = surfaceTemperatureFluxWithoutRunoff & + tracersSurfaceFluxRunoff(index_temperature_flux,iCell) @@ -603,6 +747,125 @@ subroutine ocn_surface_bulk_forcing_active_tracers(meshPool, forcingPool, tracer end subroutine ocn_surface_bulk_forcing_active_tracers!}}} +!*********************************************************************** +! +! routine ocn_surface_bulk_forcing_active_tracers_subglacial_runoff +! +!> \brief Determines the active tracers forcing array used for the bulk forcing. +!> \author Irena Vankova +!> \date July 2024 +!> \details +!> This routine computes the active tracers forcing arrays used later in MPAS. +! +!----------------------------------------------------------------------- + + subroutine ocn_surface_bulk_forcing_active_tracers_subglacial_runoff(meshPool, forcingPool, & + tracersSurfaceFluxSubglacialRunoff, err)!{{{ + + !----------------------------------------------------------------- + ! + ! input variables + ! + !----------------------------------------------------------------- + type (mpas_pool_type), intent(in) :: meshPool !< Input: mesh information + + !----------------------------------------------------------------- + ! + ! input/output variables + ! + !----------------------------------------------------------------- + type (mpas_pool_type), intent(inout) :: forcingPool !< Input: Forcing information + real (kind=RKIND), dimension(:,:), intent(inout) :: tracersSurfaceFluxSubglacialRunoff + + !----------------------------------------------------------------- + ! + ! output variables + ! + !----------------------------------------------------------------- + + integer, intent(out) :: err !< Output: Error flag + + !----------------------------------------------------------------- + ! + ! local variables + ! + !----------------------------------------------------------------- + + integer :: iCell, nCells + integer, pointer :: index_temperature_fluxPtr, index_salinity_fluxPtr + integer :: index_temperature_flux, index_salinity_flux + integer, dimension(:), pointer :: nCellsArray + + type(mpas_pool_type),pointer :: tracersSurfaceFluxPool + + real (kind=RKIND), dimension(:), pointer :: subglacialRunoffFlux + real (kind=RKIND), dimension(:), pointer :: totalFreshWaterTemperatureFlux + real (kind=RKIND), dimension(:), pointer :: landIcePressure + + err = 0 + + call mpas_pool_get_dimension(meshPool, 'nCellsArray', nCellsArray) + + call mpas_pool_get_subpool(forcingPool, 'tracersSurfaceFlux',tracersSurfaceFluxPool) + + call mpas_pool_get_dimension(tracersSurfaceFluxPool, & + 'index_temperatureSurfaceFlux', & + index_temperature_fluxPtr) + call mpas_pool_get_dimension(tracersSurfaceFluxPool, & + 'index_salinitySurfaceFlux', & + index_salinity_fluxPtr) + index_temperature_flux = index_temperature_fluxPtr + index_salinity_flux = index_salinity_fluxPtr + + call mpas_pool_get_array(forcingPool, 'subglacialRunoffFlux', subglacialRunoffFlux) + + call mpas_pool_get_array(forcingPool, 'landIcePressure', landIcePressure) + + call mpas_pool_get_array(forcingPool, 'totalFreshWaterTemperatureFlux', totalFreshWaterTemperatureFlux) + + nCells = nCellsArray( 3 ) + + ! Surface fluxes of water have an associated heat content, but the coupled system does not account for this + ! Assume surface fluxes of water have a temperature dependent on the incoming mass flux. + ! Assume surface fluxes of water have zero salinity. So the RHS forcing is zero for salinity. + ! Only include this heat forcing when bulk thickness is turned on + ! indices on tracerGroup are (iTracer, iLevel, iCell) + if (.not. bulkThicknessFluxOff) then + !$omp parallel + !$omp do schedule(runtime) + do iCell = 1, nCells + + if ( config_use_sgr_opt_temp_prescribed ) then + !sgr with fixed prescribed temperature + tracersSurfaceFluxSubglacialRunoff(index_temperature_flux,iCell) = subglacialRunoffFlux(iCell) * & + config_sgr_temperature_prescribed / rho_sw + else + !sgr with temperature equal to the local freezing point of freshwater + tracersSurfaceFluxSubglacialRunoff(index_temperature_flux,iCell) = subglacialRunoffFlux(iCell) * & + ocn_freezing_temperature(salinity=0.0_RKIND, pressure=landIcePressure(iCell), & + inLandIceCavity=.true.) / rho_sw + end if + + if ( config_use_sgr_opt_salt_prescribed ) then + !sgr with fixed prescribed temperature + tracersSurfaceFluxSubglacialRunoff(index_salinity_flux,iCell) = subglacialRunoffFlux(iCell) * & + config_sgr_salinity_prescribed / rho_sw + else + !sgr with temperature equal to the local freezing point of freshwater + tracersSurfaceFluxSubglacialRunoff(index_salinity_flux,iCell) = 0.0_RKIND + end if + + ! add subglacial runoff contribution for sending through coupler + totalFreshWaterTemperatureFlux(iCell) = totalFreshWaterTemperatureFlux(iCell) & + + tracersSurfaceFluxSubglacialRunoff(index_temperature_flux,iCell) + + end do + !$omp end do + !$omp end parallel + endif ! bulkThicknessFluxOn + + end subroutine ocn_surface_bulk_forcing_active_tracers_subglacial_runoff!}}} + end module ocn_surface_bulk_forcing diff --git a/components/mpas-ocean/src/shared/mpas_ocn_tendency.F b/components/mpas-ocean/src/shared/mpas_ocn_tendency.F index a16e52f14499..f85427913b09 100644 --- a/components/mpas-ocean/src/shared/mpas_ocn_tendency.F +++ b/components/mpas-ocean/src/shared/mpas_ocn_tendency.F @@ -128,12 +128,14 @@ subroutine ocn_tend_thick(tendPool, forcingPool)!{{{ ! pointers for the actual output variables within the pools above real (kind=RKIND), dimension(:), pointer, contiguous :: & surfaceThicknessFlux, &! surface thickness flux - surfaceThicknessFluxRunoff ! surface thickness flux from runoff + surfaceThicknessFluxRunoff, &! surface thickness flux from runoff + surfaceThicknessFluxSubglacialRunoff ! surface thickness flux from runoff real (kind=RKIND), dimension(:,:), pointer, contiguous :: & tendThick, &! accumulated layer thickness tendency fractionAbsorbed, &! fraction of sfc flux absorbed - fractionAbsorbedRunoff ! fraction of runoff flux absorbed + fractionAbsorbedRunoff, &! fraction of sfc flux absorbed + fractionAbsorbedSubglacialRunoff ! fraction of subglacial runoff flux absorbed !----------------------------------------------------------------- ! local variables @@ -154,10 +156,16 @@ subroutine ocn_tend_thick(tendPool, forcingPool)!{{{ surfaceThicknessFlux) call mpas_pool_get_array(forcingPool, 'surfaceThicknessFluxRunoff', & surfaceThicknessFluxRunoff) + call mpas_pool_get_array(forcingPool, 'surfaceThicknessFluxSubglacialRunoff', & + surfaceThicknessFluxSubglacialRunoff) call mpas_pool_get_array(forcingPool, 'fractionAbsorbed', & fractionAbsorbed) call mpas_pool_get_array(forcingPool, 'fractionAbsorbedRunoff', & fractionAbsorbedRunoff) + call mpas_pool_get_array(forcingPool, 'fractionAbsorbedSubglacialRunoff', & + fractionAbsorbedSubglacialRunoff) + + ! ! layer thickness tendency: @@ -185,6 +193,25 @@ subroutine ocn_tend_thick(tendPool, forcingPool)!{{{ !$omp end parallel #endif + if (trim(config_subglacial_runoff_mode) == 'data') then +#ifdef MPAS_OPENACC + !$acc enter data create(surfaceThicknessFluxSubglacialRunoff) + + !$acc parallel loop & + !$acc present(surfaceThicknessFluxSubglacialRunoff) +#else + !$omp parallel + !$omp do schedule(runtime) +#endif + do iCell = 1, nCellsAll + surfaceThicknessFluxSubglacialRunoff(iCell) = 0.0_RKIND + end do +#ifndef MPAS_OPENACC + !$omp end do + !$omp end parallel +#endif + end if + ! If turned off, return with zero fluxes, tendencies ! Otherwise, start time and call routines to accumulate if (config_disable_thick_all_tend) return @@ -195,6 +222,11 @@ subroutine ocn_tend_thick(tendPool, forcingPool)!{{{ surfaceThicknessFlux, & surfaceThicknessFluxRunoff, err) + if (trim(config_subglacial_runoff_mode) == 'data') then + call ocn_surface_bulk_forcing_thick_subglacial_runoff(forcingPool, & + surfaceThicknessFluxSubglacialRunoff, err) + end if + ! Compute surface thickness flux from land ice call ocn_surface_land_ice_fluxes_thick(forcingPool, & surfaceThicknessFlux, err) @@ -217,6 +249,11 @@ subroutine ocn_tend_thick(tendPool, forcingPool)!{{{ surfaceThicknessFlux, & surfaceThicknessFluxRunoff, & tendThick, err) + if (trim(config_subglacial_runoff_mode) == 'data') then + call ocn_thick_surface_flux_tend_subglacial_runoff(fractionAbsorbedSubglacialRunoff, & + surfaceThicknessFluxSubglacialRunoff, & + tendThick, err) + end if ! Compute contribution from frazil ice formation call ocn_frazil_forcing_layer_thickness(forcingPool, & @@ -230,7 +267,8 @@ subroutine ocn_tend_thick(tendPool, forcingPool)!{{{ call ocn_manufactured_solution_tend_thick(tendThick, err) #ifdef MPAS_OPENACC - !$acc exit data copyout(tendThick, surfaceThicknessFlux, surfaceThicknessFluxRunoff) + !$acc exit data copyout(tendThick, surfaceThicknessFlux, surfaceThicknessFluxRunoff, & + !$acc surfaceThicknessFluxSubglacialRunoff) #endif call mpas_timer_stop("ocn_tend_thick") @@ -600,9 +638,11 @@ subroutine ocn_tend_tracer(tendPool, statePool, forcingPool, & real (kind=RKIND), dimension(:,:), pointer, contiguous :: & layerThickness, &! layer thickness tracerGroupSurfaceFlux, &! tracer flux at surface - fractionAbsorbed, &! frac sfc flux aborbed - fractionAbsorbedRunoff, &! frac runoff flux aborbed + fractionAbsorbed, &! frac sfc flux absorbed + fractionAbsorbedRunoff, &! frac runoff flux absorbed + fractionAbsorbedSubglacialRunoff, &! frac subglacial runoff flux absorbed tracerGroupSurfaceFluxRunoff, &! runoff flux + tracerGroupSurfaceFluxSubglacialRunoff, &! subglacial runoff flux tracerGroupSurfaceFluxRemoved,&! total sfc flux absorbed nonLocalSurfaceTracerFlux ! non-local fluxes (eg KPP) @@ -664,6 +704,8 @@ subroutine ocn_tend_tracer(tendPool, statePool, forcingPool, & fractionAbsorbed) call mpas_pool_get_array(forcingPool, 'fractionAbsorbedRunoff', & fractionAbsorbedRunoff) + call mpas_pool_get_array(forcingPool, 'fractionAbsorbedSubglacialRunoff', & + fractionAbsorbedSubglacialRunoff) ! allocate and transfer data not specific to tracer groups allocate(normalThicknessFlux(nVertLevels, nEdgesAll+1)) @@ -788,6 +830,16 @@ subroutine ocn_tend_tracer(tendPool, statePool, forcingPool, & modifiedGroupName, & tracerGroupSurfaceFluxRunoff) + if (trim(config_subglacial_runoff_mode) == 'data') then + ! Get surface flux due to subglacial runoff array + ! only active tracers have subglacial runoff flux for now, + ! but we still need to associate for ALL tracers + modifiedGroupName = groupName // "SurfaceFluxSubglacialRunoff" + call mpas_pool_get_array(tracersSurfaceFluxPool, & + modifiedGroupName, & + tracerGroupSurfaceFluxSubglacialRunoff) + end if + ! Get surface flux removed array to keep track of how much ! flux is ignored modifiedGroupName = groupName // "SurfaceFluxRemoved" @@ -820,6 +872,18 @@ subroutine ocn_tend_tracer(tendPool, statePool, forcingPool, & !$omp end do !$omp end parallel + if (trim(config_subglacial_runoff_mode) == 'data') then + !$omp parallel + !$omp do schedule(runtime) private(n) + do iCell = 1, nCellsAll + do n=1,nTracersGroup + tracerGroupSurfaceFluxSubglacialRunoff (n,iCell) = 0.0_RKIND + end do + end do + !$omp end do + !$omp end parallel + end if + ! ! compute surface tracer flux from bulk forcing ! @@ -831,6 +895,11 @@ subroutine ocn_tend_tracer(tendPool, statePool, forcingPool, & tracerGroupSurfaceFluxRunoff, & tracerGroupSurfaceFluxRemoved, & dt, layerThickness, err) + if (trim(config_subglacial_runoff_mode) == 'data') then + call ocn_surface_bulk_forcing_tracers_subglacial_runoff(meshPool, groupName, & + forcingPool, & + tracerGroupSurfaceFluxSubglacialRunoff, err) + end if end if ! sfc bulk forcing @@ -1188,10 +1257,15 @@ subroutine ocn_tend_tracer(tendPool, statePool, forcingPool, & endif ! compute budgets call ocn_tracer_surface_flux_tend(meshPool, fractionAbsorbed, & - fractionAbsorbedRunoff, layerThickness, & - tracerGroupSurfaceFlux, & + fractionAbsorbedRunoff, & + layerThickness, tracerGroupSurfaceFlux, & tracerGroupSurfaceFluxRunoff, & tracerGroupTend, err) + if (trim(config_subglacial_runoff_mode) == 'data') then + call ocn_tracer_surface_flux_tend_subglacial_runoff(meshPool, fractionAbsorbedSubglacialRunoff, & + layerThickness, tracerGroupSurfaceFluxSubglacialRunoff, & + tracerGroupTend, err) + end if ! ! Compute shortwave absorption @@ -1243,12 +1317,12 @@ subroutine ocn_tend_tracer(tendPool, statePool, forcingPool, & ! ! Compute tracer tendency due to non-local flux computed in KPP ! - if (config_use_cvmix_kpp) then - call mpas_timer_start("non-local flux from KPP") - if (.not. config_cvmix_kpp_nonlocal_with_implicit_mix) then - call ocn_compute_KPP_input_fields(statePool, forcingPool,& + if (config_use_cvmix_kpp .or. config_use_gotm) then + call ocn_compute_KPP_input_fields(statePool, forcingPool,& meshPool, timeLevel) + if (.not. config_cvmix_kpp_nonlocal_with_implicit_mix) then + call mpas_timer_start("non-local flux from KPP") if (computeBudgets) then !$omp parallel !$omp do schedule(runtime) private(k,n) @@ -1291,8 +1365,8 @@ subroutine ocn_tend_tracer(tendPool, statePool, forcingPool, & !$omp end do !$omp end parallel endif ! compute budgets + call mpas_timer_stop("non-local flux from KPP") end if ! not non-local with implicit mix - call mpas_timer_stop("non-local flux from KPP") end if ! KPP ! Compute tracer tendency due to production/destruction of diff --git a/components/mpas-ocean/src/shared/mpas_ocn_thick_surface_flux.F b/components/mpas-ocean/src/shared/mpas_ocn_thick_surface_flux.F index 438aabafee17..1c535532cea2 100644 --- a/components/mpas-ocean/src/shared/mpas_ocn_thick_surface_flux.F +++ b/components/mpas-ocean/src/shared/mpas_ocn_thick_surface_flux.F @@ -46,7 +46,8 @@ module ocn_thick_surface_flux !-------------------------------------------------------------------- public :: ocn_thick_surface_flux_tend, & - ocn_thick_surface_flux_init + ocn_thick_surface_flux_init, & + ocn_thick_surface_flux_tend_subglacial_runoff !-------------------------------------------------------------------- ! @@ -69,7 +70,7 @@ module ocn_thick_surface_flux !> \date 15 September 2011 !> \details !> This routine computes the horizontal advection tendency for -!> thicknes based on current state and user choices of forcings. +!> thickness based on current state and user choices of forcings. ! !----------------------------------------------------------------------- @@ -86,8 +87,8 @@ subroutine ocn_thick_surface_flux_tend(transmissionCoefficients, transmissionCoe transmissionCoefficientsRunoff !< Input: Coefficients for the transmission of surface fluxes due to river runoff real (kind=RKIND), dimension(:), intent(in) :: & - surfaceThicknessFlux, &!< Input: surface flux of thickness - surfaceThicknessFluxRunoff !< Input: surface flux of thickness due to river runoff + surfaceThicknessFlux, &!< Input: surface flux of thickness + surfaceThicknessFluxRunoff !< Input: surface flux of thickness due to river runoff !----------------------------------------------------------------- @@ -140,7 +141,6 @@ subroutine ocn_thick_surface_flux_tend(transmissionCoefficients, transmissionCoe do k = minLevelCell(iCell), maxLevelCell(iCell) remainingFlux = remainingFlux - transmissionCoefficients(k, iCell) remainingFluxRunoff = remainingFluxRunoff - transmissionCoefficientsRunoff(k, iCell) - tend(k, iCell) = tend(k, iCell) + surfaceThicknessFlux(iCell) * transmissionCoefficients(k, iCell) & + surfaceThicknessFluxRunoff(iCell) * transmissionCoefficientsRunoff(k, iCell) end do @@ -153,6 +153,7 @@ subroutine ocn_thick_surface_flux_tend(transmissionCoefficients, transmissionCoe tend(maxLevelCell(iCell), iCell) = tend(maxLevelCell(iCell), iCell) & + remainingFluxRunoff * surfaceThicknessFluxRunoff(iCell) end if + end do #ifndef MPAS_OPENACC !$omp end do @@ -169,6 +170,107 @@ subroutine ocn_thick_surface_flux_tend(transmissionCoefficients, transmissionCoe end subroutine ocn_thick_surface_flux_tend!}}} +!*********************************************************************** +! +! routine ocn_thick_surface_flux_tend_subglacial_runoff +! +!> \brief Computes tendency term from horizontal advection of thickness +!> \author Irena Vankova +!> \date July 2024 +!> \details +!> This routine computes the horizontal advection tendency for +!> thickness based on current state and user choices of forcings. +! +!----------------------------------------------------------------------- + + subroutine ocn_thick_surface_flux_tend_subglacial_runoff(transmissionCoefficientsSubglacialRunoff, & + surfaceThicknessFluxSubglacialRunoff, tend, err)!{{{ + !----------------------------------------------------------------- + ! + ! input variables + ! + !----------------------------------------------------------------- + + real (kind=RKIND), dimension(:,:), intent(in) :: & + transmissionCoefficientsSubglacialRunoff !< Input: Coefficients for the transmission of surface fluxes due to subglacial runoff + + real (kind=RKIND), dimension(:), intent(in) :: & + surfaceThicknessFluxSubglacialRunoff !< Input: surface flux of thickness due to subglacial runoff + + + !----------------------------------------------------------------- + ! + ! input/output variables + ! + !----------------------------------------------------------------- + + real (kind=RKIND), dimension(:,:), intent(inout) :: & + tend !< Input/Output: thickness tendency + + !----------------------------------------------------------------- + ! + ! output variables + ! + !----------------------------------------------------------------- + + integer, intent(out) :: err !< Output: error flag + + !----------------------------------------------------------------- + ! + ! local variables + ! + !----------------------------------------------------------------- + + integer :: iCell, k + + real (kind=RKIND) :: remainingFlux, remainingFluxRunoff, remainingFluxSubglacialRunoff + + err = 0 + + if (.not. surfaceThicknessFluxOn) return + + call mpas_timer_start("thick surface flux") + +#ifdef MPAS_OPENACC + !$acc enter data copyin(transmissionCoefficientsSubglacialRunoff) + + !$acc parallel loop & + !$acc present(tend, & + !$acc surfaceThicknessFluxSubglacialRunoff, transmissionCoefficientsSubglacialRunoff, & + !$acc minLevelCell, maxLevelCell) & + !$acc private(k, remainingFluxSubglacialRunoff) +#else + !$omp parallel + !$omp do schedule(runtime) private(remainingFluxSubglacialRunoff, k) +#endif + do iCell = 1, nCellsOwned + remainingFluxSubglacialRunoff = 1.0_RKIND + do k = minLevelCell(iCell), maxLevelCell(iCell) + remainingFluxSubglacialRunoff = remainingFluxSubglacialRunoff - transmissionCoefficientsSubglacialRunoff(k, iCell) + tend(k, iCell) = tend(k, iCell) + surfaceThicknessFluxSubglacialRunoff(iCell) * transmissionCoefficientsSubglacialRunoff(k, iCell) + end do + + if(maxLevelCell(iCell) > 0 .and. remainingFluxSubglacialRunoff > 0.0_RKIND) then + tend(maxLevelCell(iCell), iCell) = tend(maxLevelCell(iCell), iCell) & + + remainingFluxSubglacialRunoff * surfaceThicknessFluxSubglacialRunoff(iCell) + end if + + end do +#ifndef MPAS_OPENACC + !$omp end do + !$omp end parallel +#endif + +#ifdef MPAS_OPENACC + !$acc exit data delete(transmissionCoefficientsSubglacialRunoff) +#endif + + call mpas_timer_stop("thick surface flux") + + !-------------------------------------------------------------------- + + end subroutine ocn_thick_surface_flux_tend_subglacial_runoff!}}} + !*********************************************************************** ! ! routine ocn_thick_surface_flux_init diff --git a/components/mpas-ocean/src/shared/mpas_ocn_tracer_surface_flux_to_tend.F b/components/mpas-ocean/src/shared/mpas_ocn_tracer_surface_flux_to_tend.F index 57e2949bac9b..ba97203c4ec3 100644 --- a/components/mpas-ocean/src/shared/mpas_ocn_tracer_surface_flux_to_tend.F +++ b/components/mpas-ocean/src/shared/mpas_ocn_tracer_surface_flux_to_tend.F @@ -45,7 +45,8 @@ module ocn_tracer_surface_flux_to_tend !-------------------------------------------------------------------- public :: ocn_tracer_surface_flux_tend, & - ocn_tracer_surface_flux_init + ocn_tracer_surface_flux_init, & + ocn_tracer_surface_flux_tend_subglacial_runoff !-------------------------------------------------------------------- ! @@ -71,8 +72,8 @@ module ocn_tracer_surface_flux_to_tend ! !----------------------------------------------------------------------- - subroutine ocn_tracer_surface_flux_tend(meshPool, fractionAbsorbed, fractionAbsorbedRunoff, layerThickness, & - surfaceTracerFlux, surfaceTracerFluxRunoff, tend, err)!{{{ + subroutine ocn_tracer_surface_flux_tend(meshPool, fractionAbsorbed, fractionAbsorbedRunoff, & + layerThickness, surfaceTracerFlux, surfaceTracerFluxRunoff, tend, err)!{{{ !----------------------------------------------------------------- ! ! input variables @@ -197,11 +198,120 @@ subroutine ocn_tracer_surface_flux_tend(meshPool, fractionAbsorbed, fractionAbso call mpas_timer_stop("surface_tracer_runoff_flux") end if - !-------------------------------------------------------------------- end subroutine ocn_tracer_surface_flux_tend!}}} + +!*********************************************************************** +! +! routine ocn_tracer_surface_flux_tend_subglacial_runoff +! +!> \brief Computes tendency term for surface fluxes +!> \author Irena Vankova +!> \date July 2024 +!> \details +!> This routine computes the tendency for tracers based on surface fluxes. +! +!----------------------------------------------------------------------- + + subroutine ocn_tracer_surface_flux_tend_subglacial_runoff(meshPool, fractionAbsorbedSubglacialRunoff, & + layerThickness, surfaceTracerFluxSubglacialRunoff, tend, err)!{{{ + !----------------------------------------------------------------- + ! + ! input variables + ! + !----------------------------------------------------------------- + + type (mpas_pool_type), intent(in) :: & + meshPool !< Input: mesh information + + real (kind=RKIND), dimension(:,:), intent(in) :: & + layerThickness !< Input: Layer thickness + + real (kind=RKIND), dimension(:,:), intent(in), pointer :: & + surfaceTracerFluxSubglacialRunoff !< Input: surface tracer fluxes from subglacial runoff + + real (kind=RKIND), dimension(:,:), intent(in) :: & + fractionAbsorbedSubglacialRunoff !< Input: Coefficients for the application of surface fluxes due to subglacial runoff + + + !----------------------------------------------------------------- + ! + ! input/output variables + ! + !----------------------------------------------------------------- + + real (kind=RKIND), dimension(:,:,:), intent(inout) :: & + tend !< Input/Output: velocity tendency + + !----------------------------------------------------------------- + ! + ! output variables + ! + !----------------------------------------------------------------- + + integer, intent(out) :: err !< Output: error flag + + !----------------------------------------------------------------- + ! + ! local variables + ! + !----------------------------------------------------------------- + + integer :: iCell, k, iTracer, nTracers, nCells + integer, pointer :: nVertLevels + integer, dimension(:), pointer :: nCellsArray + integer, dimension(:), pointer :: minLevelCell, maxLevelCell + + real (kind=RKIND) :: remainingFlux + + err = 0 + + if (.not. surfaceTracerFluxOn) return + + call mpas_pool_get_dimension(meshPool, 'nCellsArray', nCellsArray) + call mpas_pool_get_dimension(meshPool, 'nVertLevels', nVertLevels) + nTracers = size(tend, dim=1) + + call mpas_pool_get_array(meshPool, 'minLevelCell', minLevelCell) + call mpas_pool_get_array(meshPool, 'maxLevelCell', maxLevelCell) + + nCells = nCellsArray( 1 ) + + ! now do subglacial runoff component + + call mpas_timer_start("surface_tracer_subglacial_runoff_flux") + + !$omp parallel + !$omp do schedule(runtime) private(remainingFlux, k, iTracer) + do iCell = 1, nCells + remainingFlux = 1.0_RKIND + do k = minLevelCell(iCell), maxLevelCell(iCell) + remainingFlux = remainingFlux - fractionAbsorbedSubglacialRunoff(k, iCell) + + do iTracer = 1, nTracers + tend(iTracer, k, iCell) = tend(iTracer, k, iCell) + & + surfaceTracerFluxSubglacialRunoff(iTracer, iCell) * fractionAbsorbedSubglacialRunoff(k, iCell) + end do + end do + + if(maxLevelCell(iCell) > 0 .and. remainingFlux > 0.0_RKIND) then + do iTracer = 1, nTracers + tend(iTracer, maxLevelCell(iCell), iCell) = tend(iTracer, maxLevelCell(iCell), iCell) & + + surfaceTracerFluxSubglacialRunoff(iTracer, iCell) * remainingFlux + end do + end if + end do + !$omp end do + !$omp end parallel + + call mpas_timer_stop("surface_tracer_subglacial_runoff_flux") + + !-------------------------------------------------------------------- + + end subroutine ocn_tracer_surface_flux_tend_subglacial_runoff!}}} + !*********************************************************************** ! ! routine ocn_tracer_surface_flux_init diff --git a/components/mpas-ocean/src/tracer_groups/Registry_CFC.xml b/components/mpas-ocean/src/tracer_groups/Registry_CFC.xml index d77859dcef86..b0adb7d595f5 100644 --- a/components/mpas-ocean/src/tracer_groups/Registry_CFC.xml +++ b/components/mpas-ocean/src/tracer_groups/Registry_CFC.xml @@ -95,6 +95,15 @@ description="CFC12 Surface Flux Due to Runoff" /> + + + + + + + + + + + + + + + + + + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/components/mpas-ocean/src/tracer_groups/Registry_idealAge.xml b/components/mpas-ocean/src/tracer_groups/Registry_idealAge.xml index c6adca3ea636..3a45bc10b794 100644 --- a/components/mpas-ocean/src/tracer_groups/Registry_idealAge.xml +++ b/components/mpas-ocean/src/tracer_groups/Registry_idealAge.xml @@ -69,6 +69,11 @@ description="Flux of iAge through the ocean surface due to river runoff. Positive into ocean." /> + + + ".true."); add_default($nl, 'config_use_DON', 'val'=>".true."); add_default($nl, 'config_use_iron', 'val'=>".true."); + add_default($nl, 'config_couple_biogeochemistry_fields'); } else { add_default($nl, 'config_use_vertical_biochemistry', 'val'=>".false."); add_default($nl, 'config_use_vertical_tracers', 'val'=>".false."); @@ -694,11 +695,14 @@ if ($ice_bgc eq 'ice_bgc') { add_default($nl, 'config_use_humics', 'val'=>".false."); add_default($nl, 'config_use_DON', 'val'=>".false."); add_default($nl, 'config_use_iron', 'val'=>".false."); + add_default($nl, 'config_couple_biogeochemistry_fields', 'val'=>".false."); } add_default($nl, 'config_use_chlorophyll'); add_default($nl, 'config_use_macromolecules'); add_default($nl, 'config_use_modal_aerosols'); add_default($nl, 'config_use_zaerosols'); +add_default($nl, 'config_use_atm_dust_file'); +add_default($nl, 'config_use_iron_solubility_file'); add_default($nl, 'config_skeletal_bgc_flux_type'); add_default($nl, 'config_scale_initial_vertical_bgc'); add_default($nl, 'config_biogrid_bottom_molecular_sublayer'); diff --git a/components/mpas-seaice/bld/build-namelist-section b/components/mpas-seaice/bld/build-namelist-section index eac96b5a10b9..d2866ee4c813 100644 --- a/components/mpas-seaice/bld/build-namelist-section +++ b/components/mpas-seaice/bld/build-namelist-section @@ -193,6 +193,7 @@ add_default($nl, 'config_use_floe_size_distribution'); # Namelist group: biogeochemistry # ################################### +add_default($nl, 'config_couple_biogeochemistry_fields'); add_default($nl, 'config_use_brine'); add_default($nl, 'config_use_vertical_zsalinity'); add_default($nl, 'config_use_vertical_biochemistry'); @@ -212,6 +213,8 @@ add_default($nl, 'config_use_DON'); add_default($nl, 'config_use_iron'); add_default($nl, 'config_use_modal_aerosols'); add_default($nl, 'config_use_zaerosols'); +add_default($nl, 'config_use_atm_dust_file'); +add_default($nl, 'config_use_iron_solubility_file'); add_default($nl, 'config_skeletal_bgc_flux_type'); add_default($nl, 'config_scale_initial_vertical_bgc'); add_default($nl, 'config_biogrid_bottom_molecular_sublayer'); diff --git a/components/mpas-seaice/bld/namelist_files/namelist_defaults_mpassi.xml b/components/mpas-seaice/bld/namelist_files/namelist_defaults_mpassi.xml index dee59f726e25..d62797de4518 100644 --- a/components/mpas-seaice/bld/namelist_files/namelist_defaults_mpassi.xml +++ b/components/mpas-seaice/bld/namelist_files/namelist_defaults_mpassi.xml @@ -221,6 +221,7 @@ false +false false false false @@ -240,6 +241,8 @@ false false false +false +false 'Jin2006' false 0.006 @@ -286,9 +289,9 @@ 0.063 0.063 0.063 -0.0 -0.7 -0.7 +0.19 +0.19 +0.19 0.007 0.007 0.007 @@ -349,12 +352,12 @@ 0.0 0.0 0.5 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 +-1.0 +-1.0 +-1.0 +-1.0 +-1.0 +-1.0 7.0 7.0 7.0 diff --git a/components/mpas-seaice/bld/namelist_files/namelist_definition_mpassi.xml b/components/mpas-seaice/bld/namelist_files/namelist_definition_mpassi.xml index f12f82ea1378..efbaef07cb9d 100644 --- a/components/mpas-seaice/bld/namelist_files/namelist_definition_mpassi.xml +++ b/components/mpas-seaice/bld/namelist_files/namelist_definition_mpassi.xml @@ -955,6 +955,14 @@ Default: Defined in namelist_defaults.xml + +Couple ocean and seaice biogeochemical fields + +Valid values: true or false +Default: Defined in namelist_defaults.xml + + Use the brine height tracer @@ -1107,6 +1115,22 @@ Valid values: true or false Default: Defined in namelist_defaults.xml + +Read atmospheric dust fluxes from a file + +Valid values: true or false +Default: Defined in namelist_defaults.xml + + + +Read atmospheric dust-iron solubility from a file + +Valid values: true or false +Default: Defined in namelist_defaults.xml + + Determines the ocean-ice fluxes of biogeochemistry for the bottom1-layer model: in Jin2006, the piston velocity is a function of ice growth/melt rate, in default, the piston velocity is constant diff --git a/components/mpas-seaice/cime_config/buildnml b/components/mpas-seaice/cime_config/buildnml index 5522d8ac6511..c38ca08a31da 100755 --- a/components/mpas-seaice/cime_config/buildnml +++ b/components/mpas-seaice/cime_config/buildnml @@ -72,6 +72,7 @@ def buildnml(case, caseroot, compname): decomp_prefix = '' data_iceberg_file = '' points_file = '' + dust_iron_file = '' if ice_grid == 'oEC60to30v3': decomp_date = '230424' @@ -300,6 +301,7 @@ def buildnml(case, caseroot, compname): decomp_date = '20231120' decomp_prefix = 'partitions/mpas-seaice.graph.info.' data_iceberg_file = 'Iceberg_Climatology_Merino.IcoswISC30E3r5.20231120.nc' + dust_iron_file = 'ecoForcingSurfaceMonthly+WetDryDustSolFrac.IcoswISC30E3r5.20240511.nc' if ice_ic_mode == 'spunup': if iceberg_mode == 'data': grid_date = '20240207' @@ -357,6 +359,8 @@ def buildnml(case, caseroot, compname): input_list.write("points = {}/ice/mpas-seaice/{}/{}\n".format(din_loc_root, ice_mask, points_file)) if iceberg_mode == 'data': input_list.write("data_iceberg = {}/ice/mpas-seaice/{}/{}\n".format(din_loc_root, ice_mask, data_iceberg_file)) + if dust_iron_file != '': + input_list.write("dust_iron = {}/ocn/mpas-o/{}/{}\n".format(din_loc_root, ice_mask, dust_iron_file)) #-------------------------------------------------------------------- # Invoke mpas build-namelist - output will go in $CASEBUILD/mpassiconf @@ -602,10 +606,19 @@ def buildnml(case, caseroot, compname): lines.append('') lines.append('') + if dust_iron_file != '': + lines.append('') + lines.append('') + lines.append('') @@ -748,6 +761,15 @@ def buildnml(case, caseroot, compname): lines.append(' ') lines.append(' ') lines.append(' ') + lines.append(' ') + lines.append(' ') + lines.append(' ') + lines.append(' ') + lines.append(' ') + lines.append(' ') + lines.append(' ') + lines.append(' ') + lines.append(' ') lines.append('') lines.append('') lines.append(' domain % blocklist @@ -1950,7 +1949,8 @@ subroutine ice_import_mct(x2i_i, errorCode)!{{{ config_use_aerosols, & config_use_modal_aerosols, & config_use_zaerosols, & - config_use_column_biogeochemistry + config_use_column_biogeochemistry, & + config_couple_biogeochemistry_fields character(len=strKIND), pointer :: & config_column_physics_type, & @@ -1998,7 +1998,9 @@ subroutine ice_import_mct(x2i_i, errorCode)!{{{ oceanZAerosolConcField, & atmosAerosolFluxField, & atmosBlackCarbonFluxField, & - atmosDustFluxField + atmosDustFluxField, & + atmosWetDustFluxField, & + atmosDryDustFluxField real (kind=RKIND), dimension(:), pointer :: & seaSurfaceTemperature, & @@ -2044,7 +2046,9 @@ subroutine ice_import_mct(x2i_i, errorCode)!{{{ oceanZAerosolConc, & atmosAerosolFlux, & atmosBlackCarbonFlux, & - atmosDustFlux + atmosDustFlux, & + atmosWetDustFlux, & + atmosDryDustFlux !----------------------------------------------------------------------- ! @@ -2070,6 +2074,8 @@ subroutine ice_import_mct(x2i_i, errorCode)!{{{ call mpas_pool_get_config(configs, "config_use_aerosols", config_use_aerosols) call mpas_pool_get_config(configs, "config_use_modal_aerosols", config_use_modal_aerosols) call mpas_pool_get_config(configs, "config_use_column_biogeochemistry", config_use_column_biogeochemistry) + call mpas_pool_get_config(configs, "config_couple_biogeochemistry_fields", config_couple_biogeochemistry_fields) + call mpas_pool_get_config(configs, "config_use_zaerosols", config_use_zaerosols) call mpas_pool_get_subpool(block_ptr % structs, 'mesh', meshPool) call mpas_pool_get_subpool(block_ptr % structs, 'ocean_coupling', oceanCoupling) @@ -2108,9 +2114,14 @@ subroutine ice_import_mct(x2i_i, errorCode)!{{{ call mpas_pool_get_array(aerosols, "atmosAerosolFlux", atmosAerosolFlux) endif - if (config_use_column_biogeochemistry) then - call mpas_pool_get_config(configs, "config_use_zaerosols", config_use_zaerosols) - call mpas_pool_get_subpool(block_ptr % structs, 'biogeochemistry', biogeochemistry) + call mpas_pool_get_subpool(block_ptr % structs, 'biogeochemistry', biogeochemistry) + if (config_use_zaerosols) then + call mpas_pool_get_array(biogeochemistry, 'atmosBlackCarbonFlux', atmosBlackCarbonFlux) + call mpas_pool_get_array(biogeochemistry, 'atmosDustFlux', atmosDustFlux) + call mpas_pool_get_array(biogeochemistry, "atmosWetDustFlux", atmosWetDustFlux) + call mpas_pool_get_array(biogeochemistry, "atmosDryDustFlux", atmosDryDustFlux) + endif + if (config_use_column_biogeochemistry .and. config_couple_biogeochemistry_fields) then call mpas_pool_get_array(biogeochemistry, 'oceanAlgaeConc', oceanAlgaeConc) call mpas_pool_get_array(biogeochemistry, 'oceanDOCConc', oceanDOCConc) @@ -2124,15 +2135,10 @@ subroutine ice_import_mct(x2i_i, errorCode)!{{{ call mpas_pool_get_array(biogeochemistry, 'oceanHumicsConc', oceanHumicsConc) call mpas_pool_get_array(biogeochemistry, 'oceanParticulateIronConc', oceanParticulateIronConc) call mpas_pool_get_array(biogeochemistry, 'oceanDissolvedIronConc', oceanDissolvedIronConc) - call mpas_pool_get_array(biogeochemistry, 'oceanZAerosolConc', oceanZAerosolConc) call mpas_pool_get_array(biogeochemistry, 'carbonToNitrogenRatioAlgae', carbonToNitrogenRatioAlgae) call mpas_pool_get_array(biogeochemistry, 'carbonToNitrogenRatioDON', carbonToNitrogenRatioDON) call mpas_pool_get_array(biogeochemistry, 'DOCPoolFractions', DOCPoolFractions) - if (config_use_zaerosols) then - call mpas_pool_get_array(biogeochemistry, "atmosBlackCarbonFlux", atmosBlackCarbonFlux) - call mpas_pool_get_array(biogeochemistry, "atmosDustFlux", atmosDustFlux) - endif endif do i = 1, nCellsSolve @@ -2224,8 +2230,67 @@ subroutine ice_import_mct(x2i_i, errorCode)!{{{ endif endif + ! set aerosols, if configured + if (config_use_zaerosols .or. config_use_column_biogeochemistry) then + call mpas_pool_get_array(biogeochemistry, 'oceanZAerosolConc', oceanZAerosolConc) + oceanZAerosolConc(1,i) = 0.0_RKIND !x2i_i % rAttr(index_x2i_So_zaer1, n) + oceanZAerosolConc(2,i) = 0.0_RKIND !x2i_i % rAttr(index_x2i_So_zaer2, n) + oceanZAerosolConc(3,i) = 0.0_RKIND !x2i_i % rAttr(index_x2i_So_zaer3, n) + oceanZAerosolConc(4,i) = 0.0_RKIND !x2i_i % rAttr(index_x2i_So_zaer4, n) + oceanZAerosolConc(5,i) = 0.0_RKIND !x2i_i % rAttr(index_x2i_So_zaer5, n) + oceanZAerosolConc(6,i) = 0.0_RKIND !x2i_i % rAttr(index_x2i_So_zaer6, n) + end if + if (config_use_zaerosols) then + if (config_use_modal_aerosols) then + atmosBlackCarbonFlux(1,i) = x2i_i % rAttr(index_x2i_Faxa_bcphodry, n) & + + x2i_i % rAttr(index_x2i_Faxa_bcphidry, n) + atmosBlackCarbonFlux(2,i) = x2i_i % rAttr(index_x2i_Faxa_bcphiwet, n) + !combine wet and dry dust + atmosDustFlux(1,i) = x2i_i % rAttr(index_x2i_Faxa_dstwet1, n) & + + x2i_i % rAttr(index_x2i_Faxa_dstdry1, n) + atmosDustFlux(2,i) = x2i_i % rAttr(index_x2i_Faxa_dstwet2, n) & + + x2i_i % rAttr(index_x2i_Faxa_dstdry2, n) + atmosDustFlux(3,i) = x2i_i % rAttr(index_x2i_Faxa_dstwet3, n) & + + x2i_i % rAttr(index_x2i_Faxa_dstdry3, n) + atmosDustFlux(4,i) = x2i_i % rAttr(index_x2i_Faxa_dstwet4, n) & + + x2i_i % rAttr(index_x2i_Faxa_dstdry4, n) + + atmosWetDustFlux(1,i) = x2i_i % rAttr(index_x2i_Faxa_dstwet1, n) + atmosWetDustFlux(2,i) = x2i_i % rAttr(index_x2i_Faxa_dstwet2, n) + atmosWetDustFlux(3,i) = x2i_i % rAttr(index_x2i_Faxa_dstwet3, n) + atmosWetDustFlux(4,i) = x2i_i % rAttr(index_x2i_Faxa_dstwet4, n) + + atmosDryDustFlux(1,i) = x2i_i % rAttr(index_x2i_Faxa_dstdry1, n) + atmosDryDustFlux(2,i) = x2i_i % rAttr(index_x2i_Faxa_dstdry2, n) + atmosDryDustFlux(3,i) = x2i_i % rAttr(index_x2i_Faxa_dstdry3, n) + atmosDryDustFlux(4,i) = x2i_i % rAttr(index_x2i_Faxa_dstdry4, n) + else + atmosBlackCarbonFlux(1,i) = x2i_i % rAttr(index_x2i_Faxa_bcphodry, n) + atmosBlackCarbonFlux(2,i) = x2i_i % rAttr(index_x2i_Faxa_bcphidry, n) & + + x2i_i % rAttr(index_x2i_Faxa_bcphiwet, n) + ! combine wet and dry dust + atmosDustFlux(1,i) = x2i_i % rAttr(index_x2i_Faxa_dstwet1, n) & + + x2i_i % rAttr(index_x2i_Faxa_dstdry1, n) + atmosDustFlux(2,i) = x2i_i % rAttr(index_x2i_Faxa_dstwet2, n) & + + x2i_i % rAttr(index_x2i_Faxa_dstdry2, n) + atmosDustFlux(3,i) = x2i_i % rAttr(index_x2i_Faxa_dstwet3, n) & + + x2i_i % rAttr(index_x2i_Faxa_dstdry3, n) + atmosDustFlux(4,i) = x2i_i % rAttr(index_x2i_Faxa_dstwet4, n) & + + x2i_i % rAttr(index_x2i_Faxa_dstdry4, n) + + atmosDryDustFlux(1,i) = x2i_i % rAttr(index_x2i_Faxa_dstdry1, n) + atmosDryDustFlux(2,i) = x2i_i % rAttr(index_x2i_Faxa_dstdry2, n) + atmosDryDustFlux(3,i) = x2i_i % rAttr(index_x2i_Faxa_dstdry3, n) + atmosDryDustFlux(4,i) = x2i_i % rAttr(index_x2i_Faxa_dstdry4, n) + + atmosWetDustFlux(1,i) = x2i_i % rAttr(index_x2i_Faxa_dstwet1, n) + atmosWetDustFlux(2,i) = x2i_i % rAttr(index_x2i_Faxa_dstwet2, n) + atmosWetDustFlux(3,i) = x2i_i % rAttr(index_x2i_Faxa_dstwet3, n) + atmosWetDustFlux(4,i) = x2i_i % rAttr(index_x2i_Faxa_dstwet4, n) + endif + endif ! import biogeochemistry fields, if configured - if (config_use_column_biogeochemistry) then + if (config_use_column_biogeochemistry .and. config_couple_biogeochemistry_fields) then oceanAlgaeConc(1,i) = x2i_i % rAttr(index_x2i_So_algae1, n) oceanAlgaeConc(2,i) = x2i_i % rAttr(index_x2i_So_algae2, n) oceanAlgaeConc(3,i) = 0.0_RKIND !x2i_i % rAttr(index_x2i_So_algae3, n) @@ -2245,42 +2310,6 @@ subroutine ice_import_mct(x2i_i, errorCode)!{{{ oceanParticulateIronConc(2,i) = x2i_i % rAttr(index_x2i_So_fep2, n) oceanDissolvedIronConc(1,i) = x2i_i % rAttr(index_x2i_So_fed1, n) oceanDissolvedIronConc(2,i) = x2i_i % rAttr(index_x2i_So_fed2, n) - oceanZAerosolConc(1,i) = 0.0_RKIND !x2i_i % rAttr(index_x2i_So_zaer1, n) - oceanZAerosolConc(2,i) = 0.0_RKIND !x2i_i % rAttr(index_x2i_So_zaer2, n) - oceanZAerosolConc(3,i) = 0.0_RKIND !x2i_i % rAttr(index_x2i_So_zaer3, n) - oceanZAerosolConc(4,i) = 0.0_RKIND !x2i_i % rAttr(index_x2i_So_zaer4, n) - oceanZAerosolConc(5,i) = 0.0_RKIND !x2i_i % rAttr(index_x2i_So_zaer5, n) - oceanZAerosolConc(6,i) = 0.0_RKIND !x2i_i % rAttr(index_x2i_So_zaer6, n) - ! set aerosols, if configured - if (config_use_zaerosols) then - if (config_use_modal_aerosols) then - atmosBlackCarbonFlux(1,i) = x2i_i % rAttr(index_x2i_Faxa_bcphodry, n) & - + x2i_i % rAttr(index_x2i_Faxa_bcphidry, n) - atmosBlackCarbonFlux(2,i) = x2i_i % rAttr(index_x2i_Faxa_bcphiwet, n) - ! combine wet and dry dust - atmosDustFlux(1,i) = x2i_i % rAttr(index_x2i_Faxa_dstwet1, n) & - + x2i_i % rAttr(index_x2i_Faxa_dstdry1, n) - atmosDustFlux(2,i) = x2i_i % rAttr(index_x2i_Faxa_dstwet2, n) & - + x2i_i % rAttr(index_x2i_Faxa_dstdry2, n) - atmosDustFlux(3,i) = x2i_i % rAttr(index_x2i_Faxa_dstwet3, n) & - + x2i_i % rAttr(index_x2i_Faxa_dstdry3, n) - atmosDustFlux(4,i) = x2i_i % rAttr(index_x2i_Faxa_dstwet4, n) & - + x2i_i % rAttr(index_x2i_Faxa_dstdry4, n) - else - atmosBlackCarbonFlux(1,i) = x2i_i % rAttr(index_x2i_Faxa_bcphodry, n) - atmosBlackCarbonFlux(2,i) = x2i_i % rAttr(index_x2i_Faxa_bcphidry, n) & - + x2i_i % rAttr(index_x2i_Faxa_bcphiwet, n) - ! combine wet and dry dust - atmosDustFlux(1,i) = x2i_i % rAttr(index_x2i_Faxa_dstwet1, n) & - + x2i_i % rAttr(index_x2i_Faxa_dstdry1, n) - atmosDustFlux(2,i) = x2i_i % rAttr(index_x2i_Faxa_dstwet2, n) & - + x2i_i % rAttr(index_x2i_Faxa_dstdry2, n) - atmosDustFlux(3,i) = x2i_i % rAttr(index_x2i_Faxa_dstwet3, n) & - + x2i_i % rAttr(index_x2i_Faxa_dstdry3, n) - atmosDustFlux(4,i) = x2i_i % rAttr(index_x2i_Faxa_dstwet4, n) & - + x2i_i % rAttr(index_x2i_Faxa_dstdry4, n) - endif - endif endif end do @@ -2293,7 +2322,7 @@ subroutine ice_import_mct(x2i_i, errorCode)!{{{ seaSurfaceTemperature(i) = seaSurfaceTemperature(i) - seaiceFreshWaterFreezingPoint - if (config_use_column_biogeochemistry) then + if (config_use_column_biogeochemistry .and. config_couple_biogeochemistry_fields) then ! convert from mmol C/m^3 to mmol N/m^3 oceanAlgaeConc(1,i) = oceanAlgaeConc(1,i) / carbonToNitrogenRatioAlgae(1) oceanAlgaeConc(2,i) = oceanAlgaeConc(2,i) / carbonToNitrogenRatioAlgae(2) @@ -2343,7 +2372,16 @@ subroutine ice_import_mct(x2i_i, errorCode)!{{{ call mpas_pool_get_field(aerosols, "atmosAerosolFlux", atmosAerosolFluxField) endif - if (config_use_column_biogeochemistry) then + if (config_use_zaerosols .or. config_use_column_biogeochemistry) & + call mpas_pool_get_field(biogeochemistry, 'oceanZAerosolConc', oceanZAerosolConcField) + + if (config_use_zaerosols) then + call mpas_pool_get_field(biogeochemistry, "atmosBlackCarbonFlux", atmosBlackCarbonFluxField) + call mpas_pool_get_field(biogeochemistry, "atmosDustFlux", atmosDustFluxField) + call mpas_pool_get_field(biogeochemistry, "atmosWetDustFlux", atmosWetDustFluxField) + call mpas_pool_get_field(biogeochemistry, "atmosDryDustFlux", atmosDryDustFluxField) + endif + if (config_use_column_biogeochemistry .and. config_couple_biogeochemistry_fields) then call mpas_pool_get_subpool(domain % blocklist % structs, 'biogeochemistry', biogeochemistry) call mpas_pool_get_field(biogeochemistry, 'oceanAlgaeConc', oceanAlgaeConcField) @@ -2358,11 +2396,6 @@ subroutine ice_import_mct(x2i_i, errorCode)!{{{ call mpas_pool_get_field(biogeochemistry, 'oceanHumicsConc', oceanHumicsConcField) call mpas_pool_get_field(biogeochemistry, 'oceanParticulateIronConc', oceanParticulateIronConcField) call mpas_pool_get_field(biogeochemistry, 'oceanDissolvedIronConc', oceanDissolvedIronConcField) - call mpas_pool_get_field(biogeochemistry, 'oceanZAerosolConc', oceanZAerosolConcField) - if (config_use_zaerosols) then - call mpas_pool_get_field(biogeochemistry, "atmosBlackCarbonFlux", atmosBlackCarbonFluxField) - call mpas_pool_get_field(biogeochemistry, "atmosDustFlux", atmosDustFluxField) - endif endif call mpas_dmpar_exch_halo_field(seaSurfaceTemperatureField) @@ -2393,8 +2426,16 @@ subroutine ice_import_mct(x2i_i, errorCode)!{{{ if (config_use_aerosols) then call mpas_dmpar_exch_halo_field(atmosAerosolFluxField) endif + if (config_use_zaerosols .or. config_use_column_biogeochemistry) & + call mpas_dmpar_exch_halo_field(oceanZAerosolConcField) - if (config_use_column_biogeochemistry) then + if (config_use_zaerosols) then + call mpas_dmpar_exch_halo_field(atmosBlackCarbonFluxField) + call mpas_dmpar_exch_halo_field(atmosDustFluxField) + call mpas_dmpar_exch_halo_field(atmosDryDustFluxField) + call mpas_dmpar_exch_halo_field(atmosWetDustFluxField) + endif + if (config_use_column_biogeochemistry .and. config_couple_biogeochemistry_fields) then call mpas_dmpar_exch_halo_field(oceanAlgaeConcField) call mpas_dmpar_exch_halo_field(oceanDOCConcField) call mpas_dmpar_exch_halo_field(oceanDICConcField) @@ -2407,11 +2448,6 @@ subroutine ice_import_mct(x2i_i, errorCode)!{{{ call mpas_dmpar_exch_halo_field(oceanHumicsConcField) call mpas_dmpar_exch_halo_field(oceanParticulateIronConcField) call mpas_dmpar_exch_halo_field(oceanDissolvedIronConcField) - call mpas_dmpar_exch_halo_field(oceanZAerosolConcField) - if (config_use_zaerosols) then - call mpas_dmpar_exch_halo_field(atmosBlackCarbonFluxField) - call mpas_dmpar_exch_halo_field(atmosDustFluxField) - endif endif ! REVISION HISTORY: @@ -2486,6 +2522,8 @@ subroutine ice_export_mct(i2x_i, errorCode) !{{{ config_rotate_cartesian_grid, & config_use_topo_meltponds, & config_use_column_biogeochemistry, & + config_use_zaerosols, & + config_couple_biogeochemistry_fields, & config_use_column_shortwave, & config_use_data_icebergs @@ -2535,6 +2573,7 @@ subroutine ice_export_mct(i2x_i, errorCode) !{{{ oceanDMSPpFlux, & oceanDMSPdFlux, & oceanHumicsFlux, & + oceanDustIronFlux, & carbonToNitrogenRatioAlgae, & carbonToNitrogenRatioDON @@ -2557,7 +2596,9 @@ subroutine ice_export_mct(i2x_i, errorCode) !{{{ configs => block_ptr % configs call MPAS_pool_get_config(configs, "config_rotate_cartesian_grid", config_rotate_cartesian_grid) call MPAS_pool_get_config(configs, "config_use_topo_meltponds", config_use_topo_meltponds) + call MPAS_pool_get_config(configs, "config_use_zaerosols", config_use_zaerosols) call MPAS_pool_get_config(configs, "config_use_column_biogeochemistry", config_use_column_biogeochemistry) + call mpas_pool_get_config(configs, "config_couple_biogeochemistry_fields", config_couple_biogeochemistry_fields) call MPAS_pool_get_config(configs, "config_use_column_shortwave", config_use_column_shortwave) call MPAS_pool_get_config(configs, "config_use_data_icebergs", config_use_data_icebergs) @@ -2620,7 +2661,7 @@ subroutine ice_export_mct(i2x_i, errorCode) !{{{ call MPAS_pool_get_array(icebergFluxes, "bergLatentHeatFlux", bergLatentHeatFlux) endif - if (config_use_column_biogeochemistry) then + if (config_use_column_biogeochemistry .and. config_couple_biogeochemistry_fields) then call mpas_pool_get_subpool(block_ptr % structs, 'biogeochemistry', biogeochemistry) call mpas_pool_get_array(biogeochemistry, 'oceanAlgaeFlux', oceanAlgaeFlux) @@ -2640,6 +2681,9 @@ subroutine ice_export_mct(i2x_i, errorCode) !{{{ call mpas_pool_get_array(biogeochemistry, 'carbonToNitrogenRatioDON', carbonToNitrogenRatioDON) endif + if (config_use_zaerosols .and. config_couple_biogeochemistry_fields) & + call mpas_pool_get_array(biogeochemistry, 'oceanDustIronFlux', oceanDustIronFlux) + do i = 1, nCellsSolve n = n + 1 @@ -2741,7 +2785,7 @@ subroutine ice_export_mct(i2x_i, errorCode) !{{{ i2x_i % rAttr(index_i2x_Fioi_tauy ,n) = tauyo ! export biogeochemistry fields, if configured - if (config_use_column_biogeochemistry) then + if (config_use_column_biogeochemistry .and. config_couple_biogeochemistry_fields) then ! convert from mmol N/m^3 to mmol C/m^3 i2x_i % rAttr(index_i2x_Fioi_algae1,n) = oceanAlgaeFlux(1,i) * carbonToNitrogenRatioAlgae(1) i2x_i % rAttr(index_i2x_Fioi_algae2,n) = oceanAlgaeFlux(2,i) * carbonToNitrogenRatioAlgae(2) @@ -2764,6 +2808,9 @@ subroutine ice_export_mct(i2x_i, errorCode) !{{{ i2x_i % rAttr(index_i2x_Fioi_fed1 ,n) = oceanDissolvedIronFlux(1,i) / 1000._RKIND i2x_i % rAttr(index_i2x_Fioi_fed2 ,n) = oceanDissolvedIronFlux(2,i) / 1000._RKIND endif + ! export dust, if configured kg/m2/s of dust + if (config_use_zaerosols .and. config_couple_biogeochemistry_fields) & + i2x_i % rAttr(index_i2x_Fioi_dust1 ,n) = oceanDustIronFlux(i) endif enddo @@ -3092,8 +3139,10 @@ subroutine ice_export_moab(EClock) config_rotate_cartesian_grid, & config_use_topo_meltponds, & config_use_column_biogeochemistry, & + config_use_zaerosols, & config_use_column_shortwave, & - config_use_data_icebergs + config_use_data_icebergs, & + config_couple_biogeochemistry_fields real(kind=RKIND), pointer :: & sphere_radius @@ -3141,6 +3190,7 @@ subroutine ice_export_moab(EClock) oceanDMSPpFlux, & oceanDMSPdFlux, & oceanHumicsFlux, & + oceanDustIronFlux, & carbonToNitrogenRatioAlgae, & carbonToNitrogenRatioDON @@ -3154,23 +3204,25 @@ subroutine ice_export_moab(EClock) integer :: ent_type, ierr, cur_ice_stepno character(len=32), parameter :: sub = 'ice_export_moab' - + character(len=100) :: outfile, wopts, localmeshfile, lnum character(CXX) :: tagname - !----------------------------------------------------------------------- + !----------------------------------------------------------------------- call shr_file_setLogUnit (iceLogUnit) n = 0 i2x_im(: ,:) = 0.0_RKIND block_ptr => domain % blocklist do while(associated(block_ptr)) - + configs => block_ptr % configs call MPAS_pool_get_config(configs, "config_rotate_cartesian_grid", config_rotate_cartesian_grid) call MPAS_pool_get_config(configs, "config_use_topo_meltponds", config_use_topo_meltponds) + call MPAS_pool_get_config(configs, "config_use_zaerosols", config_use_zaerosols) call MPAS_pool_get_config(configs, "config_use_column_biogeochemistry", config_use_column_biogeochemistry) + call mpas_pool_get_config(configs, "config_couple_biogeochemistry_fields", config_couple_biogeochemistry_fields) call MPAS_pool_get_config(configs, "config_use_column_shortwave", config_use_column_shortwave) call MPAS_pool_get_config(configs, "config_use_data_icebergs", config_use_data_icebergs) - + call MPAS_pool_get_subpool(block_ptr % structs, 'mesh', meshPool) call MPAS_pool_get_subpool(block_ptr % structs, "tracers_aggregate", tracersAggregate) call MPAS_pool_get_subpool(block_ptr % structs, "velocity_solver", velocitySolver) @@ -3179,7 +3231,7 @@ subroutine ice_export_moab(EClock) call MPAS_pool_get_subpool(block_ptr % structs, 'ocean_coupling', oceanCoupling) call MPAS_pool_get_subpool(block_ptr % structs, "atmos_fluxes", atmosFluxes) call MPAS_pool_get_subpool(block_ptr % structs, "ocean_fluxes", oceanFluxes) - + call MPAS_pool_get_dimension(meshPool, 'nCellsSolve', nCellsSolve) call MPAS_pool_get_config(meshPool, "sphere_radius", sphere_radius) call MPAS_pool_get_array(meshPool, "latCell", latCell) @@ -3187,7 +3239,7 @@ subroutine ice_export_moab(EClock) call MPAS_pool_get_array(meshPool, "xCell", xCell) call MPAS_pool_get_array(meshPool, "yCell", yCell) call MPAS_pool_get_array(meshPool, "zCell", zCell) - + call MPAS_pool_get_array(tracersAggregate, 'iceAreaCell', iceAreaCell) call MPAS_pool_get_array(tracersAggregate, 'iceVolumeCell', iceVolumeCell) call MPAS_pool_get_array(tracersAggregate, 'snowVolumeCell', snowVolumeCell) @@ -3195,44 +3247,44 @@ subroutine ice_export_moab(EClock) call MPAS_pool_get_array(tracersAggregate, 'pondLidThicknessCell', pondLidThicknessCell) call MPAS_pool_get_array(tracersAggregate, 'pondAreaCell', pondAreaCell) call MPAS_pool_get_array(tracersAggregate, 'surfaceTemperatureCell', surfaceTemperatureCell) - + call MPAS_pool_get_array(velocitySolver, 'airStressCellU', airStressCellU) call MPAS_pool_get_array(velocitySolver, 'airStressCellV', airStressCellV) call MPAS_pool_get_array(velocitySolver, 'oceanStressCellU', oceanStressCellU) call MPAS_pool_get_array(velocitySolver, 'oceanStressCellV', oceanStressCellV) - + call MPAS_pool_get_array(shortwave, 'albedoVisibleDirectCell', albedoVisibleDirectCell) call MPAS_pool_get_array(shortwave, 'albedoIRDirectCell', albedoIRDirectCell) call MPAS_pool_get_array(shortwave, 'albedoVisibleDiffuseCell', albedoVisibleDiffuseCell) call MPAS_pool_get_array(shortwave, 'albedoIRDiffuseCell', albedoIRDiffuseCell) call MPAS_pool_get_array(shortwave, 'absorbedShortwaveFlux', absorbedShortwaveFlux) - + call MPAS_pool_get_array(atmosCoupling, 'atmosReferenceSpeed10m', atmosReferenceSpeed10m) call MPAS_pool_get_array(atmosCoupling, 'atmosReferenceTemperature2m', atmosReferenceTemperature2m) call MPAS_pool_get_array(atmosCoupling, 'atmosReferenceHumidity2m', atmosReferenceHumidity2m) - + call MPAS_pool_get_array(oceanCoupling, 'frazilMassAdjust', frazilMassAdjust) - + call MPAS_pool_get_array(atmosFluxes, 'latentHeatFlux', latentHeatFlux) call MPAS_pool_get_array(atmosFluxes, 'sensibleHeatFlux', sensibleHeatFlux) call MPAS_pool_get_array(atmosFluxes, 'longwaveUp', longwaveUp) call MPAS_pool_get_array(atmosFluxes, 'evaporativeWaterFlux', evaporativeWaterFlux) - + call MPAS_pool_get_array(oceanFluxes, 'oceanHeatFlux', oceanHeatFlux) call MPAS_pool_get_array(oceanFluxes, 'oceanShortwaveFlux', oceanShortwaveFlux) call MPAS_pool_get_array(oceanFluxes, 'oceanFreshWaterFlux', oceanFreshWaterFlux) call MPAS_pool_get_array(oceanFluxes, 'oceanSaltFlux', oceanSaltFlux) - + if (config_use_data_icebergs) then call MPAS_pool_get_subpool(block_ptr % structs, "berg_fluxes", icebergFluxes) - + call MPAS_pool_get_array(icebergFluxes, "bergFreshwaterFlux", bergFreshwaterFlux) call MPAS_pool_get_array(icebergFluxes, "bergLatentHeatFlux", bergLatentHeatFlux) endif - - if (config_use_column_biogeochemistry) then + + if (config_use_column_biogeochemistry .and. config_couple_biogeochemistry_fields) then call mpas_pool_get_subpool(block_ptr % structs, 'biogeochemistry', biogeochemistry) - + call mpas_pool_get_array(biogeochemistry, 'oceanAlgaeFlux', oceanAlgaeFlux) call mpas_pool_get_array(biogeochemistry, 'oceanDOCFlux', oceanDOCFlux) call mpas_pool_get_array(biogeochemistry, 'oceanDICFlux', oceanDICFlux) @@ -3249,18 +3301,20 @@ subroutine ice_export_moab(EClock) call mpas_pool_get_array(biogeochemistry, 'carbonToNitrogenRatioAlgae', carbonToNitrogenRatioAlgae) call mpas_pool_get_array(biogeochemistry, 'carbonToNitrogenRatioDON', carbonToNitrogenRatioDON) endif - + if (config_use_zaerosols .and. config_couple_biogeochemistry_fields) & + call mpas_pool_get_array(biogeochemistry, 'oceanDustIronFlux', oceanDustIronFlux) + do i = 1, nCellsSolve n = n + 1 - + ! ice fraction ailohi = min(iceAreaCell(i), 1.0_RKIND) - + !TODO: CICE has a check for ailohi < 0 - + ! surface temperature Tsrf = seaiceFreshWaterFreezingPoint + surfaceTemperatureCell(i) - + ! basal pressure if ( ailohi > 0.0_RKIND ) then call basal_pressure(& @@ -3272,7 +3326,7 @@ subroutine ice_export_moab(EClock) pondAreaCell(i), & config_use_topo_meltponds) endif - + ! wind stress (on T-grid: convert to lat-lon) call seaice_latlon_vector_rotation_backward(& tauxa, & @@ -3286,7 +3340,7 @@ subroutine ice_export_moab(EClock) zCell(i), & sphere_radius, & config_rotate_cartesian_grid) - + ! ice/ocean stress (on POP T-grid: convert to lat-lon) call seaice_latlon_vector_rotation_backward(& tauxo, & @@ -3300,25 +3354,25 @@ subroutine ice_export_moab(EClock) zCell(i), & sphere_radius, & config_rotate_cartesian_grid) - - !-------states-------------------- + + !-------states-------------------- i2x_im(n, index_i2x_Si_ifrac) = ailohi - + if (config_use_data_icebergs) then i2x_im(n, index_i2x_Fioi_bergw) = bergFreshwaterFlux(i) i2x_im(n, index_i2x_Fioi_bergh) = bergLatentHeatFlux(i) endif - + if ( ailohi > 0.0_RKIND ) then - - !-------states-------------------- + + !-------states-------------------- i2x_im(n, index_i2x_Si_t) = Tsrf i2x_im(n, index_i2x_Si_bpress) = basalPressure i2x_im(n, index_i2x_Si_u10) = atmosReferenceSpeed10m(i) i2x_im(n, index_i2x_Si_tref) = atmosReferenceTemperature2m(i) i2x_im(n, index_i2x_Si_qref) = atmosReferenceHumidity2m(i) i2x_im(n, index_i2x_Si_snowh) = snowVolumeCell(i) / ailohi - + !--- a/i fluxes computed by ice i2x_im(n, index_i2x_Faii_taux) = tauxa i2x_im(n, index_i2x_Faii_tauy) = tauya @@ -3328,17 +3382,17 @@ subroutine ice_export_moab(EClock) i2x_im(n, index_i2x_Faii_evap) = evaporativeWaterFlux(i) i2x_im(n, index_i2x_Faii_swnet) = absorbedShortwaveFlux(i) i2x_im(n, index_i2x_Faii_evap) = evaporativeWaterFlux(i) - + if (config_use_column_shortwave) then i2x_im(n, index_i2x_Si_avsdr) = albedoVisibleDirectCell(i) i2x_im(n, index_i2x_Si_anidr) = albedoIRDirectCell(i) i2x_im(n, index_i2x_Si_avsdf) = albedoVisibleDiffuseCell(i) i2x_im(n, index_i2x_Si_anidf) = albedoIRDiffuseCell(i) - + i2x_im(n, index_i2x_Faii_swnet) = absorbedShortwaveFlux(i) endif - - ! i/o fluxes computed by ice, as well as additional freshwater and salt calculated at the last + + ! i/o fluxes computed by ice, as well as additional freshwater and salt calculated at the last ! coupling import and needed to grow sea ice from frazil passed from the ocean model in the ! field frazilMassAdjust. i2x_im(n, index_i2x_Fioi_melth) = oceanHeatFlux(i) @@ -3347,9 +3401,9 @@ subroutine ice_export_moab(EClock) i2x_im(n, index_i2x_Fioi_salt ) = oceanSaltFlux(i) + seaiceReferenceSalinity*0.001_RKIND*frazilMassAdjust(i)/ailohi i2x_im(n, index_i2x_Fioi_taux ) = tauxo i2x_im(n, index_i2x_Fioi_tauy ) = tauyo - + ! export biogeochemistry fields, if configured - if (config_use_column_biogeochemistry) then + if (config_use_column_biogeochemistry .and. config_couple_biogeochemistry_fields) then ! convert from mmol N/m^3 to mmol C/m^3 i2x_im(n, index_i2x_Fioi_algae1) = oceanAlgaeFlux(1,i) * carbonToNitrogenRatioAlgae(1) i2x_im(n, index_i2x_Fioi_algae2) = oceanAlgaeFlux(2,i) * carbonToNitrogenRatioAlgae(2) @@ -3372,9 +3426,12 @@ subroutine ice_export_moab(EClock) i2x_im(n, index_i2x_Fioi_fed1 ) = oceanDissolvedIronFlux(1,i) / 1000._RKIND i2x_im(n, index_i2x_Fioi_fed2 ) = oceanDissolvedIronFlux(2,i) / 1000._RKIND endif + ! export dust, kg/m2/s + if (config_use_zaerosols .and. config_couple_biogeochemistry_fields) & + i2x_im(n, index_i2x_Fioi_dust1 ) = oceanDustIronFlux(i) endif enddo - + block_ptr => block_ptr % next enddo @@ -3385,7 +3442,7 @@ subroutine ice_export_moab(EClock) if ( ierr /= 0 ) then write(iceLogUnit,*) 'Fail to set MOAB fields ' endif - + call seq_timemgr_EClockGetData( EClock, stepno=cur_ice_stepno ) #ifdef MOABDEBUG write(lnum,"(I0.2)")cur_ice_stepno @@ -3564,7 +3621,9 @@ subroutine ice_import_moab(Eclock)!{{{ oceanZAerosolConcField, & atmosAerosolFluxField, & atmosBlackCarbonFluxField, & - atmosDustFluxField + atmosDustFluxField, & + atmosWetDustFluxField, & + atmosDryDustFluxField real (kind=RKIND), dimension(:), pointer :: & seaSurfaceTemperature, & @@ -3609,7 +3668,9 @@ subroutine ice_import_moab(Eclock)!{{{ oceanZAerosolConc, & atmosAerosolFlux, & atmosBlackCarbonFlux, & - atmosDustFlux + atmosDustFlux, & + atmosWetDustFlux, & + atmosDryDustFlux character(CXX) :: tagname integer :: ierr, ent_type integer :: cur_ice_stepno @@ -3697,9 +3758,7 @@ subroutine ice_import_moab(Eclock)!{{{ endif if (config_use_column_biogeochemistry) then - call mpas_pool_get_config(configs, "config_use_zaerosols", config_use_zaerosols) call mpas_pool_get_subpool(block_ptr % structs, 'biogeochemistry', biogeochemistry) - call mpas_pool_get_array(biogeochemistry, 'oceanAlgaeConc', oceanAlgaeConc) call mpas_pool_get_array(biogeochemistry, 'oceanDOCConc', oceanDOCConc) call mpas_pool_get_array(biogeochemistry, 'oceanDICConc', oceanDICConc) @@ -3712,14 +3771,19 @@ subroutine ice_import_moab(Eclock)!{{{ call mpas_pool_get_array(biogeochemistry, 'oceanHumicsConc', oceanHumicsConc) call mpas_pool_get_array(biogeochemistry, 'oceanParticulateIronConc', oceanParticulateIronConc) call mpas_pool_get_array(biogeochemistry, 'oceanDissolvedIronConc', oceanDissolvedIronConc) - call mpas_pool_get_array(biogeochemistry, 'oceanZAerosolConc', oceanZAerosolConc) call mpas_pool_get_array(biogeochemistry, 'carbonToNitrogenRatioAlgae', carbonToNitrogenRatioAlgae) call mpas_pool_get_array(biogeochemistry, 'carbonToNitrogenRatioDON', carbonToNitrogenRatioDON) + endif + + call mpas_pool_get_config(configs, "config_use_zaerosols", config_use_zaerosols) if (config_use_zaerosols) then call mpas_pool_get_array(biogeochemistry, "atmosBlackCarbonFlux", atmosBlackCarbonFlux) call mpas_pool_get_array(biogeochemistry, "atmosDustFlux", atmosDustFlux) + call mpas_pool_get_array(biogeochemistry, "atmosWetDustFlux", atmosWetDustFlux) + call mpas_pool_get_array(biogeochemistry, "atmosDryDustFlux", atmosDryDustFlux) endif - endif + if (config_use_column_biogeochemistry .or. config_use_zaerosols) & + call mpas_pool_get_array(biogeochemistry, 'oceanZAerosolConc', oceanZAerosolConc) do i = 1, nCellsSolve n = n + 1 @@ -3734,8 +3798,8 @@ subroutine ice_import_moab(Eclock)!{{{ seaSurfaceTiltV(i) = x2i_im(n,index_x2i_So_dhdy) if (trim(config_ocean_surface_type) == "free") then ! free surface (MPAS-O) - - ! freezingMeltingPotential(i) is the ocean energy associated with frazil formation + + ! freezingMeltingPotential(i) is the ocean energy associated with frazil formation ! when it is positive and frazilMassFlux is positive. Conversely, freezingMeltingPotential(i) ! is negative when there is the melting potential in which case frazilMassFlux is zero. @@ -3744,7 +3808,7 @@ subroutine ice_import_moab(Eclock)!{{{ frazilMassFlux = x2i_im(n,index_x2i_Fioo_frazil) ! Now determine the sea ice mass associated with the frazil heat flux given when - ! freezingMeltingPotential(i) is positive. This produces a revised mass flux, given + ! freezingMeltingPotential(i) is positive. This produces a revised mass flux, given ! in frazilMassFluxRev for the given sea surface salinity. The resulting difference ! is assigned to frazilMassAdjust(i) which is exported to the ocean in the subsequent ! coupling step as a freshwater and salt flux. This step is required to balance mass @@ -3752,7 +3816,7 @@ subroutine ice_import_moab(Eclock)!{{{ call frazil_mass(freezingMeltingPotential(i), frazilMassFluxRev, seaSurfaceSalinity(i)) - frazilMassAdjust(i) = frazilMassFlux-frazilMassFluxRev + frazilMassAdjust(i) = frazilMassFlux-frazilMassFluxRev else ! non-free surface (SOM) @@ -3826,46 +3890,72 @@ subroutine ice_import_moab(Eclock)!{{{ oceanParticulateIronConc(2,i) = x2i_im(n,index_x2i_So_fep2) oceanDissolvedIronConc(1,i) = x2i_im(n,index_x2i_So_fed1) oceanDissolvedIronConc(2,i) = x2i_im(n,index_x2i_So_fed2) + endif + if (config_use_zaerosols .or. config_use_column_biogeochemistry) then oceanZAerosolConc(1,i) = 0.0_RKIND oceanZAerosolConc(2,i) = 0.0_RKIND oceanZAerosolConc(3,i) = 0.0_RKIND oceanZAerosolConc(4,i) = 0.0_RKIND oceanZAerosolConc(5,i) = 0.0_RKIND oceanZAerosolConc(6,i) = 0.0_RKIND - ! set aerosols, if configured - if (config_use_zaerosols) then - if (config_use_modal_aerosols) then - atmosBlackCarbonFlux(1,i) = x2i_im(n,index_x2i_Faxa_bcphodry) & - + x2i_im(n,index_x2i_Faxa_bcphidry) - atmosBlackCarbonFlux(2,i) = x2i_im(n,index_x2i_Faxa_bcphiwet) - ! combine wet and dry dust - atmosDustFlux(1,i) = x2i_im(n,index_x2i_Faxa_dstwet1) & - + x2i_im(n,index_x2i_Faxa_dstdry1) - atmosDustFlux(2,i) = x2i_im(n,index_x2i_Faxa_dstwet2) & - + x2i_im(n,index_x2i_Faxa_dstdry2) - atmosDustFlux(3,i) = x2i_im(n,index_x2i_Faxa_dstwet3) & - + x2i_im(n,index_x2i_Faxa_dstdry3) - atmosDustFlux(4,i) = x2i_im(n,index_x2i_Faxa_dstwet4) & - + x2i_im(n,index_x2i_Faxa_dstdry4) - else - atmosBlackCarbonFlux(1,i) = x2i_im(n,index_x2i_Faxa_bcphodry) - atmosBlackCarbonFlux(2,i) = x2i_im(n,index_x2i_Faxa_bcphidry) & - + x2i_im(n,index_x2i_Faxa_bcphiwet) - ! combine wet and dry dust - atmosDustFlux(1,i) = x2i_im(n,index_x2i_Faxa_dstwet1) & - + x2i_im(n,index_x2i_Faxa_dstdry1) - atmosDustFlux(2,i) = x2i_im(n,index_x2i_Faxa_dstwet2) & - + x2i_im(n,index_x2i_Faxa_dstdry2) - atmosDustFlux(3,i) = x2i_im(n,index_x2i_Faxa_dstwet3) & - + x2i_im(n,index_x2i_Faxa_dstdry3) - atmosDustFlux(4,i) = x2i_im(n,index_x2i_Faxa_dstwet4) & - + x2i_im(n,index_x2i_Faxa_dstdry4) - endif + end if + ! set zaerosols, if configured + if (config_use_zaerosols) then + if (config_use_modal_aerosols) then + atmosBlackCarbonFlux(1,i) = x2i_im(n,index_x2i_Faxa_bcphodry) & + + x2i_im(n,index_x2i_Faxa_bcphidry) + atmosBlackCarbonFlux(2,i) = x2i_im(n,index_x2i_Faxa_bcphiwet) + ! combine wet and dry dust + atmosDustFlux(1,i) = x2i_im(n,index_x2i_Faxa_dstwet1) & + + x2i_im(n,index_x2i_Faxa_dstdry1) + atmosDustFlux(2,i) = x2i_im(n,index_x2i_Faxa_dstwet2) & + + x2i_im(n,index_x2i_Faxa_dstdry2) + atmosDustFlux(3,i) = x2i_im(n,index_x2i_Faxa_dstwet3) & + + x2i_im(n,index_x2i_Faxa_dstdry3) + atmosDustFlux(4,i) = x2i_im(n,index_x2i_Faxa_dstwet4) & + + x2i_im(n,index_x2i_Faxa_dstdry4) + + ! wet dust + atmosWetDustFlux(1,i) = x2i_im(n,index_x2i_Faxa_dstwet1) + atmosWetDustFlux(2,i) = x2i_im(n,index_x2i_Faxa_dstwet2) + atmosWetDustFlux(3,i) = x2i_im(n,index_x2i_Faxa_dstwet3) + atmosWetDustFlux(4,i) = x2i_im(n,index_x2i_Faxa_dstwet4) + + ! dry dust + atmosDryDustFlux(1,i) = x2i_im(n,index_x2i_Faxa_dstdry1) + atmosDryDustFlux(2,i) = x2i_im(n,index_x2i_Faxa_dstdry2) + atmosDryDustFlux(3,i) = x2i_im(n,index_x2i_Faxa_dstdry3) + atmosDryDustFlux(4,i) = x2i_im(n,index_x2i_Faxa_dstdry4) + else + atmosBlackCarbonFlux(1,i) = x2i_im(n,index_x2i_Faxa_bcphodry) + atmosBlackCarbonFlux(2,i) = x2i_im(n,index_x2i_Faxa_bcphidry) & + + x2i_im(n,index_x2i_Faxa_bcphiwet) + ! combine wet and dry dust + atmosDustFlux(1,i) = x2i_im(n,index_x2i_Faxa_dstwet1) & + + x2i_im(n,index_x2i_Faxa_dstdry1) + atmosDustFlux(2,i) = x2i_im(n,index_x2i_Faxa_dstwet2) & + + x2i_im(n,index_x2i_Faxa_dstdry2) + atmosDustFlux(3,i) = x2i_im(n,index_x2i_Faxa_dstwet3) & + + x2i_im(n,index_x2i_Faxa_dstdry3) + atmosDustFlux(4,i) = x2i_im(n,index_x2i_Faxa_dstwet4) & + + x2i_im(n,index_x2i_Faxa_dstdry4) + + ! wet dust + atmosWetDustFlux(1,i) = x2i_im(n,index_x2i_Faxa_dstwet1) + atmosWetDustFlux(2,i) = x2i_im(n,index_x2i_Faxa_dstwet2) + atmosWetDustFlux(3,i) = x2i_im(n,index_x2i_Faxa_dstwet3) + atmosWetDustFlux(4,i) = x2i_im(n,index_x2i_Faxa_dstwet4) + + ! dry dust + atmosDryDustFlux(1,i) = x2i_im(n,index_x2i_Faxa_dstdry1) + atmosDryDustFlux(2,i) = x2i_im(n,index_x2i_Faxa_dstdry2) + atmosDryDustFlux(3,i) = x2i_im(n,index_x2i_Faxa_dstdry3) + atmosDryDustFlux(4,i) = x2i_im(n,index_x2i_Faxa_dstdry4) endif endif end do -!----------------------------------------------------------------------- +!----------------------------------------------------------------------- ! ! unit conversions and any manipulation of coupled fields ! @@ -3939,13 +4029,15 @@ subroutine ice_import_moab(Eclock)!{{{ call mpas_pool_get_field(biogeochemistry, 'oceanHumicsConc', oceanHumicsConcField) call mpas_pool_get_field(biogeochemistry, 'oceanParticulateIronConc', oceanParticulateIronConcField) call mpas_pool_get_field(biogeochemistry, 'oceanDissolvedIronConc', oceanDissolvedIronConcField) + endif + if (config_use_zaerosols .or. config_use_column_biogeochemistry) & call mpas_pool_get_field(biogeochemistry, 'oceanZAerosolConc', oceanZAerosolConcField) - if (config_use_zaerosols) then - call mpas_pool_get_field(biogeochemistry, "atmosBlackCarbonFlux", atmosBlackCarbonFluxField) - call mpas_pool_get_field(biogeochemistry, "atmosDustFlux", atmosDustFluxField) - endif + if (config_use_zaerosols) then + call mpas_pool_get_field(biogeochemistry, "atmosBlackCarbonFlux", atmosBlackCarbonFluxField) + call mpas_pool_get_field(biogeochemistry, "atmosDustFlux", atmosDustFluxField) + call mpas_pool_get_field(biogeochemistry, "atmosWetDustFlux", atmosWetDustFluxField) + call mpas_pool_get_field(biogeochemistry, "atmosDryDustFlux", atmosDryDustFluxField) endif - call mpas_dmpar_exch_halo_field(seaSurfaceTemperatureField) call mpas_dmpar_exch_halo_field(seaSurfaceSalinityField) call mpas_dmpar_exch_halo_field(seaFreezingTemperatureField) @@ -3988,11 +4080,14 @@ subroutine ice_import_moab(Eclock)!{{{ call mpas_dmpar_exch_halo_field(oceanHumicsConcField) call mpas_dmpar_exch_halo_field(oceanParticulateIronConcField) call mpas_dmpar_exch_halo_field(oceanDissolvedIronConcField) + endif + if (config_use_zaerosols .or. config_use_column_biogeochemistry) & call mpas_dmpar_exch_halo_field(oceanZAerosolConcField) - if (config_use_zaerosols) then + if (config_use_zaerosols) then call mpas_dmpar_exch_halo_field(atmosBlackCarbonFluxField) call mpas_dmpar_exch_halo_field(atmosDustFluxField) - endif + call mpas_dmpar_exch_halo_field(atmosWetDustFluxField) + call mpas_dmpar_exch_halo_field(atmosDryDustFluxField) endif ! REVISION HISTORY: diff --git a/components/mpas-seaice/src/Registry.xml b/components/mpas-seaice/src/Registry.xml index 1fb95093b416..7c842ca2f3c4 100644 --- a/components/mpas-seaice/src/Registry.xml +++ b/components/mpas-seaice/src/Registry.xml @@ -790,7 +790,11 @@ /> - + + + + - - - - - - + + + + + + + + + + + + @@ -5274,7 +5328,21 @@ /> + + + + + @@ -5302,7 +5394,7 @@ type="real" dimensions="nZBGCTracers nCategories nCells Time" units="mmol m-2 s-1" - description="Tracers are ordered: diatom nitrogen, smallPlankton nitrogen, phaeocystis nitrogen, nitrate, polysaccarid carbon, lipid carbon, ammonium, silicate, DMSPp, DMSPd, DMS, Nonreactive nitrate, Protein nitrogen, dissolved iron in umol/m2/s, particulate iron in umol/m2/s, humic carbon, black carbon1 in mg/m2/s, black carbon2 in mg/m2/s, dust1 in mg/m2/s, dust2 in mg/m2/s, dust3 in mg/m2/s, dust4 in mg/m2/s" + description="Only bio tracers used in the order: diatom nitrogen, smallPlankton nitrogen, phaeocystis nitrogen, nitrate, polysaccarid carbon, lipid carbon, dissolved inorganic carbon,ammonium, silicate, DMSPp, DMSPd, DMS, Nonreactive nitrate, Protein nitrogen, dissolved iron in umol/m2/s, particulate iron in umol/m2/s, humic carbon, black carbon1 in kg/m2/s, black carbon2 in kg/m2/s, dust1 in kg/m2/s, dust2 in kg/m2/s, dust3 in kg/m2/s, dust4 in kg/m2/s" icepack_name="flux_bion" packages="pkgColumnBiogeochemistry;pkgColumnPackage" /> @@ -5310,130 +5402,305 @@ type="real" dimensions="nZBGCTracers nCells Time" units="mmol m-3" - description="Tracers are ordered: diatom nitrogen, smallPlankton nitrogen, phaeocystis nitrogen, nitrate, polysaccarid carbon, lipid carbon, ammonium, silicate, DMSPp, DMSPd, DMS, Nonreactive nitrate, Protein nitrogen, dissolved iron in umol/m3, particulate iron in umol/m3, humic carbon, black carbon1 in mg/m3, black carbon2 in mg/m3,dust1 in mg/m3, dust2 in mg/m3, dust3 in mg/m3, dust4 in mg/m3" + description="All possible bio tracers in order: maxAlgaeType, nitrate, maxDOCType, maxDICType, chl (maxAlgaeType), ammonium, silicate, DMSPp, DMSPd, DMS, Nonreactive nitrate, maxDONType, dFe (maxFeType, umol/m3), pFe (maxFeType, umol/m3), maxBCType (kg/m3), maxDustType (kg/m3), humic carbon" + icepack_name="ocean_bio" + packages="pkgColumnBiogeochemistry;pkgColumnPackage" + /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + blockPtr % next + enddo + + ! sum across processors + call MPAS_dmpar_sum_real_array(domain % dminfo, nHemispheres, blackCarbon, totalBlackCarbon) + + ! clean up + deallocate(blackCarbon) + + end subroutine compute_total_black_carbon + !*********************************************************************** ! ! compute_carbon_cell @@ -3059,6 +3488,127 @@ subroutine compute_carbon_cell(blockPtr,totalCarbonContentCell) end subroutine compute_carbon_cell +!*********************************************************************** +! +! compute_black_carbon_cell +! +!> \brief +!> \author Nicole Jeffery, LANL +!> \date 11 Mar 2024 +!> \details Calculate the total carbon concentration in the sea ice cell +!> by summing the appropriate biogeochemical tracers in units of kg C +!> +!> Total black carbon = black carbon 1 + black carbon 2 +! +!----------------------------------------------------------------------- + + subroutine compute_black_carbon_cell(blockPtr,totalBlackCarbonContentCell) + + real(kind=RKIND), dimension(:), intent(out) :: & + totalBlackCarbonContentCell + + type(block_type), intent(in) :: & + blockPtr + + logical, pointer :: & + config_use_zaerosols + + integer, pointer :: & + nBioLayersP1, & + nBioLayersP3, & + nBioLayers, & + nzAerosols, & + maxBCType, & + TWO + + type(MPAS_pool_type), pointer :: & + mesh, & + biogeochemistry, & + tracers_aggregate + + real(kind=RKIND), dimension(:), pointer :: & + brineFractionCell, & + iceVolumeCell, & + snowVolumeCell + + real(kind=RKIND), dimension(:,:), pointer :: & + verticalAerosolsConcCell + + integer, pointer :: & + nCellsSolve, & + nSnowLayers + + real(kind=RKIND), dimension(:), allocatable :: & + verticalGridSpace + + real(kind=RKIND) :: & + snowleveltop, & + snowlevelint + + integer :: & + iBioTracers, & + iBioCount, & + iBioData, & + iCell, & + nBC + + call MPAS_pool_get_config(blockPtr % configs, "config_use_zaerosols",config_use_zaerosols) + + call MPAS_pool_get_dimension(blockPtr % dimensions, "nBioLayers", nBioLayers) + call MPAS_pool_get_dimension(blockPtr % dimensions, "nBioLayersP1", nBioLayersP1) + call MPAS_pool_get_dimension(blockPtr % dimensions, "nBioLayersP3", nBioLayersP3) + call MPAS_pool_get_dimension(blockPtr % dimensions, "nzAerosols", nzAerosols) + call MPAS_pool_get_dimension(blockPtr % dimensions, "maxBCType", maxBCType) + call MPAS_pool_get_dimension(blockPtr % dimensions, "TWO", TWO) + + call MPAS_pool_get_subpool(blockPtr % structs, "tracers_aggregate", tracers_aggregate) + call MPAS_pool_get_subpool(blockPtr % structs, "mesh", mesh) + call MPAS_pool_get_subpool(blockPtr % structs, "biogeochemistry", biogeochemistry) + + call MPAS_pool_get_dimension(mesh, "nCellsSolve", nCellsSolve) + call MPAS_pool_get_dimension(mesh, 'nSnowLayers', nSnowLayers) + + call MPAS_pool_get_array(tracers_aggregate, "verticalAerosolsConcCell", verticalAerosolsConcCell) + call MPAS_pool_get_array(tracers_aggregate, "brineFractionCell", brineFractionCell) + call MPAS_pool_get_array(tracers_aggregate, "iceVolumeCell", iceVolumeCell) + call MPAS_pool_get_array(tracers_aggregate, "snowVolumeCell", snowVolumeCell) + + allocate(verticalGridSpace(nBioLayersP1)) + + verticalGridSpace(:) = 1.0_RKIND/real(nBioLayers,kind=RKIND) + verticalGridSpace(1) = verticalGridSpace(1)/2.0_RKIND + verticalGridSpace(nBioLayersP1) = verticalGridSpace(1) + + totalBlackCarbonContentCell(:) = 0.0_RKIND + + if (config_use_zaerosols) then + nBC = min(nzAerosols,maxBCType) + do iCell = 1, nCellsSolve + iBioCount = 0 + + ! BC + snowleveltop = snowVolumeCell(iCell)/real(nSnowLayers,kind=RKIND)/2.0_RKIND + snowlevelint = snowVolumeCell(iCell) - snowleveltop + do iBioTracers = 1, nBC + iBioData = (iBioTracers-1)*nBioLayersP3 + ! ice BC + do iBioCount = 1, nBioLayersP1 + totalBlackCarbonContentCell(iCell) = totalBlackCarbonContentCell(iCell) + & + verticalAerosolsConcCell(iBioData + iBioCount,iCell) * verticalGridSpace(iBioCount) * & + iceVolumeCell(iCell) * brineFractionCell(iCell) + end do + ! snow BC + totalBlackCarbonContentCell(iCell) = totalBlackCarbonContentCell(iCell) + & + verticalAerosolsConcCell(iBioData+nBioLayersP1+1,iCell) * snowleveltop + & + verticalAerosolsConcCell(iBioData+nBioLayersP1+2,iCell) * snowlevelint + enddo + enddo + endif + + deallocate(verticalGridSpace) + + end subroutine compute_black_carbon_cell + !*********************************************************************** ! ! routine reset_accumulated_variables @@ -3082,7 +3632,8 @@ subroutine reset_accumulated_variables(domain) conservationCheckEnergyAMPool, & conservationCheckMassAMPool, & conservationCheckSaltAMPool, & - conservationCheckCarbonAMPool + conservationCheckCarbonAMPool, & + conservationCheckBlackCarbonAMPool integer, pointer :: & nAccumulate @@ -3125,6 +3676,12 @@ subroutine reset_accumulated_variables(domain) carbonConsHumicsFlux, & carbonConsSemiLabileDOCFlux + real(kind=RKIND), dimension(:), pointer :: & + blackCarbonConsOceanBlackCarbonFlux, & + blackCarbonConsAtmBlackCarbonFlux, & + blackCarbonConsAtmBC1Flux, & + blackCarbonConsAtmBC2Flux + ! number of accumulations call MPAS_pool_get_subpool(domain % blocklist % structs, "conservationCheckAM", conservationCheckAMPool) call MPAS_pool_get_array(conservationCheckAMPool, "nAccumulate", nAccumulate) @@ -3209,6 +3766,19 @@ subroutine reset_accumulated_variables(domain) carbonConsHumicsFlux(:) = 0.0_RKIND carbonConsSemiLabileDOCFlux(:) = 0.0_RKIND + ! black carbon + + call MPAS_pool_get_subpool(domain % blocklist % structs, "conservationCheckBlackCarbonAM", conservationCheckBlackCarbonAMPool) + call MPAS_pool_get_array(conservationCheckBlackCarbonAMPool, "blackCarbonConsOceanBlackCarbonFlux", blackCarbonConsOceanBlackCarbonFlux) + call MPAS_pool_get_array(conservationCheckBlackCarbonAMPool, "blackCarbonConsAtmBlackCarbonFlux", blackCarbonConsAtmBlackCarbonFlux) + call MPAS_pool_get_array(conservationCheckBlackCarbonAMPool, "blackCarbonConsAtmBC1Flux", blackCarbonConsAtmBC1Flux) + call MPAS_pool_get_array(conservationCheckBlackCarbonAMPool, "blackCarbonConsAtmBC2Flux", blackCarbonConsAtmBC2Flux) + + blackCarbonConsOceanBlackCarbonFlux(:) = 0.0_RKIND + blackCarbonConsAtmBlackCarbonFlux(:) = 0.0_RKIND + blackCarbonConsAtmBC1Flux(:) = 0.0_RKIND + blackCarbonConsAtmBC2Flux(:) = 0.0_RKIND + end subroutine reset_accumulated_variables !*********************************************************************** diff --git a/components/mpas-seaice/src/build_options.mk b/components/mpas-seaice/src/build_options.mk index 5f2bdcfe2771..0ef6fc91e5d7 100644 --- a/components/mpas-seaice/src/build_options.mk +++ b/components/mpas-seaice/src/build_options.mk @@ -3,7 +3,7 @@ ifeq "$(ROOT_DIR)" "" endif EXE_NAME=seaice_model NAMELIST_SUFFIX=seaice -FCINCLUDES += -I$(ROOT_DIR)/column -I$(ROOT_DIR)/shared -I$(ROOT_DIR)/analysis_members -I$(ROOT_DIR)/model_forward +FCINCLUDES += -I$(ROOT_DIR)/icepack/columnphysics -I$(ROOT_DIR)/column -I$(ROOT_DIR)/shared -I$(ROOT_DIR)/analysis_members -I$(ROOT_DIR)/model_forward override CPPFLAGS += -DCORE_SEAICE -DUSE_SNICARHC ifneq "$(ESM)" "" override CPPFLAGS += -Dcoupled -DCCSMCOUPLED diff --git a/components/mpas-seaice/src/column/ice_aerosol.F90 b/components/mpas-seaice/src/column/ice_aerosol.F90 index c3e6a9d0bf27..a4a270713a80 100644 --- a/components/mpas-seaice/src/column/ice_aerosol.F90 +++ b/components/mpas-seaice/src/column/ice_aerosol.F90 @@ -580,17 +580,21 @@ subroutine update_snow_bgc (dt, nblyr, & if (dzssl_new .lt. hs_ssl_min) then ! Put atm BC/dust flux directly into the sea ice do k=1,nbtrcr - flux_bio(k) = flux_bio(k) + & + flux_bio_o(k) = flux_bio(k) + if (hilyr .lt. hs_ssl_min) then + flux_bio(k) = flux_bio(k) + & (trcrn(bio_index(k)+ nblyr+1)*dzssl+ & trcrn(bio_index(k)+ nblyr+2)*dzint)/dt - trcrn(bio_index(k) + nblyr+1) = c0 - trcrn(bio_index(k) + nblyr+2) = c0 - if (hilyr .lt. hs_ssl_min) then flux_bio(k) = flux_bio(k) + flux_bio_atm(k) else + zbgc_snow(k) = zbgc_snow(k) + & + (trcrn(bio_index(k)+ nblyr+1)*dzssl+ & + trcrn(bio_index(k)+ nblyr+2)*dzint) zbgc_atm(k) = zbgc_atm(k) & + flux_bio_atm(k)*dt end if + trcrn(bio_index(k) + nblyr+1) = c0 + trcrn(bio_index(k) + nblyr+2) = c0 enddo else @@ -616,7 +620,7 @@ subroutine update_snow_bgc (dt, nblyr, & end if if (dzint <= puny) then do k = 1,nbtrcr - flux_bio(k) = flux_bio(k) + (aerosno(k,2) + aerosno(k,1))/dt + zbgc_snow(k) = zbgc_snow(k) + (aerosno(k,2) + aerosno(k,1)) aerosno(k,2) = c0 aerosno(k,1) = c0 end do @@ -636,6 +640,7 @@ subroutine update_snow_bgc (dt, nblyr, & dzssl = dzssl - dz + fsnow/rhos*dt dzint = dzint + dz end if + if (dzssl <= puny) then do k = 1,nbtrcr aerosno(k,2) = aerosno(k,2) + aerosno(k,1) @@ -644,7 +649,7 @@ subroutine update_snow_bgc (dt, nblyr, & end if if (dzint <= puny) then do k = 1,nbtrcr - flux_bio(k) = flux_bio(k) + (aerosno(k,2) + aerosno(k,1))/dt + zbgc_snow(k) = zbgc_snow(k) + (aerosno(k,2) + aerosno(k,1)) aerosno(k,2) = c0 aerosno(k,1) = c0 end do @@ -664,7 +669,7 @@ subroutine update_snow_bgc (dt, nblyr, & sloss2 = kscavz(bio_index_o(k))*aerosno(k,2) & *max(-dhs_melts-dzssl,c0)/dzint aerosno(k,2) = max(c0,aerosno(k,2) - sloss2) - flux_bio(k) = flux_bio(k) + (sloss1+sloss2)/dt ! all not scavenged ends in ocean + zbgc_snow(k) = zbgc_snow(k) + (sloss1+sloss2) ! all not scavenged ends in ice enddo ! update snow thickness @@ -795,6 +800,7 @@ subroutine update_snow_bgc (dt, nblyr, & else if (aerotot(k) > c0) then aero_cons(k) = aero_cons(k)/aerotot(k) end if + if (aero_cons(k) > puny .or. zbgc_snow(k) + zbgc_atm(k) < c0) then write(warning,*) 'Conservation failure: aerosols in snow' call add_warning(warning) diff --git a/components/mpas-seaice/src/column/ice_algae.F90 b/components/mpas-seaice/src/column/ice_algae.F90 index d235d988fa53..e65dbed667ec 100644 --- a/components/mpas-seaice/src/column/ice_algae.F90 +++ b/components/mpas-seaice/src/column/ice_algae.F90 @@ -304,7 +304,7 @@ subroutine zbio (dt, nblyr, & carbonError = carbonInitial-carbonFlux*dt-carbonFinal - if (abs(carbonError) > accuracy * maxval ((/carbonInitial, carbonFinal/))) then + if (abs(carbonError) > max(puny,accuracy * maxval ((/carbonInitial, carbonFinal/)))) then write(warning,*) 'carbonError:', carbonError call add_warning(warning) write(warning,*) 'carbonInitial:', carbonInitial @@ -315,6 +315,8 @@ subroutine zbio (dt, nblyr, & call add_warning(warning) write(warning,*) 'accuracy * maxval ((/carbonInitial, carbonFinal/:)', accuracy * maxval ((/carbonInitial, carbonFinal/)) call add_warning(warning) + write(warning,*) 'puny', puny + call add_warning(warning) if (aicen > c0) then hsnow_f = vsnon/aicen write(warning,*) 'after z_biogeochemistry' @@ -347,8 +349,12 @@ subroutine zbio (dt, nblyr, & call add_warning(warning) write(warning,*) Tot_BGC_i(mm) + flux_bio_atm(mm)*dt - flux_bion(mm)*dt call add_warning(warning) - !l_stop = .true. - !stop_label = "carbon conservation in ice_algae.F90" + write(warning,*) 'hbri, hbri_old' + call add_warning(warning) + write(warning,*) hbri, hbri_old + call add_warning(warning) + l_stop = .true. + stop_label = "carbon conservation in ice_algae.F90" enddo endif endif @@ -1012,7 +1018,7 @@ subroutine z_biogeochemistry (n_cat, dt, & ! local parameters real (kind=dbl_kind), parameter :: & - accuracy = 1.0e-14_dbl_kind, & + accuracy = 1.0e-13_dbl_kind, & ! 1.0e-14_dbl_kind, & r_c = 3.0e3_dbl_kind , & ! ice crystal radius (um) r_bac= 4.7_dbl_kind , & ! diatom large radius (um) r_alg= 10.0_dbl_kind , & ! diatom small radius (um) @@ -1021,7 +1027,7 @@ subroutine z_biogeochemistry (n_cat, dt, & Nquota_I = 0.0408_dbl_kind, & ! Intercept in N quota to cell volume fit f_s = p1, & ! fracton of sites available for saturation f_a = 0.3_dbl_kind, & !c1 , & ! fraction of collector available for attachment - f_v = 0.7854 ! fraction of algal coverage on area availabel for attachment + f_v = 0.7854_dbl_kind ! fraction of algal coverage on area availabel for attachment ! 4(pi r^2)/(4r)^2 [Johnson et al, 1995, water res. research] integer, parameter :: & @@ -1058,7 +1064,7 @@ subroutine z_biogeochemistry (n_cat, dt, & iphin_N(k) = iphin(k) bphin_N(1) = bphi_min - if (abs(trcrn(bio_index(m) + k-1)) < puny) then + if (abs(trcrn(bio_index(m) + k-1)) < accuracy) then flux_bio(m) = flux_bio(m) + trcrn(bio_index(m) + k-1)* hbri_old * dz(k)/dt trcrn(bio_index(m) + k-1) = c0 in_init_cons(k,m) = c0 @@ -1319,8 +1325,7 @@ subroutine z_biogeochemistry (n_cat, dt, & trcrn(nt_zbgc_frac+mm-1) = zbgc_frac_init(mm) if (sum_tot > c0) trcrn(nt_zbgc_frac+mm-1) = sum_new/sum_tot - if (abs(sum_initial-sum_tot-flux_bio(mm)*dt + source(mm)) > accuracy*max(sum_initial,sum_tot) .or. & -! if (abs(sum_new-sum_old) > accuracy*sum_old .or. & + if (abs(sum_initial-sum_tot-flux_bio(mm)*dt + source(mm)) > max(accuracy,accuracy*max(sum_initial,sum_tot)) .or. & minval(biocons(:)) < c0 .or. minval(initcons_stationary(:)) < c0 & .or. l_stop) then write(warning,*)'zbgc FCT tracer solution failed,mm', mm @@ -1406,15 +1411,24 @@ subroutine z_biogeochemistry (n_cat, dt, & do m = 1,nbtrcr do k = 1,nblyr+1 ! back to bulk quantity bio_tmp = (biomat_brine(k,m) + react(k,m))*iphin_N(k) - if (tr_bgc_C .and. m .eq. nlt_bgc_DIC(1) .and. bio_tmp < -puny) then ! satisfy DIC demands from ocean - write(warning, *) 'DIC demand from ocean' - call add_warning(warning) - write(warning, *) 'm, nlt_bgc_DIC(1), bio_tmp, react(k,m):' - call add_warning(warning) - write(warning, *) m, nlt_bgc_DIC(1), bio_tmp, react(k,m) - call add_warning(warning) - flux_bio(m) = flux_bio(m) + bio_tmp*dz(k)*hbri_old/dt + if (tr_bgc_C .and. m .eq. nlt_bgc_DIC(1) .and. bio_tmp .le. -accuracy) then ! satisfy DIC demands from ocean + !uncomment for additional diagnostics + ! write(warning, *) 'DIC demand from ocean' + ! call add_warning(warning) + ! write(warning, *) 'm, nlt_bgc_DIC(1), bio_tmp, react(k,m):' + ! call add_warning(warning) + ! write(warning, *) m, nlt_bgc_DIC(1), bio_tmp, react(k,m) + ! call add_warning(warning) + ! write(warning,*)'flux_bio(m) Initial, hbri_old, dz(k)' + ! call add_warning(warning) + ! write(warning,*) flux_bio(m), hbri_old, dz(k) + ! call add_warning(warning) + flux_bio(m) = flux_bio(m) + bio_tmp*dz(k)*hbri/dt bio_tmp = c0 + ! write(warning,*) 'flux_bio(m)' + ! call add_warning(warning) + ! write(warning,*) flux_bio(m) + ! call add_warning(warning) end if if (m .eq. nlt_bgc_Nit) then initcons_mobile(k) = max(c0,(biomat_brine(k,m)-nitrification(k) + & @@ -1441,8 +1455,8 @@ subroutine z_biogeochemistry (n_cat, dt, & call add_warning(warning) l_stop = .true. stop_label = 'C in algal_dyn not conserved' - elseif (abs(bio_tmp) < puny) then - flux_bio(m) = flux_bio(m) + bio_tmp*dz(k)*hbri_old/dt + elseif (abs(bio_tmp) < accuracy) then + flux_bio(m) = flux_bio(m) + bio_tmp*dz(k)*hbri/dt bio_tmp = c0 elseif (bio_tmp > 1.0e8_dbl_kind) then write(warning, *) 'very large bgc value' @@ -2258,6 +2272,10 @@ subroutine algal_dyn (dt, & write(warning, *) 'Conservation error!' call add_warning(warning) if (tr_bgc_DON) then + write(warning, *) 'Error bound = max(puny,maxval(abs(reactb(:)))*1.0e-13_dbl_kind)' + call add_warning(warning) + write(warning, *) max(puny,maxval(abs(reactb(:)))*1.0e-13_dbl_kind) + call add_warning(warning) write(warning, *) 'dN,DONin(1), kn_bac(1),secday,dt,n_doc' call add_warning(warning) write(warning, *) dN, DONin(1),kn_bac(1),secday,dt,n_doc @@ -2271,10 +2289,16 @@ subroutine algal_dyn (dt, & call add_warning(warning) write(warning, *) dN,secday,dt,n_doc call add_warning(warning) - write(warning, *) 'reactb(nlt_bgc_Nit),reactb(nlt_bgc_N(1)),reactb(nlt_bgc_N(2)' + write(warning, *) 'reactb(nlt_bgc_Nit),fr_resp' call add_warning(warning) - write(warning, *) reactb(nlt_bgc_Nit),reactb(nlt_bgc_N(1)),reactb(nlt_bgc_N(2)) + write(warning, *) reactb(nlt_bgc_Nit),fr_resp call add_warning(warning) + do k = 1,n_algae + write(warning, *) 'reactb(nlt_bgc_N(k)),fr_graze(k), grow_N(k), mort(k)' + call add_warning(warning) + write(warning, *) reactb(nlt_bgc_N(k)),fr_graze(k), grow_N(k), mort(k) + call add_warning(warning) + enddo if (tr_bgc_Am) then write(warning, *) 'reactb(nlt_bgc_Am),Am_r, Am_s' call add_warning(warning) @@ -2297,6 +2321,7 @@ subroutine algal_dyn (dt, & write(warning, *) 'DOC_r,DOC_s' call add_warning(warning) write(warning, *) DOC_r(k),DOC_s(k) + call add_warning(warning) end do do k = 1,n_dic write(warning, *) 'DICin' @@ -2311,7 +2336,6 @@ subroutine algal_dyn (dt, & call add_warning(warning) write(warning, *) DIC_r(k),DIC_s(k) end do - call add_warning(warning) write(warning, *) 'Zoo' call add_warning(warning) write(warning, *) Zoo @@ -2850,8 +2874,8 @@ subroutine check_conservation_FCT & C_low(k) = C_new(k) enddo - accuracy = 1.0e-14_dbl_kind*max(c1, C_init_tot, C_new_tot) - fluxbio = (C_init_tot - C_new_tot + source)/dt + accuracy = 1.0e-11_dbl_kind*max(c1, C_init_tot, C_new_tot) + fluxbio = fluxbio + (C_init_tot - C_new_tot + source)/dt diff_dt =C_new_tot - C_init_tot - (S_top+S_bot+L_bot*C_new(nblyr+1)+L_top*C_new(1))*dt if (minval(C_low) < c0) then @@ -2861,7 +2885,7 @@ subroutine check_conservation_FCT & endif if (abs(diff_dt) > accuracy ) then - !l_stop = .true. + l_stop = .true. write(warning,*) 'Conservation of zbgc low order solution failed: diff_dt:',& diff_dt call add_warning(warning) diff --git a/components/mpas-seaice/src/column/ice_colpkg.F90 b/components/mpas-seaice/src/column/ice_colpkg.F90 index a8bf6bc2a73f..ac0435b1f842 100644 --- a/components/mpas-seaice/src/column/ice_colpkg.F90 +++ b/components/mpas-seaice/src/column/ice_colpkg.F90 @@ -2538,7 +2538,7 @@ subroutine colpkg_step_therm2 (dt, ncat, n_aero, nbtrcr, & real (kind=dbl_kind), dimension(:,:), intent(inout) :: & trcrn ! tracers - + logical (kind=log_kind), dimension(:), intent(inout) :: & first_ice ! true until ice forms @@ -4594,6 +4594,7 @@ subroutine colpkg_init_parameters(& real (kind=dbl_kind), intent(in) :: & grid_oS_in , & ! for bottom flux (zsalinity) l_skS_in ! 0.02 characteristic skeletal layer thickness (m) (zsalinity) + real (kind=dbl_kind), intent(in) :: & ratio_Si2N_diatoms_in, & ! algal Si to N (mol/mol) ratio_Si2N_sp_in , & @@ -5458,7 +5459,8 @@ subroutine colpkg_biogeochemistry(dt, & upNO, upNH, iDi, iki, zfswin, & zsal_tot, darcy_V, grow_net, & PP_net, hbri,dhbr_bot, dhbr_top, Zoo,& - fbio_snoice, fbio_atmice, ocean_bio, & + fbio_snoice, fbio_atmice, & + ocean_bio, & first_ice, fswpenln, bphi, bTiz, ice_bio_net, & snow_bio_net, totalChla, fswthrun, Rayleigh_criteria, & sice_rho, fzsal, fzsal_g, & @@ -5815,7 +5817,7 @@ subroutine colpkg_biogeochemistry(dt, & n_don, & n_fed, n_fep, & n_zaero, first_ice(n), & - hin_old(n), ocean_bio(:), & + hin_old(n), ocean_bio(1:nbtrcr), & bphi(:,n), iphin, & iDi(:,n), sss, & fswpenln(:,n), & diff --git a/components/mpas-seaice/src/column/ice_therm_itd.F90 b/components/mpas-seaice/src/column/ice_therm_itd.F90 index 81930d017e49..22b9d3cd894a 100644 --- a/components/mpas-seaice/src/column/ice_therm_itd.F90 +++ b/components/mpas-seaice/src/column/ice_therm_itd.F90 @@ -553,7 +553,7 @@ subroutine linear_itd (ncat, hin_max, & enddo enddo endif - + call shift_ice (ntrcr, ncat, & trcr_depend, & trcr_base, & @@ -913,7 +913,9 @@ subroutine lateral_melt (dt, ncat, & dvint ! snow interior layer real (kind=dbl_kind), dimension (ncat) :: & - vicen_init ! volume per unit area of ice (m) + vicen_init, & ! initial volume per unit area of ice (m) + aicen_init, & ! initial area + vsnon_init ! initial volume of snow (m) if (rside > c0) then ! grid cells with lateral melting. @@ -944,6 +946,8 @@ subroutine lateral_melt (dt, ncat, & ! state variables vicen_init(n) = vicen(n) + aicen_init(n) = aicen(n) + vsnon_init(n) = vsnon(n) aicen(n) = aicen(n) * (c1 - rside) vicen(n) = vicen(n) * (c1 - rside) vsnon(n) = vsnon(n) * (c1 - rside) @@ -980,8 +984,8 @@ subroutine lateral_melt (dt, ncat, & !----------------------------------------------------------------- if (z_tracers) then ! snow tracers - dvssl = min(p5*vsnon(n)/real(nslyr,kind=dbl_kind), hs_ssl*aicen(n)) !snow surface layer - dvint = vsnon(n)- dvssl !snow interior + dvssl = min(p5*vsnon_init(n)/real(nslyr,kind=dbl_kind), hs_ssl*aicen_init(n)) !snow surface layer + dvint = vsnon_init(n)- dvssl !snow interior do k = 1, nbtrcr flux_bio(k) = flux_bio(k) & + (trcrn(bio_index(k)+nblyr+1,n)*dvssl & diff --git a/components/mpas-seaice/src/column/ice_warnings.F90 b/components/mpas-seaice/src/column/ice_warnings.F90 index a3424c176bb7..091c8b2be944 100644 --- a/components/mpas-seaice/src/column/ice_warnings.F90 +++ b/components/mpas-seaice/src/column/ice_warnings.F90 @@ -82,7 +82,7 @@ subroutine add_warning(warning) deallocate(warningsTmp) endif - + endif ! increase warning number diff --git a/components/mpas-seaice/src/column/ice_zbgc.F90 b/components/mpas-seaice/src/column/ice_zbgc.F90 index 1f1c6a7d9106..b537fa0140aa 100644 --- a/components/mpas-seaice/src/column/ice_zbgc.F90 +++ b/components/mpas-seaice/src/column/ice_zbgc.F90 @@ -11,6 +11,7 @@ module ice_zbgc use ice_kinds_mod use ice_zbgc_shared ! everything + use ice_warnings, only: add_warning implicit none @@ -109,7 +110,8 @@ subroutine add_new_ice_bgc (dt, nblyr, & location , & ! 1 (add frazil to bottom), 0 (add frazil throughout) n , & ! ice category index k , & ! ice layer index - m + m , & + nbiolayer real (kind=dbl_kind) :: & vbri1 , & ! starting volume of existing brine @@ -119,12 +121,14 @@ subroutine add_new_ice_bgc (dt, nblyr, & real (kind=dbl_kind) :: & vsurp , & ! volume of new ice added to each cat vtmp ! total volume of new and old ice - + real (kind=dbl_kind), dimension (ncat) :: & - vbrin ! trcrn(nt_fbri,n)*vicen(n) + vbrin , & ! trcrn(nt_fbri,n)*vicen(n) + brine_frac_init ! initial trcrn(nt_fbri,n) real (kind=dbl_kind) :: & - vice_new ! vicen_init + vsurp + vice_new , & ! vicen_init + vsurp + bio0new ! ocean_bio * zbgc_init_fac real (kind=dbl_kind) :: & Tmlts ! melting temperature (oC) @@ -132,9 +136,8 @@ subroutine add_new_ice_bgc (dt, nblyr, & character (len=char_len) :: & fieldid ! field identifier - real (kind=dbl_kind), dimension (nbtrcr) :: & - total_bio_initial, & ! Initial column bio concentration (mmol/m2) - total_bio_final ! final column bio concentration (mmol/m2) + character(len=char_len_long) :: & + warning real (kind=dbl_kind), dimension (nblyr+1) :: & zspace ! vertical grid spacing @@ -152,19 +155,13 @@ subroutine add_new_ice_bgc (dt, nblyr, & if (tr_brine) vbrin(n) = trcrn(nt_fbri,n)*vicen_init(n) enddo - do m = 1, nbtrcr - total_bio_initial(m) = c0 - do n = 1, ncat - do k = 1, nblyr+1 - total_bio_initial(m) = total_bio_initial(m) + vbrin(n) * zspace(k)*trcrn(bio_index(m)+k-1,n) - enddo - enddo - enddo - call column_sum (ncat, vbrin, vbri_init) vbri_init = vbri_init + vi0_init + do k = 1, nbtrcr + flux_bio(k) = flux_bio(k) - vi0_init/dt*ocean_bio(k)*zbgc_init_frac(k) + enddo !----------------------------------------------------------------- ! Distribute bgc in new ice volume among all ice categories by ! increasing ice thickness, leaving ice area unchanged. @@ -178,34 +175,27 @@ subroutine add_new_ice_bgc (dt, nblyr, & vtmp = c0 do n = 1,ncat - - if (hsurp > c0) then + brine_frac_init(n) = c1 + if (hsurp > c0) then ! add ice to all categories vtmp = vbrin(n) - vsurp = hsurp * aicen_init(n) + vsurp = hsurp * aicen_init(n) vbrin(n) = vbrin(n) + vsurp vice_new = vicen_init(n) + vsurp - if (tr_brine .and. vicen(n) > c0) then - trcrn(nt_fbri,n) = vbrin(n)/vicen(n) + if (tr_brine .and. vice_new > c0) then ! NJvicen(n) > c0) then + brine_frac_init(n) = trcrn(nt_fbri,n) !NJ + trcrn(nt_fbri,n) = vbrin(n)/vice_new !NJ vicen(n) elseif (tr_brine .and. vicen(n) <= c0) then trcrn(nt_fbri,n) = c1 endif - if (nbtrcr > 0) then - location = 1 - call adjust_tracer_profile(nbtrcr, dt, ntrcr, & - aicen_init(n), & - vbrin(n), & - vice_new, & - trcrn(:,n), & - vtmp, & - vsurp, sss, & - nilyr, nblyr, & - solve_zsal, bgrid, & - cgrid, & - ocean_bio, igrid, & - location, & - l_stop, stop_label) + if (nbtrcr > 0) then + do m = 1, nbtrcr + bio0new = ocean_bio(m)*zbgc_init_frac(m) + nbiolayer = nblyr+1 + call update_vertical_bio_tracers(nbiolayer, trcrn(bio_index(m):bio_index(m) + nblyr,n), & + vtmp, vbrin(n), bio0new,zspace(:)) + enddo !nbtrcr if (l_stop) return endif ! nbtrcr endif ! hsurp > 0 @@ -214,36 +204,30 @@ subroutine add_new_ice_bgc (dt, nblyr, & !----------------------------------------------------------------- ! Combine bgc in new ice grown in open water with category 1 ice. !----------------------------------------------------------------- - + if (vi0new > c0) then - vbri1 = vbrin(1) + vbri1 = vbrin(1) vbrin(1) = vbrin(1) + vi0new if (tr_brine .and. vicen(1) > c0) then trcrn(nt_fbri,1) = vbrin(1)/vicen(1) elseif (tr_brine .and. vicen(1) <= c0) then trcrn(nt_fbri,1) = c1 endif - + ! Diffuse_bio handles concentration changes from ice growth/melt ! ice area changes ! add salt throughout, location = 0 - if (nbtrcr > 0) then - location = 0 - call adjust_tracer_profile(nbtrcr, dt, ntrcr, & - aicen(1), & - vbrin(1), & - vicen(1), & - trcrn(:,1), & - vbri1, & - vi0new, sss, & - nilyr, nblyr, & - solve_zsal, bgrid, & - cgrid, & - ocean_bio, igrid, & - location, & - l_stop, stop_label) + if (nbtrcr > 0 .and. vbrin(1) > c0) then + do m = 1, nbtrcr + bio0new = ocean_bio(m)*zbgc_init_frac(m) + do k = 1, nblyr+1 + trcrn(bio_index(m) + k-1,1) = & + (trcrn(bio_index(m) + k-1,1)*vbri1 + bio0new * vi0new)/vbrin(1) + enddo + enddo + if (l_stop) return if (solve_zsal .and. vsnon1 .le. c0) then @@ -253,16 +237,6 @@ subroutine add_new_ice_bgc (dt, nblyr, & endif ! nbtrcr > 0 endif ! vi0new > 0 - do m = 1, nbtrcr - total_bio_final(m) = c0 - do n = 1, ncat - do k = 1, nblyr+1 - total_bio_final(m) = total_bio_final(m) + trcrn(nt_fbri,n) * vicen(n) *zspace(k)*trcrn(bio_index(m)+k-1,n) - enddo - enddo - flux_bio(m) = flux_bio(m) + (total_bio_initial(m) - total_bio_final(m))/dt - enddo - if (tr_brine .and. l_conservation_check) then call column_sum (ncat, vbrin, vbri_final) @@ -320,10 +294,6 @@ subroutine lateral_melt_bgc (dt, & ! local variables - real (kind=dbl_kind) :: & - total_bio_initial, & ! initial column tracer concentration (mmol/m2) - total_bio_final ! final column tracer concentration (mmol/m20 - integer (kind=int_kind) :: & k , & ! layer index m , & ! @@ -332,9 +302,12 @@ subroutine lateral_melt_bgc (dt, & real (kind=dbl_kind), dimension (nblyr+1) :: & zspace ! vertical grid spacing + character(len=char_len_long) :: & + warning + zspace(:) = c1/real(nblyr,kind=dbl_kind) - zspace(1) = p5*zspace(1) - zspace(nblyr+1) = p5*zspace(nblyr+1) + zspace(1) = p5*zspace(2) + zspace(nblyr+1) = p5*zspace(nblyr) if (solve_zsal) then do n = 1, ncat @@ -347,15 +320,13 @@ subroutine lateral_melt_bgc (dt, & endif do m = 1, nbtrcr - total_bio_initial = c0 - total_bio_final = c0 do n = 1, ncat do k = 1, nblyr+1 - total_bio_initial = total_bio_initial + trcrn(nt_fbri,n) * vicen_init(n) *zspace(k)*trcrn(bio_index(m)+k-1,n) - total_bio_final = total_bio_final + trcrn(nt_fbri,n) * vicen(n) *zspace(k)*trcrn(bio_index(m)+k-1,n) - enddo + flux_bio(m) = flux_bio(m) + trcrn(nt_fbri,n) & + * vicen_init(n)*zspace(k)*trcrn(bio_index(m)+k-1,n) & + * rside/dt enddo - flux_bio(m) = flux_bio(m) + (total_bio_initial - total_bio_final)/dt + enddo enddo end subroutine lateral_melt_bgc @@ -462,7 +433,7 @@ subroutine adjust_tracer_profile (nbtrcr, dt, ntrcr, & hbri_old = vtmp if (solve_zsal) then top_conc = sss * salt_loss - do k = 1, nblyr + do k = 1, nblyr S_stationary(k) = trcrn(nt_bgc_S+k-1)* hbri_old enddo call regrid_stationary (S_stationary, hbri_old, & @@ -472,7 +443,7 @@ subroutine adjust_tracer_profile (nbtrcr, dt, ntrcr, & bgrid(2:nblyr+1), fluxb,& l_stop, stop_label) if (l_stop) return - do k = 1, nblyr + do k = 1, nblyr trcrn(nt_bgc_S+k-1) = S_stationary(k)/hbri trtmp0(nt_sice+k-1) = trcrn(nt_bgc_S+k-1) enddo @@ -480,7 +451,7 @@ subroutine adjust_tracer_profile (nbtrcr, dt, ntrcr, & do m = 1, nbtrcr top_conc = ocean_bio(m)*zbgc_init_frac(m) - do k = 1, nblyr+1 + do k = 1, nblyr+1 C_stationary(k) = trcrn(bio_index(m) + k-1)* hbri_old enddo !k call regrid_stationary (C_stationary, hbri_old, & @@ -679,9 +650,9 @@ subroutine merge_bgc_fluxes (dt, nblyr, & snow_bio_net(mm) = snow_bio_net(mm) & + trcrn(bio_index(mm)+nblyr+1)*dvssl & + trcrn(bio_index(mm)+nblyr+2)*dvint - flux_bio (mm) = flux_bio (mm) + flux_bion (mm)*aice_init - zbgc_snow (mm) = zbgc_snow(mm) + zbgc_snown(mm)*aice_init/dt - zbgc_atm (mm) = zbgc_atm (mm) + zbgc_atmn (mm)*aice_init/dt + flux_bio (mm) = flux_bio (mm) + flux_bion (mm)*aicen + zbgc_snow (mm) = zbgc_snow(mm) + zbgc_snown(mm)*aicen/dt + zbgc_atm (mm) = zbgc_atm (mm) + zbgc_atmn (mm)*aicen/dt enddo ! mm ! diagnostics : mean cell bio interface grid profiles @@ -789,6 +760,95 @@ subroutine merge_bgc_fluxes_skl (ntrcr, & enddo end subroutine merge_bgc_fluxes_skl +!======================================================================= +! +! Given some added new ice to the base of the existing ice, recalculate +! vertical bio tracer so that new grid cells are all the same size. +! +! author: N. Jeffery, LANL +! + subroutine update_vertical_bio_tracers(nbiolyr, trc, h1, h2, trc0, zspace) + + use ice_constants_colpkg, only: c0, puny + + integer (kind=int_kind), intent(in) :: & + nbiolyr ! number of bio layers nblyr+1 + + real (kind=dbl_kind), dimension(:), intent(inout) :: & + trc ! vertical tracer + + real (kind=dbl_kind), intent(in) :: & + h1, & ! old thickness + h2, & ! new thickness + trc0 ! tracer value of added ice on ice bottom + + real (kind=dbl_kind), dimension(nbiolyr), intent(in) :: & + zspace + + ! local variables + + real(kind=dbl_kind), dimension(nbiolyr) :: trc2 ! updated tracer temporary + + ! vertical indices for old and new grid + integer :: k1, k2 + + real (kind=dbl_kind) :: & + z1a, z1b, & ! upper, lower boundary of old cell/added new ice at bottom + z2a, z2b, & ! upper, lower boundary of new cell + overlap , & ! overlap between old and new cell + rnilyr + + !rnilyr = real(nilyr,dbl_kind) + z2a = c0 + z2b = c0 + + if (h2 > puny) then + ! loop over new grid cells + do k2 = 1, nbiolyr + + ! initialize new tracer + trc2(k2) = c0 + + ! calculate upper and lower boundary of new cell + z2a = z2b !((k2 - 1) * h2) * zspace(k2)+z2b ! / rnilyr + z2b = z2b + h2 * zspace(k2) !(k2 * h2) * zspace(k2)+z2a !/ rnilyr + + z1a = c0 + z1b = c0 + ! loop over old grid cells + do k1 = 1, nbiolyr + + ! calculate upper and lower boundary of old cell + z1a = z1b !((k1 - 1) * h1) * zspace(k1)+z1b !/ rnilyr + z1b = z1b + h1 * zspace(k1) !(k1 * h1) * zspace(k1)+z1a !/ rnilyr + + ! calculate overlap between old and new cell + overlap = max(min(z1b, z2b) - max(z1a, z2a), c0) + + ! aggregate old grid cell contribution to new cell + trc2(k2) = trc2(k2) + overlap * trc(k1) + + enddo ! k1 + + ! calculate upper and lower boundary of added new ice at bottom + z1a = h1 + z1b = h2 + + ! calculate overlap between added ice and new cell + overlap = max(min(z1b, z2b) - max(z1a, z2a), c0) + ! aggregate added ice contribution to new cell + trc2(k2) = trc2(k2) + overlap * trc0 + ! renormalize new grid cell + trc2(k2) = trc2(k2)/zspace(k2)/h2 !(rnilyr * trc2(k2)) / h2 + + enddo ! k2 + else + trc2 = trc + endif ! h2 > 0 + ! update vertical tracer array with the adjusted tracer + trc = trc2 + + end subroutine update_vertical_bio_tracers !======================================================================= diff --git a/components/mpas-seaice/src/icepack b/components/mpas-seaice/src/icepack index 8fad768ce400..31ce42217717 160000 --- a/components/mpas-seaice/src/icepack +++ b/components/mpas-seaice/src/icepack @@ -1 +1 @@ -Subproject commit 8fad768ce400536904f376376e91c698a82882ba +Subproject commit 31ce42217717dbbde87b73129d7a4ff3d052455d diff --git a/components/mpas-seaice/src/model_forward/mpas_seaice_core_interface.F b/components/mpas-seaice/src/model_forward/mpas_seaice_core_interface.F index 7dcdd4c94f66..4b128d0c534d 100644 --- a/components/mpas-seaice/src/model_forward/mpas_seaice_core_interface.F +++ b/components/mpas-seaice/src/model_forward/mpas_seaice_core_interface.F @@ -315,12 +315,14 @@ subroutine setup_packages_column_physics(configPool, packagePool, ierr)!{{{ call MPAS_pool_get_config(configPool, "config_use_column_physics", config_use_column_physics) call MPAS_pool_get_config(configPool, "config_use_column_biogeochemistry", config_use_column_biogeochemistry) + call MPAS_pool_get_config(configPool, "config_use_zaerosols", config_use_zaerosols) call MPAS_pool_get_package(packagePool, "pkgColumnPackageActive", pkgColumnPackageActive) call MPAS_pool_get_package(packagePool, "pkgColumnBiogeochemistryActive", pkgColumnBiogeochemistryActive) pkgColumnPackageActive = config_use_column_physics - pkgColumnBiogeochemistryActive = (config_use_column_biogeochemistry .and. config_use_column_physics) + pkgColumnBiogeochemistryActive = ((config_use_column_biogeochemistry .or. config_use_zaerosols) & + .and. config_use_column_physics) !pkgColumnPackageActive = .true. !pkgColumnBiogeochemistryActive = .true. @@ -384,7 +386,6 @@ subroutine setup_packages_column_physics(configPool, packagePool, ierr)!{{{ call MPAS_pool_get_config(configPool, "config_use_humics", config_use_humics) call MPAS_pool_get_config(configPool, "config_use_DON", config_use_DON) call MPAS_pool_get_config(configPool, "config_use_iron", config_use_iron) - call MPAS_pool_get_config(configPool, "config_use_zaerosols", config_use_zaerosols) call MPAS_pool_get_config(configPool, "config_use_effective_snow_density", config_use_effective_snow_density) call MPAS_pool_get_config(configPool, "config_use_snow_grain_radius", config_use_snow_grain_radius) @@ -494,8 +495,6 @@ subroutine setup_packages_column_physics(configPool, packagePool, ierr)!{{{ endif if (.not. config_use_column_biogeochemistry .and. config_use_column_physics) then - pkgTracerBrineActive = .false. - pkgTracerMobileFractionActive = .false. pkgTracerSkeletalAlgaeActive = .false. pkgTracerSkeletalNitrateActive = .false. pkgTracerSkeletalCarbonActive = .false. @@ -516,7 +515,6 @@ subroutine setup_packages_column_physics(configPool, packagePool, ierr)!{{{ pkgTracerVerticalHumicsActive = .false. pkgTracerVerticalDONActive = .false. pkgTracerVerticalIronActive = .false. - pkgTracerZAerosolsActive = .false. pkgTracerZSalinityActive = .false. endif @@ -601,6 +599,9 @@ subroutine setup_packages_other(configPool, packagePool, ierr)!{{{ logical, pointer :: & config_use_forcing, & config_use_data_icebergs, & + config_use_zaerosols, & + config_use_iron_solubility_file, & + config_use_atm_dust_file, & config_testing_system_test, & config_use_snicar_ad, & config_use_prescribed_ice, & @@ -615,17 +616,28 @@ subroutine setup_packages_other(configPool, packagePool, ierr)!{{{ pkgPrescribedActive, & pkgSpecialBoundariesActive + logical :: & + config_use_dust_file + ierr = 0 ! pkgForcing call MPAS_pool_get_config(configPool, "config_use_forcing", config_use_forcing) call MPAS_pool_get_config(configPool, "config_use_data_icebergs", config_use_data_icebergs) + call MPAS_pool_get_config(configPool, "config_use_zaerosols", config_use_zaerosols) + call MPAS_pool_get_config(configPool, "config_use_atm_dust_file", config_use_atm_dust_file) + call MPAS_pool_get_config(configPool, "config_use_iron_solubility_file", config_use_iron_solubility_file) call MPAS_pool_get_package(packagePool, "pkgForcingActive", pkgForcingActive) + config_use_dust_file = .false. + if (config_use_zaerosols .and. (config_use_iron_solubility_file .or. & + config_use_atm_dust_file) ) config_use_dust_file = .true. + ! see if we are using the forcing system - if (config_use_forcing .or. config_use_data_icebergs) then + if (config_use_forcing .or. config_use_data_icebergs .or. & + config_use_dust_file) then pkgForcingActive = .true. diff --git a/components/mpas-seaice/src/shared/mpas_seaice_column.F b/components/mpas-seaice/src/shared/mpas_seaice_column.F index 7e102135f811..80a00a154d99 100644 --- a/components/mpas-seaice/src/shared/mpas_seaice_column.F +++ b/components/mpas-seaice/src/shared/mpas_seaice_column.F @@ -263,10 +263,12 @@ subroutine seaice_init_column_physics_package_variables(domain, clock) config_do_restart, & config_use_column_biogeochemistry, & config_use_column_shortwave, & - config_use_column_snow_tracers + config_use_column_snow_tracers, & + config_use_zaerosols call MPAS_pool_get_config(domain % configs, "config_use_column_physics", config_use_column_physics) call MPAS_pool_get_config(domain % configs, "config_use_column_biogeochemistry", config_use_column_biogeochemistry) + call MPAS_pool_get_config(domain % configs, "config_use_zaerosols", config_use_zaerosols) if (config_use_column_physics) then @@ -280,7 +282,7 @@ subroutine seaice_init_column_physics_package_variables(domain, clock) call init_column_thermodynamic_profiles(domain) ! initialize biogoechemistry profiles - if (config_use_column_biogeochemistry) & + if (config_use_column_biogeochemistry .or. config_use_zaerosols) & call init_column_biogeochemistry_profiles(domain, ciceTracerObject) ! history variables @@ -1054,7 +1056,8 @@ subroutine seaice_column_predynamics_time_integration(domain, clock) config_use_column_biogeochemistry, & config_use_column_itd_thermodynamics, & config_calc_surface_temperature, & - config_use_vertical_tracers + config_use_vertical_tracers, & + config_use_zaerosols real(kind=RKIND), pointer :: & config_dt @@ -1067,6 +1070,7 @@ subroutine seaice_column_predynamics_time_integration(domain, clock) call MPAS_pool_get_config(domain % configs, "config_use_column_vertical_thermodynamics", & config_use_column_vertical_thermodynamics) call MPAS_pool_get_config(domain % configs, "config_use_column_biogeochemistry", config_use_column_biogeochemistry) + call MPAS_pool_get_config(domain % configs, "config_use_zaerosols", config_use_zaerosols) call MPAS_pool_get_config(domain % configs, "config_use_column_itd_thermodynamics", config_use_column_itd_thermodynamics) call MPAS_pool_get_config(domain % configs, "config_calc_surface_temperature", config_calc_surface_temperature) call MPAS_pool_get_config(domain % configs, "config_use_vertical_tracers", config_use_vertical_tracers) @@ -1096,7 +1100,7 @@ subroutine seaice_column_predynamics_time_integration(domain, clock) !----------------------------------------------------------------- call mpas_timer_start("Column biogeochemistry") - if (config_use_column_biogeochemistry) & + if (config_use_column_biogeochemistry .or. config_use_zaerosols) & call column_biogeochemistry(domain) call mpas_timer_stop("Column biogeochemistry") @@ -2106,6 +2110,9 @@ subroutine column_itd_thermodynamics(domain, clock) colpkg_step_therm2, & colpkg_clear_warnings + use seaice_constants, only: & + seaicePuny + type(domain_type), intent(inout) :: domain type(MPAS_clock_type), intent(in) :: clock @@ -2133,7 +2140,8 @@ subroutine column_itd_thermodynamics(domain, clock) logical, pointer :: & config_update_ocean_fluxes, & - config_use_column_biogeochemistry + config_use_column_biogeochemistry, & + config_use_zaerosols ! dimensions integer, pointer :: & @@ -2197,13 +2205,13 @@ subroutine column_itd_thermodynamics(domain, clock) iBioLayers ! test carbon conservation - real(kind=RKIND), dimension(:), allocatable :: & + real(kind=RKIND), dimension(:,:), allocatable :: & totalCarbonCatFinal, & totalCarbonCatInitial, & - oceanBioFluxesTemp, & - verticalGridSpace + oceanBioFluxesTemp - real(kind=RKIND) :: & + real(kind=RKIND), dimension(:), allocatable :: & + verticalGridSpace, & oceanCarbonFlux, & totalCarbonFinal, & totalCarbonInitial, & @@ -2254,6 +2262,7 @@ subroutine column_itd_thermodynamics(domain, clock) call MPAS_pool_get_config(block % configs, "config_dt", config_dt) call MPAS_pool_get_config(block % configs, "config_update_ocean_fluxes", config_update_ocean_fluxes) call MPAS_pool_get_config(block % configs, "config_use_column_biogeochemistry", config_use_column_biogeochemistry) + call MPAS_pool_get_config(block % configs, "config_use_zaerosols", config_use_zaerosols) call MPAS_pool_get_dimension(mesh, "nCellsSolve", nCellsSolve) call MPAS_pool_get_dimension(mesh, "nCategories", nCategories) @@ -2311,11 +2320,22 @@ subroutine column_itd_thermodynamics(domain, clock) ! newly formed ice allocate(newlyFormedIceLogical(nCategories)) allocate(oceanBioConcentrationsUsed(ciceTracerObject % nBioTracers)) - allocate(oceanBioFluxesTemp(ciceTracerObject % nBioTracers)) + allocate(oceanBioFluxesTemp(ciceTracerObject % nBioTracers,nCellsSolve)) allocate(verticalGridSpace(nBioLayersP1)) if (checkCarbon) then - allocate(totalCarbonCatFinal(nCategories)) - allocate(totalCarbonCatInitial(nCategories)) + allocate(totalCarbonCatFinal(nCategories,nCellsSolve)) + allocate(totalCarbonCatInitial(nCategories,nCellsSolve)) + allocate(totalCarbonInitial(nCellsSolve)) + allocate(totalCarbonFinal(nCellsSolve)) + allocate(oceanCarbonFlux(nCellsSolve)) + allocate(carbonError(nCellsSolve)) + else + allocate(totalCarbonCatFinal(1,1)) + allocate(totalCarbonCatInitial(1,1)) + allocate(totalCarbonInitial(1)) + allocate(totalCarbonFinal(1)) + allocate(oceanCarbonFlux(1)) + allocate(carbonError(1)) endif verticalGridSpace(:) = 1.0_RKIND/real(nBioLayers,kind=RKIND) @@ -2323,7 +2343,7 @@ subroutine column_itd_thermodynamics(domain, clock) verticalGridSpace(nBioLayersP1) = verticalGridSpace(1) setGetPhysicsTracers = .true. - setGetBGCTracers = config_use_column_biogeochemistry + setGetBGCTracers = (config_use_column_biogeochemistry .or. config_use_zaerosols) ! code abort abortFlag = .false. @@ -2331,8 +2351,10 @@ subroutine column_itd_thermodynamics(domain, clock) anyAbort = .false. !$omp parallel do default(shared) private(iCategory,iBioTracers,iBioData,& - !$omp& totalCarbonInitial,abortMessage,oceanBioFluxesTemp,totalCarbonFinal,& - !$omp& carbonError) firstprivate(newlyFormedIceLogical,oceanBioConcentrationsUsed) & + !$omp& totalCarbonInitial,totalCarbonCatInitial,totalCarbonCatFinal,& + !$omp& abortMessage,oceanBioFluxesTemp,totalCarbonFinal,& + !$omp& oceanCarbonFlux, carbonError) & + !$omp& firstprivate(newlyFormedIceLogical,oceanBioConcentrationsUsed) & !$omp& reduction(.or.:abortFlag) do iCell = 1, nCellsSolve @@ -2352,14 +2374,14 @@ subroutine column_itd_thermodynamics(domain, clock) tracerArrayCategory, iCell, setGetPhysicsTracers, setGetBGCTracers) if (checkCarbon) then - totalCarbonInitial = 0.0_RKIND - call seaice_total_carbon_content_category(block,totalCarbonCatInitial,iceAreaCategory(1,:,:),iceVolumeCategory(1,:,:),iCell) + totalCarbonInitial(iCell) = 0.0_RKIND + call seaice_total_carbon_content_category(block,totalCarbonCatInitial(:,iCell),iceAreaCategory(1,:,:),iceVolumeCategory(1,:,:),iCell) do iCategory = 1,nCategories - totalCarbonInitial = totalCarbonInitial + totalCarbonCatInitial(iCategory)*iceAreaCategory(1,iCategory,iCell) + totalCarbonInitial(iCell) = totalCarbonInitial(iCell) + totalCarbonCatInitial(iCategory,iCell)*iceAreaCategory(1,iCategory,iCell) enddo endif - oceanBioFluxesTemp(:) = 0.0_RKIND + oceanBioFluxesTemp(:,iCell) = 0.0_RKIND call colpkg_clear_warnings() call colpkg_step_therm2(& @@ -2402,7 +2424,7 @@ subroutine column_itd_thermodynamics(domain, clock) oceanAerosolFlux(:,iCell), & newlyFormedIceLogical(:), & !first_ice, intent(inout) zSalinityFlux(iCell), & - oceanBioFluxesTemp(:), & + oceanBioFluxesTemp(:,iCell), & oceanBioConcentrationsUsed(:), & !ocean_bio, intent(in) abortFlag, & abortMessage, & @@ -2411,7 +2433,7 @@ subroutine column_itd_thermodynamics(domain, clock) dayOfYear) do iBioTracers = 1, ciceTracerObject % nBioTracers - oceanBioFluxes(iBioTracers,iCell) = oceanBioFluxes(iBioTracers,iCell) + oceanBioFluxesTemp(iBioTracers) + oceanBioFluxes(iBioTracers,iCell) = oceanBioFluxes(iBioTracers,iCell) + oceanBioFluxesTemp(iBioTracers,iCell) enddo call column_write_warnings(abortFlag) @@ -2427,26 +2449,26 @@ subroutine column_itd_thermodynamics(domain, clock) tracerArrayCategory, iCell, setGetPhysicsTracers, setGetBGCTracers) if (checkCarbon) then - totalCarbonFinal = 0.0_RKIND - call seaice_total_carbon_content_category(block,totalCarbonCatFinal,iceAreaCategory(1,:,:),iceVolumeCategory(1,:,:),iCell) - call seaice_ocean_carbon_flux_cell(block,oceanCarbonFlux,oceanBioFluxesTemp,iCell) + totalCarbonFinal(iCell) = 0.0_RKIND + call seaice_total_carbon_content_category(block,totalCarbonCatFinal(:,iCell),iceAreaCategory(1,:,:),iceVolumeCategory(1,:,:),iCell) + call seaice_ocean_carbon_flux_cell(block,oceanCarbonFlux(iCell),oceanBioFluxesTemp(:,iCell),iCell) do iCategory = 1,nCategories - totalCarbonFinal = totalCarbonFinal + totalCarbonCatFinal(iCategory)*iceAreaCategory(1,iCategory,iCell) + totalCarbonFinal(iCell) = totalCarbonFinal(iCell) + totalCarbonCatFinal(iCategory,iCell)*iceAreaCategory(1,iCategory,iCell) enddo - carbonError = totalCarbonInitial - oceanCarbonFlux*config_dt - totalCarbonFinal + carbonError(iCell) = (totalCarbonFinal(iCell) - totalCarbonInitial(iCell))/config_dt + oceanCarbonFlux(iCell) - if (abs(carbonError) > 1.0e-14_RKIND*MAXVAL((/totalCarbonInitial,totalCarbonFinal/))) then + if (abs(carbonError(iCell)) > max(seaicePuny,1.0e-14_RKIND*abs(oceanCarbonFlux(iCell)))) then call mpas_log_write("column_step_therm2, carbon conservation error", messageType=MPAS_LOG_ERR) call mpas_log_write("iCell: $i", messageType=MPAS_LOG_ERR, intArgs=(/indexToCellID(iCell)/)) - call mpas_log_write("carbonError: $r", messageType=MPAS_LOG_ERR, realArgs=(/carbonError/)) - call mpas_log_write("totalCarbonInitial: $r", messageType=MPAS_LOG_ERR, realArgs=(/totalCarbonInitial/)) - call mpas_log_write("totalCarbonFinal: $r", messageType=MPAS_LOG_ERR, realArgs=(/totalCarbonFinal/)) - call mpas_log_write("oceanCarbonFlux: $r", messageType=MPAS_LOG_ERR, realArgs=(/oceanCarbonFlux/)) + call mpas_log_write("carbonError: $r", messageType=MPAS_LOG_ERR, realArgs=(/carbonError(iCell)/)) + call mpas_log_write("totalCarbonInitial: $r", messageType=MPAS_LOG_ERR, realArgs=(/totalCarbonInitial(iCell)/)) + call mpas_log_write("totalCarbonFinal: $r", messageType=MPAS_LOG_ERR, realArgs=(/totalCarbonFinal(iCell)/)) + call mpas_log_write("oceanCarbonFlux: $r", messageType=MPAS_LOG_ERR, realArgs=(/oceanCarbonFlux(iCell)/)) do iCategory = 1, nCategories call mpas_log_write("iCategory: $i", messageType=MPAS_LOG_ERR, intArgs=(/iCategory/)) - call mpas_log_write("totalCarbonCatFinal(iCategory): $r", messageType=MPAS_LOG_ERR, realArgs=(/totalCarbonCatFinal(iCategory)/)) - call mpas_log_write("totalCarbonCatInitial(iCategory): $r", messageType=MPAS_LOG_ERR, realArgs=(/totalCarbonCatFinal(iCategory)/)) + call mpas_log_write("totalCarbonCatFinal(iCategory,iCell): $r", messageType=MPAS_LOG_ERR, realArgs=(/totalCarbonCatFinal(iCategory,iCell)/)) + call mpas_log_write("totalCarbonCatInitial(iCategory,iCell): $r", messageType=MPAS_LOG_ERR, realArgs=(/totalCarbonCatFinal(iCategory,iCell)/)) enddo endif endif @@ -2466,10 +2488,12 @@ subroutine column_itd_thermodynamics(domain, clock) call seaice_critical_error_write_block(domain, block, anyAbort) call seaice_check_critical_error(domain, anyAbort) - if (checkCarbon) then - deallocate(totalCarbonCatFinal) - deallocate(totalCarbonCatInitial) - endif + deallocate(totalCarbonCatFinal) + deallocate(totalCarbonCatInitial) + deallocate(totalCarbonInitial) + deallocate(totalCarbonFinal) + deallocate(oceanCarbonFlux) + deallocate(carbonError) ! newly formed ice deallocate(newlyFormedIceLogical) @@ -2658,7 +2682,8 @@ subroutine column_snow(domain) logical, pointer :: & config_use_effective_snow_density, & config_use_snow_grain_radius, & - config_use_column_biogeochemistry + config_use_column_biogeochemistry, & + config_use_zaerosols real(kind=RKIND), dimension(:,:,:), pointer :: & snowIceMass, & @@ -2749,6 +2774,7 @@ subroutine column_snow(domain) call MPAS_pool_get_config(block % configs, "config_wind_compaction_factor", config_wind_compaction_factor) call MPAS_pool_get_config(block % configs, "config_snow_redistribution_factor", config_snow_redistribution_factor) call MPAS_pool_get_config(block % configs, "config_use_column_biogeochemistry", config_use_column_biogeochemistry) + call MPAS_pool_get_config(block % configs, "config_use_zaerosols", config_use_zaerosols) call MPAS_pool_get_dimension(block % dimensions, "nCellsSolve", nCellsSolve) call MPAS_pool_get_dimension(block % dimensions, "nCategories", nCategories) @@ -2792,7 +2818,7 @@ subroutine column_snow(domain) call MPAS_pool_get_array(ocean_fluxes, "oceanHeatFlux", oceanHeatFlux) setGetPhysicsTracers = .true. - setGetBGCTracers = config_use_column_biogeochemistry + setGetBGCTracers = (config_use_column_biogeochemistry .or. config_use_zaerosols) ! code abort abortFlag = .false. @@ -2924,7 +2950,8 @@ subroutine column_radiation(domain, clock, lInitialization) config_use_shortwave_bioabsorption, & config_use_brine, & config_use_modal_aerosols, & - config_use_column_biogeochemistry + config_use_column_biogeochemistry, & + config_use_zaerosols character(len=strKIND), pointer :: & config_snow_redistribution_scheme @@ -3061,6 +3088,7 @@ subroutine column_radiation(domain, clock, lInitialization) call MPAS_pool_get_config(domain % configs, "config_use_shortwave_bioabsorption", config_use_shortwave_bioabsorption) call MPAS_pool_get_config(domain % configs, "config_use_modal_aerosols",config_use_modal_aerosols) call MPAS_pool_get_config(domain % configs, "config_use_column_biogeochemistry",config_use_column_biogeochemistry) + call MPAS_pool_get_config(domain % configs, "config_use_zaerosols",config_use_zaerosols) block => domain % blocklist do while (associated(block)) @@ -3206,7 +3234,7 @@ subroutine column_radiation(domain, clock, lInitialization) allocate(aerosolsArray(4*nAerosols,nCategories)) allocate(index_shortwaveAerosol(maxAerosolType)) - if (.not. config_use_column_biogeochemistry) then + if (.not. config_use_zaerosols) then index_shortwaveAerosol(1:maxAerosolType) = 1 else do iAerosol = 1, maxAerosolType @@ -3215,7 +3243,7 @@ subroutine column_radiation(domain, clock, lInitialization) endif setGetPhysicsTracers = .true. - setGetBGCTracers = config_use_column_biogeochemistry + setGetBGCTracers = (config_use_column_biogeochemistry .or. config_use_zaerosols) !$omp parallel do default(shared) firstprivate(aerosolsArray,index_shortwaveAerosol) & !$omp& private(iCategory,iAerosol,lonCellColumn) @@ -3362,6 +3390,9 @@ subroutine column_ridging(domain) colpkg_step_ridge, & colpkg_clear_warnings + use seaice_constants, only: & + seaicePuny + type(domain_type), intent(inout) :: domain type(block_type), pointer :: block @@ -3382,7 +3413,8 @@ subroutine column_ridging(domain) ! configs logical, pointer :: & - config_use_column_biogeochemistry + config_use_column_biogeochemistry, & + config_use_zaerosols real(kind=RKIND), pointer :: & config_dt @@ -3397,7 +3429,8 @@ subroutine column_ridging(domain) nIceLayers, & nSnowLayers, & nAerosols, & - nBioLayers + nBioLayers, & + nBioLayersP1 ! variables real(kind=RKIND), dimension(:), pointer :: & @@ -3447,7 +3480,24 @@ subroutine column_ridging(domain) ! local integer :: & iCell, & - iCategory + iCategory, & + iBioTracers, & + iBioData, & + iBioLayers + + ! test carbon conservation + real(kind=RKIND), dimension(:,:), allocatable :: & + totalCarbonCatFinal, & + totalCarbonCatInitial, & + oceanBioFluxesTemp + + real(kind=RKIND), dimension(:), allocatable :: & + verticalGridSpace, & + oceanCarbonFlux, & + totalCarbonFinal, & + totalCarbonInitial, & + carbonError, & + iceAreaCategoryInitial logical, dimension(:), allocatable :: & newlyFormedIceLogical @@ -3455,12 +3505,15 @@ subroutine column_ridging(domain) logical :: & abortFlag, & setGetPhysicsTracers, & - setGetBGCTracers + setGetBGCTracers, & + checkCarbon character(len=strKIND) :: & abortMessage, & abortLocation + checkCarbon = .false. + block => domain % blocklist do while (associated(block)) @@ -3479,6 +3532,8 @@ subroutine column_ridging(domain) call MPAS_pool_get_config(block % configs, "config_dynamics_subcycle_number", config_dynamics_subcycle_number) call MPAS_pool_get_config(block % configs, "config_use_column_biogeochemistry", config_use_column_biogeochemistry) + call MPAS_pool_get_config(block % configs, "config_use_zaerosols", config_use_zaerosols) + call MPAS_pool_get_config(block % configs, "config_dt", config_dt) call MPAS_pool_get_array(velocity_solver, "dynamicsTimeStep", dynamicsTimeStep) @@ -3488,6 +3543,7 @@ subroutine column_ridging(domain) call MPAS_pool_get_dimension(mesh, "nSnowLayers", nSnowLayers) call MPAS_pool_get_dimension(mesh, "nAerosols", nAerosols) call MPAS_pool_get_dimension(block % dimensions, "nBioLayers", nBioLayers) + call MPAS_pool_get_dimension(block % dimensions, "nBioLayersP1", nBioLayersP1) call MPAS_pool_get_array(mesh, "indexToCellID", indexToCellID) @@ -3534,8 +3590,32 @@ subroutine column_ridging(domain) ! newly formed ice allocate(newlyFormedIceLogical(nCategories)) + allocate(oceanBioFluxesTemp(ciceTracerObject % nBioTracers,nCellsSolve)) + allocate(verticalGridSpace(nBioLayersP1)) + if (checkCarbon) then + allocate(totalCarbonCatFinal(nCategories,nCellsSolve)) + allocate(totalCarbonCatInitial(nCategories,nCellsSolve)) + allocate(totalCarbonInitial(nCellsSolve)) + allocate(totalCarbonFinal(nCellsSolve)) + allocate(oceanCarbonFlux(nCellsSolve)) + allocate(carbonError(nCellsSolve)) + allocate(iceAreaCategoryInitial(nCategories)) + else + allocate(totalCarbonCatFinal(1,1)) + allocate(totalCarbonCatInitial(1,1)) + allocate(totalCarbonInitial(1)) + allocate(totalCarbonFinal(1)) + allocate(oceanCarbonFlux(1)) + allocate(carbonError(1)) + allocate(iceAreaCategoryInitial(1)) + endif + + verticalGridSpace(:) = 1.0_RKIND/real(nBioLayers,kind=RKIND) + verticalGridSpace(1) = verticalGridSpace(2)/2.0_RKIND + verticalGridSpace(nBioLayersP1) = verticalGridSpace(1) + setGetPhysicsTracers = .true. - setGetBGCTracers = config_use_column_biogeochemistry + setGetBGCTracers = (config_use_column_biogeochemistry .or. config_use_zaerosols) ! code abort abortFlag = .false. @@ -3552,6 +3632,17 @@ subroutine column_ridging(domain) call set_cice_tracer_array_category(block, ciceTracerObject, & tracerArrayCategory, iCell, setGetPhysicsTracers, setGetBGCTracers) + if (checkCarbon) then + totalCarbonInitial(iCell) = 0.0_RKIND + call seaice_total_carbon_content_category(block,totalCarbonCatInitial(:,iCell),iceAreaCategory(1,:,:),iceVolumeCategory(1,:,:),iCell) + do iCategory = 1,nCategories + iceAreaCategoryInitial(iCategory) = iceAreaCategory(1,iCategory,iCell) + totalCarbonInitial(iCell) = totalCarbonInitial(iCell) + totalCarbonCatInitial(iCategory,iCell)*iceAreaCategory(1,iCategory,iCell) + enddo + endif + + oceanBioFluxesTemp(:,iCell) = 0.0_RKIND + call colpkg_clear_warnings() call colpkg_step_ridge(& dynamicsTimeStep, & @@ -3595,11 +3686,15 @@ subroutine column_ridging(domain) oceanSaltFlux(iCell), & newlyFormedIceLogical(:), & zSalinityFlux(iCell), & - oceanBioFluxes(:,iCell), & + oceanBioFluxesTemp(:,iCell), & abortFlag, & abortMessage) call column_write_warnings(abortFlag) + do iBioTracers = 1, ciceTracerObject % nBioTracers + oceanBioFluxes(iBioTracers,iCell) = oceanBioFluxes(iBioTracers,iCell) + oceanBioFluxesTemp(iBioTracers,iCell) + enddo + ! update do iCategory = 1, nCategories newlyFormedIce(iCategory,iCell) = 0 @@ -3610,6 +3705,35 @@ subroutine column_ridging(domain) call get_cice_tracer_array_category(block, ciceTracerObject, & tracerArrayCategory, iCell, setGetPhysicsTracers, setGetBGCTracers) + if (checkCarbon) then + totalCarbonFinal(iCell) = 0.0_RKIND + call seaice_total_carbon_content_category(block,totalCarbonCatFinal(:,iCell),iceAreaCategory(1,:,:),iceVolumeCategory(1,:,:),iCell) + call seaice_ocean_carbon_flux_cell(block,oceanCarbonFlux(iCell),oceanBioFluxesTemp(:,iCell),iCell) + do iCategory = 1,nCategories + totalCarbonFinal(iCell) = totalCarbonFinal(iCell) + totalCarbonCatFinal(iCategory,iCell)*iceAreaCategory(1,iCategory,iCell) + enddo + carbonError(iCell) = (totalCarbonFinal(iCell) - totalCarbonInitial(iCell))/config_dt + oceanCarbonFlux(iCell) + + if (abs(carbonError(iCell)) > max(10.0_RKIND*seaicePuny,1.0e-14_RKIND*abs(oceanCarbonFlux(iCell))) .and. & + MAXVAL(iceAreaCategory(1,:,iCell)) > seaicePuny .and. & + MAXVAL(iceAreaCategoryInitial(:)) > seaicePuny) then + call mpas_log_write("column_step_ridge, carbon conservation error", messageType=MPAS_LOG_ERR) + call mpas_log_write("iCell: $i", messageType=MPAS_LOG_ERR, intArgs=(/indexToCellID(iCell)/)) + call mpas_log_write("carbonError: $r", messageType=MPAS_LOG_ERR, realArgs=(/carbonError(iCell)/)) + call mpas_log_write("totalCarbonInitial: $r", messageType=MPAS_LOG_ERR, realArgs=(/totalCarbonInitial(iCell)/)) + call mpas_log_write("totalCarbonFinal: $r", messageType=MPAS_LOG_ERR, realArgs=(/totalCarbonFinal(iCell)/)) + call mpas_log_write("oceanCarbonFlux: $r", messageType=MPAS_LOG_ERR, realArgs=(/oceanCarbonFlux(iCell)/)) + + do iCategory = 1, nCategories + call mpas_log_write("iCategory: $i", messageType=MPAS_LOG_ERR, intArgs=(/iCategory/)) + call mpas_log_write("totalCarbonCatFinal(iCategory,iCell): $r", messageType=MPAS_LOG_ERR, realArgs=(/totalCarbonCatFinal(iCategory,iCell)/)) + call mpas_log_write("totalCarbonCatInitial(iCategory,iCell): $r", messageType=MPAS_LOG_ERR, realArgs=(/totalCarbonCatFinal(iCategory,iCell)/)) + call mpas_log_write("iceAreaCategory(1,iCategory,iCell): $r", messageType=MPAS_LOG_ERR, realArgs=(/iceAreaCategory(1,iCategory,iCell)/)) + call mpas_log_write("iceAreaCategoryInitial(iCategory): $r", messageType=MPAS_LOG_ERR, realArgs=(/iceAreaCategoryInitial(iCategory)/)) + enddo + endif + endif + ! code abort if (abortFlag) then call mpas_log_write("column_ridging: "//trim(abortMessage) , messageType=MPAS_LOG_ERR) @@ -3623,6 +3747,16 @@ subroutine column_ridging(domain) call seaice_critical_error_write_block(domain, block, abortFlag) call seaice_check_critical_error(domain, abortFlag) + deallocate(oceanBioFluxesTemp) + deallocate(verticalGridSpace) + deallocate(totalCarbonCatFinal) + deallocate(totalCarbonCatInitial) + deallocate(totalCarbonInitial) + deallocate(totalCarbonFinal) + deallocate(oceanCarbonFlux) + deallocate(carbonError) + deallocate(iceAreaCategoryInitial) + ! newly formed ice deallocate(newlyFormedIceLogical) @@ -3747,6 +3881,7 @@ subroutine column_biogeochemistry(domain) snowIceBioFluxes, & atmosIceBioFluxes, & oceanBioConcentrations, & + oceanBioConcentrationsInUse, & totalVerticalBiologyIce, & totalVerticalBiologySnow, & penetratingShortwaveFlux, & @@ -3811,7 +3946,7 @@ subroutine column_biogeochemistry(domain) iBioLayers ! test carbon conservation - real(kind=RKIND), dimension(:), allocatable :: & + real(kind=RKIND), dimension(:,:), allocatable :: & totalCarbonCatFinal, & totalCarbonCatInitial, & totalCarbonCatFlux, & @@ -3819,12 +3954,13 @@ subroutine column_biogeochemistry(domain) brineHeightCatFinal real(kind=RKIND), dimension(:), allocatable :: & - oceanBioConcentrationsUsed, & - iceCarbonInitialCategory, & - iceCarbonFinalCategory, & - iceCarbonFluxCategory, & - iceBrineInitialCategory, & - iceBrineFinalCategory + totalCarbonFinal, & + totalCarbonInitial, & + totalCarbonFlux, & + carbonError + + real(kind=RKIND):: & + errorCheck logical, dimension(:), allocatable :: & newlyFormedIceLogical @@ -3840,12 +3976,8 @@ subroutine column_biogeochemistry(domain) abortMessage, & abortLocation - real(kind=RKIND) :: & - carbonErrorCat, & - carbonErrorColumnPackage - real(kind=RKIND), parameter :: & - accuracy = 1.0e-14_RKIND + accuracy = 1.0e-13_RKIND ! test carbon conservation checkCarbon = .false. @@ -3920,6 +4052,7 @@ subroutine column_biogeochemistry(domain) call MPAS_pool_get_array(biogeochemistry, "snowIceBioFluxes", snowIceBioFluxes) call MPAS_pool_get_array(biogeochemistry, "atmosIceBioFluxes", atmosIceBioFluxes) call MPAS_pool_get_array(biogeochemistry, "oceanBioConcentrations", oceanBioConcentrations) + call MPAS_pool_get_array(biogeochemistry, "oceanBioConcentrationsInUse", oceanBioConcentrationsInUse) call MPAS_pool_get_array(biogeochemistry, "totalVerticalBiologyIce", totalVerticalBiologyIce) call MPAS_pool_get_array(biogeochemistry, "totalVerticalBiologySnow", totalVerticalBiologySnow) call MPAS_pool_get_array(biogeochemistry, "zSalinityIceDensity", zSalinityIceDensity) @@ -3983,28 +4116,58 @@ subroutine column_biogeochemistry(domain) ! newly formed ice allocate(newlyFormedIceLogical(nCategories)) - allocate(oceanBioConcentrationsUsed(ciceTracerObject % nBioTracers)) - allocate(brineHeightCatInitial(nCategories)) + allocate(brineHeightCatInitial(nCategories,nCellsSolve)) + allocate(carbonError(nCellsSolve)) if (checkCarbon) then - allocate(totalCarbonCatFinal(nCategories)) - allocate(totalCarbonCatInitial(nCategories)) - allocate(totalCarbonCatFlux(nCategories)) - allocate(brineHeightCatFinal(nCategories)) + allocate(totalCarbonCatFinal(nCategories,nCellsSolve)) + allocate(totalCarbonCatInitial(nCategories,nCellsSolve)) + allocate(totalCarbonCatFlux(nCategories,nCellsSolve)) + allocate(brineHeightCatFinal(nCategories,nCellsSolve)) + allocate(totalCarbonFinal(nCellsSolve)) + allocate(totalCarbonInitial(nCellsSolve)) + allocate(totalCarbonFlux(nCellsSolve)) + else + allocate(totalCarbonCatFinal(1,1)) + allocate(totalCarbonCatInitial(1,1)) + allocate(totalCarbonCatFlux(1,1)) + allocate(brineHeightCatFinal(1,1)) + allocate(totalCarbonFinal(1)) + allocate(totalCarbonInitial(1)) + allocate(totalCarbonFlux(1)) endif + brineHeightCatInitial(:,:) = 0.0_RKIND + carbonError(:) = 0.0_RKIND + totalCarbonCatFinal(:,:) = 0.0_RKIND + totalCarbonCatInitial(:,:) = 0.0_RKIND + totalCarbonCatFlux(:,:) = 0.0_RKIND + brineHeightCatFinal(:,:) = 0.0_RKIND + totalCarbonFinal(:) = 0.0_RKIND + totalCarbonInitial(:) = 0.0_RKIND + totalCarbonFlux(:) = 0.0_RKIND + setGetPhysicsTracers = .true. - setGetBGCTracers = config_use_column_biogeochemistry + setGetBGCTracers = (config_use_column_biogeochemistry .or. config_use_zaerosols) ! code abort abortFlag = .false. abortMessage = "" + atmosBioFluxes(:,:) = 0.0_RKIND + oceanBioConcentrationsInUse(:,:) = 0.0_RKIND + + !$offomp parallel do default(shared) private(iCategory,iBioTracers,iAlgae, iBioLayers) & + !$offomp& firstprivate(atmosBioFluxes,atmosBlackCarbonFlux, & + !$offomp& totalCarbonCatInitial, totalCarbonCatFinal, & + !$offomp& totalCarbonInitial, totalCarbonFinal, totalCarbonFlux, & + !$offomp& atmosDustFlux, bioShortwaveFluxCell, newlyFormedIce) + ! do iCell = 1, nCellsSolve ! newly formed ice do iCategory = 1, nCategories newlyFormedIceLogical(iCategory) = (newlyFormedIce(iCategory,iCell) == 1) - brineHeightCatInitial(iCategory) = brineFraction(1,iCategory,iCell) * & + brineHeightCatInitial(iCategory,iCell) = brineFraction(1,iCategory,iCell) * & iceVolumeCategoryInitial(iCategory,iCell)/(iceAreaCategoryInitial(iCategory,iCell) + seaicePuny) enddo ! iCategory rayleighCriteria = (rayleighCriteriaReal(iCell) > 0.5_RKIND) @@ -4041,7 +4204,6 @@ subroutine column_biogeochemistry(domain) atmosDustFlux(iBioTracers,iCell) = 1.e-13_RKIND enddo #endif - atmosBioFluxes(:,:) = 0.0_RKIND if (config_use_zaerosols) then indexj = ciceTracerObject % index_verticalAerosolsConcLayer(1) do iBioTracers = 1, maxBCType @@ -4054,14 +4216,20 @@ subroutine column_biogeochemistry(domain) do iBioTracers = 1, ciceTracerObject % nBioTracers iBioData = ciceTracerObject % index_LayerIndexToDataArray(iBioTracers) - oceanBioConcentrationsUsed(iBioTracers) = oceanBioConcentrations(iBioData,iCell) + oceanBioConcentrationsInUse(iBioTracers,iCell) = oceanBioConcentrations(iBioData,iCell) enddo ! iBioTracers call set_cice_tracer_array_category(block, ciceTracerObject, & tracerArrayCategory, iCell, setGetPhysicsTracers, setGetBGCTracers) - if (checkCarbon) call seaice_total_carbon_content_category(block,& - totalCarbonCatInitial,iceAreaCategoryInitial,iceVolumeCategoryInitial,iCell) + if (checkCarbon) then + call seaice_total_carbon_content_category(block,& + totalCarbonCatInitial(:,iCell),iceAreaCategoryInitial(:,:),iceVolumeCategoryInitial(:,:),iCell) + totalCarbonInitial(iCell) = 0.0_RKIND + do iCategory = 1, nCategories + totalCarbonInitial(iCell) = totalCarbonInitial(iCell) + totalCarbonCatInitial(iCategory,iCell)*iceAreaCategoryInitial(iCategory,iCell) + enddo + endif call colpkg_clear_warnings() call colpkg_biogeochemistry(& @@ -4083,7 +4251,7 @@ subroutine column_biogeochemistry(domain) verticalNitrogenLosses(:,:,iCell), & snowIceBioFluxes(:,iCell), & atmosIceBioFluxes(:,iCell), & - oceanBioConcentrationsUsed(:), & + oceanBioConcentrationsInUse(:,iCell), & newlyFormedIceLogical(:), & shortwaveLayerPenetration(:,:,iCell), & bioPorosity(:,:,iCell), & @@ -4148,35 +4316,43 @@ subroutine column_biogeochemistry(domain) tracerArrayCategory, iCell, setGetPhysicsTracers, setGetBGCTracers) if (checkCarbon) then - call seaice_total_carbon_content_category(block,totalCarbonCatFinal,iceAreaCategory(1,:,:),iceVolumeCategory(1,:,:),iCell) - call seaice_ocean_carbon_flux(block,totalCarbonCatFlux,oceanBioFluxesCategory(:,:,:),iCell) - do iCategory = 1,nCategories - brineHeightCatFinal(iCategory) = brineFraction(1,iCategory,iCell) * & + call seaice_total_carbon_content_category(block,totalCarbonCatFinal(:,iCell),iceAreaCategory(1,:,:),iceVolumeCategory(1,:,:),iCell) + call seaice_ocean_carbon_flux(block,totalCarbonCatFlux(:,iCell),oceanBioFluxesCategory(:,:,:),iCell) + totalCarbonFinal(iCell) = 0.0_RKIND + totalCarbonFlux(iCell) = 0.0_RKIND + do iCategory = 1, nCategories + totalCarbonFinal(iCell) = totalCarbonFinal(iCell) + totalCarbonCatFinal(iCategory,iCell)*iceAreaCategory(1,iCategory,iCell) + totalCarbonFlux(iCell) = totalCarbonFlux(iCell) + totalCarbonCatFlux(iCategory,iCell) * iceAreaCategory(1,iCategory,iCell) + enddo + carbonError(iCell) = (totalCarbonFinal(iCell) - totalCarbonInitial(iCell))/config_dt + totalCarbonFlux(iCell) + errorCheck = MAX(accuracy,accuracy*abs(totalCarbonFlux(iCell))) + + if (abs(carbonError(iCell)) > errorCheck) then + do iCategory = 1,nCategories + if (iceAreaCategory(1,iCategory,iCell) > seaicePuny) then + brineHeightCatFinal(iCategory,iCell) = brineFraction(1,iCategory,iCell) * & iceVolumeCategory(1,iCategory,iCell)/(iceAreaCategory(1,iCategory,iCell) + seaicePuny) - carbonErrorCat = totalCarbonCatInitial(iCategory) - totalCarbonCatFlux(iCategory)*config_dt - & - totalCarbonCatFinal(iCategory) - if (abs(carbonErrorCat) > accuracy*MAXVAL((/totalCarbonCatInitial(iCategory),totalCarbonCatFinal(iCategory)/))) then -! abortFlag = .true. -! abortMessage = "carbon conservation errror after column bgc" - call mpas_log_write("column_biogeochemistry, carbon conservation error", messageType=MPAS_LOG_ERR) - call mpas_log_write("iCell: $i", messageType=MPAS_LOG_ERR, intArgs=(/indexToCellID(iCell)/)) - call mpas_log_write("iCategory: $i", messageType=MPAS_LOG_ERR, intArgs=(/iCategory/)) - call mpas_log_write("carbonErrorCat: $r", messageType=MPAS_LOG_ERR, realArgs=(/carbonErrorCat/)) - call mpas_log_write("carbonErrorCat*iceAreaCategory: $r", messageType=MPAS_LOG_ERR, realArgs=(/carbonErrorCat*iceAreaCategory(1,iCategory,iCell)/)) - call mpas_log_write("totalCarbonCatInitial(iCategory): $r", messageType=MPAS_LOG_ERR, realArgs=(/totalCarbonCatInitial(iCategory)/)) - call mpas_log_write("totalCarbonCatFinal(iCategory): $r", messageType=MPAS_LOG_ERR, realArgs=(/totalCarbonCatFinal(iCategory)/)) - call mpas_log_write("totalCarbonCatFlux(iCategory): $r", messageType=MPAS_LOG_ERR, realArgs=(/totalCarbonCatFlux(iCategory)/)) - call mpas_log_write("brineHeightCatInitial(iCategory): $r", messageType=MPAS_LOG_ERR, realArgs=(/brineHeightCatInitial(iCategory)/)) - call mpas_log_write("brineHeightCatFinal(iCategory): $r", messageType=MPAS_LOG_ERR, realArgs=(/brineHeightCatFinal(iCategory)/)) - endif - enddo - endif + call mpas_log_write("column_biogeochemistry, carbon conservation error", messageType=MPAS_LOG_ERR) + call mpas_log_write("iCell: $i", messageType=MPAS_LOG_ERR, intArgs=(/indexToCellID(iCell)/)) + call mpas_log_write("iCategory: $i", messageType=MPAS_LOG_ERR, intArgs=(/iCategory/)) + call mpas_log_write("carbonError: $r", messageType=MPAS_LOG_ERR, realArgs=(/carbonError(iCell)/)) + call mpas_log_write("carbonError*iceAreaCategory: $r", messageType=MPAS_LOG_ERR, realArgs=(/carbonError(iCell)*iceAreaCategory(1,iCategory,iCell)/)) + call mpas_log_write("iceAreaCategory: $r", messageType=MPAS_LOG_ERR, realArgs=(/iceAreaCategory(1,iCategory,iCell)/)) + call mpas_log_write("iceAreaCategoryInitial: $r", messageType=MPAS_LOG_ERR, realArgs=(/iceAreaCategoryInitial(iCategory,iCell)/)) + call mpas_log_write("totalCarbonCatInitial(iCategory,iCell): $r", messageType=MPAS_LOG_ERR, realArgs=(/totalCarbonCatInitial(iCategory,iCell)/)) + call mpas_log_write("totalCarbonCatFinal(iCategory,iCell): $r", messageType=MPAS_LOG_ERR, realArgs=(/totalCarbonCatFinal(iCategory,iCell)/)) + call mpas_log_write("totalCarbonCatFlux(iCategory,iCell): $r", messageType=MPAS_LOG_ERR, realArgs=(/totalCarbonCatFlux(iCategory,iCell)/)) + call mpas_log_write("brineHeightCatInitial(iCategory,iCell): $r", messageType=MPAS_LOG_ERR, realArgs=(/brineHeightCatInitial(iCategory,iCell)/)) + call mpas_log_write("brineHeightCatFinal(iCategory,iCell): $r", messageType=MPAS_LOG_ERR, realArgs=(/brineHeightCatFinal(iCategory,iCell)/)) + endif + enddo + endif !carbonError + endif ! code abort if (abortFlag) then call mpas_log_write("column_biogeochemistry: "//trim(abortMessage) , messageType=MPAS_LOG_ERR) call mpas_log_write("iCell: $i", messageType=MPAS_LOG_ERR, intArgs=(/indexToCellID(iCell)/)) - exit endif totalSkeletalAlgae(iCell) = 0.0_RKIND @@ -4209,16 +4385,17 @@ subroutine column_biogeochemistry(domain) call seaice_critical_error_write_block(domain, block, abortFlag) call seaice_check_critical_error(domain, abortFlag) - if (checkCarbon) then - deallocate(totalCarbonCatFinal) - deallocate(totalCarbonCatInitial) - deallocate(totalCarbonCatFlux) - deallocate(brineHeightCatFinal) - endif + deallocate(totalCarbonCatFinal) + deallocate(totalCarbonCatInitial) + deallocate(totalCarbonCatFlux) + deallocate(brineHeightCatFinal) + deallocate(totalCarbonFinal) + deallocate(totalCarbonInitial) + deallocate(totalCarbonFlux) deallocate(brineHeightCatInitial) deallocate(newlyFormedIceLogical) - deallocate(oceanBioConcentrationsUsed) + deallocate(carbonError) block => block % next end do @@ -4492,7 +4669,8 @@ subroutine seaice_column_aggregate(domain) ocean_coupling logical, pointer :: & - config_use_column_biogeochemistry + config_use_column_biogeochemistry, & + config_use_zaerosols real(kind=RKIND), dimension(:), pointer :: & iceAreaCell, & @@ -4527,6 +4705,7 @@ subroutine seaice_column_aggregate(domain) call MPAS_pool_get_subpool(block % structs, "ocean_coupling", ocean_coupling) call MPAS_pool_get_config(block % configs, "config_use_column_biogeochemistry", config_use_column_biogeochemistry) + call MPAS_pool_get_config(block % configs, "config_use_zaerosols", config_use_zaerosols) call MPAS_pool_get_dimension(mesh, "nCellsSolve", nCellsSolve) call MPAS_pool_get_dimension(mesh, "nCategories", nCategories) @@ -4544,7 +4723,7 @@ subroutine seaice_column_aggregate(domain) call MPAS_pool_get_array(ocean_coupling, "seaFreezingTemperature", seaFreezingTemperature) setGetPhysicsTracers = .true. - setGetBGCTracers = config_use_column_biogeochemistry + setGetBGCTracers = (config_use_column_biogeochemistry .or. config_use_zaerosols) do iCell = 1, nCellsSolve @@ -4691,7 +4870,8 @@ subroutine seaice_column_coupling_prep(domain) logical, pointer :: & config_use_ocean_mixed_layer, & config_include_pond_freshwater_feedback, & - config_use_column_biogeochemistry + config_use_column_biogeochemistry, & + config_use_zaerosols type(MPAS_pool_type), pointer :: & oceanCoupling, & @@ -4742,7 +4922,17 @@ subroutine seaice_column_coupling_prep(domain) oceanDMSPdFlux, & oceanHumicsFlux, & oceanDustIronFlux, & - totalOceanCarbonFlux + oceanBlackCarbonFlux, & + totalOceanCarbonFlux, & + oceanNitrateFluxArea, & + oceanSilicateFluxArea, & + oceanAmmoniumFluxArea, & + oceanDMSFluxArea, & + oceanDMSPpFluxArea, & + oceanDMSPdFluxArea, & + oceanHumicsFluxArea, & + oceanDustIronFluxArea, & + oceanBlackCarbonFluxArea real(kind=RKIND), dimension(:,:), pointer :: & albedoVisibleDirectCategory, & @@ -4759,7 +4949,13 @@ subroutine seaice_column_coupling_prep(domain) oceanDICFlux, & oceanDONFlux, & oceanParticulateIronFlux, & - oceanDissolvedIronFlux + oceanDissolvedIronFlux, & + oceanAlgaeFluxArea, & + oceanDOCFluxArea, & + oceanDICFluxArea, & + oceanDONFluxArea, & + oceanParticulateIronFluxArea, & + oceanDissolvedIronFluxArea real(kind=RKIND), dimension(:,:,:), pointer :: & iceAreaCategory @@ -4802,6 +4998,7 @@ subroutine seaice_column_coupling_prep(domain) call MPAS_pool_get_config(domain % configs, "config_dt", config_dt) call MPAS_pool_get_config(domain % configs, "config_include_pond_freshwater_feedback", config_include_pond_freshwater_feedback) call MPAS_pool_get_config(domain % configs, "config_use_column_biogeochemistry", config_use_column_biogeochemistry) + call MPAS_pool_get_config(domain % configs, "config_use_zaerosols", config_use_zaerosols) call MPAS_pool_get_config(domain % configs, "config_ratio_C_to_N_diatoms", config_ratio_C_to_N_diatoms) call MPAS_pool_get_config(domain % configs, "config_ratio_C_to_N_small_plankton", config_ratio_C_to_N_small_plankton) call MPAS_pool_get_config(domain % configs, "config_ratio_C_to_N_phaeocystis", config_ratio_C_to_N_phaeocystis) @@ -4881,6 +5078,7 @@ subroutine seaice_column_coupling_prep(domain) call MPAS_pool_get_array(biogeochemistry, "oceanDMSPdFlux", oceanDMSPdFlux) call MPAS_pool_get_array(biogeochemistry, "oceanHumicsFlux", oceanHumicsFlux) call MPAS_pool_get_array(biogeochemistry, "oceanDustIronFlux", oceanDustIronFlux) + call MPAS_pool_get_array(biogeochemistry, "oceanBlackCarbonFlux", oceanBlackCarbonFlux) call MPAS_pool_get_array(biogeochemistry, "oceanBioFluxes", oceanBioFluxes) call MPAS_pool_get_array(biogeochemistry, "oceanAlgaeFlux", oceanAlgaeFlux) call MPAS_pool_get_array(biogeochemistry, "oceanDOCFlux", oceanDOCFlux) @@ -4890,6 +5088,22 @@ subroutine seaice_column_coupling_prep(domain) call MPAS_pool_get_array(biogeochemistry, "oceanDissolvedIronFlux", oceanDissolvedIronFlux) call MPAS_pool_get_array(biogeochemistry, "totalOceanCarbonFlux", totalOceanCarbonFlux) + call MPAS_pool_get_array(biogeochemistry, "oceanNitrateFluxArea", oceanNitrateFluxArea) + call MPAS_pool_get_array(biogeochemistry, "oceanSilicateFluxArea", oceanSilicateFluxArea) + call MPAS_pool_get_array(biogeochemistry, "oceanAmmoniumFluxArea", oceanAmmoniumFluxArea) + call MPAS_pool_get_array(biogeochemistry, "oceanDMSFluxArea", oceanDMSFluxArea) + call MPAS_pool_get_array(biogeochemistry, "oceanDMSPpFluxArea", oceanDMSPpFluxArea) + call MPAS_pool_get_array(biogeochemistry, "oceanDMSPdFluxArea", oceanDMSPdFluxArea) + call MPAS_pool_get_array(biogeochemistry, "oceanHumicsFluxArea", oceanHumicsFluxArea) + call MPAS_pool_get_array(biogeochemistry, "oceanDustIronFluxArea", oceanDustIronFluxArea) + call MPAS_pool_get_array(biogeochemistry, "oceanBlackCarbonFluxArea", oceanBlackCarbonFluxArea) + call MPAS_pool_get_array(biogeochemistry, "oceanAlgaeFluxArea", oceanAlgaeFluxArea) + call MPAS_pool_get_array(biogeochemistry, "oceanDOCFluxArea", oceanDOCFluxArea) + call MPAS_pool_get_array(biogeochemistry, "oceanDICFluxArea", oceanDICFluxArea) + call MPAS_pool_get_array(biogeochemistry, "oceanDONFluxArea", oceanDONFluxArea) + call MPAS_pool_get_array(biogeochemistry, "oceanParticulateIronFluxArea", oceanParticulateIronFluxArea) + call MPAS_pool_get_array(biogeochemistry, "oceanDissolvedIronFluxArea", oceanDissolvedIronFluxArea) + call MPAS_pool_get_dimension(mesh, "nZBGCTracers", nZBGCTracers) call MPAS_pool_get_dimension(mesh, "maxAlgaeType", maxAlgaeType) call MPAS_pool_get_dimension(mesh, "maxDOCType", maxDOCType) @@ -4994,10 +5208,12 @@ subroutine seaice_column_coupling_prep(domain) !----------------------------------------------------------------- ! Define ocean biogeochemical flux variables !----------------------------------------------------------------- - if (config_use_column_biogeochemistry) then + + oceanBioFluxesAll(:) = 0.0_RKIND + + if (config_use_column_biogeochemistry .or. config_use_zaerosols) then totalOceanCarbonFlux(iCell) = 0.0_RKIND - oceanBioFluxesAll(:) = 0.0_RKIND oceanAlgaeFlux(:,iCell) = 0.0_RKIND oceanDOCFlux(:,iCell) = 0.0_RKIND oceanDICFlux(:,iCell) = 0.0_RKIND @@ -5011,6 +5227,7 @@ subroutine seaice_column_coupling_prep(domain) oceanDMSPdFlux(iCell) = 0.0_RKIND oceanDMSFlux(iCell) = 0.0_RKIND oceanDustIronFlux(iCell) = 0.0_RKIND + oceanBlackCarbonFlux(iCell) = 0.0_RKIND oceanHumicsFlux(iCell) = 0.0_RKIND do iBioTracers = 1, ciceTracerObject % nBioTracers @@ -5023,6 +5240,7 @@ subroutine seaice_column_coupling_prep(domain) do iBioTracers = 1, maxAlgaeType iBioData = iBioData+1 oceanAlgaeFlux(iBioTracers,iCell) = oceanBioFluxesAll(iBioData) + oceanAlgaeFluxArea(iBioTracers,iCell) = oceanBioFluxesAll(iBioData) totalOceanCarbonFlux(iCell) = totalOceanCarbonFlux(iCell) + & oceanAlgaeFlux(iBioTracers,iCell) * ratio_C_to_N(iBioTracers) enddo @@ -5030,11 +5248,13 @@ subroutine seaice_column_coupling_prep(domain) ! Nitrate iBioData = iBioData+1 oceanNitrateFlux(iCell) = oceanBioFluxesAll(iBioData) + oceanNitrateFluxArea(iCell) = oceanBioFluxesAll(iBioData) ! Polysaccharids and Lipids do iBioTracers = 1, maxDOCType iBioData = iBioData+1 oceanDOCFlux(iBioTracers,iCell) = oceanBioFluxesAll(iBioData) + oceanDOCFluxArea(iBioTracers,iCell) = oceanBioFluxesAll(iBioData) totalOceanCarbonFlux(iCell) = totalOceanCarbonFlux(iCell) + & oceanDOCFlux(iBioTracers,iCell) enddo @@ -5043,6 +5263,7 @@ subroutine seaice_column_coupling_prep(domain) do iBioTracers = 1, maxDICType iBioData = iBioData+1 oceanDICFlux(iBioTracers,iCell) = oceanBioFluxesAll(iBioData) + oceanDICFluxArea(iBioTracers,iCell) = oceanBioFluxesAll(iBioData) totalOceanCarbonFlux(iCell) = totalOceanCarbonFlux(iCell) + & oceanDICFlux(iBioTracers,iCell) enddo @@ -5053,22 +5274,27 @@ subroutine seaice_column_coupling_prep(domain) ! Ammonium iBioData = iBioData+1 oceanAmmoniumFlux(iCell) = oceanBioFluxesAll(iBioData) + oceanAmmoniumFluxArea(iCell) = oceanBioFluxesAll(iBioData) ! Silicate iBioData = iBioData+1 oceanSilicateFlux(iCell) = oceanBioFluxesAll(iBioData) + oceanSilicateFluxArea(iCell) = oceanBioFluxesAll(iBioData) ! DMSPp iBioData = iBioData+1 oceanDMSPpFlux(iCell) = oceanBioFluxesAll(iBioData) + oceanDMSPpFluxArea(iCell) = oceanBioFluxesAll(iBioData) ! DMSPd iBioData = iBioData+1 oceanDMSPdFlux(iCell) = oceanBioFluxesAll(iBioData) + oceanDMSPdFluxArea(iCell) = oceanBioFluxesAll(iBioData) ! DMS iBioData = iBioData+1 oceanDMSFlux(iCell) = oceanBioFluxesAll(iBioData) + oceanDMSFluxArea(iCell) = oceanBioFluxesAll(iBioData) ! PON iBioData = iBioData+1 @@ -5077,6 +5303,7 @@ subroutine seaice_column_coupling_prep(domain) do iBioTracers = 1, maxDONType iBioData = iBioData+1 oceanDONFlux(iBioTracers,iCell) = oceanBioFluxesAll(iBioData) + oceanDONFluxArea(iBioTracers,iCell) = oceanBioFluxesAll(iBioData) totalOceanCarbonFlux(iCell) = totalOceanCarbonFlux(iCell) + & oceanDONFlux(iBioTracers,iCell) * config_ratio_C_to_N_proteins enddo @@ -5085,30 +5312,38 @@ subroutine seaice_column_coupling_prep(domain) do iBioTracers = 1, maxIronType iBioData = iBioData+1 oceanDissolvedIronFlux(iBioTracers,iCell) = oceanBioFluxesAll(iBioData) + oceanDissolvedIronFluxArea(iBioTracers,iCell) = oceanBioFluxesAll(iBioData) enddo ! Particulate Iron do iBioTracers = 1, maxIronType iBioData = iBioData+1 oceanParticulateIronFlux(iBioTracers,iCell) = oceanBioFluxesAll(iBioData) + oceanParticulateIronFluxArea(iBioTracers,iCell) = oceanBioFluxesAll(iBioData) enddo - ! Black Carbon (not saved) - iBioData = iBioData + maxBCType + ! Black Carbon (combined; saved for conservation) + do iBioTracers = 1, maxBCType + iBioData = iBioData + 1 + oceanBlackCarbonFlux(iCell) = oceanBlackCarbonFlux(iCell) + oceanBioFluxesAll(iBioData) + enddo + oceanBlackCarbonFluxArea(iCell) = oceanBlackCarbonFlux(iCell) ! Dust (combined) do iBioTracers = 1, maxDustType iBioData = iBioData+1 oceanDustIronFlux(iCell) = oceanDustIronFlux(iCell) + oceanBioFluxesAll(iBioData) enddo + oceanDustIronFluxArea(iCell) = oceanDustIronFlux(iCell) ! Humics iBioData = iBioData+1 oceanHumicsFlux(iCell) = oceanBioFluxesAll(iBioData) + oceanHumicsFluxArea(iCell) = oceanBioFluxesAll(iBioData) totalOceanCarbonFlux(iCell) = totalOceanCarbonFlux(iCell) + & oceanHumicsFlux(iCell) - endif ! config_use_column_biogeochemistry + endif ! config_use_column_biogeochemistry .or. config_use_zaerosols enddo ! iCell @@ -5156,7 +5391,8 @@ subroutine seaice_column_scale_fluxes(domain) mesh logical, pointer :: & - config_use_column_biogeochemistry + config_use_column_biogeochemistry, & + config_use_zaerosols real(kind=RKIND), dimension(:), pointer :: & iceAreaCell, & @@ -5216,6 +5452,7 @@ subroutine seaice_column_scale_fluxes(domain) iBioTracers call MPAS_pool_get_config(domain % configs, "config_use_column_biogeochemistry", config_use_column_biogeochemistry) + call MPAS_pool_get_config(domain % configs, "config_use_zaerosols", config_use_zaerosols) block => domain % blocklist do while (associated(block)) @@ -5308,6 +5545,9 @@ subroutine seaice_column_scale_fluxes(domain) albedoVisibleDiffuseCell(iCell) = albedoVisibleDiffuseCell(iCell) * iceAreaInverse albedoIRDiffuseCell(iCell) = albedoIRDiffuseCell(iCell) * iceAreaInverse + if (config_use_zaerosols) & + oceanDustIronFlux(iCell) = oceanDustIronFlux(iCell) * iceAreaInverse + if (config_use_column_biogeochemistry) then oceanNitrateFlux(iCell) = oceanNitrateFlux(iCell) * iceAreaInverse @@ -5317,7 +5557,6 @@ subroutine seaice_column_scale_fluxes(domain) oceanDMSPdFlux(iCell) = oceanDMSPdFlux(iCell) * iceAreaInverse oceanDMSFlux(iCell) = oceanDMSFlux(iCell) * iceAreaInverse oceanHumicsFlux(iCell) = oceanHumicsFlux(iCell) * iceAreaInverse - oceanDustIronFlux(iCell) = oceanDustIronFlux(iCell) * iceAreaInverse do iBioTracers = 1, maxAlgaeType oceanAlgaeFlux(iBioTracers,iCell) = oceanAlgaeFlux(iBioTracers,iCell) * iceAreaInverse @@ -5360,6 +5599,9 @@ subroutine seaice_column_scale_fluxes(domain) albedoVisibleDiffuseCell(iCell) = 0.0_RKIND albedoIRDiffuseCell(iCell) = 0.0_RKIND + if (config_use_zaerosols) & + oceanDustIronFlux(iCell) = 0.0_RKIND + if (config_use_column_biogeochemistry) then oceanNitrateFlux(iCell) = 0.0_RKIND @@ -5369,7 +5611,6 @@ subroutine seaice_column_scale_fluxes(domain) oceanDMSPdFlux(iCell) = 0.0_RKIND oceanDMSFlux(iCell) = 0.0_RKIND oceanHumicsFlux(iCell) = 0.0_RKIND - oceanDustIronFlux(iCell) = 0.0_RKIND oceanAlgaeFlux(:,iCell) = 0.0_RKIND oceanDOCFlux(:,iCell) = 0.0_RKIND oceanDICFlux(:,iCell) = 0.0_RKIND @@ -6396,12 +6637,14 @@ subroutine init_column_tracer_object(domain, tracerObject) nZBGCTracers logical, pointer :: & - config_use_column_biogeochemistry + config_use_column_biogeochemistry, & + config_use_zaerosols call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nCategories", nCategories) call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nZBGCTracers", nZBGCTracers) call MPAS_pool_get_config(domain % configs, "config_use_column_biogeochemistry", config_use_column_biogeochemistry) + call MPAS_pool_get_config(domain % configs, "config_use_zaerosols", config_use_zaerosols) ! get the number of CICE tracers in trcrn call init_column_tracer_object_tracer_number(domain, tracerObject) @@ -6425,7 +6668,7 @@ subroutine init_column_tracer_object(domain, tracerObject) call init_column_tracer_object_ancestor_indices(domain, tracerObject) ! biogeochemistry - if (config_use_column_biogeochemistry) then + if (config_use_column_biogeochemistry .or. config_use_zaerosols) then allocate(tracerObject % index_LayerIndexToDataArray(nZBGCTracers)) allocate(tracerObject % index_LayerIndexToBioIndex(nZBGCTracers)) @@ -6633,7 +6876,7 @@ subroutine init_column_tracer_object_tracer_number(domain, tracerObject) ! biogeochemistry !----------------------------------------------------------------------- - if (config_use_column_biogeochemistry) then + if (config_use_column_biogeochemistry .or. config_use_zaerosols) then ! save tracer number without bio tracers counted tracerObject % nTracersNotBio = tracerObject % nTracers @@ -10273,11 +10516,11 @@ subroutine check_column_package_configs(domain) endif ! check biogeochemistry flags: - if (.not. config_use_column_biogeochemistry .and. (config_use_brine .or. config_use_vertical_zsalinity .or. & - config_use_vertical_biochemistry .or. config_use_shortwave_bioabsorption .or. config_use_vertical_tracers .or. & + if (.not. config_use_column_biogeochemistry .and. (config_use_vertical_zsalinity .or. & + config_use_vertical_biochemistry .or. & config_use_skeletal_biochemistry .or. config_use_nitrate .or. config_use_carbon .or. config_use_chlorophyll .or. & config_use_ammonium .or. config_use_silicate .or. config_use_DMS .or. config_use_nonreactive .or. config_use_humics .or. & - config_use_DON .or. config_use_iron .or. config_use_modal_aerosols .or. config_use_zaerosols)) then + config_use_DON .or. config_use_iron)) then call mpas_log_write(& "check_column_package_configs: config_use_column_biogeochemistry = false. "//& "All biogeochemistry namelist flags must also be false", & @@ -10301,10 +10544,20 @@ subroutine check_column_package_configs(domain) messageType=MPAS_LOG_CRIT) endif - ! check that vertical bio tracers and not used with skeletal bio tracers - if (config_use_vertical_tracers .and. config_use_skeletal_biochemistry) then + ! check that vertical bio tracers use brine height + if ((config_use_vertical_biochemistry .or. config_use_zaerosols) .and. & + (.not. config_use_brine .or. .not. config_use_vertical_tracers )) then call mpas_log_write(& - "check_column_package_configs: vertical bio tracers and skeletal bio tracers cannot both be true", & + "check_column_package_configs: vertical biochemistry and zaerosols require " //& + "config_use_brine and config_use_vertical_tracer = true", & + messageType=MPAS_LOG_CRIT) + endif + + ! check that brine height is used with either aerosols or bgc + if (config_use_brine .and. & + (.not. config_use_column_biogeochemistry .and. .not. config_use_zaerosols)) then + call mpas_log_write(& + "check_column_package_configs: brine tracer must be used with vertical tracers - config_use_column_biogeochemistry and/or config_use_zaerosols equal to true", & messageType=MPAS_LOG_CRIT) endif @@ -14805,11 +15058,13 @@ subroutine seaice_column_reinitialize_diagnostics_bgc(domain) bioTracerShortwave logical, pointer :: & + config_use_column_physics, & config_use_column_biogeochemistry, & config_use_column_shortwave, & - config_use_column_physics, & - config_use_vertical_biochemistry, & - config_use_vertical_zsalinity + config_use_column_package, & + config_use_vertical_tracers, & + config_use_vertical_zsalinity, & + config_use_zaerosols call MPAS_pool_get_config(domain % blocklist % configs, "config_use_column_physics", config_use_column_physics) @@ -14820,15 +15075,16 @@ subroutine seaice_column_reinitialize_diagnostics_bgc(domain) ! biogeochemistry call MPAS_pool_get_config(block % configs, "config_use_column_biogeochemistry", config_use_column_biogeochemistry) - call MPAS_pool_get_config(block % configs, "config_use_vertical_biochemistry", config_use_vertical_biochemistry) + call MPAS_pool_get_config(block % configs, "config_use_zaerosols", config_use_zaerosols) + call MPAS_pool_get_config(block % configs, "config_use_vertical_tracers", config_use_vertical_tracers) call MPAS_pool_get_config(block % configs, "config_use_vertical_zsalinity", config_use_vertical_zsalinity) - if (config_use_column_biogeochemistry) then + if (config_use_column_biogeochemistry .or. config_use_zaerosols) then call MPAS_pool_get_subpool(block % structs, "biogeochemistry", biogeochemistryPool) call MPAS_pool_get_subpool(block % structs, "diagnostics_biogeochemistry", diagnostics_biogeochemistryPool) - if (config_use_vertical_biochemistry) then + if (config_use_vertical_tracers) then call MPAS_pool_get_array(biogeochemistryPool, "primaryProduction", primaryProduction) call MPAS_pool_get_array(biogeochemistryPool, "totalChlorophyll", totalChlorophyll) call MPAS_pool_get_array(biogeochemistryPool, "netSpecificAlgalGrowthRate", netSpecificAlgalGrowthRate) @@ -14875,7 +15131,7 @@ subroutine seaice_column_reinitialize_diagnostics_bgc(domain) call MPAS_pool_get_config(block % configs, "config_use_column_shortwave", config_use_column_shortwave) - if (config_use_column_biogeochemistry .or. config_use_column_shortwave) then + if (config_use_column_biogeochemistry .or. config_use_column_shortwave .or. config_use_zaerosols) then call MPAS_pool_get_subpool(block % structs, "biogeochemistry", biogeochemistryPool) call MPAS_pool_get_array(biogeochemistryPool, "bioTracerShortwave", bioTracerShortwave) diff --git a/components/mpas-seaice/src/shared/mpas_seaice_constants.F b/components/mpas-seaice/src/shared/mpas_seaice_constants.F index 8693a6ab624f..6a611f64d2cf 100644 --- a/components/mpas-seaice/src/shared/mpas_seaice_constants.F +++ b/components/mpas-seaice/src/shared/mpas_seaice_constants.F @@ -185,8 +185,10 @@ module seaice_constants ! biogeochemistry constants real(kind=RKIND), public :: & - skeletalLayerThickness = 0.03_RKIND ,&! (m) skeletal layer thickness - gramsCarbonPerMolCarbon ! g carbon per mol carbon + skeletalLayerThickness = 0.03_RKIND , & ! (m) skeletal layer thickness + gramsCarbonPerMolCarbon = 12.0107_RKIND , & ! g carbon per mol carbon + microgramsPerKilograms = 1.0e9_RKIND , & ! kg to ug conversion + gramsIronPerMolIron = 55.845_RKIND ! g iron per mol iron ! ocean biogeochemistry ISPOL values real(kind=RKIND), parameter, public :: & diff --git a/components/mpas-seaice/src/shared/mpas_seaice_forcing.F b/components/mpas-seaice/src/shared/mpas_seaice_forcing.F index 064db418a844..ca0c4c5a962f 100644 --- a/components/mpas-seaice/src/shared/mpas_seaice_forcing.F +++ b/components/mpas-seaice/src/shared/mpas_seaice_forcing.F @@ -74,11 +74,17 @@ subroutine seaice_forcing_init(domain, clock) logical, pointer :: & config_use_forcing, & config_use_data_icebergs, & - config_use_column_biogeochemistry + config_use_column_biogeochemistry, & + config_use_zaerosols, & + config_use_atm_dust_file, & + config_use_iron_solubility_file call MPAS_pool_get_config(domain % configs, "config_use_forcing", config_use_forcing) call MPAS_pool_get_config(domain % configs, "config_use_data_icebergs", config_use_data_icebergs) call MPAS_pool_get_config(domain % configs, "config_use_column_biogeochemistry", config_use_column_biogeochemistry) + call MPAS_pool_get_config(domain % configs, "config_use_zaerosols", config_use_zaerosols) + call MPAS_pool_get_config(domain % configs, "config_use_atm_dust_file", config_use_atm_dust_file) + call MPAS_pool_get_config(domain % configs, "config_use_iron_solubility_file", config_use_iron_solubility_file) if (config_use_forcing) then @@ -94,6 +100,10 @@ subroutine seaice_forcing_init(domain, clock) endif + if (config_use_zaerosols .and. (config_use_iron_solubility_file .or. & + config_use_atm_dust_file) ) & + call init_atm_iron_bgc_forcing(domain, clock) + ! init the data iceberg forcing if (config_use_data_icebergs) call init_data_iceberg_forcing(domain, clock) @@ -597,10 +607,16 @@ subroutine seaice_forcing_get(& logical, pointer :: & config_use_forcing, & - config_use_data_icebergs + config_use_data_icebergs, & + config_use_zaerosols, & + config_use_atm_dust_file, & + config_use_iron_solubility_file call MPAS_pool_get_config(domain % configs, "config_use_forcing", config_use_forcing) call MPAS_pool_get_config(domain % configs, "config_use_data_icebergs", config_use_data_icebergs) + call MPAS_pool_get_config(domain % configs, "config_use_zaerosols", config_use_zaerosols) + call MPAS_pool_get_config(domain % configs, "config_use_atm_dust_file", config_use_atm_dust_file) + call MPAS_pool_get_config(domain % configs, "config_use_iron_solubility_file", config_use_iron_solubility_file) if (config_use_forcing) then @@ -617,6 +633,14 @@ subroutine seaice_forcing_get(& endif + if (config_use_zaerosols .and. (config_use_iron_solubility_file .or. & + config_use_atm_dust_file) ) & + call atmospheric_aerosols_forcing(& + streamManager, & + domain, & + simulationClock, & + firstTimeStep) + ! data iceberg forcing if (config_use_data_icebergs) then @@ -657,7 +681,7 @@ subroutine atmospheric_forcing(& config_dt character(len=strKIND), pointer :: & - config_atmospheric_forcing_type + config_atmospheric_forcing_type ! configurations call mpas_pool_get_config(domain % configs, 'config_dt', config_dt) @@ -724,6 +748,55 @@ subroutine atmospheric_forcing(& end subroutine atmospheric_forcing +!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +! +! atmospheric_aerosols_forcing +! +!> \brief +!> \author Nicole Jeffery, LANL +!> \date +!> \details: reads data file for dust fluxes and dust-iron solubility +!> +! +!----------------------------------------------------------------------- + + subroutine atmospheric_aerosols_forcing(& + streamManager, & + domain, & + simulationClock, & + firstTimeStep) + + type (MPAS_streamManager_type), intent(inout) :: streamManager + + type (domain_type) :: domain + + type (MPAS_clock_type) :: simulationClock + + logical, intent(in) :: & + firstTimeStep + + type (block_type), pointer :: block + + real(kind=RKIND), pointer :: & + config_dt + + ! configurations + call mpas_pool_get_config(domain % configs, 'config_dt', config_dt) + + call MPAS_forcing_get_forcing(seaiceForcingGroups, & + 'seaice_atm_bgc_forcing_monthly', streamManager, config_dt) + + block => domain % blocklist + do while (associated(block)) + + ! convert the input forcing variables to the coupling variables + call prepare_atmospheric_dust_coupling_variables(block) + + block => block % next + end do + + end subroutine atmospheric_aerosols_forcing + !||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ! ! prepare_atmospheric_coupling_variables_CORE @@ -1044,6 +1117,74 @@ subroutine prepare_atmospheric_coupling_variables_ISPOL(block) end subroutine prepare_atmospheric_coupling_variables_ISPOL +!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +! +! prepare_atmospheric_dust_coupling_variables +! +!> \brief +!> \author Nicole Jeffery, LANL +!> \date +!> \details +!> Defines the atm flux fields for dust if reading from a file +! +!----------------------------------------------------------------------- + + subroutine prepare_atmospheric_dust_coupling_variables(block) + + type (block_type), pointer :: block + + type (mpas_pool_type), pointer :: & + mesh, & + atmosCoupling, & + atmosForcing, & + biogeochemistry + + real(kind=RKIND), dimension(:,:), pointer :: & + atmosDustFlux, & + atmosWetDustFlux, & + atmosDryDustFlux + + real(kind=RKIND), dimension(:), pointer :: & + dust_FLUZ_WET, & + dust_FLUZ_DRY + + integer, pointer :: & + nCellsSolve, & + maxBCType, & + nzAerosols + + integer :: & + iCell, & + iBioTracers, & + nDust + + call MPAS_pool_get_subpool(block % structs, "mesh", mesh) + call MPAS_pool_get_subpool(block % structs, "atmos_forcing", atmosForcing) + + call MPAS_pool_get_dimension(mesh, "nCellsSolve", nCellsSolve) + + ! zaerosols + + call MPAS_pool_get_subpool(block % structs, "biogeochemistry", biogeochemistry) + call MPAS_pool_get_dimension(mesh, "maxBCType", maxBCType) + call MPAS_pool_get_dimension(mesh, "nzAerosols", nzAerosols) + call MPAS_pool_get_array(biogeochemistry, "atmosDustFlux", atmosDustFlux) + call MPAS_pool_get_array(biogeochemistry, "atmosWetDustFlux", atmosWetDustFlux) + call MPAS_pool_get_array(biogeochemistry, "atmosDryDustFlux", atmosDryDustFlux) + call MPAS_pool_get_array(atmosForcing, "dust_FLUZ_WET", dust_FLUZ_WET) + call MPAS_pool_get_array(atmosForcing, "dust_FLUZ_DRY", dust_FLUZ_DRY) + + nDust = MAX(1,nzAerosols - maxBCType) + do iCell = 1, nCellsSolve + do iBioTracers = maxBCType + 1, nzAerosols + atmosDustFlux(iBioTracers,iCell) = (dust_FLUZ_WET(iCell) + dust_FLUZ_DRY(iCell))/nDust + atmosWetDustFlux(iBioTracers,iCell) = dust_FLUZ_WET(iCell)/nDust + atmosDryDustFlux(iBiotracers,iCell) = dust_FLUZ_DRY(iCell)/nDust + enddo + end do + + end subroutine prepare_atmospheric_dust_coupling_variables + !||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ! ! post_atmospheric_coupling @@ -1675,6 +1816,122 @@ subroutine init_oceanic_bgc_forcing(domain) end subroutine init_oceanic_bgc_forcing +!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +! +! init_atm_iron_bgc_forcing +! +!> \brief +!> \author Nicole Jeffery, LANL +!> \date 5th April 2024 +!> \details +!> Uses monthly iron solubility maps from CAM6-MIMI (Yan Feng) +! to convert dust to dissolved iron for bgc. +!----------------------------------------------------------------------- + + subroutine init_atm_iron_bgc_forcing(domain, clock) + + type (domain_type) :: domain + + type (MPAS_Clock_type) :: clock + + logical, pointer :: & + config_do_restart + + character(len=strKIND) :: & + forcingIntervalMonthly, & + forcingReferenceTimeMonthly + + ! get forcing configuration options + call MPAS_pool_get_config(domain % configs, "config_do_restart", config_do_restart) + + ! create the dust iron solubility forcing group + + call MPAS_forcing_init_group(& + seaiceForcingGroups, & + "seaice_atm_bgc_forcing_monthly", & + domain, & + '0000-01-01_00:00:00', & + '0000-01-01_00:00:00', & + '0001-00-00_00:00:00', & + config_do_restart) + + forcingIntervalMonthly = "00-01-00_00:00:00" + forcingReferenceTimeMonthly = "0001-01-15_00:00:00" + + ! iron solubility fraction of wet dust iron + call MPAS_forcing_init_field(& + domain % streamManager, & + seaiceForcingGroups, & + 'seaice_atm_bgc_forcing_monthly', & + 'IRON_Zolubility_wet', & + 'DustIronMonthlyForcing', & + 'atmos_forcing', & + 'IRON_Zolubility_wet', & + 'linear', & + forcingReferenceTimeMonthly, & + forcingIntervalMonthly) + + ! iron solubility fraction of dry dust iron + call MPAS_forcing_init_field(& + domain % streamManager, & + seaiceForcingGroups, & + 'seaice_atm_bgc_forcing_monthly', & + 'IRON_Zolubility_dry', & + 'DustIronMonthlyForcing', & + 'atmos_forcing', & + 'IRON_Zolubility_dry', & + 'linear', & + forcingReferenceTimeMonthly, & + forcingIntervalMonthly) + + ! atmospheric wet dust flux + call MPAS_forcing_init_field(& + domain % streamManager, & + seaiceForcingGroups, & + 'seaice_atm_bgc_forcing_monthly', & + 'dust_FLUZ_WET', & + 'DustIronMonthlyForcing', & + 'atmos_forcing', & + 'dust_FLUZ_WET', & + 'linear', & + forcingReferenceTimeMonthly, & + forcingIntervalMonthly) + + ! atmospheric dry dust flux + call MPAS_forcing_init_field(& + domain % streamManager, & + seaiceForcingGroups, & + 'seaice_atm_bgc_forcing_monthly', & + 'dust_FLUZ_DRY', & + 'DustIronMonthlyForcing', & + 'atmos_forcing', & + 'dust_FLUZ_DRY', & + 'linear', & + forcingReferenceTimeMonthly, & + forcingIntervalMonthly) + + ! iron fraction in dust + call MPAS_forcing_init_field(& + domain % streamManager, & + seaiceForcingGroups, & + 'seaice_atm_bgc_forcing_monthly', & + 'IRON_in_duzt_fraction', & + 'DustIronMonthlyForcing', & + 'atmos_forcing', & + 'IRON_in_duzt_fraction', & + 'linear', & + forcingReferenceTimeMonthly, & + forcingIntervalMonthly) + + call MPAS_forcing_init_field_data(& + seaiceForcingGroups, & + 'seaice_atm_bgc_forcing_monthly', & + domain % streamManager, & + config_do_restart, & + .false.) + + end subroutine init_atm_iron_bgc_forcing + !||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ! ! init_oceanic_forcing_ncar @@ -3177,10 +3434,12 @@ subroutine reset_atmospheric_coupler_fluxes(domain) real(kind=RKIND), dimension(:,:), pointer :: & atmosBioFluxes, & atmosBlackCarbonFlux, & - atmosDustFlux + atmosDustFlux, & + atmosWetDustFlux, & + atmosDryDustFlux logical, pointer :: & - config_use_column_biogeochemistry + config_use_zaerosols block => domain % blocklist do while (associated(block)) @@ -3219,20 +3478,24 @@ subroutine reset_atmospheric_coupler_fluxes(domain) atmosReferenceTemperature2m = 0.0_RKIND atmosReferenceHumidity2m = 0.0_RKIND - ! biogeochemistry - call MPAS_pool_get_config(block % configs, "config_use_column_biogeochemistry", config_use_column_biogeochemistry) + ! zaerosols + call MPAS_pool_get_config(block % configs, "config_use_zaerosols", config_use_zaerosols) - if (config_use_column_biogeochemistry) then + if (config_use_zaerosols) then call MPAS_pool_get_subpool(block % structs, "biogeochemistry", biogeochemistry) call MPAS_pool_get_array(biogeochemistry, "atmosBioFluxes", atmosBioFluxes) call MPAS_pool_get_array(biogeochemistry, "atmosBlackCarbonFlux", atmosBlackCarbonFlux) call MPAS_pool_get_array(biogeochemistry, "atmosDustFlux", atmosDustFlux) + call MPAS_pool_get_array(biogeochemistry, "atmosWetDustFlux", atmosWetDustFlux) + call MPAS_pool_get_array(biogeochemistry, "atmosDryDustFlux", atmosDryDustFlux) atmosBioFluxes = 0.0_RKIND atmosBlackCarbonFlux = 0.0_RKIND atmosDustFlux = 0.0_RKIND + atmosWetDustFlux = 0.0_RKIND + atmosDryDustFlux = 0.0_RKIND endif @@ -3396,16 +3659,21 @@ subroutine seaice_forcing_write_restart_times(domain) config_use_forcing, & config_use_prescribed_ice, & config_use_prescribed_ice_forcing, & - config_use_data_icebergs + config_use_data_icebergs, & + config_use_atm_dust_file, & + config_use_iron_solubility_file call MPAS_pool_get_config(domain % configs, "config_use_forcing", config_use_forcing) call MPAS_pool_get_config(domain % configs, "config_use_prescribed_ice", config_use_prescribed_ice) call MPAS_pool_get_config(domain % configs, "config_use_prescribed_ice_forcing", config_use_prescribed_ice_forcing) call MPAS_pool_get_config(domain % configs, "config_use_data_icebergs", config_use_data_icebergs) + call MPAS_pool_get_config(domain % configs, "config_use_atm_dust_file", config_use_atm_dust_file) + call MPAS_pool_get_config(domain % configs, "config_use_iron_solubility_file", config_use_iron_solubility_file) if (config_use_forcing .or. & (config_use_prescribed_ice .and. config_use_prescribed_ice_forcing) .or. & - config_use_data_icebergs) then + config_use_data_icebergs .or. & + config_use_atm_dust_file .or. config_use_iron_solubility_file) then call MPAS_forcing_write_restart_times(seaiceForcingGroups) diff --git a/components/mpas-seaice/src/shared/mpas_seaice_icepack.F b/components/mpas-seaice/src/shared/mpas_seaice_icepack.F index 9136ab1b56e3..36899b4b10d7 100644 --- a/components/mpas-seaice/src/shared/mpas_seaice_icepack.F +++ b/components/mpas-seaice/src/shared/mpas_seaice_icepack.F @@ -255,10 +255,12 @@ subroutine seaice_init_icepack_physics_package_variables(domain, clock) config_do_restart, & config_use_column_biogeochemistry, & config_use_column_shortwave, & - config_use_column_snow_tracers + config_use_column_snow_tracers, & + config_use_zaerosols call MPAS_pool_get_config(domain % configs, "config_use_column_physics", config_use_column_physics) call MPAS_pool_get_config(domain % configs, "config_use_column_biogeochemistry", config_use_column_biogeochemistry) + call MPAS_pool_get_config(domain % configs, "config_use_zaerosols", config_use_zaerosols) if (config_use_column_physics) then @@ -272,7 +274,7 @@ subroutine seaice_init_icepack_physics_package_variables(domain, clock) call init_column_thermodynamic_profiles(domain) ! initialize biogoechemistry profiles - if (config_use_column_biogeochemistry) & + if (config_use_column_biogeochemistry .or. config_use_zaerosols) & call init_column_biogeochemistry_profiles(domain, ciceTracerObject) ! history variables @@ -338,7 +340,6 @@ subroutine init_column_itd(domain) call MPAS_pool_get_array(initial, "categoryThicknessLimits", categoryThicknessLimits) call icepack_init_itd(& - nCategories, & categoryThicknessLimits) call seaice_icepack_write_warnings(icepack_warnings_aborted()) @@ -398,7 +399,6 @@ subroutine init_column_thermodynamic_profiles(domain) allocate(initialSalinityProfileVertical(1:nIceLayers+1)) call icepack_init_thermo(& - nIceLayers, & initialSalinityProfileVertical) call seaice_icepack_write_warnings(icepack_warnings_aborted()) @@ -862,8 +862,6 @@ subroutine init_column_thermodynamic_tracers(domain) integer, pointer :: & nCellsSolve, & - nIceLayers, & - nSnowLayers, & nCategories integer :: & @@ -881,8 +879,6 @@ subroutine init_column_thermodynamic_tracers(domain) call MPAS_pool_get_dimension(mesh, "nCellsSolve", nCellsSolve) call MPAS_pool_get_dimension(mesh, "nCategories", nCategories) - call MPAS_pool_get_dimension(mesh, "nIceLayers", nIceLayers) - call MPAS_pool_get_dimension(mesh, "nSnowLayers", nSnowLayers) call MPAS_pool_get_array(atmos_coupling, "airTemperature", airTemperature) @@ -904,8 +900,6 @@ subroutine init_column_thermodynamic_tracers(domain) initialSalinityProfile(:,iCell), & initialMeltingTemperatureProfile(:,iCell), & surfaceTemperature(1,iCategory,iCell), & - nIceLayers, & - nSnowLayers, & iceEnthalpy(:,iCategory,iCell), & snowEnthalpy(:,iCategory,iCell)) @@ -1023,7 +1017,8 @@ subroutine seaice_icepack_predynamics_time_integration(domain, clock) config_use_column_biogeochemistry, & config_use_column_itd_thermodynamics, & config_calc_surface_temperature, & - config_use_vertical_tracers + config_use_vertical_tracers, & + config_use_zaerosols real(kind=RKIND), pointer :: & config_dt @@ -1036,6 +1031,7 @@ subroutine seaice_icepack_predynamics_time_integration(domain, clock) call MPAS_pool_get_config(domain % configs, "config_use_column_vertical_thermodynamics", & config_use_column_vertical_thermodynamics) call MPAS_pool_get_config(domain % configs, "config_use_column_biogeochemistry", config_use_column_biogeochemistry) + call MPAS_pool_get_config(domain % configs, "config_use_zaerosols", config_use_zaerosols) call MPAS_pool_get_config(domain % configs, "config_use_column_itd_thermodynamics", config_use_column_itd_thermodynamics) call MPAS_pool_get_config(domain % configs, "config_calc_surface_temperature", config_calc_surface_temperature) call MPAS_pool_get_config(domain % configs, "config_use_vertical_tracers", config_use_vertical_tracers) @@ -1065,7 +1061,7 @@ subroutine seaice_icepack_predynamics_time_integration(domain, clock) !----------------------------------------------------------------- call mpas_timer_start("Column biogeochemistry") - if (config_use_column_biogeochemistry) & + if (config_use_column_biogeochemistry .or. config_use_zaerosols) & call column_biogeochemistry(domain) call mpas_timer_stop("Column biogeochemistry") @@ -1252,7 +1248,8 @@ end subroutine seaice_icepack_postdynamics_time_integration subroutine column_vertical_thermodynamics(domain, clock) use icepack_intfc, only: & - icepack_step_therm1 + icepack_step_therm1, & + icepack_warnings_clear use seaice_constants, only: & seaicePuny @@ -1686,14 +1683,18 @@ subroutine column_vertical_thermodynamics(domain, clock) endif ! code abort - abortFlag = .false. - abortMessage = "" + !abortFlag = .false. + !abortMessage = "" - !$omp parallel do default(shared) private(iCategory,iAerosol,northernHemisphereMask,& - !$omp& abortMessage) firstprivate(specificSnowAerosol,specificIceAerosol) & - !$omp& reduction(.or.:abortFlag) + !$offomp parallel do default(shared) private(iCategory,iAerosol,northernHemisphereMask,& + !$offomp& abortMessage) firstprivate(specificSnowAerosol,specificIceAerosol) + !$offomp& reduction(.or.:abortFlag) do iCell = 1, nCellsSolve + ! code abort + abortFlag = .false. + abortMessage = "" + ! initial state values iceAreaCellInitial(iCell) = iceAreaCell(iCell) @@ -1733,11 +1734,9 @@ subroutine column_vertical_thermodynamics(domain, clock) northernHemisphereMask = .false. endif + call icepack_warnings_clear() call icepack_step_therm1(& dt=config_dt, & - ncat=nCategories, & - nilyr=nIceLayers, & - nslyr=nSnowLayers, & aicen_init=iceAreaCategoryInitial(:,iCell), & vicen_init=iceVolumeCategoryInitial(:,iCell), & vsnon_init=snowVolumeCategoryInitial(:,iCell), & @@ -1867,6 +1866,7 @@ subroutine column_vertical_thermodynamics(domain, clock) frz_onset=freezeOnset(iCell), & yday=dayOfYear, & prescribed_ice=config_use_prescribed_ice) + abortFlag = icepack_warnings_aborted() call seaice_icepack_write_warnings(abortFlag) @@ -2055,7 +2055,6 @@ subroutine column_vertical_thermodynamics(domain, clock) enddo ! iCategory endif - enddo ! iCell ! error-checking @@ -2088,6 +2087,9 @@ subroutine column_itd_thermodynamics(domain, clock) use icepack_intfc, only: & icepack_step_therm2 + use seaice_constants, only: & + seaicePuny + type(domain_type), intent(inout) :: domain type(MPAS_clock_type), intent(in) :: clock @@ -2117,7 +2119,8 @@ subroutine column_itd_thermodynamics(domain, clock) logical, pointer :: & config_update_ocean_fluxes, & - config_use_column_biogeochemistry + config_use_column_biogeochemistry, & + config_use_zaerosols ! dimensions integer, pointer :: & @@ -2149,9 +2152,6 @@ subroutine column_itd_thermodynamics(domain, clock) oceanHeatFlux, & freezeOnset, & categoryThicknessLimits, & - biologyGrid, & - verticalGrid, & - interfaceBiologyGrid, & frazilGrowthDiagnostic ! frazilGrowthDiagnostic, & ! WaveFrequency, & @@ -2166,6 +2166,7 @@ subroutine column_itd_thermodynamics(domain, clock) oceanAerosolFlux, & oceanBioFluxes, & oceanBioConcentrations, & + oceanBioConcentrationsInUse, & initialSalinityProfile ! WaveSpectra, & ! DFloeSizeNewIce, & @@ -2194,21 +2195,8 @@ subroutine column_itd_thermodynamics(domain, clock) iBioData, & iBioLayers - ! test carbon conservation - real(kind=RKIND), dimension(:), allocatable :: & - totalCarbonCatFinal, & - totalCarbonCatInitial, & - oceanBioFluxesTemp, & - verticalGridSpace - - real(kind=RKIND) :: & - oceanCarbonFlux, & - totalCarbonFinal, & - totalCarbonInitial, & - carbonError - - real(kind=RKIND), dimension(:), allocatable :: & - oceanBioConcentrationsUsed + real(kind=RKIND), dimension(:,:), allocatable :: & + oceanBioFluxesTemp logical, dimension(:), allocatable :: & newlyFormedIceLogical @@ -2216,8 +2204,7 @@ subroutine column_itd_thermodynamics(domain, clock) logical :: & abortFlag, & setGetPhysicsTracers, & - setGetBGCTracers, & - checkCarbon + setGetBGCTracers character(len=strKIND) :: & abortMessage, & @@ -2229,8 +2216,6 @@ subroutine column_itd_thermodynamics(domain, clock) ! day of year call get_day_of_year(clock, dayOfYear) - checkCarbon = .false. - block => domain % blocklist do while (associated(block)) @@ -2253,6 +2238,7 @@ subroutine column_itd_thermodynamics(domain, clock) call MPAS_pool_get_config(block % configs, "config_dt", config_dt) call MPAS_pool_get_config(block % configs, "config_update_ocean_fluxes", config_update_ocean_fluxes) call MPAS_pool_get_config(block % configs, "config_use_column_biogeochemistry", config_use_column_biogeochemistry) + call MPAS_pool_get_config(block % configs, "config_use_zaerosols", config_use_zaerosols) call MPAS_pool_get_dimension(mesh, "nCellsSolve", nCellsSolve) call MPAS_pool_get_dimension(mesh, "nCategories", nCategories) @@ -2313,9 +2299,7 @@ subroutine column_itd_thermodynamics(domain, clock) call MPAS_pool_get_array(biogeochemistry, "newlyFormedIce", newlyFormedIce) call MPAS_pool_get_array(biogeochemistry, "oceanBioFluxes", oceanBioFluxes) call MPAS_pool_get_array(biogeochemistry, "oceanBioConcentrations", oceanBioConcentrations) - call MPAS_pool_get_array(biogeochemistry, "biologyGrid", biologyGrid) - call MPAS_pool_get_array(biogeochemistry, "verticalGrid", verticalGrid) - call MPAS_pool_get_array(biogeochemistry, "interfaceBiologyGrid", interfaceBiologyGrid) + call MPAS_pool_get_array(biogeochemistry, "oceanBioConcentrationsInUse", oceanBioConcentrationsInUse) call MPAS_pool_get_array(initial, "initialSalinityProfile", initialSalinityProfile) call MPAS_pool_get_array(initial, "categoryThicknessLimits", categoryThicknessLimits) @@ -2324,29 +2308,21 @@ subroutine column_itd_thermodynamics(domain, clock) ! newly formed ice allocate(newlyFormedIceLogical(nCategories)) - allocate(oceanBioConcentrationsUsed(ciceTracerObject % nBioTracers)) - allocate(oceanBioFluxesTemp(ciceTracerObject % nBioTracers)) - allocate(verticalGridSpace(nBioLayersP1)) - if (checkCarbon) then - allocate(totalCarbonCatFinal(nCategories)) - allocate(totalCarbonCatInitial(nCategories)) - endif - - verticalGridSpace(:) = 1.0_RKIND/real(nBioLayers,kind=RKIND) - verticalGridSpace(1) = verticalGridSpace(1)/2.0_RKIND - verticalGridSpace(nBioLayersP1) = verticalGridSpace(1) - + allocate(oceanBioFluxesTemp(ciceTracerObject % nBioTracers,nCellsSolve)) setGetPhysicsTracers = .true. - setGetBGCTracers = config_use_column_biogeochemistry + setGetBGCTracers = (config_use_column_biogeochemistry .or. config_use_zaerosols) + oceanBioConcentrationsInUse(:,:) = 0.0_RKIND ! code abort abortFlag = .false. abortMessage = "" - !$omp parallel do default(shared) private(iCategory,iBioTracers,iBioData,& - !$omp& totalCarbonInitial,abortMessage,oceanBioFluxesTemp,totalCarbonFinal,& - !$omp& carbonError) firstprivate(newlyFormedIceLogical,oceanBioConcentrationsUsed) & - !$omp& reduction(.or.:abortFlag) + !$offomp parallel do default(shared) private(iCategory,iBioTracers,iBioData,& + !$offomp& totalCarbonInitial,abortMessage,oceanBioFluxesTemp,totalCarbonFinal,& + !$offomp& totalCarbonCatInitial, totalCarbonCatFinal, & + !$offomp& oceanCarbonFlux, carbonError) & + !$offomp& firstprivate(newlyFormedIceLogical) & + !$offomp& reduction(.or.:abortFlag) do iCell = 1, nCellsSolve ! newly formed ice @@ -2357,22 +2333,14 @@ subroutine column_itd_thermodynamics(domain, clock) ! read the required ocean concentration fields into the allocated array do iBioTracers = 1, ciceTracerObject % nBioTracers iBioData = ciceTracerObject % index_LayerIndexToDataArray(iBioTracers) - oceanBioConcentrationsUsed(iBioTracers) = oceanBioConcentrations(iBioData, iCell) + oceanBioConcentrationsInUse(iBioTracers, iCell) = oceanBioConcentrations(iBioData, iCell) enddo ! iBioTracers ! set the category tracer array call set_cice_tracer_array_category(block, ciceTracerObject,& tracerArrayCategory, iCell, setGetPhysicsTracers, setGetBGCTracers) - if (checkCarbon) then - totalCarbonInitial = 0.0_RKIND - call seaice_total_carbon_content_category(block,totalCarbonCatInitial,iceAreaCategory(1,:,:),iceVolumeCategory(1,:,:),iCell) - do iCategory = 1,nCategories - totalCarbonInitial = totalCarbonInitial + totalCarbonCatInitial(iCategory)*iceAreaCategory(1,iCategory,iCell) - enddo - endif - - oceanBioFluxesTemp(:) = 0.0_RKIND + oceanBioFluxesTemp(:,iCell) = 0.0_RKIND ! CICE calculates the Sig Wave Height from the wave spectrum as follows before step therm2: ! we will use the Sig Wave Height from WW3, but could use this for testing without WW3 @@ -2380,12 +2348,7 @@ subroutine column_itd_thermodynamics(domain, clock) call icepack_step_therm2(& dt=config_dt, & - ncat=nCategories, & - nltrcr=ciceTracerObject % nBioTracers, & ! CHECK/FIX for BGC - nilyr=nIcelayers, & - nslyr=nSnowLayers, & hin_max=categoryThicknessLimits(:), & - nblyr=nBioLayers, & aicen=iceAreaCategory(1,:,iCell), & vicen=iceVolumeCategory(1,:,iCell), & vsnon=snowVolumeCategory(1,:,iCell), & @@ -2412,13 +2375,10 @@ subroutine column_itd_thermodynamics(domain, clock) fresh=oceanFreshWaterFlux(iCell), & fsalt=oceanSaltFlux(iCell), & fhocn=oceanHeatFlux(iCell), & - bgrid=biologyGrid(:), & - cgrid=verticalGrid(:), & - igrid=interfaceBiologyGrid(:), & faero_ocn=oceanAerosolFlux(:,iCell), & first_ice=newlyFormedIceLogical(:), & - flux_bio=oceanBioFluxesTemp(:), & - ocean_bio=oceanBioConcentrationsUsed(:), & + flux_bio=oceanBioFluxesTemp(:,iCell), & + ocean_bio=oceanBioConcentrationsInUse(:,iCell), & frazil_diag=frazilGrowthDiagnostic(iCell), & frz_onset=freezeOnset(iCell), & ! optional yday=dayOfYear) ! optional @@ -2436,11 +2396,12 @@ subroutine column_itd_thermodynamics(domain, clock) ! d_afsd_newi=DFloeSizeNewIce(:,iCell), & ! d_afsd_latm=DFloeSizeLateralMelt(:,iCell), & ! d_afsd_weld=DFloeSizeWeld(:,iCell), & -! floe_rad_c=FloeSizeBinCenter(:), & +! floe_rad_c=FloeSizeBinCenter(:), & ! floe_binwidth=FloeSizeBinWidth(:)) - abortFlag = icepack_warnings_aborted() - call seaice_icepack_write_warnings(abortFlag) + do iBioTracers = 1, ciceTracerObject % nBioTracers + oceanBioFluxes(iBioTracers,iCell) = oceanBioFluxes(iBioTracers,iCell) + oceanBioFluxesTemp(iBioTracers,iCell) + enddo ! update do iCategory = 1, nCategories @@ -2452,36 +2413,13 @@ subroutine column_itd_thermodynamics(domain, clock) call get_cice_tracer_array_category(block, ciceTracerObject, & tracerArrayCategory, iCell, setGetPhysicsTracers, setGetBGCTracers) - if (checkCarbon) then - totalCarbonFinal = 0.0_RKIND - call seaice_total_carbon_content_category(block,totalCarbonCatFinal,iceAreaCategory(1,:,:),iceVolumeCategory(1,:,:),iCell) - call seaice_ocean_carbon_flux_cell(block,oceanCarbonFlux,oceanBioFluxesTemp,iCell) - do iCategory = 1,nCategories - totalCarbonFinal = totalCarbonFinal + totalCarbonCatFinal(iCategory)*iceAreaCategory(1,iCategory,iCell) - enddo - carbonError = totalCarbonInitial - oceanCarbonFlux*config_dt - totalCarbonFinal - - if (abs(carbonError) > 1.0e-14_RKIND*MAXVAL((/totalCarbonInitial,totalCarbonFinal/))) then - call mpas_log_write("column_step_therm2, carbon conservation error", messageType=MPAS_LOG_ERR) - call mpas_log_write("iCell: $i", messageType=MPAS_LOG_ERR, intArgs=(/indexToCellID(iCell)/)) - call mpas_log_write("carbonError: $r", messageType=MPAS_LOG_ERR, realArgs=(/carbonError/)) - call mpas_log_write("totalCarbonInitial: $r", messageType=MPAS_LOG_ERR, realArgs=(/totalCarbonInitial/)) - call mpas_log_write("totalCarbonFinal: $r", messageType=MPAS_LOG_ERR, realArgs=(/totalCarbonFinal/)) - call mpas_log_write("oceanCarbonFlux: $r", messageType=MPAS_LOG_ERR, realArgs=(/oceanCarbonFlux/)) - - do iCategory = 1, nCategories - call mpas_log_write("iCategory: $i", messageType=MPAS_LOG_ERR, intArgs=(/iCategory/)) - call mpas_log_write("totalCarbonCatFinal(iCategory): $r", messageType=MPAS_LOG_ERR, realArgs=(/totalCarbonCatFinal(iCategory)/)) - call mpas_log_write("totalCarbonCatInitial(iCategory): $r", messageType=MPAS_LOG_ERR, realArgs=(/totalCarbonCatFinal(iCategory)/)) - enddo - endif - endif - + abortFlag = icepack_warnings_aborted() ! cell-specific abort message if (abortFlag) then call mpas_log_write("column_itd_thermodynamics: "//trim(abortMessage) , messageType=MPAS_LOG_ERR) call mpas_log_write("iCell: $i", messageType=MPAS_LOG_ERR, intArgs=(/indexToCellID(iCell)/)) endif + call seaice_icepack_write_warnings(abortFlag) enddo ! iCell @@ -2489,16 +2427,9 @@ subroutine column_itd_thermodynamics(domain, clock) call seaice_critical_error_write_block(domain, block, abortFlag) call seaice_check_critical_error(domain, abortFlag) - if (checkCarbon) then - deallocate(totalCarbonCatFinal) - deallocate(totalCarbonCatInitial) - endif - ! newly formed ice deallocate(newlyFormedIceLogical) - deallocate(oceanBioConcentrationsUsed) deallocate(oceanBioFluxesTemp) - deallocate(verticalGridSpace) block => block % next end do @@ -2816,9 +2747,6 @@ subroutine column_snow(domain) call icepack_step_snow (& dt=config_dt, & wind=windSpeed(iCell), & - nilyr=nIceLayers, & - nslyr=nSnowLayers, & - ncat=nCategories, & aice=iceAreaCell(iCell), & aicen=iceAreaCategory(1,:,iCell), & vicen=iceVolumeCategory(1,:,iCell), & @@ -2915,7 +2843,8 @@ subroutine column_radiation(domain, clock, lInitialization) config_use_shortwave_bioabsorption, & config_use_brine, & config_use_modal_aerosols, & - config_use_column_biogeochemistry + config_use_column_biogeochemistry, & + config_use_zaerosols ! dimensions integer, pointer :: & @@ -2938,9 +2867,7 @@ subroutine column_radiation(domain, clock, lInitialization) shortwaveIRDirectDown, & shortwaveIRDiffuseDown, & solarZenithAngleCosine, & - snowfallRate, & - verticalShortwaveGrid, & - verticalGrid + snowfallRate real(kind=RKIND), dimension(:,:), pointer :: & surfaceShortwaveFlux, & @@ -2980,7 +2907,9 @@ subroutine column_radiation(domain, clock, lInitialization) iceBodyAerosol, & brineFraction, & bioTracerShortwave, & - snowGrainRadius + snowGrainRadius, & + verticalAerosolsConc, & + verticalAlgaeConc real(kind=RKIND), pointer :: & dayOfNextShortwaveCalculation ! needed for CESM like coupled simulations @@ -3004,11 +2933,6 @@ subroutine column_radiation(domain, clock, lInitialization) iAerosol, & iBioTracers - integer, dimension(:), allocatable :: & - index_shortwaveAerosol, & - index_verticalAerosolsConc, & - index_algaeConc - real(kind=RKIND) :: & dayOfYear, & lonCellColumn @@ -3035,6 +2959,7 @@ subroutine column_radiation(domain, clock, lInitialization) call MPAS_pool_get_config(domain % configs, "config_use_shortwave_bioabsorption", config_use_shortwave_bioabsorption) call MPAS_pool_get_config(domain % configs, "config_use_modal_aerosols",config_use_modal_aerosols) call MPAS_pool_get_config(domain % configs, "config_use_column_biogeochemistry",config_use_column_biogeochemistry) + call MPAS_pool_get_config(domain % configs, "config_use_zaerosols",config_use_zaerosols) block => domain % blocklist do while (associated(block)) @@ -3048,11 +2973,11 @@ subroutine column_radiation(domain, clock, lInitialization) call MPAS_pool_get_config(block % configs, "config_dt", config_dt) - call MPAS_pool_get_dimension(mesh, "nCellsSolve", nCellsSolve) - call MPAS_pool_get_dimension(mesh, "nCategories", nCategories) - call MPAS_pool_get_dimension(mesh, "nIceLayers", nIceLayers) - call MPAS_pool_get_dimension(mesh, "nSnowLayers", nSnowLayers) - call MPAS_pool_get_dimension(mesh, "nAerosols", nAerosols) + call MPAS_pool_get_dimension(block % dimensions, "nCellsSolve", nCellsSolve) + call MPAS_pool_get_dimension(block % dimensions, "nCategories", nCategories) + call MPAS_pool_get_dimension(block % dimensions, "nIceLayers", nIceLayers) + call MPAS_pool_get_dimension(block % dimensions, "nSnowLayers", nSnowLayers) + call MPAS_pool_get_dimension(block % dimensions, "nAerosols", nAerosols) call MPAS_pool_get_dimension(block % dimensions, "nAlgae", nAlgae) call MPAS_pool_get_dimension(block % dimensions, "nBioLayers", nBioLayers) call MPAS_pool_get_dimension(block % dimensions, "nzAerosols", nzAerosols) @@ -3075,6 +3000,8 @@ subroutine column_radiation(domain, clock, lInitialization) call MPAS_pool_get_array(tracers, "iceBodyAerosol", iceBodyAerosol, 1) call MPAS_pool_get_array(tracers, "brineFraction", brineFraction, 1) call MPAS_pool_get_array(tracers, "snowGrainRadius", snowGrainRadius, 1) + call MPAS_pool_get_array(tracers, "verticalAlgaeConc", verticalAlgaeConc, 1) + call MPAS_pool_get_array(tracers, "verticalAerosolsConc", verticalAerosolsConc, 1) call MPAS_pool_get_array(atmos_coupling, "shortwaveVisibleDirectDown", shortwaveVisibleDirectDown) call MPAS_pool_get_array(atmos_coupling, "shortwaveVisibleDiffuseDown", shortwaveVisibleDiffuseDown) @@ -3108,8 +3035,6 @@ subroutine column_radiation(domain, clock, lInitialization) call MPAS_pool_get_array(ponds, "pondLidMeltFluxFraction", pondLidMeltFluxFraction) call MPAS_pool_get_array(biogeochemistry, "bioTracerShortwave", bioTracerShortwave) - call MPAS_pool_get_array(biogeochemistry, "verticalShortwaveGrid", verticalShortwaveGrid) - call MPAS_pool_get_array(biogeochemistry, "verticalGrid", verticalGrid) ! calendar type call MPAS_pool_get_config(block % configs, "config_calendar_type", config_calendar_type) @@ -3122,32 +3047,16 @@ subroutine column_radiation(domain, clock, lInitialization) ! aerosols array allocate(aerosolsArray(4*nAerosols,nCategories)) - allocate(index_shortwaveAerosol(maxAerosolType)) - allocate(index_verticalAerosolsConc(maxAerosolType)) - allocate(index_algaeConc(nAlgae)) - if (.not. config_use_column_biogeochemistry) then - index_shortwaveAerosol(1:maxAerosolType) = 1 - index_verticalAerosolsConc(1:maxAerosolType) = 1 - index_algaeConc(1:nAlgae) = 1 - else - do iAerosol = 1, maxAerosolType - index_shortwaveAerosol(iAerosol) = ciceTracerObject % index_verticalAerosolsConcShortwave(iAerosol) - index_verticalAerosolsConc(iAerosol) = ciceTracerObject % index_verticalAerosolsConc(iAerosol) - enddo - do iBioTracers = 1, nAlgae - index_algaeConc(iBioTracers) = ciceTracerObject % index_algaeConc(iBioTracers) - enddo - endif - setGetPhysicsTracers = .true. - setGetBGCTracers = config_use_column_biogeochemistry + setGetBGCTracers = (config_use_column_biogeochemistry .or. config_use_zaerosols) ! snow grain radius array allocate(snow_grain_radius(nSnowLayers,nCategories)) !$omp parallel do default(shared) & - !$omp& firstprivate(aerosolsArray,index_shortwaveAerosol,snow_grain_radius) & + !$omp& firstprivate(aerosolsArray,snow_grain_radius) & !$omp& private(iCategory,iAerosol,lonCellColumn,iSnowLayer) + do iCell = 1, nCellsSolve ! set aerosols array @@ -3163,7 +3072,7 @@ subroutine column_radiation(domain, clock, lInitialization) enddo ! iCategory snow_grain_radius(:,:) = 0.0_RKIND - if (config_use_snow_grain_radius) then + if (config_use_snow_grain_radius) then do iCategory = 1, nCategories do iSnowLayer = 1, nSnowLayers snow_grain_radius(iSnowLayer, iCategory) = snowGrainRadius(iSnowLayer,iCategory,iCell) @@ -3174,14 +3083,8 @@ subroutine column_radiation(domain, clock, lInitialization) lonCellColumn = lonCell(iCell) if (lonCellColumn > seaicePi) lonCellColumn = lonCellColumn - 2.0_RKIND * seaicePi - ! set the category tracer array - call set_cice_tracer_array_category(block, ciceTracerObject, & - tracerArrayCategory, iCell, setGetPhysicsTracers, setGetBGCTracers) - call icepack_step_radiation(& dt=config_dt, & - swgrid=verticalShortwaveGrid(:), & - igrid=verticalGrid(:), & fbri=brineFraction(1,:,iCell), & aicen=iceAreaCategory(1,:,iCell), & vicen=iceVolumeCategory(1,:,iCell), & @@ -3192,8 +3095,8 @@ subroutine column_radiation(domain, clock, lInitialization) hpndn=pondDepth(1,:,iCell), & ipndn=pondLidThickness(1,:,iCell), & aeron=aerosolsArray, & - bgcNn=tracerArrayCategory(index_algaeConc(:),:), & - zaeron=tracerArrayCategory(index_verticalAerosolsConc(:),:), & + bgcNn=verticalAlgaeConc(:,:,iCell), & + zaeron=verticalAerosolsConc(:,:,iCell), & trcrn_bgcsw=bioTracerShortwave(:,:,iCell), & TLAT=latCell(iCell), & TLON=lonCellColumn, & @@ -3233,19 +3136,12 @@ subroutine column_radiation(domain, clock, lInitialization) l_print_point=.false., & initonly=lInitialization) - ! set the category tracer array - call get_cice_tracer_array_category(block, ciceTracerObject, & - tracerArrayCategory, iCell, setGetPhysicsTracers, setGetBGCTracers) - enddo ! iCell deallocate(snow_grain_radius) ! aerosols array deallocate(aerosolsArray) - deallocate(index_shortwaveAerosol) - deallocate(index_verticalAerosolsConc) - deallocate(index_algaeConc) block => block % next end do @@ -3271,6 +3167,9 @@ subroutine column_ridging(domain) use icepack_intfc, only: & icepack_step_ridge + use seaice_constants, only: & + seaicePuny + type(domain_type), intent(inout) :: domain type(block_type), pointer :: block @@ -3291,7 +3190,8 @@ subroutine column_ridging(domain) ! configs logical, pointer :: & - config_use_column_biogeochemistry + config_use_column_biogeochemistry, & + config_use_zaerosols real(kind=RKIND), pointer :: & config_dt @@ -3302,11 +3202,7 @@ subroutine column_ridging(domain) ! dimensions integer, pointer :: & nCellsSolve, & - nCategories, & - nIceLayers, & - nSnowLayers, & - nAerosols, & - nBioLayers + nCategories ! variables real(kind=RKIND), dimension(:), pointer :: & @@ -3355,7 +3251,13 @@ subroutine column_ridging(domain) ! local integer :: & iCell, & - iCategory + iCategory, & + iBioTracers, & + iBioData, & + iBioLayers + + real(kind=RKIND), dimension(:,:), allocatable :: & + oceanBioFluxesTemp logical, dimension(:), allocatable :: & newlyFormedIceLogical @@ -3382,15 +3284,13 @@ subroutine column_ridging(domain) call MPAS_pool_get_config(block % configs, "config_dynamics_subcycle_number", config_dynamics_subcycle_number) call MPAS_pool_get_config(block % configs, "config_use_column_biogeochemistry", config_use_column_biogeochemistry) + call MPAS_pool_get_config(block % configs, "config_use_zaerosols", config_use_zaerosols) + call MPAS_pool_get_config(block % configs, "config_dt", config_dt) call MPAS_pool_get_array(velocity_solver, "dynamicsTimeStep", dynamicsTimeStep) call MPAS_pool_get_dimension(mesh, "nCellsSolve", nCellsSolve) call MPAS_pool_get_dimension(mesh, "nCategories", nCategories) - call MPAS_pool_get_dimension(mesh, "nIceLayers", nIceLayers) - call MPAS_pool_get_dimension(mesh, "nSnowLayers", nSnowLayers) - call MPAS_pool_get_dimension(mesh, "nAerosols", nAerosols) - call MPAS_pool_get_dimension(block % dimensions, "nBioLayers", nBioLayers) call MPAS_pool_get_array(mesh, "indexToCellID", indexToCellID) @@ -3437,7 +3337,9 @@ subroutine column_ridging(domain) allocate(newlyFormedIceLogical(nCategories)) setGetPhysicsTracers = .true. - setGetBGCTracers = config_use_column_biogeochemistry + setGetBGCTracers = (config_use_column_biogeochemistry .or. config_use_zaerosols) + + allocate(oceanBioFluxesTemp(ciceTracerObject % nBioTracers,nCellsSolve)) do iCell = 1, nCellsSolve @@ -3450,13 +3352,11 @@ subroutine column_ridging(domain) call set_cice_tracer_array_category(block, ciceTracerObject, & tracerArrayCategory, iCell, setGetPhysicsTracers, setGetBGCTracers) + oceanBioFluxesTemp(:,iCell) = 0.0_RKIND + call icepack_step_ridge(& dt=dynamicsTimeStep, & ndtd=config_dynamics_subcycle_number, & - nilyr=nIceLayers, & - nslyr=nSnowLayers, & - nblyr=nBioLayers, & - ncat=nCategories, & hin_max=categoryThicknessLimits, & ! hin_max, dimension(0:ncat), intent(inout) rdg_conv=ridgeConvergence(iCell), & rdg_shear=ridgeShear(iCell), & @@ -3476,7 +3376,6 @@ subroutine column_ridging(domain) fpond=pondFreshWaterFlux(iCell), & fresh=oceanFreshWaterFlux(iCell), & fhocn=oceanHeatFlux(iCell), & - n_aero=nAerosols, & faero_ocn=oceanAerosolFlux(:,iCell), & ! DC no fiso_ocn argument aparticn=ridgeParticipationFunction(:,iCell), & krdgn=ratioRidgeThicknessToIce(:,iCell), & @@ -3490,7 +3389,7 @@ subroutine column_ridging(domain) aice=iceAreaCell(iCell), & fsalt=oceanSaltFlux(iCell), & first_ice=newlyFormedIceLogical(:), & - flux_bio=oceanBioFluxes(:,iCell), & ! DC no closing argument + flux_bio=oceanBioFluxesTemp(:,iCell), & Tf=seaFreezingTemperature(iCell)) ! update @@ -3499,16 +3398,20 @@ subroutine column_ridging(domain) if (newlyFormedIceLogical(iCategory)) newlyFormedIce(iCategory,iCell) = 1 enddo ! iCategory + do iBioTracers = 1, ciceTracerObject % nBioTracers + oceanBioFluxes(iBioTracers,iCell) = oceanBioFluxes(iBioTracers,iCell) + oceanBioFluxesTemp(iBioTracers,iCell) + enddo + ! get category tracer array call get_cice_tracer_array_category(block, ciceTracerObject, & tracerArrayCategory, iCell, setGetPhysicsTracers, setGetBGCTracers) + call seaice_icepack_write_warnings(icepack_warnings_aborted()) enddo ! iCell - call seaice_icepack_write_warnings(icepack_warnings_aborted()) - ! newly formed ice deallocate(newlyFormedIceLogical) + deallocate(oceanBioFluxesTemp) block => block % next end do @@ -3529,13 +3432,15 @@ end subroutine column_ridging subroutine column_biogeochemistry(domain) - use ice_colpkg, only: & - colpkg_biogeochemistry, & - colpkg_init_OceanConcArray, & - colpkg_clear_warnings + use icepack_intfc, only: & + icepack_biogeochemistry, & + icepack_load_ocean_bio_array, & + icepack_warnings_clear use seaice_constants, only: & - seaicePuny + seaicePuny, & + microgramsPerKilograms, & + gramsIronPerMolIron type(domain_type), intent(inout) :: domain @@ -3551,6 +3456,7 @@ subroutine column_biogeochemistry(domain) melt_growth_rates, & ocean_coupling, & atmos_coupling, & + atmos_forcing, & initial ! configs @@ -3562,29 +3468,17 @@ subroutine column_biogeochemistry(domain) config_use_skeletal_biochemistry, & config_use_column_biogeochemistry, & config_use_zaerosols, & - config_use_vertical_tracers + config_use_vertical_tracers, & + config_use_atm_dust_file, & + config_use_iron_solubility_file ! dimensions integer, pointer :: & nCellsSolve, & nCategories, & - nIceLayers, & - nSnowLayers, & nzAerosols, & - nBioLayers, & nBioLayersP1, & nAlgae, & - nDOC, & - nDIC, & - nDON, & - nParticulateIron, & - nDissolvedIron, & - nZBGCTracers, & - maxAlgaeType, & - maxDOCType, & - maxDICType, & - maxDONType, & - maxIronType, & maxBCType, & maxDustType, & maxAerosolType @@ -3592,24 +3486,15 @@ subroutine column_biogeochemistry(domain) ! variables real(kind=RKIND), dimension(:), pointer :: & - rayleighCriteriaReal, & netNitrateUptake, & netAmmoniumUptake, & - totalVerticalSalinity, & netSpecificAlgalGrowthRate, & primaryProduction, & netBrineHeight, & - biologyGrid, & - interfaceBiologyGrid, & - interfaceGrid, & - verticalGrid, & seaSurfaceTemperature, & seaSurfaceSalinity, & seaFreezingTemperature, & snowfallRate, & - zSalinityFlux, & !echmod deprecate - zSalinityGDFlux, & !echmod deprecate - oceanMixedLayerDepth, & totalSkeletalAlgae, & oceanNitrateConc, & oceanSilicateConc, & @@ -3618,7 +3503,10 @@ subroutine column_biogeochemistry(domain) oceanDMSPConc, & oceanHumicsConc, & openWaterArea, & - totalChlorophyll + totalChlorophyll, & + IRON_Zolubility_wet, & + IRON_Zolubility_dry, & + IRON_in_duzt_fraction real(kind=RKIND), dimension(:,:), pointer :: & iceAreaCategoryInitial, & @@ -3631,10 +3519,11 @@ subroutine column_biogeochemistry(domain) snowIceBioFluxes, & atmosIceBioFluxes, & oceanBioConcentrations, & + oceanBioConcentrationsInUse, & + oceanBioToIceInUse, & totalVerticalBiologyIce, & totalVerticalBiologySnow, & penetratingShortwaveFlux, & - zSalinityIceDensity, & !echmod deprecate basalIceMeltCategory, & surfaceIceMeltCategory, & congelationCategory, & @@ -3644,6 +3533,8 @@ subroutine column_biogeochemistry(domain) atmosBioFluxes, & atmosBlackCarbonFlux, & atmosDustFlux, & + atmosWetDustFlux, & + atmosDryDustFlux, & oceanBioFluxes, & oceanAlgaeConc, & oceanDOCConc, & @@ -3692,10 +3583,12 @@ subroutine column_biogeochemistry(domain) iSnowCount, & iIceCount, & indexj, & - iBioLayers + iBioLayers, & + iWarning, & + nWarnings ! test carbon conservation - real(kind=RKIND), dimension(:), allocatable :: & + real(kind=RKIND), dimension(:,:), allocatable :: & totalCarbonCatFinal, & totalCarbonCatInitial, & totalCarbonCatFlux, & @@ -3703,19 +3596,18 @@ subroutine column_biogeochemistry(domain) brineHeightCatFinal real(kind=RKIND), dimension(:), allocatable :: & - oceanBioConcentrationsUsed, & - iceCarbonInitialCategory, & - iceCarbonFinalCategory, & - iceCarbonFluxCategory, & - iceBrineInitialCategory, & - iceBrineFinalCategory + totalCarbonFinal, & + totalCarbonInitial, & + totalCarbonFlux + + real(kind=RKIND) :: & + errorCheck logical, dimension(:), allocatable :: & newlyFormedIceLogical logical :: & abortFlag, & - rayleighCriteria, & setGetPhysicsTracers, & setGetBGCTracers, & checkCarbon @@ -3724,12 +3616,11 @@ subroutine column_biogeochemistry(domain) abortMessage, & abortLocation - real(kind=RKIND) :: & - carbonErrorCat, & - carbonErrorColumnPackage + real(kind=RKIND), dimension(:), allocatable :: & + carbonError real(kind=RKIND), parameter :: & - accuracy = 1.0e-14_RKIND + accuracy = 1.0e-13_RKIND ! test carbon conservation checkCarbon = .false. @@ -3744,30 +3635,16 @@ subroutine column_biogeochemistry(domain) call MPAS_pool_get_subpool(block % structs, "diagnostics_biogeochemistry", diagnostics_biogeochemistry) call MPAS_pool_get_subpool(block % structs, "shortwave", shortwave) call MPAS_pool_get_subpool(block % structs, "atmos_coupling", atmos_coupling) + call MPAS_pool_get_subpool(block % structs, "atmos_forcing", atmos_forcing) call MPAS_pool_get_subpool(block % structs, "melt_growth_rates", melt_growth_rates) call MPAS_pool_get_subpool(block % structs, "ocean_coupling", ocean_coupling) call MPAS_pool_get_subpool(block % structs, "initial", initial) call MPAS_pool_get_dimension(mesh, "nCellsSolve", nCellsSolve) call MPAS_pool_get_dimension(mesh, "nCategories", nCategories) - call MPAS_pool_get_dimension(mesh, "nIceLayers", nIceLayers) - call MPAS_pool_get_dimension(mesh, "nSnowLayers", nSnowLayers) call MPAS_pool_get_dimension(mesh, "nzAerosols", nzAerosols) - call MPAS_pool_get_dimension(mesh, "nBioLayers", nBioLayers) call MPAS_pool_get_dimension(mesh, "nBioLayersP1", nBioLayersP1) call MPAS_pool_get_dimension(mesh, "nAlgae", nAlgae) - call MPAS_pool_get_dimension(mesh, "nDOC", nDOC) - call MPAS_pool_get_dimension(mesh, "nDIC", nDIC) - call MPAS_pool_get_dimension(mesh, "nDON", nDON) - call MPAS_pool_get_dimension(mesh, "nParticulateIron", nParticulateIron) - call MPAS_pool_get_dimension(mesh, "nDissolvedIron", nDissolvedIron) - call MPAS_pool_get_dimension(mesh, "nZBGCTracers", nZBGCTracers) - call MPAS_pool_get_dimension(mesh, "maxAlgaeType", maxAlgaeType) - call MPAS_pool_get_dimension(mesh, "maxDOCType", maxDOCType) - call MPAS_pool_get_dimension(mesh, "maxDICType", maxDICType) - call MPAS_pool_get_dimension(mesh, "maxDONType", maxDONType) - call MPAS_pool_get_dimension(mesh, "maxAerosolType", maxAerosolType) - call MPAS_pool_get_dimension(mesh, "maxIronType", maxIronType) call MPAS_pool_get_dimension(mesh, "maxBCType", maxBCType) call MPAS_pool_get_dimension(mesh, "maxDustType", maxDustType) @@ -3779,11 +3656,12 @@ subroutine column_biogeochemistry(domain) call MPAS_pool_get_config(block % configs, "config_use_column_biogeochemistry", config_use_column_biogeochemistry) call MPAS_pool_get_config(block % configs, "config_use_zaerosols",config_use_zaerosols) call MPAS_pool_get_config(block % configs, "config_use_vertical_tracers",config_use_vertical_tracers) + call MPAS_pool_get_config(block % configs, "config_use_atm_dust_file", config_use_atm_dust_file) + call MPAS_pool_get_config(block % configs, "config_use_iron_solubility_file", config_use_iron_solubility_file) call MPAS_pool_get_array(biogeochemistry, "newlyFormedIce", newlyFormedIce) call MPAS_pool_get_array(biogeochemistry, "netNitrateUptake", netNitrateUptake) call MPAS_pool_get_array(biogeochemistry, "netAmmoniumUptake", netAmmoniumUptake) - call MPAS_pool_get_array(biogeochemistry, "totalVerticalSalinity", totalVerticalSalinity) call MPAS_pool_get_array(biogeochemistry, "totalChlorophyll", totalChlorophyll) call MPAS_pool_get_array(biogeochemistry, "netSpecificAlgalGrowthRate", netSpecificAlgalGrowthRate) call MPAS_pool_get_array(biogeochemistry, "primaryProduction", primaryProduction) @@ -3791,11 +3669,6 @@ subroutine column_biogeochemistry(domain) call MPAS_pool_get_array(biogeochemistry, "brineBottomChange", brineBottomChange) call MPAS_pool_get_array(biogeochemistry, "brineTopChange", brineTopChange) call MPAS_pool_get_array(biogeochemistry, "bioPorosity", bioPorosity) - call MPAS_pool_get_array(biogeochemistry, "rayleighCriteriaReal", rayleighCriteriaReal) - call MPAS_pool_get_array(biogeochemistry, "biologyGrid", biologyGrid) - call MPAS_pool_get_array(biogeochemistry, "interfaceBiologyGrid", interfaceBiologyGrid) - call MPAS_pool_get_array(biogeochemistry, "interfaceGrid", interfaceGrid) - call MPAS_pool_get_array(biogeochemistry, "verticalGrid", verticalGrid) call MPAS_pool_get_array(biogeochemistry, "bioDiffusivity", bioDiffusivity) call MPAS_pool_get_array(biogeochemistry, "bioPermeability", bioPermeability) call MPAS_pool_get_array(biogeochemistry, "bioShortwaveFlux", bioShortwaveFlux) @@ -3804,14 +3677,15 @@ subroutine column_biogeochemistry(domain) call MPAS_pool_get_array(biogeochemistry, "snowIceBioFluxes", snowIceBioFluxes) call MPAS_pool_get_array(biogeochemistry, "atmosIceBioFluxes", atmosIceBioFluxes) call MPAS_pool_get_array(biogeochemistry, "oceanBioConcentrations", oceanBioConcentrations) + call MPAS_pool_get_array(biogeochemistry, "oceanBioConcentrationsInUse", oceanBioConcentrationsInUse) + call MPAS_pool_get_array(biogeochemistry, "oceanBioToIceInUse", oceanBioToIceInUse) call MPAS_pool_get_array(biogeochemistry, "totalVerticalBiologyIce", totalVerticalBiologyIce) call MPAS_pool_get_array(biogeochemistry, "totalVerticalBiologySnow", totalVerticalBiologySnow) - call MPAS_pool_get_array(biogeochemistry, "zSalinityIceDensity", zSalinityIceDensity) !echmod deprecate - call MPAS_pool_get_array(biogeochemistry, "zSalinityFlux", zSalinityFlux) !echmod deprecate - call MPAS_pool_get_array(biogeochemistry, "zSalinityGDFlux", zSalinityGDFlux) !echmod deprecate call MPAS_pool_get_array(biogeochemistry, "atmosBioFluxes", atmosBioFluxes) call MPAS_pool_get_array(biogeochemistry, "atmosBlackCarbonFlux", atmosBlackCarbonFlux) call MPAS_pool_get_array(biogeochemistry, "atmosDustFlux", atmosDustFlux) + call MPAS_pool_get_array(biogeochemistry, "atmosWetDustFlux", atmosWetDustFlux) + call MPAS_pool_get_array(biogeochemistry, "atmosDryDustFlux", atmosDryDustFlux) call MPAS_pool_get_array(biogeochemistry, "oceanBioFluxes", oceanBioFluxes) call MPAS_pool_get_array(biogeochemistry, "oceanBioFluxesCategory", oceanBioFluxesCategory) call MPAS_pool_get_array(biogeochemistry, "verticalNitrogenLosses", verticalNitrogenLosses) @@ -3838,10 +3712,13 @@ subroutine column_biogeochemistry(domain) call MPAS_pool_get_array(ocean_coupling, "seaSurfaceTemperature", seaSurfaceTemperature) call MPAS_pool_get_array(ocean_coupling, "seaSurfaceSalinity", seaSurfaceSalinity) call MPAS_pool_get_array(ocean_coupling, "seaFreezingTemperature", seaFreezingTemperature) - call MPAS_pool_get_array(ocean_coupling, "oceanMixedLayerDepth", oceanMixedLayerDepth) call MPAS_pool_get_array(atmos_coupling, "snowfallRate", snowfallRate) + call MPAS_pool_get_array(atmos_forcing, "IRON_Zolubility_wet", IRON_Zolubility_wet) + call MPAS_pool_get_array(atmos_forcing, "IRON_Zolubility_dry", IRON_Zolubility_dry) + call MPAS_pool_get_array(atmos_forcing, "IRON_in_duzt_fraction", IRON_in_duzt_fraction) + call MPAS_pool_get_array(icestate, "iceAreaCategoryInitial", iceAreaCategoryInitial) call MPAS_pool_get_array(icestate, "iceVolumeCategoryInitial", iceVolumeCategoryInitial) call MPAS_pool_get_array(icestate, "snowVolumeCategoryInitial", snowVolumeCategoryInitial) @@ -3867,65 +3744,89 @@ subroutine column_biogeochemistry(domain) ! newly formed ice allocate(newlyFormedIceLogical(nCategories)) - allocate(oceanBioConcentrationsUsed(ciceTracerObject % nBioTracers)) - allocate(brineHeightCatInitial(nCategories)) + allocate(brineHeightCatInitial(nCategories,nCellsSolve)) if (checkCarbon) then - allocate(totalCarbonCatFinal(nCategories)) - allocate(totalCarbonCatInitial(nCategories)) - allocate(totalCarbonCatFlux(nCategories)) - allocate(brineHeightCatFinal(nCategories)) + allocate(carbonError(nCellsSolve)) + allocate(totalCarbonCatFinal(nCategories,nCellsSolve)) + allocate(totalCarbonCatInitial(nCategories,nCellsSolve)) + allocate(totalCarbonCatFlux(nCategories,nCellsSolve)) + allocate(brineHeightCatFinal(nCategories,nCellsSolve)) + allocate(totalCarbonFinal(nCellsSolve)) + allocate(totalCarbonInitial(nCellsSolve)) + allocate(totalCarbonFlux(nCellsSolve)) + else + allocate(carbonError(1)) + allocate(totalCarbonCatFinal(1,1)) + allocate(totalCarbonCatInitial(1,1)) + allocate(totalCarbonCatFlux(1,1)) + allocate(brineHeightCatFinal(1,1)) + allocate(totalCarbonFinal(1)) + allocate(totalCarbonInitial(1)) + allocate(totalCarbonFlux(1)) endif - setGetPhysicsTracers = .true. - setGetBGCTracers = config_use_column_biogeochemistry - - ! code abort - abortFlag = .false. - abortMessage = "" + brineHeightCatInitial(:,:) = 0.0_RKIND + carbonError(:) = 0.0_RKIND + totalCarbonCatFinal(:,:) = 0.0_RKIND + totalCarbonCatInitial(:,:) = 0.0_RKIND + totalCarbonCatFlux(:,:) = 0.0_RKIND + brineHeightCatFinal(:,:) = 0.0_RKIND + totalCarbonFinal(:) = 0.0_RKIND + totalCarbonInitial(:) = 0.0_RKIND + totalCarbonFlux(:) = 0.0_RKIND + setGetPhysicsTracers = .true. + setGetBGCTracers = (config_use_column_biogeochemistry .or. config_use_zaerosols) + + atmosBioFluxes(:,:) = 0.0_RKIND + oceanBioConcentrationsInUse(:,:) = 0.0_RKIND + oceanBioToIceInUse(:,:) = 0.0_RKIND + + !$offomp parallel do default(shared) private(iCategory,iBioTracers,iAlgae, iBioLayers) & + !$offomp& firstprivate(atmosBioFluxes,atmosBlackCarbonFlux, & + !$offomp& totalCarbonCatInitial, totalCarbonCatFinal, & + !$offomp& totalCarbonInitial, totalCarbonFinal, totalCarbonFlux, & + !$offomp& atmosDustFlux, bioShortwaveFluxCell, newlyFormedIce) + ! do iCell = 1, nCellsSolve ! newly formed ice do iCategory = 1, nCategories newlyFormedIceLogical(iCategory) = (newlyFormedIce(iCategory,iCell) == 1) - brineHeightCatInitial(iCategory) = brineFraction(1,iCategory,iCell) * & + brineHeightCatInitial(iCategory,iCell) = brineFraction(1,iCategory,iCell) * & iceVolumeCategoryInitial(iCategory,iCell)/(iceAreaCategoryInitial(iCategory,iCell) + seaicePuny) enddo ! iCategory - rayleighCriteria = (rayleighCriteriaReal(iCell) > 0.5_RKIND) !update ocean concentrations fields and atmospheric fluxes into allocated array + #ifdef coupled - call colpkg_init_OceanConcArray(& - nZBGCTracers, & - maxAlgaeType, & - maxDONType, & - maxDOCType, & - maxDICType, & - maxAerosolType, & - maxIronType, & - oceanNitrateConc(iCell), & - oceanAmmoniumConc(iCell), & - oceanSilicateConc(iCell),& - oceanDMSPConc(iCell), & - oceanDMSConc(iCell), & - oceanAlgaeConc(:,iCell), & - oceanDOCConc(:,iCell), & - oceanDONConc(:,iCell), & - oceanDICConc(:,iCell), & - oceanDissolvedIronConc(:,iCell), & - oceanParticulateIronConc(:,iCell), & - oceanZAerosolConc(:,iCell), & - oceanBioConcentrations(:,iCell), & - oceanHumicsConc(iCell)) + call icepack_load_ocean_bio_array(& + nit=oceanNitrateConc(iCell), & + amm=oceanAmmoniumConc(iCell), & + sil=oceanSilicateConc(iCell), & + dmsp=oceanDMSPConc(iCell), & + dms=oceanDMSConc(iCell), & + algalN=oceanAlgaeConc(:,iCell), & + doc=oceanDOCConc(:,iCell), & + don=oceanDONConc(:,iCell), & + dic=oceanDICConc(:,iCell), & + fed=oceanDissolvedIronConc(:,iCell), & + fep=oceanParticulateIronConc(:,iCell), & + zaeros=oceanZAerosolConc(:,iCell), & + ocean_bio_all=oceanBioConcentrations(:,iCell), & + hum=oceanHumicsConc(iCell)) #else do iBioTracers = 1, maxBCType atmosBlackCarbonFlux(iBioTracers,iCell) = 1.e-12_RKIND enddo - do iBioTracers = 1, maxDustType - atmosDustFlux(iBioTracers,iCell) = 1.e-13_RKIND - enddo + if (.not. config_use_atm_dust_file) then + do iBioTracers = 1, maxDustType + atmosDustFlux(iBioTracers,iCell) = 1.e-13_RKIND + atmosWetDustFlux(iBioTracers,iCell) = 1.e-13_RKIND * 0.5_RKIND + atmosDryDustFlux(iBioTracers,iCell) = 1.e-13_RKIND * 0.5_RKIND + enddo + endif #endif - atmosBioFluxes(:,:) = 0.0_RKIND if (config_use_zaerosols) then indexj = ciceTracerObject % index_verticalAerosolsConcLayer(1) do iBioTracers = 1, maxBCType @@ -3934,132 +3835,130 @@ subroutine column_biogeochemistry(domain) do iBioTracers = maxBCType + 1, nzAerosols atmosBioFluxes(indexj -1 + iBioTracers, iCell) = atmosDustFlux(iBioTracers-maxBCType,iCell) enddo + indexj = ciceTracerObject % index_dissolvedIronConcLayer(1) + if (config_use_iron_solubility_file) then + atmosBioFluxes(indexj,iCell) = 0.0_RKIND + do iBioTracers = maxBCType + 1, nzAerosols + atmosBioFluxes(indexj,iCell) = atmosBioFluxes(indexj,iCell) + & + (atmosWetDustFlux(iBioTracers-maxBCType,iCell) * IRON_Zolubility_wet(iCell) + & + atmosDryDustFlux(iBioTracers-maxBCType,iCell) * IRON_Zolubility_dry(iCell) ) * & + IRON_in_duzt_fraction(iCell) * microgramsPerKilograms / gramsIronPerMolIron + end do + end if endif do iBioTracers = 1, ciceTracerObject % nBioTracers iBioData = ciceTracerObject % index_LayerIndexToDataArray(iBioTracers) - oceanBioConcentrationsUsed(iBioTracers) = oceanBioConcentrations(iBioData,iCell) + oceanBioConcentrationsInUse(iBioTracers,iCell) = oceanBioConcentrations(iBioData,iCell) enddo ! iBioTracers - abortFlag = .false. - call set_cice_tracer_array_category(block, ciceTracerObject, & tracerArrayCategory, iCell, setGetPhysicsTracers, setGetBGCTracers) - if (checkCarbon) call seaice_total_carbon_content_category(block,& - totalCarbonCatInitial,iceAreaCategoryInitial,iceVolumeCategoryInitial,iCell) - - call colpkg_clear_warnings() - call colpkg_biogeochemistry(& - config_dt, & - ciceTracerObject % nTracers, & - ciceTracerObject % nBioTracers, & - netNitrateUptake(iCell), & - netAmmoniumUptake(iCell), & - bioDiffusivity(:,:,iCell), & - bioPermeability(:,:,iCell), & - bioShortwaveFlux(:,:,iCell), & - totalVerticalSalinity(iCell), & - darcyVelocityBio(:,iCell), & - netSpecificAlgalGrowthRate(iCell), & - primaryProduction(iCell), & - netBrineHeight(iCell), & - brineBottomChange(:,iCell), & - brineTopChange(:,iCell), & - verticalNitrogenLosses(:,:,iCell), & - snowIceBioFluxes(:,iCell), & - atmosIceBioFluxes(:,iCell), & - oceanBioConcentrationsUsed(:), & - newlyFormedIceLogical(:), & - shortwaveLayerPenetration(:,:,iCell), & - bioPorosity(:,:,iCell), & - bioTemperature(:,:,iCell), & - totalVerticalBiologyIce(:,iCell), & - totalVerticalBiologySnow(:,iCell), & - totalChlorophyll(iCell), & - penetratingShortwaveFlux(:,iCell), & - rayleighCriteria, & - zSalinityIceDensity(:,iCell), & !echmod deprecate - zSalinityFlux(iCell), & !echmod deprecate - zSalinityGDFlux(iCell), & !echmod deprecate - biologyGrid, & - interfaceBiologyGrid, & - interfaceGrid, & - verticalGrid, & - nBioLayers, & - nIceLayers, & - nSnowLayers, & - nAlgae, & - nzAerosols, & - nCategories, & - nDOC, & - nDIC, & - nDON, & - nDissolvedIron, & - nParticulateIron, & - basalIceMeltCategory(:,iCell), & - surfaceIceMeltCategory(:,iCell), & - congelationCategory(:,iCell), & - snowiceFormationCategory(:,iCell), & - seaSurfaceTemperature(iCell), & - seaSurfaceSalinity(iCell), & - seaFreezingTemperature(iCell), & - snowfallRate(iCell), & - snowMeltCategory(:,iCell), & - oceanMixedLayerDepth(iCell), & - initialSalinityProfile(:,iCell), & - iceThicknessCategoryInitial(:,iCell), & - oceanBioFluxes(:,iCell), & - atmosBioFluxes(:,iCell), & - iceAreaCategoryInitial(:,iCell), & - iceVolumeCategoryInitial(:,iCell), & - iceAreaCategory(1,:,iCell), & - iceVolumeCategory(1,:,iCell), & - snowVolumeCategory(1,:,iCell), & - openWaterArea(iCell), & - tracerArrayCategory, & - snowVolumeCategoryInitial(:,iCell), & - config_use_skeletal_biochemistry, & - maxAlgaeType, & - nZBGCTracers, & - oceanBioFluxesCategory(:,:,iCell), & - bgridPorosityIceCell(:,iCell), & - bgridSalinityIceCell(:,iCell), & - bgridTemperatureIceCell(:,iCell), & - abortFlag, & - abortMessage) - call column_write_warnings(abortFlag) + if (checkCarbon) then + call seaice_total_carbon_content_category(block,& + totalCarbonCatInitial(:,iCell),iceAreaCategoryInitial(:,:),iceVolumeCategoryInitial(:,:),iCell) + totalCarbonInitial(iCell) = 0.0_RKIND + do iCategory = 1, nCategories + totalCarbonInitial(iCell) = totalCarbonInitial(iCell) + totalCarbonCatInitial(iCategory,iCell)*iceAreaCategoryInitial(iCategory,iCell) + enddo + endif + + ! code abort + abortFlag = .false. + abortMessage = "" + + call icepack_warnings_clear() + call icepack_biogeochemistry(& + dt=config_dt, & + upNO=netNitrateUptake(iCell), & + upNH=netAmmoniumUptake(iCell), & + iDi=bioDiffusivity(:,:,iCell), & + iki=bioPermeability(:,:,iCell), & + zfswin=bioShortwaveFlux(:,:,iCell), & + darcy_V=darcyVelocityBio(:,iCell), & + grow_net=netSpecificAlgalGrowthRate(iCell), & + PP_net=primaryProduction(iCell), & + hbri=netBrineHeight(iCell), & + dhbr_bot=brineBottomChange(:,iCell), & + dhbr_top=brineTopChange(:,iCell), & + Zoo=verticalNitrogenLosses(:,:,iCell), & + fbio_snoice=snowIceBioFluxes(:,iCell), & + fbio_atmice=atmosIceBioFluxes(:,iCell), & + ocean_bio_dh=oceanBioToIceInUse(:,iCell), & + ocean_bio=oceanBioConcentrationsInUse(:,iCell), & + first_ice=newlyFormedIceLogical(:), & + fswpenln=shortwaveLayerPenetration(:,:,iCell), & + bphi=bioPorosity(:,:,iCell), & + bTiz=bioTemperature(:,:,iCell), & + ice_bio_net=totalVerticalBiologyIce(:,iCell), & + snow_bio_net=totalVerticalBiologySnow(:,iCell), & + totalChla=totalChlorophyll(iCell), & + fswthrun=penetratingShortwaveFlux(:,iCell), & + meltbn=basalIceMeltCategory(:,iCell), & + melttn=surfaceIceMeltCategory(:,iCell), & + congeln=congelationCategory(:,iCell), & + snoicen=snowiceFormationCategory(:,iCell), & + sst=seaSurfaceTemperature(iCell), & + sss=seaSurfaceSalinity(iCell), & + Tf=seaFreezingTemperature(iCell), & + fsnow=snowfallRate(iCell), & + meltsn=snowMeltCategory(:,iCell), & + hin_old=iceThicknessCategoryInitial(:,iCell), & + flux_bio=oceanBioFluxes(:,iCell), & + flux_bio_atm=atmosBioFluxes(:,iCell), & + aicen_init=iceAreaCategoryInitial(:,iCell), & + vicen_init=iceVolumeCategoryInitial(:,iCell), & + aicen=iceAreaCategory(1,:,iCell), & + vicen=iceVolumeCategory(1,:,iCell), & + vsnon=snowVolumeCategory(1,:,iCell), & + aice0=openWaterArea(iCell), & + trcrn=tracerArrayCategory, & + vsnon_init=snowVolumeCategoryInitial(:,iCell), & + flux_bion=oceanBioFluxesCategory(:,:,iCell), & + bioPorosityIceCell=bgridPorosityIceCell(:,iCell), & + bioSalinityIceCell=bgridSalinityIceCell(:,iCell), & + bioTemperatureIceCell=bgridTemperatureIceCell(:,iCell)) + + abortFlag = icepack_warnings_aborted() call get_cice_tracer_array_category(block, ciceTracerObject, & tracerArrayCategory, iCell, setGetPhysicsTracers, setGetBGCTracers) if (checkCarbon) then - call seaice_total_carbon_content_category(block,totalCarbonCatFinal,iceAreaCategory(1,:,:),iceVolumeCategory(1,:,:),iCell) - call seaice_ocean_carbon_flux(block,totalCarbonCatFlux,oceanBioFluxesCategory(:,:,:),iCell) - do iCategory = 1,nCategories - brineHeightCatFinal(iCategory) = brineFraction(1,iCategory,iCell) * & - iceVolumeCategory(1,iCategory,iCell)/(iceAreaCategory(1,iCategory,iCell) + seaicePuny) - carbonErrorCat = totalCarbonCatInitial(iCategory) - totalCarbonCatFlux(iCategory)*config_dt - & - totalCarbonCatFinal(iCategory) - if (abs(carbonErrorCat) > accuracy*MAXVAL((/totalCarbonCatInitial(iCategory),totalCarbonCatFinal(iCategory)/))) then -! abortFlag = .true. -! abortMessage = "carbon conservation errror after column bgc" - call mpas_log_write("column_biogeochemistry, carbon conservation error", messageType=MPAS_LOG_ERR) - call mpas_log_write("iCell: $i", messageType=MPAS_LOG_ERR, intArgs=(/indexToCellID(iCell)/)) - call mpas_log_write("iCategory: $i", messageType=MPAS_LOG_ERR, intArgs=(/iCategory/)) - call mpas_log_write("carbonErrorCat: $r", messageType=MPAS_LOG_ERR, realArgs=(/carbonErrorCat/)) - call mpas_log_write("carbonErrorCat*iceAreaCategory: $r", messageType=MPAS_LOG_ERR, realArgs=(/carbonErrorCat*iceAreaCategory(1,iCategory,iCell)/)) - call mpas_log_write("totalCarbonCatInitial(iCategory): $r", messageType=MPAS_LOG_ERR, realArgs=(/totalCarbonCatInitial(iCategory)/)) - call mpas_log_write("totalCarbonCatFinal(iCategory): $r", messageType=MPAS_LOG_ERR, realArgs=(/totalCarbonCatFinal(iCategory)/)) - call mpas_log_write("totalCarbonCatFlux(iCategory): $r", messageType=MPAS_LOG_ERR, realArgs=(/totalCarbonCatFlux(iCategory)/)) - call mpas_log_write("brineHeightCatInitial(iCategory): $r", messageType=MPAS_LOG_ERR, realArgs=(/brineHeightCatInitial(iCategory)/)) - call mpas_log_write("brineHeightCatFinal(iCategory): $r", messageType=MPAS_LOG_ERR, realArgs=(/brineHeightCatFinal(iCategory)/)) - endif + call seaice_total_carbon_content_category(block,totalCarbonCatFinal(:,iCell),iceAreaCategory(1,:,:),iceVolumeCategory(1,:,:),iCell) + call seaice_ocean_carbon_flux(block,totalCarbonCatFlux(:,iCell),oceanBioFluxesCategory(:,:,:),iCell) + totalCarbonFinal(iCell) = 0.0_RKIND + totalCarbonFlux(iCell) = 0.0_RKIND + do iCategory = 1, nCategories + totalCarbonFinal(iCell) = totalCarbonFinal(iCell) + totalCarbonCatFinal(iCategory,iCell)*iceAreaCategory(1,iCategory,iCell) + totalCarbonFlux(iCell) = totalCarbonFlux(iCell) + totalCarbonCatFlux(iCategory,iCell) * iceAreaCategory(1,iCategory,iCell) enddo - endif - - ! code abort - if (abortFlag) exit + carbonError(iCell) = (totalCarbonFinal(iCell) - totalCarbonInitial(iCell))/config_dt +totalCarbonFlux(iCell) + errorCheck = max(accuracy,accuracy*abs(totalCarbonFlux(iCell))) + + if (abs(carbonError(iCell)) > errorCheck) then + do iCategory = 1,nCategories + if (iceAreaCategory(1,iCategory,iCell) > seaicePuny) then + brineHeightCatFinal(iCategory,iCell) = brineFraction(1,iCategory,iCell) * & + iceVolumeCategory(1,iCategory,iCell)/(iceAreaCategory(1,iCategory,iCell) + seaicePuny) + call mpas_log_write("column_biogeochemistry, carbon conservation error", messageType=MPAS_LOG_ERR) + call mpas_log_write("iCell: $i", messageType=MPAS_LOG_ERR, intArgs=(/indexToCellID(iCell)/)) + call mpas_log_write("iCategory: $i", messageType=MPAS_LOG_ERR, intArgs=(/iCategory/)) + call mpas_log_write("carbonError: $r", messageType=MPAS_LOG_ERR, realArgs=(/carbonError(iCell)/)) + call mpas_log_write("carbonError*iceAreaCategory: $r", messageType=MPAS_LOG_ERR, realArgs=(/carbonError(iCell)*iceAreaCategory(1,iCategory,iCell)/)) + call mpas_log_write("iceAreaCategory: $r", messageType=MPAS_LOG_ERR, realArgs=(/iceAreaCategory(1,iCategory,iCell)/)) + call mpas_log_write("iceAreaCategoryInitial: $r", messageType=MPAS_LOG_ERR, realArgs=(/iceAreaCategoryInitial(iCategory,iCell)/)) + call mpas_log_write("totalCarbonCatInitial(iCategory): $r", messageType=MPAS_LOG_ERR, realArgs=(/totalCarbonCatInitial(iCategory,iCell)/)) + call mpas_log_write("totalCarbonCatFinal(iCategory,iCell): $r", messageType=MPAS_LOG_ERR, realArgs=(/totalCarbonCatFinal(iCategory,iCell)/)) + call mpas_log_write("totalCarbonCatFlux(iCategory,iCell): $r", messageType=MPAS_LOG_ERR, realArgs=(/totalCarbonCatFlux(iCategory,iCell)/)) + call mpas_log_write("brineHeightCatInitial(iCategory,iCell): $r", messageType=MPAS_LOG_ERR, realArgs=(/brineHeightCatInitial(iCategory,iCell)/)) + call mpas_log_write("brineHeightCatFinal(iCategory,iCell): $r", messageType=MPAS_LOG_ERR, realArgs=(/brineHeightCatFinal(iCategory,iCell)/)) + call mpas_log_write("iceAreaCategory(1,iCategory,iCell): $r", messageType=MPAS_LOG_ERR, realArgs=(/iceAreaCategory(1,iCategory,iCell)/)) + end if + enddo !categories + endif ! carbonError + endif ! checkCarbon totalSkeletalAlgae(iCell) = 0.0_RKIND bioShortwaveFluxCell(:,iCell) = 0.0_RKIND @@ -4083,28 +3982,30 @@ subroutine column_biogeochemistry(domain) if (newlyFormedIceLogical(iCategory)) newlyFormedIce(iCategory,iCell) = 1 enddo ! iCategory - if (.not. rayleighCriteria) rayleighCriteriaReal(iCell) = 0.0_RKIND + ! code abort + if (abortFlag) then + call mpas_log_write("column_biogeochemistry: "//trim(abortMessage) , messageType=MPAS_LOG_ERR) + call mpas_log_write("iCell: $i", messageType=MPAS_LOG_ERR, intArgs=(/indexToCellID(iCell)/)) + endif + + call seaice_icepack_write_warnings(abortFlag) enddo ! iCell - ! code abort - if (abortFlag) then - call mpas_log_write("column_biogeochemistry: "//trim(abortMessage) , messageType=MPAS_LOG_ERR) - call mpas_log_write("iCell: $i", messageType=MPAS_LOG_ERR, intArgs=(/indexToCellID(iCell)/)) - endif call seaice_critical_error_write_block(domain, block, abortFlag) call seaice_check_critical_error(domain, abortFlag) - if (checkCarbon) then - deallocate(totalCarbonCatFinal) - deallocate(totalCarbonCatInitial) - deallocate(totalCarbonCatFlux) - deallocate(brineHeightCatFinal) - endif + deallocate(totalCarbonCatFinal) + deallocate(totalCarbonCatInitial) + deallocate(totalCarbonCatFlux) + deallocate(brineHeightCatFinal) + deallocate(totalCarbonFinal) + deallocate(totalCarbonInitial) + deallocate(totalCarbonFlux) + deallocate(carbonError) deallocate(brineHeightCatInitial) deallocate(newlyFormedIceLogical) - deallocate(oceanBioConcentrationsUsed) block => block % next end do @@ -4378,7 +4279,8 @@ subroutine seaice_icepack_aggregate(domain) ocean_coupling logical, pointer :: & - config_use_column_biogeochemistry + config_use_column_biogeochemistry, & + config_use_zaerosols real(kind=RKIND), dimension(:), pointer :: & iceAreaCell, & @@ -4396,8 +4298,10 @@ subroutine seaice_icepack_aggregate(domain) iCell integer, pointer :: & - nCellsSolve, & - nCategories + nCellsSolve + + integer, dimension(:), pointer :: & + indexToCellID logical :: & setGetPhysicsTracers, & @@ -4413,9 +4317,10 @@ subroutine seaice_icepack_aggregate(domain) call MPAS_pool_get_subpool(block % structs, "ocean_coupling", ocean_coupling) call MPAS_pool_get_config(block % configs, "config_use_column_biogeochemistry", config_use_column_biogeochemistry) + call MPAS_pool_get_config(block % configs, "config_use_zaerosols", config_use_zaerosols) call MPAS_pool_get_dimension(mesh, "nCellsSolve", nCellsSolve) - call MPAS_pool_get_dimension(mesh, "nCategories", nCategories) + call MPAS_pool_get_array(mesh, "indexToCellID", indexToCellID) call MPAS_pool_get_array(tracers, "iceAreaCategory", iceAreaCategory, 1) call MPAS_pool_get_array(tracers, "iceVolumeCategory", iceVolumeCategory, 1) @@ -4430,7 +4335,7 @@ subroutine seaice_icepack_aggregate(domain) call MPAS_pool_get_array(ocean_coupling, "seaFreezingTemperature", seaFreezingTemperature) setGetPhysicsTracers = .true. - setGetBGCTracers = config_use_column_biogeochemistry + setGetBGCTracers = (config_use_column_biogeochemistry .or. config_use_zaerosols) do iCell = 1, nCellsSolve @@ -4439,7 +4344,6 @@ subroutine seaice_icepack_aggregate(domain) tracerArrayCategory, iCell, setGetPhysicsTracers, setGetBGCTracers) call icepack_aggregate( & - nCategories, & iceAreaCategory(1,:,iCell), & tracerArrayCategory, & ! trcrn iceVolumeCategory(1,:,iCell), & @@ -4449,7 +4353,6 @@ subroutine seaice_icepack_aggregate(domain) iceVolumeCell(iCell), & snowVolumeCell(iCell), & openWaterArea(iCell), & - ciceTracerObject % nTracers, & ciceTracerObject % parentIndex, & ! trcr_depend ciceTracerObject % firstAncestorMask, & ! trcr_base ciceTracerObject % ancestorNumber, & ! n_trcr_strata @@ -4579,7 +4482,8 @@ subroutine seaice_icepack_coupling_prep(domain) logical, pointer :: & config_use_ocean_mixed_layer, & config_include_pond_freshwater_feedback, & - config_use_column_biogeochemistry + config_use_column_biogeochemistry, & + config_use_zaerosols type(MPAS_pool_type), pointer :: & oceanCoupling, & @@ -4630,7 +4534,17 @@ subroutine seaice_icepack_coupling_prep(domain) oceanDMSPdFlux, & oceanHumicsFlux, & oceanDustIronFlux, & - totalOceanCarbonFlux + oceanBlackCarbonFlux, & + totalOceanCarbonFlux, & + oceanNitrateFluxArea, & + oceanSilicateFluxArea, & + oceanAmmoniumFluxArea, & + oceanDMSFluxArea, & + oceanDMSPpFluxArea, & + oceanDMSPdFluxArea, & + oceanHumicsFluxArea, & + oceanDustIronFluxArea, & + oceanBlackCarbonFluxArea real(kind=RKIND), dimension(:,:), pointer :: & albedoVisibleDirectCategory, & @@ -4647,7 +4561,13 @@ subroutine seaice_icepack_coupling_prep(domain) oceanDICFlux, & oceanDONFlux, & oceanParticulateIronFlux, & - oceanDissolvedIronFlux + oceanDissolvedIronFlux, & + oceanAlgaeFluxArea, & + oceanDOCFluxArea, & + oceanDICFluxArea, & + oceanDONFluxArea, & + oceanParticulateIronFluxArea, & + oceanDissolvedIronFluxArea real(kind=RKIND), dimension(:,:,:), pointer :: & iceAreaCategory @@ -4690,6 +4610,7 @@ subroutine seaice_icepack_coupling_prep(domain) call MPAS_pool_get_config(domain % configs, "config_dt", config_dt) call MPAS_pool_get_config(domain % configs, "config_include_pond_freshwater_feedback", config_include_pond_freshwater_feedback) call MPAS_pool_get_config(domain % configs, "config_use_column_biogeochemistry", config_use_column_biogeochemistry) + call MPAS_pool_get_config(domain % configs, "config_use_zaerosols", config_use_zaerosols) call MPAS_pool_get_config(domain % configs, "config_ratio_C_to_N_diatoms", config_ratio_C_to_N_diatoms) call MPAS_pool_get_config(domain % configs, "config_ratio_C_to_N_small_plankton", config_ratio_C_to_N_small_plankton) call MPAS_pool_get_config(domain % configs, "config_ratio_C_to_N_phaeocystis", config_ratio_C_to_N_phaeocystis) @@ -4769,6 +4690,7 @@ subroutine seaice_icepack_coupling_prep(domain) call MPAS_pool_get_array(biogeochemistry, "oceanDMSPdFlux", oceanDMSPdFlux) call MPAS_pool_get_array(biogeochemistry, "oceanHumicsFlux", oceanHumicsFlux) call MPAS_pool_get_array(biogeochemistry, "oceanDustIronFlux", oceanDustIronFlux) + call MPAS_pool_get_array(biogeochemistry, "oceanBlackCarbonFlux", oceanBlackCarbonFlux) call MPAS_pool_get_array(biogeochemistry, "oceanBioFluxes", oceanBioFluxes) call MPAS_pool_get_array(biogeochemistry, "oceanAlgaeFlux", oceanAlgaeFlux) call MPAS_pool_get_array(biogeochemistry, "oceanDOCFlux", oceanDOCFlux) @@ -4778,6 +4700,22 @@ subroutine seaice_icepack_coupling_prep(domain) call MPAS_pool_get_array(biogeochemistry, "oceanDissolvedIronFlux", oceanDissolvedIronFlux) call MPAS_pool_get_array(biogeochemistry, "totalOceanCarbonFlux", totalOceanCarbonFlux) + call MPAS_pool_get_array(biogeochemistry, "oceanNitrateFluxArea", oceanNitrateFluxArea) + call MPAS_pool_get_array(biogeochemistry, "oceanSilicateFluxArea", oceanSilicateFluxArea) + call MPAS_pool_get_array(biogeochemistry, "oceanAmmoniumFluxArea", oceanAmmoniumFluxArea) + call MPAS_pool_get_array(biogeochemistry, "oceanDMSFluxArea", oceanDMSFluxArea) + call MPAS_pool_get_array(biogeochemistry, "oceanDMSPpFluxArea", oceanDMSPpFluxArea) + call MPAS_pool_get_array(biogeochemistry, "oceanDMSPdFluxArea", oceanDMSPdFluxArea) + call MPAS_pool_get_array(biogeochemistry, "oceanHumicsFluxArea", oceanHumicsFluxArea) + call MPAS_pool_get_array(biogeochemistry, "oceanDustIronFluxArea", oceanDustIronFluxArea) + call MPAS_pool_get_array(biogeochemistry, "oceanBlackCarbonFluxArea", oceanBlackCarbonFluxArea) + call MPAS_pool_get_array(biogeochemistry, "oceanAlgaeFluxArea", oceanAlgaeFluxArea) + call MPAS_pool_get_array(biogeochemistry, "oceanDOCFluxArea", oceanDOCFluxArea) + call MPAS_pool_get_array(biogeochemistry, "oceanDICFluxArea", oceanDICFluxArea) + call MPAS_pool_get_array(biogeochemistry, "oceanDONFluxArea", oceanDONFluxArea) + call MPAS_pool_get_array(biogeochemistry, "oceanParticulateIronFluxArea", oceanParticulateIronFluxArea) + call MPAS_pool_get_array(biogeochemistry, "oceanDissolvedIronFluxArea", oceanDissolvedIronFluxArea) + call MPAS_pool_get_dimension(mesh, "nZBGCTracers", nZBGCTracers) call MPAS_pool_get_dimension(mesh, "maxAlgaeType", maxAlgaeType) call MPAS_pool_get_dimension(mesh, "maxDOCType", maxDOCType) @@ -4882,10 +4820,12 @@ subroutine seaice_icepack_coupling_prep(domain) !----------------------------------------------------------------- ! Define ocean biogeochemical flux variables !----------------------------------------------------------------- - if (config_use_column_biogeochemistry) then + + oceanBioFluxesAll(:) = 0.0_RKIND + + if (config_use_column_biogeochemistry .or. config_use_zaerosols) then totalOceanCarbonFlux(iCell) = 0.0_RKIND - oceanBioFluxesAll(:) = 0.0_RKIND oceanAlgaeFlux(:,iCell) = 0.0_RKIND oceanDOCFlux(:,iCell) = 0.0_RKIND oceanDICFlux(:,iCell) = 0.0_RKIND @@ -4899,6 +4839,7 @@ subroutine seaice_icepack_coupling_prep(domain) oceanDMSPdFlux(iCell) = 0.0_RKIND oceanDMSFlux(iCell) = 0.0_RKIND oceanDustIronFlux(iCell) = 0.0_RKIND + oceanBlackCarbonFlux(iCell) = 0.0_RKIND oceanHumicsFlux(iCell) = 0.0_RKIND do iBioTracers = 1, ciceTracerObject % nBioTracers @@ -4911,6 +4852,7 @@ subroutine seaice_icepack_coupling_prep(domain) do iBioTracers = 1, maxAlgaeType iBioData = iBioData+1 oceanAlgaeFlux(iBioTracers,iCell) = oceanBioFluxesAll(iBioData) + oceanAlgaeFluxArea(iBioTracers,iCell) = oceanBioFluxesAll(iBioData) totalOceanCarbonFlux(iCell) = totalOceanCarbonFlux(iCell) + & oceanAlgaeFlux(iBioTracers,iCell) * ratio_C_to_N(iBioTracers) enddo @@ -4918,11 +4860,13 @@ subroutine seaice_icepack_coupling_prep(domain) ! Nitrate iBioData = iBioData+1 oceanNitrateFlux(iCell) = oceanBioFluxesAll(iBioData) + oceanNitrateFluxArea(iCell) = oceanBioFluxesAll(iBioData) ! Polysaccharids and Lipids do iBioTracers = 1, maxDOCType iBioData = iBioData+1 oceanDOCFlux(iBioTracers,iCell) = oceanBioFluxesAll(iBioData) + oceanDOCFluxArea(iBioTracers,iCell) = oceanBioFluxesAll(iBioData) totalOceanCarbonFlux(iCell) = totalOceanCarbonFlux(iCell) + & oceanDOCFlux(iBioTracers,iCell) enddo @@ -4931,6 +4875,7 @@ subroutine seaice_icepack_coupling_prep(domain) do iBioTracers = 1, maxDICType iBioData = iBioData+1 oceanDICFlux(iBioTracers,iCell) = oceanBioFluxesAll(iBioData) + oceanDICFluxArea(iBioTracers,iCell) = oceanBioFluxesAll(iBioData) totalOceanCarbonFlux(iCell) = totalOceanCarbonFlux(iCell) + & oceanDICFlux(iBioTracers,iCell) enddo @@ -4941,22 +4886,27 @@ subroutine seaice_icepack_coupling_prep(domain) ! Ammonium iBioData = iBioData+1 oceanAmmoniumFlux(iCell) = oceanBioFluxesAll(iBioData) + oceanAmmoniumFluxArea(iCell) = oceanBioFluxesAll(iBioData) ! Silicate iBioData = iBioData+1 oceanSilicateFlux(iCell) = oceanBioFluxesAll(iBioData) + oceanSilicateFluxArea(iCell) = oceanBioFluxesAll(iBioData) ! DMSPp iBioData = iBioData+1 oceanDMSPpFlux(iCell) = oceanBioFluxesAll(iBioData) + oceanDMSPpFluxArea(iCell) = oceanBioFluxesAll(iBioData) ! DMSPd iBioData = iBioData+1 oceanDMSPdFlux(iCell) = oceanBioFluxesAll(iBioData) + oceanDMSPdFluxArea(iCell) = oceanBioFluxesAll(iBioData) ! DMS iBioData = iBioData+1 oceanDMSFlux(iCell) = oceanBioFluxesAll(iBioData) + oceanDMSFluxArea(iCell) = oceanBioFluxesAll(iBioData) ! PON iBioData = iBioData+1 @@ -4965,6 +4915,7 @@ subroutine seaice_icepack_coupling_prep(domain) do iBioTracers = 1, maxDONType iBioData = iBioData+1 oceanDONFlux(iBioTracers,iCell) = oceanBioFluxesAll(iBioData) + oceanDONFluxArea(iBioTracers,iCell) = oceanBioFluxesAll(iBioData) totalOceanCarbonFlux(iCell) = totalOceanCarbonFlux(iCell) + & oceanDONFlux(iBioTracers,iCell) * config_ratio_C_to_N_proteins enddo @@ -4973,30 +4924,38 @@ subroutine seaice_icepack_coupling_prep(domain) do iBioTracers = 1, maxIronType iBioData = iBioData+1 oceanDissolvedIronFlux(iBioTracers,iCell) = oceanBioFluxesAll(iBioData) + oceanDissolvedIronFluxArea(iBioTracers,iCell) = oceanBioFluxesAll(iBioData) enddo ! Particulate Iron do iBioTracers = 1, maxIronType iBioData = iBioData+1 oceanParticulateIronFlux(iBioTracers,iCell) = oceanBioFluxesAll(iBioData) + oceanParticulateIronFluxArea(iBioTracers,iCell) = oceanBioFluxesAll(iBioData) enddo - ! Black Carbon (not saved) - iBioData = iBioData + maxBCType + ! Black Carbon (combined; saved for conservation) + do iBioTracers = 1, maxBCType + iBioData = iBioData + 1 + oceanBlackCarbonFlux(iCell) = oceanBlackCarbonFlux(iCell) + oceanBioFluxesAll(iBioData) + enddo + oceanBlackCarbonFluxArea(iCell) = oceanBlackCarbonFlux(iCell) ! Dust (combined) do iBioTracers = 1, maxDustType iBioData = iBioData+1 oceanDustIronFlux(iCell) = oceanDustIronFlux(iCell) + oceanBioFluxesAll(iBioData) - enddo + enddo + oceanDustIronFluxArea(iCell) = oceanDustIronFlux(iCell) ! Humics iBioData = iBioData+1 oceanHumicsFlux(iCell) = oceanBioFluxesAll(iBioData) + oceanHumicsFluxArea(iCell) = oceanBioFluxesAll(iBioData) totalOceanCarbonFlux(iCell) = totalOceanCarbonFlux(iCell) + & - oceanHumicsFlux(iCell) + oceanHumicsFlux(iCell) - endif ! config_use_column_biogeochemistry + endif ! config_use_column_biogeochemistry .or. config_use_zaerosols enddo ! iCell @@ -5044,7 +5003,8 @@ subroutine seaice_column_scale_fluxes(domain) mesh logical, pointer :: & - config_use_column_biogeochemistry + config_use_column_biogeochemistry, & + config_use_zaerosols real(kind=RKIND), dimension(:), pointer :: & iceAreaCell, & @@ -5075,6 +5035,7 @@ subroutine seaice_column_scale_fluxes(domain) oceanDMSPpFlux, & oceanDMSPdFlux, & oceanHumicsFlux, & + oceanBlackCarbonFlux, & oceanDustIronFlux real(kind=RKIND), dimension(:,:), pointer :: & @@ -5104,6 +5065,7 @@ subroutine seaice_column_scale_fluxes(domain) iBioTracers call MPAS_pool_get_config(domain % configs, "config_use_column_biogeochemistry", config_use_column_biogeochemistry) + call MPAS_pool_get_config(domain % configs, "config_use_zaerosols", config_use_zaerosols) block => domain % blocklist do while (associated(block)) @@ -5156,6 +5118,7 @@ subroutine seaice_column_scale_fluxes(domain) call MPAS_pool_get_array(biogeochemistry, "oceanDMSPdFlux", oceanDMSPdFlux) call MPAS_pool_get_array(biogeochemistry, "oceanHumicsFlux", oceanHumicsFlux) call MPAS_pool_get_array(biogeochemistry, "oceanDustIronFlux", oceanDustIronFlux) + call MPAS_pool_get_array(biogeochemistry, "oceanBlackCarbonFlux", oceanBlackCarbonFlux) call MPAS_pool_get_array(biogeochemistry, "oceanAlgaeFlux", oceanAlgaeFlux) call MPAS_pool_get_array(biogeochemistry, "oceanDOCFlux", oceanDOCFlux) call MPAS_pool_get_array(biogeochemistry, "oceanDICFlux", oceanDICFlux) @@ -5196,6 +5159,11 @@ subroutine seaice_column_scale_fluxes(domain) albedoVisibleDiffuseCell(iCell) = albedoVisibleDiffuseCell(iCell) * iceAreaInverse albedoIRDiffuseCell(iCell) = albedoIRDiffuseCell(iCell) * iceAreaInverse + if (config_use_zaerosols) then + oceanDustIronFlux(iCell) = oceanDustIronFlux(iCell) * iceAreaInverse + oceanBlackCarbonFlux(iCell) = oceanBlackCarbonFlux(iCell) * iceAreaInverse + end if + if (config_use_column_biogeochemistry) then oceanNitrateFlux(iCell) = oceanNitrateFlux(iCell) * iceAreaInverse @@ -5205,7 +5173,6 @@ subroutine seaice_column_scale_fluxes(domain) oceanDMSPdFlux(iCell) = oceanDMSPdFlux(iCell) * iceAreaInverse oceanDMSFlux(iCell) = oceanDMSFlux(iCell) * iceAreaInverse oceanHumicsFlux(iCell) = oceanHumicsFlux(iCell) * iceAreaInverse - oceanDustIronFlux(iCell) = oceanDustIronFlux(iCell) * iceAreaInverse do iBioTracers = 1, maxAlgaeType oceanAlgaeFlux(iBioTracers,iCell) = oceanAlgaeFlux(iBioTracers,iCell) * iceAreaInverse @@ -5248,6 +5215,11 @@ subroutine seaice_column_scale_fluxes(domain) albedoVisibleDiffuseCell(iCell) = 0.0_RKIND albedoIRDiffuseCell(iCell) = 0.0_RKIND + if (config_use_zaerosols) then + oceanDustIronFlux(iCell) = 0.0_RKIND + oceanBlackCarbonFlux(iCell) = 0.0_RKIND + end if + if (config_use_column_biogeochemistry) then oceanNitrateFlux(iCell) = 0.0_RKIND @@ -5257,7 +5229,6 @@ subroutine seaice_column_scale_fluxes(domain) oceanDMSPdFlux(iCell) = 0.0_RKIND oceanDMSFlux(iCell) = 0.0_RKIND oceanHumicsFlux(iCell) = 0.0_RKIND - oceanDustIronFlux(iCell) = 0.0_RKIND oceanAlgaeFlux(:,iCell) = 0.0_RKIND oceanDOCFlux(:,iCell) = 0.0_RKIND oceanDICFlux(:,iCell) = 0.0_RKIND @@ -5524,18 +5495,12 @@ subroutine seaice_icepack_init_trcr(& initialSalinityProfile, & initialMeltingTemperatureProfile, & surfaceTemperature, & - nIceLayers, & - nSnowLayers, & iceEnthalpy, & snowEnthalpy) use icepack_intfc, only: & icepack_init_trcr - integer, intent(in) :: & - nIceLayers, & ! number of ice layers - nSnowLayers ! number of snow layers - real(kind=RKIND), intent(in) :: & airTemperature, & ! air temperature (C) seaFreezingTemperature ! freezing temperature (C) @@ -5556,8 +5521,6 @@ subroutine seaice_icepack_init_trcr(& initialSalinityProfile, & initialMeltingTemperatureProfile, & surfaceTemperature, & - nIceLayers, & - nSnowLayers, & iceEnthalpy, & snowEnthalpy) @@ -5581,21 +5544,11 @@ subroutine seaice_icepack_init_ocean_conc(& oceanNitrateConc, & oceanSilicateConc,& oceanZAerosolConc, & - maxDICType, & - maxDONType, & - maxIronType, & - maxAerosolType, & carbonToNitrogenRatioAlgae, & carbonToNitrogenRatioDON) - use ice_colpkg, only: & - colpkg_init_ocean_conc - - integer, intent(in) :: & - maxDICType, & - maxDONType, & - maxIronType, & - maxAerosolType + use icepack_intfc, only: & + icepack_init_ocean_bio real(kind=RKIND), intent(out):: & oceanAmmoniumConc, & ! ammonium @@ -5614,30 +5567,26 @@ subroutine seaice_icepack_init_ocean_conc(& oceanParticulateIronConc, & ! Particulate Iron oceanZAerosolConc ! BC and dust - real(kind=RKIND), dimension(:), intent(inout), optional :: & + real(kind=RKIND), dimension(:), intent(out), optional :: & carbonToNitrogenRatioAlgae, & ! carbon to nitrogen ratio for algae carbonToNitrogenRatioDON ! nitrogen to carbon ratio for proteins - call colpkg_init_ocean_conc(& - oceanAmmoniumConc, & - oceanDMSPConc, & - oceanDMSConc, & - oceanAlgaeConc, & - oceanDOCConc, & - oceanDICConc, & - oceanDONConc, & - oceanDissolvedIronConc, & - oceanParticulateIronConc, & - oceanHumicsConc, & - oceanNitrateConc, & - oceanSilicateConc,& - oceanZAerosolConc, & - maxDICType, & - maxDONType, & - maxIronType, & - maxAerosolType, & - carbonToNitrogenRatioAlgae, & - carbonToNitrogenRatioDON) + call icepack_init_ocean_bio(& + amm=oceanAmmoniumConc, & + dmsp=oceanDMSPConc, & + dms=oceanDMSConc, & + algalN=oceanAlgaeConc(:), & + doc=oceanDOCConc(:), & + dic=oceanDICConc(:), & + don=oceanDONConc(:), & + fed=oceanDissolvedIronConc(:), & + fep=oceanParticulateIronConc(:), & + hum=oceanHumicsConc, & + nit=oceanNitrateConc, & + sil=oceanSilicateConc,& + zaeros=oceanZAerosolConc(:), & + CToN=carbonToNitrogenRatioAlgae(:), & + CToN_DON=carbonToNitrogenRatioDON(:)) end subroutine seaice_icepack_init_ocean_conc @@ -5731,12 +5680,14 @@ subroutine init_column_tracer_object(domain, tracerObject) nZBGCTracers logical, pointer :: & - config_use_column_biogeochemistry + config_use_column_biogeochemistry, & + config_use_zaerosols call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nCategories", nCategories) call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nZBGCTracers", nZBGCTracers) call MPAS_pool_get_config(domain % configs, "config_use_column_biogeochemistry", config_use_column_biogeochemistry) + call MPAS_pool_get_config(domain % configs, "config_use_zaerosols", config_use_zaerosols) ! get the number of CICE tracers in trcrn call init_column_tracer_object_tracer_number(domain, tracerObject) @@ -5760,7 +5711,7 @@ subroutine init_column_tracer_object(domain, tracerObject) call init_column_tracer_object_ancestor_indices(domain, tracerObject) ! biogeochemistry - if (config_use_column_biogeochemistry) then + if (config_use_column_biogeochemistry .or. config_use_zaerosols) then allocate(tracerObject % index_LayerIndexToDataArray(nZBGCTracers)) allocate(tracerObject % index_LayerIndexToBioIndex(nZBGCTracers)) @@ -5965,7 +5916,7 @@ subroutine init_column_tracer_object_tracer_number(domain, tracerObject) ! biogeochemistry !----------------------------------------------------------------------- - if (config_use_column_biogeochemistry) then + if (config_use_column_biogeochemistry .or. config_use_zaerosols) then ! save tracer number without bio tracers counted tracerObject % nTracersNotBio = tracerObject % nTracers @@ -5982,6 +5933,7 @@ subroutine init_column_tracer_object_tracer_number(domain, tracerObject) ! tracerObject % nTracers = tracerObject % nTracers + nBioLayers ! tracerObject % nBioTracersLayer = tracerObject % nBioTracersLayer + 1 ! endif + nMobileTracers = 0 ! Skeletal Biogeochemistry @@ -9172,7 +9124,6 @@ subroutine init_icepack_package_parameters(domain, tracerObject) call init_icepack_package_tracer_indices(tracerObject) ! set the column parameters - call init_column_package_configs(domain) !echmod - temporary until colpkg_constants are moved call init_icepack_package_configs(domain) end subroutine init_icepack_package_parameters @@ -9591,11 +9542,13 @@ subroutine check_column_package_configs(domain) endif ! check biogeochemistry flags: - if (.not. config_use_column_biogeochemistry .and. (config_use_brine .or. & - config_use_vertical_biochemistry .or. config_use_shortwave_bioabsorption .or. config_use_vertical_tracers .or. & - config_use_skeletal_biochemistry .or. config_use_nitrate .or. config_use_carbon .or. config_use_chlorophyll .or. & - config_use_ammonium .or. config_use_silicate .or. config_use_DMS .or. config_use_nonreactive .or. config_use_humics .or. & - config_use_DON .or. config_use_iron .or. config_use_modal_aerosols .or. config_use_zaerosols)) then + + if (.not. config_use_column_biogeochemistry .and. (config_use_vertical_biochemistry .or. & + config_use_skeletal_biochemistry .or. config_use_nitrate .or. config_use_carbon .or. & + config_use_chlorophyll .or. config_use_ammonium .or. config_use_silicate .or. & + config_use_DMS .or. config_use_nonreactive .or. config_use_humics .or. & + config_use_DON .or. config_use_iron)) then + call mpas_log_write(& "check_column_package_configs: config_use_column_biogeochemistry = false. "//& "All biogeochemistry namelist flags must also be false", & @@ -9618,6 +9571,14 @@ subroutine check_column_package_configs(domain) messageType=MPAS_LOG_CRIT) endif + ! check that brine height is used with either aerosols or bgc + if (config_use_brine .and. & + (.not. config_use_column_biogeochemistry .and. .not. config_use_zaerosols)) then + call mpas_log_write(& + "check_column_package_configs: brine tracer must be used with vertical tracers - config_use_column_biogeochemistry and/or config_use_zaerosols equal to true", & + messageType=MPAS_LOG_CRIT) + endif + ! check that the shortwave scheme and bioabsorption is consistent if (config_use_shortwave_bioabsorption .and. .not. (trim(config_shortwave_type(1:4)) == "dEdd")) then call mpas_log_write(& @@ -9719,7 +9680,7 @@ subroutine init_icepack_package_tracer_flags(domain) tr_pond_in = use_meltponds, & tr_pond_lvl_in = config_use_level_meltponds, & tr_pond_topo_in = config_use_topo_meltponds, & - !tr_fsd_in = , & + !tr_fsd_in = config_use_floe_size_distribution, & tr_aero_in = config_use_aerosols, & !tr_iso_in = , & tr_brine_in = config_use_brine, & @@ -9768,13 +9729,27 @@ subroutine init_icepack_package_tracer_sizes(domain, tracerObject) nIceLayers, & nSnowLayers, & nAerosols, & - nBioLayers + nBioLayers, & + nAlgae, & + nDOC, & + nDIC, & + nDON, & + nParticulateIron, & + nDissolvedIron, & + nzAerosols call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nCategories", nCategories) call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nIceLayers", nIceLayers) call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nSnowLayers", nSnowLayers) call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nBioLayers", nBioLayers) call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nAerosols", nAerosols) + call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nzAerosols", nzAerosols) + call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nAlgae", nAlgae) + call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nDOC", nDOC) + call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nDIC", nDIC) + call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nDON", nDON) + call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nParticulateIron", nParticulateIron) + call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nDissolvedIron", nDissolvedIron) call icepack_init_tracer_sizes(& ncat_in = nCategories, & @@ -9782,17 +9757,17 @@ subroutine init_icepack_package_tracer_sizes(domain, tracerObject) nslyr_in = nSnowLayers, & nblyr_in = nBioLayers, & !nfsd_in = , & - !n_algae_in = , & - !n_DOC_in = , & - n_aero_in = nAerosols, & !n_iso_in = , & - !n_DON_in = , & - !n_DIC_in = , & - !n_fed_in = , & - !n_fep_in = , & - !n_zaero_in = , & + !n_aero_in = nAerosols, & + n_algae_in = nAlgae, & + n_DOC_in = nDOC, & + n_DON_in = nDON, & + n_DIC_in = nDIC, & + n_fed_in = nDissolvedIron, & + n_fep_in = nParticulateIron, & + n_zaero_in = nzAerosols, & ntrcr_in = tracerObject % nTracers, & - !ntrcr_o_in = , & + ntrcr_o_in = tracerObject % nTracersNotBio, & nbtrcr_in = tracerObject % nBioTracers, & nbtrcr_sw_in = tracerObject % nBioTracersShortwave) @@ -9888,203 +9863,84 @@ end subroutine init_icepack_package_tracer_indices !||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ! -! init_column_package_configs +! init_icepack_package_configs ! !> \brief -!> \author Adrian K. Turner, LANL -!> \date 2nd Feburary 2015 +!> \author Adrian K. Turner, Elizabeth Hunke, Darin Comeau, Nicole Jeffery, Andrew Roberts, Erin Thomas, Jon Wolfe, LANL, Anthony Craig, NOAA (cntr), David Bailey, NCAR +!> \date 2022-2023 !> \details !> ! !----------------------------------------------------------------------- - subroutine init_column_package_configs(domain) !colpkg routine - remove - - !use ice_colpkg_shared, only: & - ! ktherm, & - ! conduct, & - ! fbot_xfer_type, & - ! heat_capacity, & - ! calc_Tsfc, & - ! ustar_min, & - ! a_rapid_mode, & - ! Rac_rapid_mode, & - ! aspect_rapid_mode, & - ! dSdt_slow_mode, & - ! phi_c_slow_mode, & - ! phi_i_mushy, & - ! shortwave, & - ! albedo_type, & - ! albicev, & - ! albicei, & - ! albsnowv, & - ! albsnowi, & - ! ahmax, & - ! R_ice, & - ! R_pnd, & - ! R_snw, & - ! dT_mlt, & - ! rsnw_mlt, & - ! kalg, & - ! kstrength, & - ! krdg_partic, & - ! krdg_redist, & - ! mu_rdg, & - ! Cf, & - ! atmbndy, & - ! calc_strair, & - ! formdrag, & - ! highfreq, & - ! natmiter, & - ! oceanmixed_ice, & - ! tfrz_option, & - ! kitd, & - ! kcatbound, & - ! hs0, & - ! frzpnd, & - ! dpscale, & - ! rfracmin, & - ! rfracmax, & - ! pndaspect, & - ! hs1, & - ! hp1 - ! bgc_flux_type, & - ! z_tracers, & - ! scale_bgc, & - ! solve_zbgc, & - ! dEdd_algae, & - ! modal_aero, & - ! skl_bgc, & - ! solve_zsal, & - ! grid_o, & - ! l_sk, & - ! grid_o_t, & - ! initbio_frac, & - ! frazil_scav, & - ! grid_oS, & - ! l_skS, & - ! phi_snow, & - ! ratio_Si2N_diatoms, & - ! ratio_Si2N_sp , & - ! ratio_Si2N_phaeo , & - ! ratio_S2N_diatoms , & - ! ratio_S2N_sp , & - ! ratio_S2N_phaeo , & - ! ratio_Fe2C_diatoms, & - ! ratio_Fe2C_sp , & - ! ratio_Fe2C_phaeo , & - ! ratio_Fe2N_diatoms, & - ! ratio_Fe2N_sp , & - ! ratio_Fe2N_phaeo , & - ! ratio_Fe2DON , & - ! ratio_Fe2DOC_s , & - ! ratio_Fe2DOC_l , & - ! fr_resp , & - ! tau_min , & - ! tau_max , & - ! algal_vel , & - ! R_dFe2dust , & - ! dustFe_sol , & - ! chlabs_diatoms , & - ! chlabs_sp , & - ! chlabs_phaeo , & - ! alpha2max_low_diatoms , & - ! alpha2max_low_sp , & - ! alpha2max_low_phaeo , & - ! beta2max_diatoms , & - ! beta2max_sp , & - ! beta2max_phaeo , & - ! mu_max_diatoms , & - ! mu_max_sp , & - ! mu_max_phaeo , & - ! grow_Tdep_diatoms, & - ! grow_Tdep_sp , & - ! grow_Tdep_phaeo , & - ! fr_graze_diatoms , & - ! fr_graze_sp , & - ! fr_graze_phaeo , & - ! mort_pre_diatoms , & - ! mort_pre_sp , & - ! mort_pre_phaeo , & - ! mort_Tdep_diatoms, & - ! mort_Tdep_sp , & - ! mort_Tdep_phaeo , & - ! k_exude_diatoms , & - ! k_exude_sp , & - ! k_exude_phaeo , & - ! K_Nit_diatoms , & - ! K_Nit_sp , & - ! K_Nit_phaeo , & - ! K_Am_diatoms , & - ! K_Am_sp , & - ! K_Am_phaeo , & - ! K_Sil_diatoms , & - ! K_Sil_sp , & - ! K_Sil_phaeo , & - ! K_Fe_diatoms , & - ! K_Fe_sp , & - ! K_Fe_phaeo , & - ! f_don_protein , & - ! kn_bac_protein , & - ! f_don_Am_protein , & - ! f_doc_s , & - ! f_doc_l , & - ! f_exude_s , & - ! f_exude_l , & - ! k_bac_s , & - ! k_bac_l , & - ! T_max , & - ! fsal , & - ! op_dep_min , & - ! fr_graze_s , & - ! fr_graze_e , & - ! fr_mort2min , & - ! fr_dFe , & - ! k_nitrif , & - ! t_iron_conv , & - ! max_loss , & - ! max_dfe_doc1 , & - ! fr_resp_s , & - ! y_sk_DMS , & - ! t_sk_conv , & - ! t_sk_ox , & - ! algaltype_diatoms , & - ! algaltype_sp , & - ! algaltype_phaeo , & - ! nitratetype , & - ! ammoniumtype , & - ! silicatetype , & - ! dmspptype , & - ! dmspdtype , & - ! humtype , & - ! doctype_s , & - ! doctype_l , & - ! dontype_protein , & - ! fedtype_1 , & - ! feptype_1 , & - ! zaerotype_bc1 , & - ! zaerotype_bc2 , & - ! zaerotype_dust1 , & - ! zaerotype_dust2 , & - ! zaerotype_dust3 , & - ! zaerotype_dust4 , & - ! ratio_C2N_diatoms , & - ! ratio_C2N_sp , & - ! ratio_C2N_phaeo , & - ! ratio_chl2N_diatoms, & - ! ratio_chl2N_sp , & - ! ratio_chl2N_phaeo , & - ! F_abs_chl_diatoms , & - ! F_abs_chl_sp , & - ! F_abs_chl_phaeo , & - ! ratio_C2N_proteins - - use ice_colpkg, only: & - colpkg_init_parameters + subroutine init_icepack_package_configs(domain) + + use icepack_intfc, only: & + icepack_init_parameters, & + icepack_write_parameters, & + icepack_configure, & + icepack_query_parameters ! debugging + + use seaice_constants, only: & + seaicePuny, & ! a small number + seaiceBigNumber, & ! a large number + seaiceSecondsPerDay, & ! number of seconds in 1 day + seaiceDensityIce, & ! density of ice (kg/m^3) + seaiceDensitySnow, & ! density of snow (kg/m^3) + seaiceDensitySeaWater, & ! density of seawater (kg/m^3) + seaiceDensityFreshwater, & ! density of freshwater (kg/m^3) + seaiceFreshIceSpecificHeat, & ! specific heat of fresh ice (J/kg/K) + seaiceWaterVaporSpecificHeat, & ! specific heat of water vapor (J/kg/K) + seaiceAirSpecificHeat, & ! specific heat of air (J/kg/K) + seaiceSeaWaterSpecificHeat, & ! specific heat of ocn (J/kg/K) + seaiceLatentHeatVaporization, & ! latent heat, vaporization freshwater (J/kg) + seaiceZvir, & ! rh2o/rair - 1.0 + seaiceLatentHeatSublimation, & ! latent heat, sublimation freshwater (J/kg) + seaiceLatentHeatMelting, & ! latent heat of melting of fresh ice (J/kg) + seaiceIceSurfaceMeltingTemperature, & ! melting temp. ice top surface (C) + seaiceSnowSurfaceMeltingTemperature, & ! melting temp. snow top surface (C) + seaiceStefanBoltzmann, & ! J m-2 K-4 s-1 + seaiceIceSnowEmissivity, & ! emissivity of snow and ice + seaiceSnowSurfaceScatteringLayer, & ! snow surface scattering layer thickness (m) + seaiceStabilityReferenceHeight, & ! stability reference height (m) + seaiceFreshWaterFreezingPoint, & ! freezing temp of fresh ice (K) + seaiceIceSurfaceRoughness, & ! ice surface roughness (m) + seaiceVonKarmanConstant, & ! Von Karman constant + seaiceOceanAlbedo, & ! Ocean albedo + seaiceReferenceSalinity, & ! ice reference salinity (ppt) + seaiceMaximumSalinity, & ! ice maximum salinity (ppt) + seaiceMeltingTemperatureDepression, & ! melting temperature depression factor (C/ppt) + seaiceFrazilSalinityReduction, & ! bulk salinity reduction of newly formed frazil (ppt) + seaiceFrazilIcePorosity, & ! initial liquid fraction of frazil + seaicePi, & ! pi + seaiceGravity, & ! gravitational acceleration (m/s^2) + seaiceSnowPatchiness, & ! snow patchiness parameter + seaiceIceStrengthConstantHiblerP, & ! P* constant in Hibler strength formulation + seaiceIceStrengthConstantHiblerC, & ! C* constant in Hibler strength formulation + skeletalLayerThickness, & ! skeletal layer thickness + gramsCarbonPerMolCarbon, & ! grams carbon per mol carbon + seaiceSnowMinimumDensity, & ! minimum snow density (kg/m^3) + seaiceBrineDynamicViscosity, & ! dynamic viscosity of brine (kg/m/s) + seaiceFreezingTemperatureConstant, &! constant freezing temp of seawater (C) + seaiceExtinctionCoef, & ! vis extnctn coef in ice, wvlngth<700nm (1/m) + seaiceFreshIceConductivity, & ! thermal conductivity of fresh ice(W/m/deg) + seaiceSnowMinimumThickness, & ! min snow thickness for computing zTsn (m) + seaiceFrazilMinimumThickness, & ! min thickness of new frazil ice + seaiceAlbedoWtVisibleDirect, & ! visible, direct + seaiceAlbedoWtNearIRDirect, & ! near IR, direct + seaiceAlbedoWtVisibleDiffuse, & ! visible, diffuse + seaiceAlbedoWtNearIRDiffuse, & ! near IR, diffuse + seaiceQsatQiceConstant, & ! constant for saturation humidity over ice + seaiceQsatTiceConstant, & ! constant for saturation humidity over ice + seaiceQsatQocnConstant, & ! constant for saturation humidity over ocean + seaiceQsatTocnConstant ! constant for saturation humidity over ocean type(domain_type), intent(inout) :: & domain + type(MPAS_pool_type), pointer :: & + snow + character(len=strKIND), pointer :: & config_thermodynamics_type, & config_heat_conductivity_type, & @@ -10097,13 +9953,17 @@ subroutine init_column_package_configs(domain) !colpkg routine - remove config_itd_conversion_type, & config_category_bounds_type, & config_pond_refreezing_type, & + config_salt_flux_coupling_type, & config_ocean_heat_transfer_type, & + config_frazil_coupling_type, & config_sea_freezing_temperature_type, & config_skeletal_bgc_flux_type, & config_snow_redistribution_scheme logical, pointer :: & + config_use_snicar_ad, & config_calc_surface_temperature, & + config_update_ocean_fluxes, & config_use_form_drag, & config_use_high_frequency_coupling, & config_use_ocean_mixed_layer, & @@ -10113,10 +9973,13 @@ subroutine init_column_package_configs(domain) !colpkg routine - remove config_use_vertical_biochemistry, & config_use_shortwave_bioabsorption, & config_use_skeletal_biochemistry, & - config_use_vertical_zsalinity, & config_use_modal_aerosols, & - config_use_snicar_ad, & - config_use_snow_liquid_ponds + config_use_macromolecules, & + config_do_restart_bgc, & + config_use_snow_liquid_ponds, & + config_use_snow_grain_radius, & + config_use_shortwave_redistribution, & + config_use_iron_solubility_file real(kind=RKIND), pointer :: & config_min_friction_velocity, & @@ -10127,15 +9990,21 @@ subroutine init_column_package_configs(domain) !colpkg routine - remove config_rapid_mode_aspect_ratio, & config_slow_mode_drainage_strength, & config_slow_mode_critical_porosity, & + config_macro_drainage_timescale, & config_congelation_ice_porosity, & +! config_frazil_ice_porosity, & +! config_frazil_salinity_reduction, & config_visible_ice_albedo, & config_infrared_ice_albedo, & config_visible_snow_albedo, & config_infrared_snow_albedo, & config_variable_albedo_thickness_limit, & +! config_snow_surface_scattering_layer_depth, & config_ice_shortwave_tuning_parameter, & config_pond_shortwave_tuning_parameter, & config_snow_shortwave_tuning_parameter, & + config_shortwave_redistribution_fraction, & + config_shortwave_redistribution_threshold, & config_temp_change_snow_grain_radius_change, & config_max_melting_snow_grain_radius, & config_algae_absorption_coefficient, & @@ -10151,10 +10020,6 @@ subroutine init_column_package_configs(domain) !colpkg routine - remove config_biogrid_bottom_molecular_sublayer, & config_bio_gravity_drainage_length_scale, & config_biogrid_top_molecular_sublayer, & - config_new_ice_fraction_biotracer, & - config_fraction_biotracer_in_frazil, & - config_zsalinity_molecular_sublayer, & - config_zsalinity_gravity_drainage_scale, & config_snow_porosity_at_ice_surface, & config_ratio_Si_to_N_diatoms, & config_ratio_Si_to_N_small_plankton, & @@ -10172,8 +10037,6 @@ subroutine init_column_package_configs(domain) !colpkg routine - remove config_ratio_Fe_to_DOC_saccharids, & config_ratio_Fe_to_DOC_lipids, & config_respiration_fraction_of_growth, & - config_rapid_mobile_to_stationary_time, & - config_long_mobile_to_stationary_time, & config_algal_maximum_velocity, & config_ratio_Fe_to_dust, & config_solubility_of_Fe_in_dust, & @@ -10240,52 +10103,50 @@ subroutine init_column_package_configs(domain) !colpkg routine - remove config_DMSP_to_DMS_conversion_fraction, & config_DMSP_to_DMS_conversion_time, & config_DMS_oxidation_time, & - config_mobility_type_diatoms, & - config_mobility_type_small_plankton, & - config_mobility_type_phaeocystis, & - config_mobility_type_nitrate, & - config_mobility_type_ammonium, & - config_mobility_type_silicate, & - config_mobility_type_DMSPp, & - config_mobility_type_DMSPd, & - config_mobility_type_humics, & - config_mobility_type_saccharids, & - config_mobility_type_lipids, & - config_mobility_type_inorganic_carbon, & - config_mobility_type_proteins, & - config_mobility_type_dissolved_iron, & - config_mobility_type_particulate_iron, & - config_mobility_type_black_carbon1, & - config_mobility_type_black_carbon2, & - config_mobility_type_dust1, & - config_mobility_type_dust2, & - config_mobility_type_dust3, & - config_mobility_type_dust4, & - config_ratio_C_to_N_diatoms, & - config_ratio_C_to_N_small_plankton, & - config_ratio_C_to_N_phaeocystis, & - config_ratio_chla_to_N_diatoms, & - config_ratio_chla_to_N_small_plankton, & - config_ratio_chla_to_N_phaeocystis, & - config_scales_absorption_diatoms, & - config_scales_absorption_small_plankton, & - config_scales_absorption_phaeocystis, & - config_ratio_C_to_N_proteins, & config_fallen_snow_radius, & config_new_snow_density, & config_max_snow_density, & config_minimum_wind_compaction, & config_wind_compaction_factor, & config_snow_redistribution_factor, & - config_max_dry_snow_radius + config_max_dry_snow_radius, & + config_floediam, & + config_floeshape + + real(kind=RKIND), dimension(:,:,:), pointer :: & + snowEmpiricalGrowthParameterTau, & + snowEmpiricalGrowthParameterKappa, & + snowPropertyRate integer, pointer :: & - config_boundary_layer_iteration_number + config_boundary_layer_iteration_number, & + nGrainAgingTemperature, & + nGrainAgingTempGradient, & + nGrainAgingSnowDensity + + integer :: & + config_thermodynamics_type_int, & + config_ice_strength_formulation_int, & + config_ridging_participation_function_int, & + config_ridging_redistribution_function_int, & + config_itd_conversion_type_int, & + config_category_bounds_type_int + + character(len=strKIND) :: tmp_config_shortwave_type + character(len=strKIND) :: tmp_config_snw_ssp_table + character(len=strKIND) :: snw_aging_table = 'snicar' + + ! debugging + integer :: itmp1, itmp2 + real(kind=RKIND) :: rtmp1, rtmp2 + character(len=strKIND) :: ctmp1, ctmp2 call MPAS_pool_get_config(domain % configs, "config_thermodynamics_type", config_thermodynamics_type) call MPAS_pool_get_config(domain % configs, "config_heat_conductivity_type", config_heat_conductivity_type) call MPAS_pool_get_config(domain % configs, "config_ocean_heat_transfer_type", config_ocean_heat_transfer_type) call MPAS_pool_get_config(domain % configs, "config_calc_surface_temperature", config_calc_surface_temperature) + call MPAS_pool_get_config(domain % configs, "config_update_ocean_fluxes", config_update_ocean_fluxes) + call MPAS_pool_get_config(domain % configs, "config_frazil_coupling_type", config_frazil_coupling_type) call MPAS_pool_get_config(domain % configs, "config_min_friction_velocity", config_min_friction_velocity) call MPAS_pool_get_config(domain % configs, "config_ice_ocean_drag_coefficient", config_ice_ocean_drag_coefficient) call MPAS_pool_get_config(domain % configs, "config_snow_thermal_conductivity", config_snow_thermal_conductivity) @@ -10294,7 +10155,10 @@ subroutine init_column_package_configs(domain) !colpkg routine - remove call MPAS_pool_get_config(domain % configs, "config_rapid_mode_aspect_ratio", config_rapid_mode_aspect_ratio) call MPAS_pool_get_config(domain % configs, "config_slow_mode_drainage_strength", config_slow_mode_drainage_strength) call MPAS_pool_get_config(domain % configs, "config_slow_mode_critical_porosity", config_slow_mode_critical_porosity) + call MPAS_pool_get_config(domain % configs, "config_macro_drainage_timescale", config_macro_drainage_timescale) call MPAS_pool_get_config(domain % configs, "config_congelation_ice_porosity", config_congelation_ice_porosity) +! call MPAS_pool_get_config(domain % configs, "config_frazil_ice_porosity", config_frazil_ice_porosity) +! call MPAS_pool_get_config(domain % configs, "config_frazil_salinity_reduction", config_frazil_salinity_reduction) call MPAS_pool_get_config(domain % configs, "config_shortwave_type", config_shortwave_type) call MPAS_pool_get_config(domain % configs, "config_use_snicar_ad", config_use_snicar_ad) call MPAS_pool_get_config(domain % configs, "config_albedo_type", config_albedo_type) @@ -10303,9 +10167,13 @@ subroutine init_column_package_configs(domain) !colpkg routine - remove call MPAS_pool_get_config(domain % configs, "config_visible_snow_albedo", config_visible_snow_albedo) call MPAS_pool_get_config(domain % configs, "config_infrared_snow_albedo", config_infrared_snow_albedo) call MPAS_pool_get_config(domain % configs, "config_variable_albedo_thickness_limit", config_variable_albedo_thickness_limit) +! call MPAS_pool_get_config(domain % configs, "config_snow_surface_scattering_layer_depth", config_snow_surface_scattering_layer_depth) call MPAS_pool_get_config(domain % configs, "config_ice_shortwave_tuning_parameter", config_ice_shortwave_tuning_parameter) call MPAS_pool_get_config(domain % configs, "config_pond_shortwave_tuning_parameter", config_pond_shortwave_tuning_parameter) call MPAS_pool_get_config(domain % configs, "config_snow_shortwave_tuning_parameter", config_snow_shortwave_tuning_parameter) + call MPAS_pool_get_config(domain % configs, "config_use_shortwave_redistribution", config_use_shortwave_redistribution) + call MPAS_pool_get_config(domain % configs, "config_shortwave_redistribution_fraction", config_shortwave_redistribution_fraction) + call MPAS_pool_get_config(domain % configs, "config_shortwave_redistribution_threshold", config_shortwave_redistribution_threshold) call MPAS_pool_get_config(domain % configs, "config_temp_change_snow_grain_radius_change", & config_temp_change_snow_grain_radius_change) call MPAS_pool_get_config(domain % configs, "config_max_melting_snow_grain_radius", config_max_melting_snow_grain_radius) @@ -10326,6 +10194,7 @@ subroutine init_column_package_configs(domain) !colpkg routine - remove call MPAS_pool_get_config(domain % configs, "config_category_bounds_type", config_category_bounds_type) call MPAS_pool_get_config(domain % configs, "config_snow_to_ice_transition_depth", config_snow_to_ice_transition_depth) call MPAS_pool_get_config(domain % configs, "config_pond_refreezing_type", config_pond_refreezing_type) + call MPAS_pool_get_config(domain % configs, "config_salt_flux_coupling_type", config_salt_flux_coupling_type) call MPAS_pool_get_config(domain % configs, "config_pond_flushing_factor", config_pond_flushing_factor) call MPAS_pool_get_config(domain % configs, "config_min_meltwater_retained_fraction", config_min_meltwater_retained_fraction) call MPAS_pool_get_config(domain % configs, "config_max_meltwater_retained_fraction", config_max_meltwater_retained_fraction) @@ -10339,17 +10208,15 @@ subroutine init_column_package_configs(domain) !colpkg routine - remove call MPAS_pool_get_config(domain % configs, "config_use_vertical_biochemistry", config_use_vertical_biochemistry) call MPAS_pool_get_config(domain % configs, "config_use_shortwave_bioabsorption", config_use_shortwave_bioabsorption) call MPAS_pool_get_config(domain % configs, "config_use_modal_aerosols", config_use_modal_aerosols) + call MPAS_pool_get_config(domain % configs, "config_use_macromolecules", config_use_macromolecules) + call MPAS_pool_get_config(domain % configs, "config_use_iron_solubility_file", config_use_iron_solubility_file) + call MPAS_pool_get_config(domain % configs, "config_do_restart_bgc", config_do_restart_bgc) call MPAS_pool_get_config(domain % configs, "config_use_skeletal_biochemistry", config_use_skeletal_biochemistry) - call MPAS_pool_get_config(domain % configs, "config_use_vertical_zsalinity", config_use_vertical_zsalinity) call MPAS_pool_get_config(domain % configs, "config_biogrid_bottom_molecular_sublayer", & config_biogrid_bottom_molecular_sublayer) call MPAS_pool_get_config(domain % configs, "config_bio_gravity_drainage_length_scale", & config_bio_gravity_drainage_length_scale) call MPAS_pool_get_config(domain % configs, "config_biogrid_top_molecular_sublayer", config_biogrid_top_molecular_sublayer) - call MPAS_pool_get_config(domain % configs, "config_zsalinity_gravity_drainage_scale", config_zsalinity_gravity_drainage_scale) - call MPAS_pool_get_config(domain % configs, "config_new_ice_fraction_biotracer", config_new_ice_fraction_biotracer) - call MPAS_pool_get_config(domain % configs, "config_fraction_biotracer_in_frazil", config_fraction_biotracer_in_frazil) - call MPAS_pool_get_config(domain % configs, "config_zsalinity_molecular_sublayer", config_zsalinity_molecular_sublayer) call MPAS_pool_get_config(domain % configs, "config_snow_porosity_at_ice_surface", config_snow_porosity_at_ice_surface) call MPAS_pool_get_config(domain % configs, "config_ratio_Si_to_N_diatoms", config_ratio_Si_to_N_diatoms) call MPAS_pool_get_config(domain % configs, "config_ratio_Si_to_N_small_plankton", config_ratio_Si_to_N_small_plankton) @@ -10367,8 +10234,6 @@ subroutine init_column_package_configs(domain) !colpkg routine - remove call MPAS_pool_get_config(domain % configs, "config_ratio_Fe_to_DOC_saccharids", config_ratio_Fe_to_DOC_saccharids) call MPAS_pool_get_config(domain % configs, "config_ratio_Fe_to_DOC_lipids", config_ratio_Fe_to_DOC_lipids) call MPAS_pool_get_config(domain % configs, "config_respiration_fraction_of_growth", config_respiration_fraction_of_growth) - call MPAS_pool_get_config(domain % configs, "config_rapid_mobile_to_stationary_time", config_rapid_mobile_to_stationary_time) - call MPAS_pool_get_config(domain % configs, "config_long_mobile_to_stationary_time", config_long_mobile_to_stationary_time) call MPAS_pool_get_config(domain % configs, "config_algal_maximum_velocity", config_algal_maximum_velocity) call MPAS_pool_get_config(domain % configs, "config_ratio_Fe_to_dust", config_ratio_Fe_to_dust) call MPAS_pool_get_config(domain % configs, "config_solubility_of_Fe_in_dust", config_solubility_of_Fe_in_dust) @@ -10444,1555 +10309,6 @@ subroutine init_column_package_configs(domain) !colpkg routine - remove call MPAS_pool_get_config(domain % configs, "config_DMSP_to_DMS_conversion_fraction", config_DMSP_to_DMS_conversion_fraction) call MPAS_pool_get_config(domain % configs, "config_DMSP_to_DMS_conversion_time", config_DMSP_to_DMS_conversion_time) call MPAS_pool_get_config(domain % configs, "config_DMS_oxidation_time", config_DMS_oxidation_time) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_diatoms", config_mobility_type_diatoms) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_small_plankton", config_mobility_type_small_plankton) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_phaeocystis", config_mobility_type_phaeocystis) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_nitrate", config_mobility_type_nitrate) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_ammonium", config_mobility_type_ammonium) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_silicate", config_mobility_type_silicate) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_DMSPp", config_mobility_type_DMSPp) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_DMSPd", config_mobility_type_DMSPd) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_humics", config_mobility_type_humics) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_saccharids", config_mobility_type_saccharids) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_lipids", config_mobility_type_lipids) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_inorganic_carbon", config_mobility_type_inorganic_carbon) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_proteins", config_mobility_type_proteins) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_dissolved_iron", config_mobility_type_dissolved_iron) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_particulate_iron", config_mobility_type_particulate_iron) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_black_carbon1", config_mobility_type_black_carbon1) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_black_carbon2", config_mobility_type_black_carbon2) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_dust1", config_mobility_type_dust1) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_dust2", config_mobility_type_dust2) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_dust3", config_mobility_type_dust3) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_dust4", config_mobility_type_dust4) - call MPAS_pool_get_config(domain % configs, "config_ratio_C_to_N_diatoms", config_ratio_C_to_N_diatoms) - call MPAS_pool_get_config(domain % configs, "config_ratio_C_to_N_small_plankton", config_ratio_C_to_N_small_plankton) - call MPAS_pool_get_config(domain % configs, "config_ratio_C_to_N_phaeocystis", config_ratio_C_to_N_phaeocystis) - call MPAS_pool_get_config(domain % configs, "config_ratio_chla_to_N_diatoms", config_ratio_chla_to_N_diatoms) - call MPAS_pool_get_config(domain % configs, "config_ratio_chla_to_N_small_plankton", config_ratio_chla_to_N_small_plankton) - call MPAS_pool_get_config(domain % configs, "config_ratio_chla_to_N_phaeocystis", config_ratio_chla_to_N_phaeocystis) - call MPAS_pool_get_config(domain % configs, "config_scales_absorption_diatoms", config_scales_absorption_diatoms) - call MPAS_pool_get_config(domain % configs, "config_scales_absorption_small_plankton", config_scales_absorption_small_plankton) - call MPAS_pool_get_config(domain % configs, "config_scales_absorption_phaeocystis", config_scales_absorption_phaeocystis) - call MPAS_pool_get_config(domain % configs, "config_ratio_C_to_N_proteins", config_ratio_C_to_N_proteins) - call MPAS_pool_get_config(domain % configs, "config_snow_redistribution_scheme", config_snow_redistribution_scheme) - call MPAS_pool_get_config(domain % configs, "config_fallen_snow_radius", config_fallen_snow_radius) - call MPAS_pool_get_config(domain % configs, "config_use_snow_liquid_ponds", config_use_snow_liquid_ponds) - call MPAS_pool_get_config(domain % configs, "config_new_snow_density", config_new_snow_density) - call MPAS_pool_get_config(domain % configs, "config_max_snow_density", config_max_snow_density) - call MPAS_pool_get_config(domain % configs, "config_minimum_wind_compaction", config_minimum_wind_compaction) - call MPAS_pool_get_config(domain % configs, "config_wind_compaction_factor", config_wind_compaction_factor) - call MPAS_pool_get_config(domain % configs, "config_snow_redistribution_factor", config_snow_redistribution_factor) - call MPAS_pool_get_config(domain % configs, "config_max_dry_snow_radius", config_max_dry_snow_radius) - - call colpkg_init_parameters(& - config_cice_int("config_thermodynamics_type", config_thermodynamics_type), & - config_heat_conductivity_type, & - config_ocean_heat_transfer_type, & - config_calc_surface_temperature, & - config_min_friction_velocity, & - config_ice_ocean_drag_coefficient, & - config_snow_thermal_conductivity, & - config_rapid_mode_channel_radius, & - config_rapid_model_critical_Ra, & - config_rapid_mode_aspect_ratio, & - config_slow_mode_drainage_strength, & - config_slow_mode_critical_porosity, & - config_congelation_ice_porosity, & - config_shortwave_type, & - config_use_snicar_ad, & - config_albedo_type, & - config_visible_ice_albedo, & - config_infrared_ice_albedo, & - config_visible_snow_albedo, & - config_infrared_snow_albedo, & - config_variable_albedo_thickness_limit, & - config_ice_shortwave_tuning_parameter, & - config_pond_shortwave_tuning_parameter, & - config_snow_shortwave_tuning_parameter, & - config_temp_change_snow_grain_radius_change, & - config_max_melting_snow_grain_radius, & - config_algae_absorption_coefficient, & - config_cice_int("config_ice_strength_formulation", config_ice_strength_formulation), & - config_cice_int("config_ridging_participation_function", config_ridging_participation_function), & - config_cice_int("config_ridging_redistribution_function", config_ridging_redistribution_function), & - config_ridging_efolding_scale, & - config_ratio_ridging_work_to_PE, & - config_atmos_boundary_method, & - config_calc_surface_stresses, & - config_use_form_drag, & - config_use_high_frequency_coupling, & - config_boundary_layer_iteration_number, & - config_use_ocean_mixed_layer, & - config_sea_freezing_temperature_type, & - config_cice_int("config_itd_conversion_type", config_itd_conversion_type), & - config_cice_int("config_category_bounds_type", config_category_bounds_type), & - config_snow_to_ice_transition_depth, & - config_pond_refreezing_type, & - config_pond_flushing_factor, & - config_min_meltwater_retained_fraction, & - config_max_meltwater_retained_fraction, & - config_pond_depth_to_fraction_ratio, & - config_snow_on_pond_ice_tapering_parameter, & - config_critical_pond_ice_thickness, & - config_skeletal_bgc_flux_type, & - config_use_vertical_tracers, & - config_scale_initial_vertical_bgc, & - config_use_vertical_biochemistry, & - config_use_shortwave_bioabsorption, & - config_use_modal_aerosols, & - config_use_skeletal_biochemistry, & - config_use_vertical_zsalinity, & - config_biogrid_bottom_molecular_sublayer, & - config_bio_gravity_drainage_length_scale, & - config_biogrid_top_molecular_sublayer, & - config_new_ice_fraction_biotracer, & - config_fraction_biotracer_in_frazil, & - config_zsalinity_molecular_sublayer, & - config_zsalinity_gravity_drainage_scale, & - config_snow_porosity_at_ice_surface, & - config_ratio_Si_to_N_diatoms, & - config_ratio_Si_to_N_small_plankton, & - config_ratio_Si_to_N_phaeocystis, & - config_ratio_S_to_N_diatoms, & - config_ratio_S_to_N_small_plankton, & - config_ratio_S_to_N_phaeocystis, & - config_ratio_Fe_to_C_diatoms, & - config_ratio_Fe_to_C_small_plankton, & - config_ratio_Fe_to_C_phaeocystis, & - config_ratio_Fe_to_N_diatoms, & - config_ratio_Fe_to_N_small_plankton, & - config_ratio_Fe_to_N_phaeocystis, & - config_ratio_Fe_to_DON, & - config_ratio_Fe_to_DOC_saccharids, & - config_ratio_Fe_to_DOC_lipids, & - config_respiration_fraction_of_growth, & - config_rapid_mobile_to_stationary_time, & - config_long_mobile_to_stationary_time, & - config_algal_maximum_velocity, & - config_ratio_Fe_to_dust, & - config_solubility_of_Fe_in_dust, & - config_chla_absorptivity_of_diatoms, & - config_chla_absorptivity_of_small_plankton, & - config_chla_absorptivity_of_phaeocystis, & - config_light_attenuation_diatoms, & - config_light_attenuation_small_plankton, & - config_light_attenuation_phaeocystis, & - config_light_inhibition_diatoms, & - config_light_inhibition_small_plankton, & - config_light_inhibition_phaeocystis, & - config_maximum_growth_rate_diatoms, & - config_maximum_growth_rate_small_plankton, & - config_maximum_growth_rate_phaeocystis, & - config_temperature_growth_diatoms, & - config_temperature_growth_small_plankton, & - config_temperature_growth_phaeocystis, & - config_grazed_fraction_diatoms, & - config_grazed_fraction_small_plankton, & - config_grazed_fraction_phaeocystis, & - config_mortality_diatoms, & - config_mortality_small_plankton, & - config_mortality_phaeocystis, & - config_temperature_mortality_diatoms, & - config_temperature_mortality_small_plankton, & - config_temperature_mortality_phaeocystis, & - config_exudation_diatoms, & - config_exudation_small_plankton, & - config_exudation_phaeocystis, & - config_nitrate_saturation_diatoms, & - config_nitrate_saturation_small_plankton, & - config_nitrate_saturation_phaeocystis, & - config_ammonium_saturation_diatoms, & - config_ammonium_saturation_small_plankton, & - config_ammonium_saturation_phaeocystis, & - config_silicate_saturation_diatoms, & - config_silicate_saturation_small_plankton, & - config_silicate_saturation_phaeocystis, & - config_iron_saturation_diatoms, & - config_iron_saturation_small_plankton, & - config_iron_saturation_phaeocystis, & - config_fraction_spilled_to_DON, & - config_degredation_of_DON, & - config_fraction_DON_ammonium, & - config_fraction_loss_to_saccharids, & - config_fraction_loss_to_lipids, & - config_fraction_exudation_to_saccharids, & - config_fraction_exudation_to_lipids, & - config_remineralization_saccharids, & - config_remineralization_lipids, & - config_maximum_brine_temperature, & - config_salinity_dependence_of_growth, & - config_minimum_optical_depth, & - config_slopped_grazing_fraction, & - config_excreted_fraction, & - config_fraction_mortality_to_ammonium, & - config_fraction_iron_remineralized, & - config_nitrification_rate, & - config_desorption_loss_particulate_iron, & - config_maximum_loss_fraction, & - config_maximum_ratio_iron_to_saccharids, & - config_respiration_loss_to_DMSPd, & - config_DMSP_to_DMS_conversion_fraction, & - config_DMSP_to_DMS_conversion_time, & - config_DMS_oxidation_time, & - config_mobility_type_diatoms, & - config_mobility_type_small_plankton, & - config_mobility_type_phaeocystis, & - config_mobility_type_nitrate, & - config_mobility_type_ammonium, & - config_mobility_type_silicate, & - config_mobility_type_DMSPp, & - config_mobility_type_DMSPd, & - config_mobility_type_humics, & - config_mobility_type_saccharids, & - config_mobility_type_lipids, & - config_mobility_type_inorganic_carbon, & - config_mobility_type_proteins, & - config_mobility_type_dissolved_iron, & - config_mobility_type_particulate_iron, & - config_mobility_type_black_carbon1, & - config_mobility_type_black_carbon2, & - config_mobility_type_dust1, & - config_mobility_type_dust2, & - config_mobility_type_dust3, & - config_mobility_type_dust4, & - config_ratio_C_to_N_diatoms, & - config_ratio_C_to_N_small_plankton, & - config_ratio_C_to_N_phaeocystis, & - config_ratio_chla_to_N_diatoms, & - config_ratio_chla_to_N_small_plankton, & - config_ratio_chla_to_N_phaeocystis, & - config_scales_absorption_diatoms, & - config_scales_absorption_small_plankton, & - config_scales_absorption_phaeocystis, & - config_ratio_C_to_N_proteins, & - config_snow_redistribution_scheme, & - config_use_snow_liquid_ponds, & - config_fallen_snow_radius, & - config_max_dry_snow_radius, & - config_new_snow_density, & - config_max_snow_density, & - config_minimum_wind_compaction, & - config_wind_compaction_factor, & - config_snow_redistribution_factor) - - !----------------------------------------------------------------------- - ! Parameters for thermodynamics - !----------------------------------------------------------------------- - - ! ktherm: - ! type of thermodynamics - ! 1 = Bitz and Lipscomb 1999 - ! 2 = mushy layer theory - !ktherm = config_cice_int("config_thermodynamics_type", config_thermodynamics_type) - - ! conduct: - ! 'MU71' or 'bubbly' - !conduct = config_heat_conductivity_type - - ! calc_Tsfc: - ! if true, calculate surface temperature - ! if false, Tsfc is computed elsewhere and - ! atmos-ice fluxes are provided to CICE - !calc_Tsfc = config_calc_surface_temperature - - ! ustar_min: - ! minimum friction velocity for ice-ocean heat flux - !ustar_min = config_min_friction_velocity - - ! mushy thermodynamics: - - ! a_rapid_mode: - ! channel radius for rapid drainage mode (m) - !a_rapid_mode = config_rapid_mode_channel_radius - - ! Rac_rapid_mode: - ! critical rayleigh number for rapid drainage mode - !Rac_rapid_mode = config_rapid_model_critical_Ra - - ! aspect_rapid_mode: - ! aspect ratio for rapid drainage mode (larger=wider) - !aspect_rapid_mode = config_rapid_mode_aspect_ratio - - ! dSdt_slow_mode: - ! slow mode drainage strength (m s-1 K-1) - !dSdt_slow_mode = config_slow_mode_drainage_strength - - ! phi_c_slow_mode: - ! liquid fraction porosity cutoff for slow mode - !phi_c_slow_mode = config_slow_mode_critical_porosity - - ! phi_i_mushy: - ! liquid fraction of congelation ice - !phi_i_mushy = config_congelation_ice_porosity - - !----------------------------------------------------------------------- - ! Parameters for radiation - !----------------------------------------------------------------------- - - ! shortwave: - ! shortwave method, 'default' ('ccsm3') or 'dEdd' - !shortwave = config_shortwave_type - - ! albedo_type: - ! albedo parameterization, 'default' ('ccsm3') or 'constant' - ! shortwave='dEdd' overrides this parameter - !albedo_type = config_albedo_type - - ! baseline albedos for ccsm3 shortwave, set in namelist - - ! albicev: - ! visible ice albedo for h > ahmax - !albicev = config_visible_ice_albedo - - ! albicei: - ! near-ir ice albedo for h > ahmax - !albicei = config_infrared_ice_albedo - - ! albsnowv: - ! cold snow albedo, visible - !albsnowv = config_visible_snow_albedo - - ! albsnowi: - ! cold snow albedo, near IR - !albsnowi = config_infrared_snow_albedo - - ! ahmax: - ! thickness above which ice albedo is constant (m) - !ahmax = config_variable_albedo_thickness_limit - - ! dEdd tuning parameters, set in namelist - - ! R_ice: - ! sea ice tuning parameter; +1 > 1sig increase in albedo - !R_ice = config_ice_shortwave_tuning_parameter - - ! R_pnd: - ! ponded ice tuning parameter; +1 > 1sig increase in albedo - !R_pnd = config_pond_shortwave_tuning_parameter - - ! R_snw: - ! snow tuning parameter; +1 > ~.01 change in broadband albedo - !R_snw = config_snow_shortwave_tuning_parameter - - ! dT_mlt: - ! change in temp for non-melt to melt snow grain radius change (C) - !dT_mlt = config_temp_change_snow_grain_radius_change - - ! rsnw_mlt: - ! maximum melting snow grain radius (10^-6 m) - !rsnw_mlt = config_max_melting_snow_grain_radius - - ! kalg: - ! algae absorption coefficient for 0.5 m thick layer - !kalg = config_algae_absorption_coefficient - - !----------------------------------------------------------------------- - ! Parameters for ridging and strength - !----------------------------------------------------------------------- - - ! kstrength: - ! 0 for simple Hibler (1979) formulation - ! 1 for Rothrock (1975) pressure formulation - !kstrength = config_cice_int("config_ice_strength_formulation", config_ice_strength_formulation) - - ! krdg_partic: - ! 0 for Thorndike et al. (1975) formulation - ! 1 for exponential participation function - !krdg_partic = config_cice_int("config_ridging_participation_function", config_ridging_participation_function) - - ! krdg_redist: - ! 0 for Hibler (1980) formulation - ! 1 for exponential redistribution function - !krdg_redist = config_cice_int("config_ridging_redistribution_function", config_ridging_redistribution_function) - - ! mu_rdg: - ! gives e-folding scale of ridged ice (m^.5) - ! (krdg_redist = 1) - !mu_rdg = config_ridging_efolding_scale - - ! Cf - ! ratio of ridging work to PE change in ridging (kstrength = 1) - !Cf = config_ratio_ridging_work_to_PE - - !----------------------------------------------------------------------- - ! Parameters for atmosphere - !----------------------------------------------------------------------- - - ! atmbndy: - ! atmo boundary method, 'default' ('ccsm3') or 'constant' - !atmbndy = config_atmos_boundary_method - - ! calc_strair: - ! if true, calculate wind stress components - !calc_strair = config_calc_surface_stresses - - ! formdrag: - ! if true, calculate form drag - !formdrag = config_use_form_drag - - ! highfreq: - ! if true, use high frequency coupling - !highfreq = config_use_high_frequency_coupling - - ! natmiter: - ! number of iterations for boundary layer calculations - !natmiter = config_boundary_layer_iteration_number - - !----------------------------------------------------------------------- - ! Parameters for ocean - !----------------------------------------------------------------------- - - ! oceanmixed_ice: - ! if true, use ocean mixed layer - !oceanmixed_ice = config_use_ocean_mixed_layer - - ! fbot_xfer_type: - ! transfer coefficient type for ice-ocean heat flux - !fbot_xfer_type = config_ocean_heat_transfer_type - - ! tfrz_option: - ! form of ocean freezing temperature - ! 'minus1p8' = -1.8 C - ! 'linear_salt' = -depressT * sss - ! 'mushy' conforms with ktherm=2 - !tfrz_option = config_sea_freezing_temperature_type - - !----------------------------------------------------------------------- - ! Parameters for the ice thickness distribution - !----------------------------------------------------------------------- - - ! kitd: - ! type of itd conversions - ! 0 = delta function - ! 1 = linear remap - !kitd = config_cice_int("config_itd_conversion_type", config_itd_conversion_type) - - ! kcatbound: - ! 0 = old category boundary formula - ! 1 = new formula giving round numbers - ! 2 = WMO standard - ! 3 = asymptotic formula - !kcatbound = config_cice_int("config_category_bounds_type", config_category_bounds_type) - - !----------------------------------------------------------------------- - ! Parameters for melt ponds - !----------------------------------------------------------------------- - - ! hs0: - ! snow depth for transition to bare sea ice (m) - !hs0 = config_snow_to_ice_transition_depth - - ! level-ice ponds - - ! frzpnd: - ! pond refreezing parameterization - !frzpnd = config_pond_refreezing_type - - ! dpscale: - ! alters e-folding time scale for flushing with BL99 thermodynamics - !dpscale = config_pond_flushing_factor - - ! rfracmin: - ! minimum retained fraction of meltwater - !rfracmin = config_min_meltwater_retained_fraction - - ! rfracmax: - ! maximum retained fraction of meltwater - !rfracmax = config_max_meltwater_retained_fraction - - ! pndaspect: - ! ratio of pond depth to pond fraction - !pndaspect = config_pond_depth_to_fraction_ratio - - ! hs1: - ! tapering parameter for snow on pond ice - !hs1 = config_snow_on_pond_ice_tapering_parameter - - ! topo ponds - - ! hp1 - ! critical parameter for pond ice thickness - !hp1 = config_critical_pond_ice_thickness - - !----------------------------------------------------------------------- - ! Parameters for biogeochemistry - !----------------------------------------------------------------------- - - ! bgc_flux_type: - ! bgc_flux_type = config_skeletal_bgc_flux_type - - ! z_tracers: - ! if .true., bgc or aerosol tracers are vertically resolved - !z_tracers = config_use_vertical_tracers - - ! scale_bgc: - ! if .true., initialize bgc tracers proportionally with salinity - !scale_bgc = config_scale_initial_vertical_bgc - - ! solve_zbgc: - ! if .true., solve vertical biochemistry portion of code - !solve_zbgc = config_use_vertical_biochemistry - - ! dEdd_algae: - ! if .true., algal absorption of Shortwave is computed in the - !dEdd_algae = config_use_shortwave_bioabsorption - - ! skl_bgc: - ! if true, solve skeletal biochemistry - !skl_bgc = config_use_skeletal_biochemistry - -! zsalinity has been deprecated -! ! solve_zsal: -! ! if true, update salinity profile from solve_S_dt -! !solve_zsal = config_use_vertical_zsalinity - - ! modal_aero: - ! if true, use modal aerosal optical properties - ! only for use with tr_aero or tr_zaero - !modal_aero = config_use_shortwave_bioabsorption - - ! grid_o: - ! for bottom flux - !grid_o = config_biogrid_bottom_molecular_sublayer - - ! l_sk: - ! characteristic diffusive scale (zsalinity) (m) - !l_sk =config_bio_gravity_drainage_length_scale - - ! grid_o_t: - ! top grid point length scale - !grid_o_t = config_biogrid_top_molecular_sublayer - - ! phi_snow: - ! porosity of snow - !phi_snow = config_snow_porosity_at_ice_surface - - ! initbio_frac: - ! fraction of ocean tracer concentration used to initialize tracer - !initbio_frac = config_new_ice_fraction_biotracer - - ! frazil_scav: - ! multiple of ocean tracer concentration due to frazil scavenging - !frazil_scav = config_fraction_biotracer_in_frazil - - ! ratio_Si2N_diatoms: - ! ratio of algal Silicate to Nitrate (mol/mol) - ! ratio_Si2N_diatoms = config_ratio_Si_to_N_diatoms - - ! ratio_Si2N_sp: - ! ratio of algal Silicate to Nitrogen (mol/mol) - ! ratio_Si2N_sp = config_ratio_Si_to_N_small_plankton - - ! ratio_Si2N_phaeo: - ! ratio of algal Silicate to Nitrogen (mol/mol) - ! ratio_Si2N_phaeo = config_ratio_Si_to_N_phaeocystis - - ! ratio_S2N_diatoms: - ! ratio of algal Sulphur to Nitrogen (mol/mol) - ! ratio_S2N_diatoms = config_ratio_S_to_N_diatoms - - ! ratio_S2N_sp: - ! ratio of algal Sulphur to Nitrogen (mol/mol) - ! ratio_S2N_sp = config_ratio_S_to_N_small_plankton - - ! ratio_S2N_phaeo: - ! ratio of algal Sulphur to Nitrogen (mol/mol) - ! ratio_S2N_phaeo = config_ratio_S_to_N_phaeocystis - - ! ratio_Fe2C_diatoms: - ! ratio of algal iron to carbon (umol/mol) - ! ratio_Fe2C_diatoms = config_ratio_Fe_to_C_diatoms - - ! ratio_Fe2C_sp: - ! ratio of algal iron to carbon (umol/mol) - ! ratio_Fe2C_sp = config_ratio_Fe_to_C_small_plankton - - ! ratio_Fe2C_phaeo: - ! ratio of algal iron to carbon (umol/mol) - ! ratio_Fe2C_phaeo = config_ratio_Fe_to_C_phaeocystis - - ! ratio_Fe2N_diatoms: - ! ratio of algal iron to nitrogen (umol/mol) - ! ratio_Fe2N_diatoms = config_ratio_Fe_to_N_diatoms - - ! ratio_Fe2N_sp: - ! ratio of algal iron to nitrogen (umol/mol) - ! ratio_Fe2N_sp = config_ratio_Fe_to_N_small_plankton - - ! ratio_Fe2N_phaeo: - ! ratio of algal iron to nitrogen (umol/mol) - ! ratio_Fe2N_phaeo = config_ratio_Fe_to_N_phaeocystis - - ! ratio_Fe2DON: - ! ratio of iron to nitrogen of DON (nmol/umol) - ! ratio_Fe2DON = config_ratio_Fe_to_DON - - ! ratio_Fe2DOC_s: - ! ratio of iron to carbon of DOC (nmol/umol) saccharids - ! ratio_Fe2DOC_s = config_ratio_Fe_to_DOC_saccharids - - ! ratio_Fe2DOC_l: - ! ratio of iron to carbon of DOC (nmol/umol) lipids - ! ratio_Fe2DOC_l = config_ratio_Fe_to_DOC_lipids - - ! fr_resp: - ! fraction of algal growth lost due to respiration - ! fr_resp = config_respiration_fraction_of_growth - - ! tau_min: - ! rapid mobile to stationary exchanges (s) = 1.5 hours - ! tau_min = config_rapid_mobile_to_stationary_time - - ! tau_max: - ! long time mobile to stationary exchanges (s) = 2 days - ! tau_max = config_long_mobile_to_stationary_time - - ! algal_vel: - ! 0.5 cm/d(m/s) Lavoie 2005 1.5 cm/day - ! algal_vel = config_algal_maximum_velocity - - ! R_dFe2dust: - ! g/g (3.5% content) Tagliabue 2009 - ! R_dFe2dust = config_ratio_Fe_to_dust - - ! dustFe_sol; - ! solubility fraction - ! dustFe_sol = config_solubility_of_Fe_in_dust - - ! chlabs_diatoms: - ! chl absorption (1/m/(mg/m^3)) - ! chlabs_diatoms = config_chla_absorptivity_of_diatoms - - ! chlabs_sp: - ! chl absorption (1/m/(mg/m^3)) - ! chlabs_sp = config_chla_absorptivity_of_small_plankton - - ! chlabs_phaeo: - ! chl absorption (1/m/(mg/m^3)) - ! chlabs_phaeo = config_chla_absorptivity_of_phaeocystis - - ! alpha2max_low_diatoms: - ! light limitation diatoms (1/(W/m^2)) - ! alpha2max_low_diatoms = config_light_attenuation_diatoms - - ! alpha2max_low_sp: - ! light limitation small plankton (1/(W/m^2)) - ! alpha2max_low_sp = config_light_attenuation_small_plankton - - ! alpha2max_low_phaeo: - ! light limitation phaeocystis (1/(W/m^2)) - ! alpha2max_low_phaeo = config_light_attenuation_phaeocystis - - ! beta2max_diatoms: - ! light inhibition diatoms(1/(W/m^2)) - ! beta2max_diatoms = config_light_inhibition_diatoms - - ! beta2max_sp: - ! light inhibition small plankton(1/(W/m^2)) - ! beta2max_sp = config_light_inhibition_small_plankton - - ! beta2max_phaeo: - ! light inhibition phaeocystis (1/(W/m^2)) - ! beta2max_phaeo = config_light_inhibition_phaeocystis - - ! mu_max_diatoms: - ! maximum growth rate diatoms (1/day) - ! mu_max_diatoms = config_maximum_growth_rate_diatoms - - ! mu_max_sp: - ! maximum growth rate small plankton (1/day) - ! mu_max_sp = config_maximum_growth_rate_small plankton - - ! mu_max_phaeo: - ! maximum growth rate phaeocystis (1/day) - ! mu_max_phaeo = config_maximum_growth_rate_phaeocystis - - ! grow_Tdep_sp: - ! Temperature dependence of growth small plankton (1/C) - ! grow_Tdep_sp = config_temperature_growth_small_plankton - - ! grow_Tdep_phaeo: - ! Temperature dependence of growth phaeocystis (1/C) - ! grow_Tdep_phaeo = config_temperature_growth_phaeocystis - - ! fr_graze_diatoms: - ! Fraction grazed diatoms - ! fr_graze_diatoms = config_grazed_fraction_diatoms - - ! fr_graze_sp: - ! Fraction grazed small_plankton - ! fr_graze_sp = config_grazed_fraction_small_plankton - - ! fr_graze_phaeo: - ! Fraction grazed phaeocystis - ! fr_graze_phaeo = config_grazed_fraction_phaeocystis - - ! mort_pre_diatoms: - ! Mortality diatoms (1/day) - ! mort_pre_diatoms = config_mortality_diatoms - - ! mort_pre_sp: - ! Mortality small_plankton (1/day) - ! mort_pre_sp = config_mortality_small_plankton - - ! mort_pre_phaeo: - ! Mortality phaeocystis (1/day) - ! mort_pre_phaeo = config_mortality_phaeocystis - - ! mort_Tdep_diatoms: - ! T dependence of mortality diatoms (1/C) - ! mort_Tdep_diatoms = config_temperature_mortality_diatoms - - ! mort_Tdep_sp: - ! T dependence of mortality small plankton (1/C) - ! mort_Tdep_sp = config_temperature_mortality_small_plankton - - ! mort_Tdep_phaeo: - ! T dependence of mortality phaeocystis (1/C) - ! mort_Tdep_phaeo = config_temperature_mortality_phaeocystis - - ! k_exude_diatoms: - ! algal exudation diatoms (1/d) - ! k_exude_diatoms = config_exudation_diatoms - - ! k_exude_sp: - ! algal exudation small_plankton (1/d) - ! k_exude_sp = config_exudation_small_plankton - - ! k_exude_phaeo: - ! algal exudation phaeocystis (1/d) - ! k_exude_phaeo = config_exudation_phaeocystis - - ! K_Nit_diatoms: - ! nitrate half saturation diatoms (mmol/m^3) - ! K_Nit_diatoms = config_nitrate_saturation_diatoms - - ! K_Nit_sp: - ! nitrate half saturation small_plankton (mmol/m^3) - ! K_Nit_sp = config_nitrate_saturation_small_plankton - - ! K_Nit_phaeo: - ! nitrate half saturation phaeocystis (mmol/m^3) - ! K_Nit_phaeocystis = config_nitrate_saturation_phaeocystis - - ! K_Am_diatoms: - ! ammonium half saturation diatoms (mmol/m^3) - ! K_Am_diatoms = config_ammonium_saturation_diatoms - - ! K_Am_sp: - ! ammonium half saturation small_plankton (mmol/m^3) - ! K_Am_sp = config_ammonium_saturation_small_plankton - - ! K_Am_phaeo: - ! ammonium half saturation phaeocystis (mmol/m^3) - ! K_Am_phaeocystis = config_ammonium_saturation_phaeocystis - - ! K_Sil_diatoms: - ! silicate half saturation diatoms (mmol/m^3) - ! K_Sil_diatoms = config_silicate_saturation_diatoms - - ! K_Sil_sp: - ! silicate half saturation small_plankton (mmol/m^3) - ! K_Sil_sp = config_silicate_saturation_small_plankton - - ! K_Sil_phaeo: - ! silicate half saturation phaeocystis (mmol/m^3) - ! K_Sil_phaeocystis = config_silicate_saturation_phaeocystis - - ! K_Fe_diatoms: - ! iron half saturation diatoms (nM) - ! K_Fe_diatoms = config_iron_saturation_diatoms - - ! K_Fe_sp: - ! iron half saturation small_plankton (nM) - ! K_Fe_sp = config_iron_saturation_small_plankton - - ! K_Fe_phaeo: - ! iron half saturation phaeocystis (nM) - ! K_Fe_phaeocystis = config_iron_saturation_phaeocystis - - ! f_don_protein: - ! fraction of spilled grazing to proteins ! - ! f_don_protein = config_fraction_spilled_to_DON - - ! kn_bac_protein: - ! Bacterial degredation of DON (1/d) ! ! - ! kn_bac_protein = config_degredation_of_DON - - ! f_don_Am_protein: - ! fraction of remineralized DON to ammonium ! - ! f_don_Am_protein = config_fraction_DON_ammonium - - ! f_doc_s: - ! fraction of mortality to DOC saccharids - ! f_doc_s = config_fraction_loss_to_saccharids - - ! f_doc_l: - ! fraction of mortality to DOC lipids - ! f_doc_l = config_fraction_loss_to_lipids - - ! f_exude_s: - ! fraction of exudation to DOC saccharids - ! f_exude_s = config_fraction_exudation_to_saccharids - - ! f_exude_l: - ! fraction of exudation to DOC lipids - ! f_exude_l = config_fraction_exudation_to_lipids - - ! k_bac_s: - ! Bacterial degredation of DOC (1/d) saccharids - ! k_bac_s = config_remineralization_saccharids - - ! k_bac_l: - ! Bacterial degredation of DOC (1/d) lipids - ! k_bac_l = config_remineralization_lipids - - ! T_max: - ! maximum temperature (C) - ! T_max = config_maximum_brine_temperature - - ! fsal: - ! Salinity limitation (ppt) - ! fsal = config_salinity_dependence_of_growth - - ! op_dep_min: - ! Light attenuates for optical depths exceeding min - ! op_dep_min = config_minimum_optical_depth - - ! fr_graze_s: - ! fraction of grazing spilled or slopped - ! fr_graze_s = config_slopped_grazing_fraction - - ! fr_graze_e: - ! fraction of assimilation excreted - ! fr_graze_e = config_excreted_fraction - - ! fr_mort2min: - ! fractionation of mortality to Am - ! fr_mort2min = config_fraction_mortality_to_ammonium - - ! fr_dFe: - ! remineralized nitrogen (in units of algal iron) - ! fr_dFe = config_fraction_iron_remineralized - - ! k_nitrif: - ! nitrification rate (1/day) - ! k_nitrif = config_nitrification_rate - - ! t_iron_conv: - ! desorption loss pFe to dFe (day) - ! t_iron_conv = config_desorption_loss_particulate_iron - - ! max_loss: - ! restrict uptake to % of remaining value - ! max_loss = config_maximum_loss_fraction - - ! max_dfe_doc1: - ! max ratio of dFe to saccharides in the ice (nM Fe/muM C) - ! max_dfe_doc1 = config_maximum_ratio_iron_to_saccharids - - ! fr_resp_s: - ! DMSPd fraction of respiration loss as DMSPd - ! fr_resp_s = config_respiration_loss_to_DMSPd - - ! y_sk_DMS: - ! fraction conversion given high yield - ! y_sk_DMS = config_DMSP_to_DMS_conversion_fraction - - ! t_sk_conv: - ! Stefels conversion time (d) - ! t_sk_conv = config_DMSP_to_DMS_conversion_time - - ! t_sk_ox: - ! DMS oxidation time (d) - ! t_sk_ox = config_DMS_oxidation_time - - ! algaltype_diatoms: - ! mobility type diatoms - ! algaltype_diatoms = config_mobility_type_diatoms - - ! algaltype_sp: - ! mobility type small_plankton - ! algaltype_sp = config_mobility_type_small_plankton - - ! algaltype_phaeo: - ! mobility type phaeocystis - ! algaltype_phaeo = config_mobility_type_phaeocystis - - ! nitratetype: - ! mobility type nitrate - ! nitratetype = config_mobility_type_nitrate - - ! ammoniumtype: - ! mobility type ammonium - ! ammoniumtype = config_mobility_type_ammonium - - ! silicatetype: - ! mobility type silicate - ! silicatetype = config_mobility_type_silicate - - ! dmspptype: - ! mobility type DMSPp - ! dmspptype = config_mobility_type_DMSPp - - ! dmspdtype: - ! mobility type DMSPd - ! dmspdtype = config_mobility_type_DMSPd - - ! humicstype: - ! mobility type humics - ! humicstype = config_mobility_type_humics - - ! doctype_s: - ! mobility type sachharids - ! doctype_s = config_mobility_type_saccharids - - ! doctype_l: - ! mobility type lipids - ! doctype_l = config_mobility_type_lipids - - ! dictype_1: - ! mobility type dissolved inorganic carbon - ! dictype_1 = config_mobility_type_inorganic_carbon - - ! dontype_protein: - ! mobility type proteins - ! dontype_protein = config_mobility_type_proteins - - ! fedtype_1: - ! mobility type dissolved iron - ! fedtype_1 = config_mobility_type_dissolved_iron - - ! feptype_1: - ! mobility type particulate iron - ! feptype_1 = config_mobility_type_particulate_iron - - ! zaerotype_bc1: - ! mobility type for black carbon 1 - ! zaerotype_bc1 = config_mobility_type_black_carbon1 - - ! zaerotype_bc2: - ! mobility type for black carbon 2 - ! zaerotype_bc2 = config_mobility_type_black_carbon2 - - ! zaerotype_dust1: - ! mobility type for dust 1 - ! zaerotype_dust1 = config_mobility_type_dust1 - - ! zaerotype_dust2: - ! mobility type for dust 2 - ! zaerotype_dust2 = config_mobility_type_dust2 - - ! zaerotype_dust3: - ! mobility type for dust 3 - ! zaerotype_dust3 = config_mobility_type_dust3 - - ! zaerotype_dust4: - ! mobility type for dust 4 - ! zaerotype_dust4 = config_mobility_type_dust4 - - ! ratio_C2N_diatoms: - ! algal C to N ratio (mol/mol) diatoms - ! ratio_C2N_diatoms = config_ratio_C_to_N_diatoms - - ! ratio_C2N_sp: - ! algal C to N ratio (mol/mol) small_plankton - ! ratio_C2N_sp = config_ratio_C_to_N_small_plankton - - ! ratio_C2N_phaeo: - ! algal C to N ratio (mol/mol) phaeocystis - ! ratio_C2N_phaeo = config_ratio_C_to_N_phaeocystis - - ! ratio_chl2N_diatoms: - ! algal chla to N ratio (mol/mol) diatoms - ! ratio_chl2N_diatoms = config_ratio_chla_to_N_diatoms - - ! ratio_chl2N_sp: - ! algal chla to N ratio (mol/mol) small_plankton - ! ratio_chl2N_sp = config_ratio_chla_to_N_small_plankton - - ! ratio_chl2N_phaeo: - ! algal chla to N ratio (mol/mol) phaeocystis - ! ratio_chl2N_phaeo = config_ratio_chla_to_N_phaeocystis - - ! F_abs_chl_diatoms: - ! scales absorbed radiation for dEdd diatoms - ! F_abs_chl_diatoms = config_scales_absorption_diatoms - - ! F_abs_chl_sp: - ! scales absorbed radiation for dEdd small_plankton - ! F_abs_chl_sp = config_scales_absorption_small_plankton - - ! F_abs_chl_phaeo: - ! scales absorbed radiation for dEdd phaeocystis - ! F_abs_chl_phaeo = config_scales_absorption_phaeocystis - - ! ratio_C2N_proteins: - ! ratio of C to N in proteins (mol/mol) - ! ratio_C2N_proteins = config_ratio_C_to_N_proteins - -! ! grid_oS: -! ! for bottom flux (zsalinity) -! !grid_oS = config_zsalinity_molecular_sublayer - - ! l_skS: -! ! 0.02 characteristic skeletal layer thickness (m) (zsalinity) -! !l_skS = config_zsalinity_gravity_drainage_scale - - !----------------------------------------------------------------------- - ! Parameters for snow - !----------------------------------------------------------------------- - - ! snwredist: - ! snow redistribution type - ! snwredist = config_snow_redistribution_scheme - - ! use_smliq_pnd: - ! convert excess snow liquid to ponds - ! use_smliq_pnd = config_use_snow_liquid_ponds - - ! rsnw_fall: - ! fallen snow grain radius (um) - ! rsnw_fall = config_fallen_snow_radius - - ! rsnw_tmax: - ! maximum dry metamorphism snow grain radius (um) - ! rsnw_tmax = config_max_dry_snow_radius - - ! rhosnew: - ! new snow density (kg/m^3) - ! rhosnew = config_new_snow_density - - ! rhosmax: - ! maximum snow density (kg/m^3) - ! rhosmax = config_max_snow_density - - ! windmin: - ! minimum wind speed to compact snow (m/s) - ! windmin = config_minimum_wind_compaction - - ! snwlvlfac: - ! snow loss factor for wind redistribution - ! snwlvlfac = config_snow_redistribution_factor - - ! drhosdwind: - ! wind compaction factor (kg s/m^4) - ! drhosdwind = config_wind_compaction_factor - - end subroutine init_column_package_configs - -!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -! -! init_icepack_package_configs -! -!> \brief -!> \author Adrian K. Turner, Elizabeth Hunke, Darin Comeau, Nicole Jeffery, Andrew Roberts, Erin Thomas, Jon Wolfe, LANL, Anthony Craig, NOAA (cntr), David Bailey, NCAR -!> \date 2022-2023 -!> \details -!> -! -!----------------------------------------------------------------------- - - subroutine init_icepack_package_configs(domain) - - use icepack_intfc, only: & - icepack_init_parameters, & - icepack_write_parameters, & - icepack_configure, & - icepack_query_parameters ! debugging - - use seaice_constants, only: & - seaicePuny, & ! a small number - seaiceBigNumber, & ! a large number - seaiceSecondsPerDay, & ! number of seconds in 1 day - seaiceDensityIce, & ! density of ice (kg/m^3) - seaiceDensitySnow, & ! density of snow (kg/m^3) - seaiceDensitySeaWater, & ! density of seawater (kg/m^3) - seaiceDensityFreshwater, & ! density of freshwater (kg/m^3) - seaiceFreshIceSpecificHeat, & ! specific heat of fresh ice (J/kg/K) - seaiceWaterVaporSpecificHeat, & ! specific heat of water vapor (J/kg/K) - seaiceAirSpecificHeat, & ! specific heat of air (J/kg/K) - seaiceSeaWaterSpecificHeat, & ! specific heat of ocn (J/kg/K) - seaiceLatentHeatVaporization, & ! latent heat, vaporization freshwater (J/kg) - seaiceZvir, & ! rh2o/rair - 1.0 - seaiceLatentHeatSublimation, & ! latent heat, sublimation freshwater (J/kg) - seaiceLatentHeatMelting, & ! latent heat of melting of fresh ice (J/kg) - seaiceIceSurfaceMeltingTemperature, & ! melting temp. ice top surface (C) - seaiceSnowSurfaceMeltingTemperature, & ! melting temp. snow top surface (C) - seaiceStefanBoltzmann, & ! J m-2 K-4 s-1 - seaiceIceSnowEmissivity, & ! emissivity of snow and ice - seaiceSnowSurfaceScatteringLayer, & ! snow surface scattering layer thickness (m) - seaiceStabilityReferenceHeight, & ! stability reference height (m) - seaiceFreshWaterFreezingPoint, & ! freezing temp of fresh ice (K) - seaiceIceSurfaceRoughness, & ! ice surface roughness (m) - seaiceVonKarmanConstant, & ! Von Karman constant - seaiceOceanAlbedo, & ! Ocean albedo - seaiceReferenceSalinity, & ! ice reference salinity (ppt) - seaiceMaximumSalinity, & ! ice maximum salinity (ppt) - seaiceMeltingTemperatureDepression, & ! melting temperature depression factor (C/ppt) - seaiceFrazilSalinityReduction, & ! bulk salinity reduction of newly formed frazil (ppt) - seaiceFrazilIcePorosity, & ! initial liquid fraction of frazil - seaicePi, & ! pi - seaiceGravity, & ! gravitational acceleration (m/s^2) - seaiceSnowPatchiness, & ! snow patchiness parameter - seaiceIceStrengthConstantHiblerP, & ! P* constant in Hibler strength formulation - seaiceIceStrengthConstantHiblerC, & ! C* constant in Hibler strength formulation - skeletalLayerThickness, & ! skeletal layer thickness - seaiceSnowMinimumDensity, & ! minimum snow density (kg/m^3) - seaiceBrineDynamicViscosity, & ! dynamic viscosity of brine (kg/m/s) - seaiceFreezingTemperatureConstant, &! constant freezing temp of seawater (C) - seaiceExtinctionCoef, & ! vis extnctn coef in ice, wvlngth<700nm (1/m) - seaiceFreshIceConductivity, & ! thermal conductivity of fresh ice(W/m/deg) - seaiceSnowMinimumThickness, & ! min snow thickness for computing zTsn (m) - seaiceFrazilMinimumThickness, & ! min thickness of new frazil ice - seaiceAlbedoWtVisibleDirect, & ! visible, direct - seaiceAlbedoWtNearIRDirect, & ! near IR, direct - seaiceAlbedoWtVisibleDiffuse, & ! visible, diffuse - seaiceAlbedoWtNearIRDiffuse, & ! near IR, diffuse - seaiceQsatQiceConstant, & ! constant for saturation humidity over ice - seaiceQsatTiceConstant, & ! constant for saturation humidity over ice - seaiceQsatQocnConstant, & ! constant for saturation humidity over ocean - seaiceQsatTocnConstant ! constant for saturation humidity over ocean - - type(domain_type), intent(inout) :: & - domain - - type(MPAS_pool_type), pointer :: & - snow - - character(len=strKIND), pointer :: & - config_thermodynamics_type, & - config_heat_conductivity_type, & - config_shortwave_type, & - config_albedo_type, & - config_ice_strength_formulation, & - config_ridging_participation_function, & - config_ridging_redistribution_function, & - config_atmos_boundary_method, & - config_itd_conversion_type, & - config_category_bounds_type, & - config_pond_refreezing_type, & - config_salt_flux_coupling_type, & - config_ocean_heat_transfer_type, & - config_frazil_coupling_type, & - config_sea_freezing_temperature_type, & - config_skeletal_bgc_flux_type, & - config_snow_redistribution_scheme - - logical, pointer :: & - config_use_snicar_ad, & - config_calc_surface_temperature, & - config_update_ocean_fluxes, & - config_use_form_drag, & - config_use_high_frequency_coupling, & - config_use_ocean_mixed_layer, & - config_calc_surface_stresses, & - config_use_vertical_tracers, & - config_scale_initial_vertical_bgc, & - config_use_vertical_biochemistry, & - config_use_shortwave_bioabsorption, & - config_use_skeletal_biochemistry, & - config_use_modal_aerosols, & - config_use_snow_liquid_ponds, & - config_use_snow_grain_radius, & - config_use_shortwave_redistribution - - real(kind=RKIND), pointer :: & - config_min_friction_velocity, & - config_ice_ocean_drag_coefficient, & - config_snow_thermal_conductivity, & - config_rapid_mode_channel_radius, & - config_rapid_model_critical_Ra, & - config_rapid_mode_aspect_ratio, & - config_slow_mode_drainage_strength, & - config_slow_mode_critical_porosity, & - config_macro_drainage_timescale, & - config_congelation_ice_porosity, & -! config_frazil_ice_porosity, & -! config_frazil_salinity_reduction, & - config_visible_ice_albedo, & - config_infrared_ice_albedo, & - config_visible_snow_albedo, & - config_infrared_snow_albedo, & - config_variable_albedo_thickness_limit, & -! config_snow_surface_scattering_layer_depth, & - config_ice_shortwave_tuning_parameter, & - config_pond_shortwave_tuning_parameter, & - config_snow_shortwave_tuning_parameter, & - config_shortwave_redistribution_fraction, & - config_shortwave_redistribution_threshold, & - config_temp_change_snow_grain_radius_change, & - config_max_melting_snow_grain_radius, & - config_algae_absorption_coefficient, & - config_ridging_efolding_scale, & - config_ratio_ridging_work_to_PE, & - config_snow_to_ice_transition_depth, & - config_pond_flushing_factor, & - config_min_meltwater_retained_fraction, & - config_max_meltwater_retained_fraction, & - config_pond_depth_to_fraction_ratio, & - config_snow_on_pond_ice_tapering_parameter, & - config_critical_pond_ice_thickness, & - config_biogrid_bottom_molecular_sublayer, & - config_bio_gravity_drainage_length_scale, & - config_biogrid_top_molecular_sublayer, & - config_new_ice_fraction_biotracer, & - config_fraction_biotracer_in_frazil, & - config_snow_porosity_at_ice_surface, & - config_ratio_Si_to_N_diatoms, & - config_ratio_Si_to_N_small_plankton, & - config_ratio_Si_to_N_phaeocystis, & - config_ratio_S_to_N_diatoms, & - config_ratio_S_to_N_small_plankton, & - config_ratio_S_to_N_phaeocystis, & - config_ratio_Fe_to_C_diatoms, & - config_ratio_Fe_to_C_small_plankton, & - config_ratio_Fe_to_C_phaeocystis, & - config_ratio_Fe_to_N_diatoms, & - config_ratio_Fe_to_N_small_plankton, & - config_ratio_Fe_to_N_phaeocystis, & - config_ratio_Fe_to_DON, & - config_ratio_Fe_to_DOC_saccharids, & - config_ratio_Fe_to_DOC_lipids, & - config_respiration_fraction_of_growth, & - config_rapid_mobile_to_stationary_time, & - config_long_mobile_to_stationary_time, & - config_algal_maximum_velocity, & - config_ratio_Fe_to_dust, & - config_solubility_of_Fe_in_dust, & - config_chla_absorptivity_of_diatoms, & - config_chla_absorptivity_of_small_plankton, & - config_chla_absorptivity_of_phaeocystis, & - config_light_attenuation_diatoms, & - config_light_attenuation_small_plankton, & - config_light_attenuation_phaeocystis, & - config_light_inhibition_diatoms, & - config_light_inhibition_small_plankton, & - config_light_inhibition_phaeocystis, & - config_maximum_growth_rate_diatoms, & - config_maximum_growth_rate_small_plankton, & - config_maximum_growth_rate_phaeocystis, & - config_temperature_growth_diatoms, & - config_temperature_growth_small_plankton, & - config_temperature_growth_phaeocystis, & - config_grazed_fraction_diatoms, & - config_grazed_fraction_small_plankton, & - config_grazed_fraction_phaeocystis, & - config_mortality_diatoms, & - config_mortality_small_plankton, & - config_mortality_phaeocystis, & - config_temperature_mortality_diatoms, & - config_temperature_mortality_small_plankton, & - config_temperature_mortality_phaeocystis, & - config_exudation_diatoms, & - config_exudation_small_plankton, & - config_exudation_phaeocystis, & - config_nitrate_saturation_diatoms, & - config_nitrate_saturation_small_plankton, & - config_nitrate_saturation_phaeocystis, & - config_ammonium_saturation_diatoms, & - config_ammonium_saturation_small_plankton, & - config_ammonium_saturation_phaeocystis, & - config_silicate_saturation_diatoms, & - config_silicate_saturation_small_plankton, & - config_silicate_saturation_phaeocystis, & - config_iron_saturation_diatoms, & - config_iron_saturation_small_plankton, & - config_iron_saturation_phaeocystis, & - config_fraction_spilled_to_DON, & - config_degredation_of_DON, & - config_fraction_DON_ammonium, & - config_fraction_loss_to_saccharids, & - config_fraction_loss_to_lipids, & - config_fraction_exudation_to_saccharids, & - config_fraction_exudation_to_lipids, & - config_remineralization_saccharids, & - config_remineralization_lipids, & - config_maximum_brine_temperature, & - config_salinity_dependence_of_growth, & - config_minimum_optical_depth, & - config_slopped_grazing_fraction, & - config_excreted_fraction, & - config_fraction_mortality_to_ammonium, & - config_fraction_iron_remineralized, & - config_nitrification_rate, & - config_desorption_loss_particulate_iron, & - config_maximum_loss_fraction, & - config_maximum_ratio_iron_to_saccharids, & - config_respiration_loss_to_DMSPd, & - config_DMSP_to_DMS_conversion_fraction, & - config_DMSP_to_DMS_conversion_time, & - config_DMS_oxidation_time, & - config_mobility_type_diatoms, & - config_mobility_type_small_plankton, & - config_mobility_type_phaeocystis, & - config_mobility_type_nitrate, & - config_mobility_type_ammonium, & - config_mobility_type_silicate, & - config_mobility_type_DMSPp, & - config_mobility_type_DMSPd, & - config_mobility_type_humics, & - config_mobility_type_saccharids, & - config_mobility_type_lipids, & - config_mobility_type_inorganic_carbon, & - config_mobility_type_proteins, & - config_mobility_type_dissolved_iron, & - config_mobility_type_particulate_iron, & - config_mobility_type_black_carbon1, & - config_mobility_type_black_carbon2, & - config_mobility_type_dust1, & - config_mobility_type_dust2, & - config_mobility_type_dust3, & - config_mobility_type_dust4, & - config_ratio_C_to_N_diatoms, & - config_ratio_C_to_N_small_plankton, & - config_ratio_C_to_N_phaeocystis, & - config_ratio_chla_to_N_diatoms, & - config_ratio_chla_to_N_small_plankton, & - config_ratio_chla_to_N_phaeocystis, & - config_scales_absorption_diatoms, & - config_scales_absorption_small_plankton, & - config_scales_absorption_phaeocystis, & - config_ratio_C_to_N_proteins, & - config_fallen_snow_radius, & - config_new_snow_density, & - config_max_snow_density, & - config_minimum_wind_compaction, & - config_wind_compaction_factor, & - config_snow_redistribution_factor, & - config_max_dry_snow_radius, & - config_floediam, & - config_floeshape - - real(kind=RKIND), dimension(:,:,:), pointer :: & - snowEmpiricalGrowthParameterTau, & - snowEmpiricalGrowthParameterKappa, & - snowPropertyRate - - integer, pointer :: & - config_boundary_layer_iteration_number, & - nGrainAgingTemperature, & - nGrainAgingTempGradient, & - nGrainAgingSnowDensity - - integer :: & - config_thermodynamics_type_int, & - config_ice_strength_formulation_int, & - config_ridging_participation_function_int, & - config_ridging_redistribution_function_int, & - config_itd_conversion_type_int, & - config_category_bounds_type_int - - character(len=strKIND) :: tmp_config_shortwave_type - character(len=strKIND) :: tmp_config_snw_ssp_table - character(len=strKIND) :: snw_aging_table = 'snicar' - - ! debugging - integer :: itmp1, itmp2 - real(kind=RKIND) :: rtmp1, rtmp2 - character(len=strKIND) :: ctmp1, ctmp2 - - call MPAS_pool_get_config(domain % configs, "config_thermodynamics_type", config_thermodynamics_type) - call MPAS_pool_get_config(domain % configs, "config_heat_conductivity_type", config_heat_conductivity_type) - call MPAS_pool_get_config(domain % configs, "config_ocean_heat_transfer_type", config_ocean_heat_transfer_type) - call MPAS_pool_get_config(domain % configs, "config_calc_surface_temperature", config_calc_surface_temperature) - call MPAS_pool_get_config(domain % configs, "config_update_ocean_fluxes", config_update_ocean_fluxes) - call MPAS_pool_get_config(domain % configs, "config_frazil_coupling_type", config_frazil_coupling_type) - call MPAS_pool_get_config(domain % configs, "config_min_friction_velocity", config_min_friction_velocity) - call MPAS_pool_get_config(domain % configs, "config_ice_ocean_drag_coefficient", config_ice_ocean_drag_coefficient) - call MPAS_pool_get_config(domain % configs, "config_snow_thermal_conductivity", config_snow_thermal_conductivity) - call MPAS_pool_get_config(domain % configs, "config_rapid_mode_channel_radius", config_rapid_mode_channel_radius) - call MPAS_pool_get_config(domain % configs, "config_rapid_model_critical_Ra", config_rapid_model_critical_Ra) - call MPAS_pool_get_config(domain % configs, "config_rapid_mode_aspect_ratio", config_rapid_mode_aspect_ratio) - call MPAS_pool_get_config(domain % configs, "config_slow_mode_drainage_strength", config_slow_mode_drainage_strength) - call MPAS_pool_get_config(domain % configs, "config_slow_mode_critical_porosity", config_slow_mode_critical_porosity) - call MPAS_pool_get_config(domain % configs, "config_macro_drainage_timescale", config_macro_drainage_timescale) - call MPAS_pool_get_config(domain % configs, "config_congelation_ice_porosity", config_congelation_ice_porosity) -! call MPAS_pool_get_config(domain % configs, "config_frazil_ice_porosity", config_frazil_ice_porosity) -! call MPAS_pool_get_config(domain % configs, "config_frazil_salinity_reduction", config_frazil_salinity_reduction) - call MPAS_pool_get_config(domain % configs, "config_shortwave_type", config_shortwave_type) - call MPAS_pool_get_config(domain % configs, "config_use_snicar_ad", config_use_snicar_ad) - call MPAS_pool_get_config(domain % configs, "config_albedo_type", config_albedo_type) - call MPAS_pool_get_config(domain % configs, "config_visible_ice_albedo", config_visible_ice_albedo) - call MPAS_pool_get_config(domain % configs, "config_infrared_ice_albedo", config_infrared_ice_albedo) - call MPAS_pool_get_config(domain % configs, "config_visible_snow_albedo", config_visible_snow_albedo) - call MPAS_pool_get_config(domain % configs, "config_infrared_snow_albedo", config_infrared_snow_albedo) - call MPAS_pool_get_config(domain % configs, "config_variable_albedo_thickness_limit", config_variable_albedo_thickness_limit) -! call MPAS_pool_get_config(domain % configs, "config_snow_surface_scattering_layer_depth", config_snow_surface_scattering_layer_depth) - call MPAS_pool_get_config(domain % configs, "config_ice_shortwave_tuning_parameter", config_ice_shortwave_tuning_parameter) - call MPAS_pool_get_config(domain % configs, "config_pond_shortwave_tuning_parameter", config_pond_shortwave_tuning_parameter) - call MPAS_pool_get_config(domain % configs, "config_snow_shortwave_tuning_parameter", config_snow_shortwave_tuning_parameter) - call MPAS_pool_get_config(domain % configs, "config_use_shortwave_redistribution", config_use_shortwave_redistribution) - call MPAS_pool_get_config(domain % configs, "config_shortwave_redistribution_fraction", config_shortwave_redistribution_fraction) - call MPAS_pool_get_config(domain % configs, "config_shortwave_redistribution_threshold", config_shortwave_redistribution_threshold) - call MPAS_pool_get_config(domain % configs, "config_temp_change_snow_grain_radius_change", & - config_temp_change_snow_grain_radius_change) - call MPAS_pool_get_config(domain % configs, "config_max_melting_snow_grain_radius", config_max_melting_snow_grain_radius) - call MPAS_pool_get_config(domain % configs, "config_algae_absorption_coefficient", config_algae_absorption_coefficient) - call MPAS_pool_get_config(domain % configs, "config_ice_strength_formulation", config_ice_strength_formulation) - call MPAS_pool_get_config(domain % configs, "config_ridging_participation_function", config_ridging_participation_function) - call MPAS_pool_get_config(domain % configs, "config_ridging_redistribution_function", config_ridging_redistribution_function) - call MPAS_pool_get_config(domain % configs, "config_ridging_efolding_scale", config_ridging_efolding_scale) - call MPAS_pool_get_config(domain % configs, "config_ratio_ridging_work_to_PE", config_ratio_ridging_work_to_PE) - call MPAS_pool_get_config(domain % configs, "config_atmos_boundary_method", config_atmos_boundary_method) - call MPAS_pool_get_config(domain % configs, "config_calc_surface_stresses", config_calc_surface_stresses) - call MPAS_pool_get_config(domain % configs, "config_use_form_drag", config_use_form_drag) - call MPAS_pool_get_config(domain % configs, "config_use_high_frequency_coupling", config_use_high_frequency_coupling) - call MPAS_pool_get_config(domain % configs, "config_boundary_layer_iteration_number", config_boundary_layer_iteration_number) - call MPAS_pool_get_config(domain % configs, "config_use_ocean_mixed_layer", config_use_ocean_mixed_layer) - call MPAS_pool_get_config(domain % configs, "config_sea_freezing_temperature_type", config_sea_freezing_temperature_type) - call MPAS_pool_get_config(domain % configs, "config_itd_conversion_type", config_itd_conversion_type) - call MPAS_pool_get_config(domain % configs, "config_category_bounds_type", config_category_bounds_type) - call MPAS_pool_get_config(domain % configs, "config_snow_to_ice_transition_depth", config_snow_to_ice_transition_depth) - call MPAS_pool_get_config(domain % configs, "config_pond_refreezing_type", config_pond_refreezing_type) - call MPAS_pool_get_config(domain % configs, "config_salt_flux_coupling_type", config_salt_flux_coupling_type) - call MPAS_pool_get_config(domain % configs, "config_pond_flushing_factor", config_pond_flushing_factor) - call MPAS_pool_get_config(domain % configs, "config_min_meltwater_retained_fraction", config_min_meltwater_retained_fraction) - call MPAS_pool_get_config(domain % configs, "config_max_meltwater_retained_fraction", config_max_meltwater_retained_fraction) - call MPAS_pool_get_config(domain % configs, "config_pond_depth_to_fraction_ratio", config_pond_depth_to_fraction_ratio) - call MPAS_pool_get_config(domain % configs, "config_snow_on_pond_ice_tapering_parameter", & - config_snow_on_pond_ice_tapering_parameter) - call MPAS_pool_get_config(domain % configs, "config_critical_pond_ice_thickness", config_critical_pond_ice_thickness) - call MPAS_pool_get_config(domain % configs, "config_skeletal_bgc_flux_type", config_skeletal_bgc_flux_type) - call MPAS_pool_get_config(domain % configs, "config_use_vertical_tracers", config_use_vertical_tracers) - call MPAS_pool_get_config(domain % configs, "config_scale_initial_vertical_bgc", config_scale_initial_vertical_bgc) - call MPAS_pool_get_config(domain % configs, "config_use_vertical_biochemistry", config_use_vertical_biochemistry) - call MPAS_pool_get_config(domain % configs, "config_use_shortwave_bioabsorption", config_use_shortwave_bioabsorption) - call MPAS_pool_get_config(domain % configs, "config_use_modal_aerosols", config_use_modal_aerosols) - call MPAS_pool_get_config(domain % configs, "config_use_skeletal_biochemistry", config_use_skeletal_biochemistry) - call MPAS_pool_get_config(domain % configs, "config_biogrid_bottom_molecular_sublayer", & - config_biogrid_bottom_molecular_sublayer) - call MPAS_pool_get_config(domain % configs, "config_bio_gravity_drainage_length_scale", & - config_bio_gravity_drainage_length_scale) - call MPAS_pool_get_config(domain % configs, "config_biogrid_top_molecular_sublayer", config_biogrid_top_molecular_sublayer) - call MPAS_pool_get_config(domain % configs, "config_new_ice_fraction_biotracer", config_new_ice_fraction_biotracer) - call MPAS_pool_get_config(domain % configs, "config_fraction_biotracer_in_frazil", config_fraction_biotracer_in_frazil) - call MPAS_pool_get_config(domain % configs, "config_snow_porosity_at_ice_surface", config_snow_porosity_at_ice_surface) - call MPAS_pool_get_config(domain % configs, "config_ratio_Si_to_N_diatoms", config_ratio_Si_to_N_diatoms) - call MPAS_pool_get_config(domain % configs, "config_ratio_Si_to_N_small_plankton", config_ratio_Si_to_N_small_plankton) - call MPAS_pool_get_config(domain % configs, "config_ratio_Si_to_N_phaeocystis", config_ratio_Si_to_N_phaeocystis) - call MPAS_pool_get_config(domain % configs, "config_ratio_S_to_N_diatoms", config_ratio_S_to_N_diatoms) - call MPAS_pool_get_config(domain % configs, "config_ratio_S_to_N_small_plankton", config_ratio_S_to_N_small_plankton) - call MPAS_pool_get_config(domain % configs, "config_ratio_S_to_N_phaeocystis", config_ratio_S_to_N_phaeocystis) - call MPAS_pool_get_config(domain % configs, "config_ratio_Fe_to_C_diatoms", config_ratio_Fe_to_C_diatoms) - call MPAS_pool_get_config(domain % configs, "config_ratio_Fe_to_C_small_plankton", config_ratio_Fe_to_C_small_plankton) - call MPAS_pool_get_config(domain % configs, "config_ratio_Fe_to_C_phaeocystis", config_ratio_Fe_to_C_phaeocystis) - call MPAS_pool_get_config(domain % configs, "config_ratio_Fe_to_N_diatoms", config_ratio_Fe_to_N_diatoms) - call MPAS_pool_get_config(domain % configs, "config_ratio_Fe_to_N_small_plankton", config_ratio_Fe_to_N_small_plankton) - call MPAS_pool_get_config(domain % configs, "config_ratio_Fe_to_N_phaeocystis", config_ratio_Fe_to_N_phaeocystis) - call MPAS_pool_get_config(domain % configs, "config_ratio_Fe_to_DON", config_ratio_Fe_to_DON) - call MPAS_pool_get_config(domain % configs, "config_ratio_Fe_to_DOC_saccharids", config_ratio_Fe_to_DOC_saccharids) - call MPAS_pool_get_config(domain % configs, "config_ratio_Fe_to_DOC_lipids", config_ratio_Fe_to_DOC_lipids) - call MPAS_pool_get_config(domain % configs, "config_respiration_fraction_of_growth", config_respiration_fraction_of_growth) - call MPAS_pool_get_config(domain % configs, "config_rapid_mobile_to_stationary_time", config_rapid_mobile_to_stationary_time) - call MPAS_pool_get_config(domain % configs, "config_long_mobile_to_stationary_time", config_long_mobile_to_stationary_time) - call MPAS_pool_get_config(domain % configs, "config_algal_maximum_velocity", config_algal_maximum_velocity) - call MPAS_pool_get_config(domain % configs, "config_ratio_Fe_to_dust", config_ratio_Fe_to_dust) - call MPAS_pool_get_config(domain % configs, "config_solubility_of_Fe_in_dust", config_solubility_of_Fe_in_dust) - call MPAS_pool_get_config(domain % configs, "config_chla_absorptivity_of_diatoms", config_chla_absorptivity_of_diatoms) - call MPAS_pool_get_config(domain % configs, "config_chla_absorptivity_of_small_plankton", & - config_chla_absorptivity_of_small_plankton) - call MPAS_pool_get_config(domain % configs, "config_chla_absorptivity_of_phaeocystis", config_chla_absorptivity_of_phaeocystis) - call MPAS_pool_get_config(domain % configs, "config_light_attenuation_diatoms", config_light_attenuation_diatoms) - call MPAS_pool_get_config(domain % configs, "config_light_attenuation_small_plankton", config_light_attenuation_small_plankton) - call MPAS_pool_get_config(domain % configs, "config_light_attenuation_phaeocystis", config_light_attenuation_phaeocystis) - call MPAS_pool_get_config(domain % configs, "config_light_inhibition_diatoms", config_light_inhibition_diatoms) - call MPAS_pool_get_config(domain % configs, "config_light_inhibition_small_plankton", config_light_inhibition_small_plankton) - call MPAS_pool_get_config(domain % configs, "config_light_inhibition_phaeocystis", config_light_inhibition_phaeocystis) - call MPAS_pool_get_config(domain % configs, "config_maximum_growth_rate_diatoms", config_maximum_growth_rate_diatoms) - call MPAS_pool_get_config(domain % configs, "config_maximum_growth_rate_small_plankton", & - config_maximum_growth_rate_small_plankton) - call MPAS_pool_get_config(domain % configs, "config_maximum_growth_rate_phaeocystis", config_maximum_growth_rate_phaeocystis) - call MPAS_pool_get_config(domain % configs, "config_temperature_growth_diatoms", config_temperature_growth_diatoms) - call MPAS_pool_get_config(domain % configs, "config_temperature_growth_small_plankton", & - config_temperature_growth_small_plankton) - call MPAS_pool_get_config(domain % configs, "config_temperature_growth_phaeocystis", config_temperature_growth_phaeocystis) - call MPAS_pool_get_config(domain % configs, "config_grazed_fraction_diatoms", config_grazed_fraction_diatoms) - call MPAS_pool_get_config(domain % configs, "config_grazed_fraction_small_plankton", config_grazed_fraction_small_plankton) - call MPAS_pool_get_config(domain % configs, "config_grazed_fraction_phaeocystis", config_grazed_fraction_phaeocystis) - call MPAS_pool_get_config(domain % configs, "config_mortality_diatoms", config_mortality_diatoms) - call MPAS_pool_get_config(domain % configs, "config_mortality_small_plankton", config_mortality_small_plankton) - call MPAS_pool_get_config(domain % configs, "config_mortality_phaeocystis", config_mortality_phaeocystis) - call MPAS_pool_get_config(domain % configs, "config_temperature_mortality_diatoms", config_temperature_mortality_diatoms) - call MPAS_pool_get_config(domain % configs, "config_temperature_mortality_small_plankton", & - config_temperature_mortality_small_plankton) - call MPAS_pool_get_config(domain % configs, "config_temperature_mortality_phaeocystis", & - config_temperature_mortality_phaeocystis) - call MPAS_pool_get_config(domain % configs, "config_exudation_diatoms", config_exudation_diatoms) - call MPAS_pool_get_config(domain % configs, "config_exudation_small_plankton", config_exudation_small_plankton) - call MPAS_pool_get_config(domain % configs, "config_exudation_phaeocystis", config_exudation_phaeocystis) - call MPAS_pool_get_config(domain % configs, "config_nitrate_saturation_diatoms", config_nitrate_saturation_diatoms) - call MPAS_pool_get_config(domain % configs, "config_nitrate_saturation_small_plankton", & - config_nitrate_saturation_small_plankton) - call MPAS_pool_get_config(domain % configs, "config_nitrate_saturation_phaeocystis", config_nitrate_saturation_phaeocystis) - call MPAS_pool_get_config(domain % configs, "config_ammonium_saturation_diatoms", config_ammonium_saturation_diatoms) - call MPAS_pool_get_config(domain % configs, "config_ammonium_saturation_small_plankton", & - config_ammonium_saturation_small_plankton) - call MPAS_pool_get_config(domain % configs, "config_ammonium_saturation_phaeocystis", & - config_ammonium_saturation_phaeocystis) - call MPAS_pool_get_config(domain % configs, "config_silicate_saturation_diatoms", config_silicate_saturation_diatoms) - call MPAS_pool_get_config(domain % configs, "config_silicate_saturation_small_plankton", & - config_silicate_saturation_small_plankton) - call MPAS_pool_get_config(domain % configs, "config_silicate_saturation_phaeocystis", config_silicate_saturation_phaeocystis) - call MPAS_pool_get_config(domain % configs, "config_iron_saturation_diatoms", config_iron_saturation_diatoms) - call MPAS_pool_get_config(domain % configs, "config_iron_saturation_small_plankton", config_iron_saturation_small_plankton) - call MPAS_pool_get_config(domain % configs, "config_iron_saturation_phaeocystis", config_iron_saturation_phaeocystis) - call MPAS_pool_get_config(domain % configs, "config_fraction_spilled_to_DON", config_fraction_spilled_to_DON) - call MPAS_pool_get_config(domain % configs, "config_degredation_of_DON", config_degredation_of_DON) - call MPAS_pool_get_config(domain % configs, "config_fraction_DON_ammonium", config_fraction_DON_ammonium) - call MPAS_pool_get_config(domain % configs, "config_fraction_loss_to_saccharids", config_fraction_loss_to_saccharids) - call MPAS_pool_get_config(domain % configs, "config_fraction_loss_to_lipids", config_fraction_loss_to_lipids) - call MPAS_pool_get_config(domain % configs, "config_fraction_exudation_to_saccharids", config_fraction_exudation_to_saccharids) - call MPAS_pool_get_config(domain % configs, "config_fraction_exudation_to_lipids", config_fraction_exudation_to_lipids) - call MPAS_pool_get_config(domain % configs, "config_remineralization_saccharids", config_remineralization_saccharids) - call MPAS_pool_get_config(domain % configs, "config_remineralization_lipids", config_remineralization_lipids) - call MPAS_pool_get_config(domain % configs, "config_maximum_brine_temperature", config_maximum_brine_temperature) - call MPAS_pool_get_config(domain % configs, "config_salinity_dependence_of_growth", config_salinity_dependence_of_growth) - call MPAS_pool_get_config(domain % configs, "config_minimum_optical_depth", config_minimum_optical_depth) - call MPAS_pool_get_config(domain % configs, "config_slopped_grazing_fraction", config_slopped_grazing_fraction) - call MPAS_pool_get_config(domain % configs, "config_excreted_fraction", config_excreted_fraction) - call MPAS_pool_get_config(domain % configs, "config_fraction_mortality_to_ammonium", config_fraction_mortality_to_ammonium) - call MPAS_pool_get_config(domain % configs, "config_fraction_iron_remineralized", config_fraction_iron_remineralized) - call MPAS_pool_get_config(domain % configs, "config_nitrification_rate", config_nitrification_rate) - call MPAS_pool_get_config(domain % configs, "config_desorption_loss_particulate_iron", config_desorption_loss_particulate_iron) - call MPAS_pool_get_config(domain % configs, "config_maximum_loss_fraction", config_maximum_loss_fraction) - call MPAS_pool_get_config(domain % configs, "config_maximum_ratio_iron_to_saccharids", config_maximum_ratio_iron_to_saccharids) - call MPAS_pool_get_config(domain % configs, "config_respiration_loss_to_DMSPd", config_respiration_loss_to_DMSPd) - call MPAS_pool_get_config(domain % configs, "config_DMSP_to_DMS_conversion_fraction", config_DMSP_to_DMS_conversion_fraction) - call MPAS_pool_get_config(domain % configs, "config_DMSP_to_DMS_conversion_time", config_DMSP_to_DMS_conversion_time) - call MPAS_pool_get_config(domain % configs, "config_DMS_oxidation_time", config_DMS_oxidation_time) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_diatoms", config_mobility_type_diatoms) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_small_plankton", config_mobility_type_small_plankton) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_phaeocystis", config_mobility_type_phaeocystis) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_nitrate", config_mobility_type_nitrate) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_ammonium", config_mobility_type_ammonium) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_silicate", config_mobility_type_silicate) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_DMSPp", config_mobility_type_DMSPp) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_DMSPd", config_mobility_type_DMSPd) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_humics", config_mobility_type_humics) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_saccharids", config_mobility_type_saccharids) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_lipids", config_mobility_type_lipids) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_inorganic_carbon", config_mobility_type_inorganic_carbon) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_proteins", config_mobility_type_proteins) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_dissolved_iron", config_mobility_type_dissolved_iron) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_particulate_iron", config_mobility_type_particulate_iron) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_black_carbon1", config_mobility_type_black_carbon1) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_black_carbon2", config_mobility_type_black_carbon2) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_dust1", config_mobility_type_dust1) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_dust2", config_mobility_type_dust2) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_dust3", config_mobility_type_dust3) - call MPAS_pool_get_config(domain % configs, "config_mobility_type_dust4", config_mobility_type_dust4) - call MPAS_pool_get_config(domain % configs, "config_ratio_C_to_N_diatoms", config_ratio_C_to_N_diatoms) - call MPAS_pool_get_config(domain % configs, "config_ratio_C_to_N_small_plankton", config_ratio_C_to_N_small_plankton) - call MPAS_pool_get_config(domain % configs, "config_ratio_C_to_N_phaeocystis", config_ratio_C_to_N_phaeocystis) - call MPAS_pool_get_config(domain % configs, "config_ratio_chla_to_N_diatoms", config_ratio_chla_to_N_diatoms) - call MPAS_pool_get_config(domain % configs, "config_ratio_chla_to_N_small_plankton", config_ratio_chla_to_N_small_plankton) - call MPAS_pool_get_config(domain % configs, "config_ratio_chla_to_N_phaeocystis", config_ratio_chla_to_N_phaeocystis) - call MPAS_pool_get_config(domain % configs, "config_scales_absorption_diatoms", config_scales_absorption_diatoms) - call MPAS_pool_get_config(domain % configs, "config_scales_absorption_small_plankton", config_scales_absorption_small_plankton) - call MPAS_pool_get_config(domain % configs, "config_scales_absorption_phaeocystis", config_scales_absorption_phaeocystis) - call MPAS_pool_get_config(domain % configs, "config_ratio_C_to_N_proteins", config_ratio_C_to_N_proteins) call MPAS_pool_get_config(domain % configs, "config_snow_redistribution_scheme", config_snow_redistribution_scheme) call MPAS_pool_get_config(domain % configs, "config_fallen_snow_radius", config_fallen_snow_radius) call MPAS_pool_get_config(domain % configs, "config_use_snow_liquid_ponds", config_use_snow_liquid_ponds) @@ -12210,6 +10526,7 @@ subroutine init_icepack_package_configs(domain) snowpatch_in = seaiceSnowPatchiness, & ! ccsm3 radiation scheme !rhosi_in = , & ! brine, zbgc, zsalinity sk_l_in = skeletalLayerThickness, & ! + R_gC2molC_in = gramsCarbonPerMolCarbon, & saltmax_in = seaiceMaximumSalinity, & phi_init_in = seaiceFrazilIcePorosity, & !min_salin_in = , & ! ktherm=1, brine, zsalinity @@ -12285,39 +10602,38 @@ subroutine init_icepack_package_configs(domain) z_tracers_in = config_use_vertical_tracers, & scale_bgc_in = config_scale_initial_vertical_bgc, & solve_zbgc_in = config_use_vertical_biochemistry, & + dEdd_algae_in = config_use_shortwave_bioabsorption, & modal_aero_in = config_use_modal_aerosols, & + use_macromolecules_in = config_use_macromolecules, & + restartbgc_in = config_do_restart_bgc, & skl_bgc_in = config_use_skeletal_biochemistry, & grid_o_in = config_biogrid_bottom_molecular_sublayer, & l_sk_in = config_bio_gravity_drainage_length_scale, & - initbio_frac_in = config_new_ice_fraction_biotracer, & -! grid_oS_in = config_zsalinity_molecular_sublayer, & -! l_skS_in = config_zsalinity_gravity_drainage_scale, & - dEdd_algae_in = config_use_shortwave_bioabsorption, & + grid_o_t_in = config_biogrid_top_molecular_sublayer, & + !grid_oS_in = config_zsalinity_molecular_sublayer, & + !l_skS_in = config_zsalinity_gravity_drainage_scale, & phi_snow_in = config_snow_porosity_at_ice_surface, & - !T_max_in = , & ! BGC - !fsal_in = , & - !fr_resp_in = , & - !algal_vel_in = , & - !R_dFe2dust_in = , & - !dustFe_sol_in = , & - !op_dep_min_in = , & - !fr_graze_s_in = , & - !fr_graze_e_in = , & - !fr_mort2min_in = , & - !fr_dFe_in = , & - !k_nitrif_in = , & - !t_iron_conv_in = , & - !max_loss_in = , & - !max_dfe_doc1_in = , & - !fr_resp_s_in = , & + fr_resp_in = config_respiration_fraction_of_growth, & + algal_vel_in = config_algal_maximum_velocity, & + R_dFe2dust_in = config_ratio_Fe_to_dust, & + dustFe_sol_in = config_solubility_of_Fe_in_dust, & + use_atm_dust_iron_in = .not.config_use_iron_solubility_file, & + T_max_in = config_maximum_brine_temperature, & + fsal_in = config_salinity_dependence_of_growth, & + op_dep_min_in = config_minimum_optical_depth, & + fr_graze_s_in = config_slopped_grazing_fraction, & + fr_graze_e_in = config_excreted_fraction, & + fr_mort2min_in = config_fraction_mortality_to_ammonium, & + fr_dFe_in = config_fraction_iron_remineralized, & + k_nitrif_in = config_nitrification_rate, & + t_iron_conv_in = config_desorption_loss_particulate_iron, & + max_loss_in = config_maximum_loss_fraction, & + max_dfe_doc1_in = config_maximum_ratio_iron_to_saccharids, & + fr_resp_s_in = config_respiration_loss_to_DMSPd, & + y_sk_DMS_in = config_DMSP_to_DMS_conversion_fraction, & + t_sk_conv_in = config_DMSP_to_DMS_conversion_time, & + t_sk_ox_in = config_DMS_oxidation_time, & !conserv_check_in = , & - !y_sk_DMS_in = , & - !t_sk_conv_in = , & - !t_sk_ox_in = , & - !frazil_scav_in = , & - sw_redist_in = config_use_shortwave_redistribution, & - sw_frac_in = config_shortwave_redistribution_fraction, & - sw_dtemp_in = config_shortwave_redistribution_threshold, & snwgrain_in = config_use_snow_grain_radius, & snwredist_in = config_snow_redistribution_scheme, & use_smliq_pnd_in = config_use_snow_liquid_ponds, & @@ -12340,15 +10656,6 @@ subroutine init_icepack_package_configs(domain) call seaice_icepack_write_warnings(icepack_warnings_aborted()) -!note that icepack_recompute_constants, called from icepck_init_parameters above, recomputes Lfresh -! - make Lfresh optional for E3SM? - -! tcraig, this will write out icepack parameters to fort.101, need to uncomment 3 lines -! if (mpas_log_info % taskID == 0) then -! call icepack_write_parameters(101) -! endif -! call seaice_icepack_write_warnings(icepack_warnings_aborted()) - call mpas_log_write(" ----- compare values after icepack init -----") ! Lfresh is derived in Icepack, not sent in from driver @@ -12397,124 +10704,6 @@ subroutine init_icepack_package_configs(domain) !call icepack_init_parameters(& ! shortwave = config_shortwave_type, & ! not working correctly above ! oceanmixed_ice = config_use_ocean_mixed_layer, & ! not used in Icepack/columnphysics (driver only) - ! grid_o_t = config_biogrid_top_molecular_sublayer, & ! not used in Icepack - ! frazil_scav = config_fraction_biotracer_in_frazil, & ! BGC - ! ratio_Si2N_diatoms = config_ratio_Si_to_N_diatoms, & - ! ratio_Si2N_sp = config_ratio_Si_to_N_small_plankton, & - ! ratio_Si2N_phaeo = config_ratio_Si_to_N_phaeocystis, & - ! ratio_S2N_diatoms = config_ratio_S_to_N_diatoms, & - ! ratio_S2N_sp = config_ratio_S_to_N_small_plankton, & - ! ratio_S2N_phaeo = config_ratio_S_to_N_phaeocystis, & - ! ratio_Fe2C_diatoms = config_ratio_Fe_to_C_diatoms, & - ! ratio_Fe2C_sp = config_ratio_Fe_to_C_small_plankton, & - ! ratio_Fe2C_phaeo = config_ratio_Fe_to_C_phaeocystis, & - ! ratio_Fe2N_diatoms = config_ratio_Fe_to_N_diatoms, & - ! ratio_Fe2N_sp = config_ratio_Fe_to_N_small_plankton, & - ! ratio_Fe2N_phaeo = config_ratio_Fe_to_N_phaeocystis, & - ! ratio_Fe2DON = config_ratio_Fe_to_DON, & - ! ratio_Fe2DOC_s = config_ratio_Fe_to_DOC_saccharids, & - ! ratio_Fe2DOC_l = config_ratio_Fe_to_DOC_lipids, & - ! fr_resp = config_respiration_fraction_of_growth, & - ! tau_min = config_rapid_mobile_to_stationary_time, & - ! tau_max = config_long_mobile_to_stationary_time, & - ! algal_vel = config_algal_maximum_velocity, & - ! R_dFe2dust = config_ratio_Fe_to_dust, & - ! dustFe_sol = config_solubility_of_Fe_in_dust, & - ! chlabs_diatoms = config_chla_absorptivity_of_diatoms, & - ! chlabs_sp = config_chla_absorptivity_of_small_plankton, & - ! chlabs_phaeo = config_chla_absorptivity_of_phaeocystis, & - ! alpha2max_low_diatoms = config_light_attenuation_diatoms, & - ! alpha2max_low_sp = config_light_attenuation_small_plankton, & - ! alpha2max_low_phaeo = config_light_attenuation_phaeocystis, & - ! beta2max_diatoms = config_light_inhibition_diatoms, & - ! beta2max_sp = config_light_inhibition_small_plankton, & - ! beta2max_phaeo = config_light_inhibition_phaeocystis, & - ! mu_max_diatoms = config_maximum_growth_rate_diatoms, & - ! mu_max_sp = config_maximum_growth_rate_small_plankton, & - ! mu_max_phaeo = config_maximum_growth_rate_phaeocystis, & - ! mu_max_diatoms = config_temperature_growth_diatoms, & ! rename - ! mu_max_sp = config_temperature_growth_small_plankton, & - ! mu_max_phaeo = config_temperature_growth_phaeocystis, & - ! fr_graze_diatoms = config_grazed_fraction_diatoms, & - ! fr_graze_sp = config_grazed_fraction_small_plankton, & - ! fr_graze_phaeo = config_grazed_fraction_phaeocystis, & - ! mort_pre_diatoms = config_mortality_diatoms, & - ! mort_pre_sp = config_mortality_small_plankton, & - ! mort_pre_phaeo = config_mortality_phaeocystis, & - ! mort_Tdep_diatoms = config_temperature_mortality_diatoms, & - ! mort_Tdep_sp = config_temperature_mortality_small_plankton, & - ! mort_Tdep_phaeo = config_temperature_mortality_phaeocystis, & - ! k_exude_diatoms = config_exudation_diatoms, & - ! k_exude_sp = config_exudation_small_plankton, & - ! k_exude_phaeo = config_exudation_phaeocystis, & - ! K_Nit_diatoms = config_nitrate_saturation_diatoms, & - ! K_Nit_sp = config_nitrate_saturation_small_plankton, & - ! K_Nit_phaeo = config_nitrate_saturation_phaeocystis, & - ! K_Am_diatoms = config_ammonium_saturation_diatoms, & - ! K_Am_sp = config_ammonium_saturation_small_plankton, & - ! K_Am_phaeo = config_ammonium_saturation_phaeocystis, & - ! K_Sil_diatoms = config_silicate_saturation_diatoms, & - ! K_Sil_sp = config_silicate_saturation_small_plankton, & - ! K_Sil_phaeo = config_silicate_saturation_phaeocystis, & - ! K_Fe_diatoms = config_iron_saturation_diatoms, & - ! K_Fe_sp = config_iron_saturation_small_plankton, & - ! K_Fe_phaeo = config_iron_saturation_phaeocystis, & - ! f_don_protein = config_fraction_spilled_to_DON, & - ! kn_bac_protein = config_degredation_of_DON, & - ! f_don_Am_protein = config_fraction_DON_ammonium, & - ! f_doc_s = config_fraction_loss_to_saccharids, & - ! f_doc_l = config_fraction_loss_to_lipids, & - ! f_exude_s = config_fraction_exudation_to_saccharids, & - ! f_exude_l = config_fraction_exudation_to_lipids, & - ! k_bac_s = config_remineralization_saccharids, & - ! k_bac_l = config_remineralization_lipids, & - ! T_max = config_maximum_brine_temperature, & - ! fsal = config_salinity_dependence_of_growth, & - ! op_dep_min = config_minimum_optical_depth, & - ! fr_graze_s = config_slopped_grazing_fraction, & - ! fr_graze_e = config_excreted_fraction, & - ! fr_mort2min = config_fraction_mortality_to_ammonium, & - ! fr_dFe = config_fraction_iron_remineralized, & - ! k_nitrif = config_nitrification_rate, & - ! t_iron_conv = config_desorption_loss_particulate_iron, & - ! max_loss = config_maximum_loss_fraction, & - ! max_dfe_doc1 = config_maximum_ratio_iron_to_saccharids, & - ! fr_resp_s = config_respiration_loss_to_DMSPd, & - ! y_sk_DMS = config_DMSP_to_DMS_conversion_fraction, & - ! t_sk_conv = config_DMSP_to_DMS_conversion_time, & - ! t_sk_ox = config_DMS_oxidation_time, & - ! algaltype_diatoms = config_mobility_type_diatoms, & - ! algaltype_sp = config_mobility_type_small_plankton, & - ! algaltype_phaeo = config_mobility_type_phaeocystis, & - ! nitratetype = config_mobility_type_nitrate, & - ! ammoniumtype = config_mobility_type_ammonium, & - ! silicatetype = config_mobility_type_silicate, & - ! dmspptype = config_mobility_type_DMSPp, & - ! dmspdtype = config_mobility_type_DMSPd, & - ! humicstype = config_mobility_type_humics, & - ! doctype_s = config_mobility_type_saccharids, & - ! dictype_1 = config_mobility_type_lipids, & - ! dictype_1 = config_mobility_type_inorganic_carbon, & - ! dontype_protein = config_mobility_type_proteins, & - ! fedtype_1 = config_mobility_type_dissolved_iron, & - ! feptype_1 = config_mobility_type_particulate_iron, & - ! zaerotype_bc1 = config_mobility_type_black_carbon1, & - ! zaerotype_bc2 = config_mobility_type_black_carbon2, & - ! zaerotype_dust1 = config_mobility_type_dust1, & - ! zaerotype_dust2 = config_mobility_type_dust2, & - ! zaerotype_dust3 = config_mobility_type_dust3, & - ! zaerotype_dust4 = config_mobility_type_dust4, & - ! ratio_C2N_diatoms = config_ratio_C_to_N_diatoms, & - ! ratio_C2N_sp = config_ratio_C_to_N_small_plankton, & - ! ratio_C2N_phaeo = config_ratio_C_to_N_phaeocystis, & - ! ratio_chl2N_diatoms = config_ratio_chla_to_N_diatoms, & - ! ratio_chl2N_sp = config_ratio_chla_to_N_small_plankton, & - ! ratio_chl2N_phaeo = config_ratio_chla_to_N_phaeocystis, & - ! F_abs_chl_diatoms = config_scales_absorption_diatoms, & - ! F_abs_chl_sp = config_scales_absorption_small_plankton, & - ! F_abs_chl_phaeo = config_scales_absorption_phaeocystis, & - ! ratio_C2N_proteins = config_ratio_C_to_N_proteins, & - !----------------------------------------------------------------------- ! Parameters for thermodynamics !----------------------------------------------------------------------- @@ -12952,6 +11141,10 @@ subroutine init_icepack_package_configs(domain) ! solubility fraction ! dustFe_sol = config_solubility_of_Fe_in_dust + ! use_atm_dust_sol; + ! compute dust iron contribution in icepack + ! use_atm_dust_sol = .not.config_use_iron_solubility_file + ! chlabs_diatoms: ! chl absorption (1/m/(mg/m^3)) ! chlabs_diatoms = config_chla_absorptivity_of_diatoms @@ -14490,7 +12683,9 @@ end subroutine seaice_column_reinitialize_oceanic_fluxes subroutine init_column_tracer_object_for_biogeochemistry(domain, tracerObject) - use ice_colpkg, only: colpkg_init_zbgc + use icepack_intfc, only: icepack_init_zbgc + use icepack_intfc, only: icepack_init_parameters + use icepack_intfc, only: icepack_query_parameters type(domain_type), intent(in) :: & domain @@ -14500,7 +12695,7 @@ subroutine init_column_tracer_object_for_biogeochemistry(domain, tracerObject) logical, pointer :: & config_use_brine, & - config_use_vertical_zsalinity, & !echmod deprecate +! config_use_vertical_zsalinity, & !echmod deprecate config_use_vertical_biochemistry, & config_use_vertical_tracers, & config_use_skeletal_biochemistry, & @@ -14629,6 +12824,7 @@ subroutine init_column_tracer_object_for_biogeochemistry(domain, tracerObject) nParticulateIron, & nDissolvedIron, & nzAerosols, & + nZBGCTracers, & maxAerosolType, & maxAlgaeType, & maxDOCType, & @@ -14643,12 +12839,22 @@ subroutine init_column_tracer_object_for_biogeochemistry(domain, tracerObject) nTracers_temp, & iAerosols + real(kind=RKIND) :: & + rtmp1, & + rtmp2 + real (kind=RKIND), dimension (:), allocatable :: & + BGCTracerType, & + initialMobileFraction, & + retentionTime, & + releaseTime, & + newIceBGCFraction + ! save tracer array size nTracers_temp = tracerObject % nTracers tracerObject % nTracers = tracerObject % nTracersNotBio call MPAS_pool_get_config(domain % configs, "config_use_brine", config_use_brine) - call MPAS_pool_get_config(domain % configs, "config_use_vertical_zsalinity", config_use_vertical_zsalinity) !echmod deprecate +! call MPAS_pool_get_config(domain % configs, "config_use_vertical_zsalinity", config_use_vertical_zsalinity) !echmod deprecate call MPAS_pool_get_config(domain % configs, "config_use_shortwave_bioabsorption", config_use_shortwave_bioabsorption) call MPAS_pool_get_config(domain % configs, "config_use_vertical_tracers", config_use_vertical_tracers) call MPAS_pool_get_config(domain % configs, "config_use_skeletal_biochemistry", config_use_skeletal_biochemistry) @@ -14771,7 +12977,386 @@ subroutine init_column_tracer_object_for_biogeochemistry(domain, tracerObject) call MPAS_pool_get_config(domain % configs, "config_scales_absorption_phaeocystis", config_scales_absorption_phaeocystis) call MPAS_pool_get_config(domain % configs, "config_ratio_C_to_N_proteins", config_ratio_C_to_N_proteins) - call MPAS_pool_get_dimension(domain % blocklist % dimensions, "ONE", ONE) + call MPAS_pool_get_dimension(domain % blocklist % dimensions, "ONE", ONE) + call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nIceLayers", nIceLayers) + call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nSnowLayers", nSnowLayers) + call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nBioLayers",nBioLayers) + call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nAlgae", nAlgae) + call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nDOC", nDOC) + call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nDIC", nDIC) + call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nDON", nDON) + call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nParticulateIron", nParticulateIron) + call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nDissolvedIron", nDissolvedIron) + call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nzAerosols", nzAerosols) + call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nZBGCTracers", nZBGCTracers) + call MPAS_pool_get_dimension(domain % blocklist % dimensions, "maxAerosolType", maxAerosolType) + call MPAS_pool_get_dimension(domain % blocklist % dimensions, "maxAlgaeType", maxAlgaeType) + call MPAS_pool_get_dimension(domain % blocklist % dimensions, "maxDOCType", maxDOCType) + call MPAS_pool_get_dimension(domain % blocklist % dimensions, "maxDICType", maxDICType) + call MPAS_pool_get_dimension(domain % blocklist % dimensions, "maxDONType", maxDONType) + call MPAS_pool_get_dimension(domain % blocklist % dimensions, "maxIronType", maxIronType) + + allocate(BGCTracerType(nZBGCTracers)) + allocate(initialMobileFraction(nZBGCTracers)) + allocate(retentionTime(nZBGCTracers)) + allocate(releaseTime(nZBGCTracers)) + allocate(newIceBGCFraction(nZBGCTracers)) + + retentionTime(:) = 0.0_RKIND + releaseTime(:) = 0.0_RKIND + initialMobileFraction(:) = 0.0_RKIND + BGCTracerType(:) = 0.0_RKIND + newIceBGCFraction(:) = 0.0_RKIND + + use_nitrogen = .false. + if (config_use_skeletal_biochemistry .or. config_use_vertical_biochemistry) & + use_nitrogen = .true. + + allocate(tracerObject % index_verticalAerosolsConc(maxAerosolType)) + allocate(tracerObject % index_verticalAerosolsConcLayer(maxAerosolType)) + allocate(tracerObject % index_verticalAerosolsConcShortwave(maxAerosolType)) + tracerObject % nzAerosolsIndex = nzAerosols + + allocate(tracerObject % index_algaeConc(maxAlgaeType)) + allocate(tracerObject % index_algaeConcLayer(maxAlgaeType)) + tracerObject % nAlgaeIndex = nAlgae + + allocate(tracerObject % index_algalCarbon(maxAlgaeType)) + allocate(tracerObject % index_algalCarbonLayer(maxAlgaeType)) + tracerObject % nAlgalCarbonIndex = nAlgae + + allocate(tracerObject % index_DOCConc(maxDOCType)) + allocate(tracerObject % index_DOCConcLayer(maxDOCType)) + tracerObject % nDOCIndex = nDOC + + allocate(tracerObject % index_DICConc(maxDICType)) + allocate(tracerObject % index_DICConcLayer(maxDICType)) + tracerObject % nDICIndex = nDIC + + allocate(tracerObject % index_algalChlorophyll(maxAlgaeType)) + allocate(tracerObject % index_algalChlorophyllLayer(maxAlgaeType)) + tracerObject % nAlgalChlorophyllIndex = nAlgae + + allocate(tracerObject % index_DONConc(maxDONType)) + allocate(tracerObject % index_DONConcLayer(maxDONType)) + tracerObject % nDONIndex = nDON + + allocate(tracerObject % index_particulateIronConc(maxIronType)) + allocate(tracerObject % index_particulateIronConcLayer(maxIronType)) + tracerObject % nParticulateIronIndex = nParticulateIron + + allocate(tracerObject % index_dissolvedIronConc(maxIronType)) + allocate(tracerObject % index_dissolvedIronConcLayer(maxIronType)) + tracerObject % nDissolvedIronIndex = nDissolvedIron + + call icepack_init_parameters(& + ratio_Si2N_diatoms_in=config_ratio_Si_to_N_diatoms, & + ratio_Si2N_sp_in=config_ratio_Si_to_N_small_plankton, & + ratio_Si2N_phaeo_in=config_ratio_Si_to_N_phaeocystis, & + ratio_S2N_diatoms_in=config_ratio_S_to_N_diatoms, & + ratio_S2N_sp_in=config_ratio_S_to_N_small_plankton, & + ratio_S2N_phaeo_in=config_ratio_S_to_N_phaeocystis, & + ratio_Fe2C_diatoms_in=config_ratio_Fe_to_C_diatoms, & + ratio_Fe2C_sp_in=config_ratio_Fe_to_C_small_plankton, & + ratio_Fe2C_phaeo_in=config_ratio_Fe_to_C_phaeocystis, & + ratio_Fe2N_diatoms_in=config_ratio_Fe_to_N_diatoms, & + ratio_Fe2N_sp_in=config_ratio_Fe_to_N_small_plankton, & + ratio_Fe2N_phaeo_in=config_ratio_Fe_to_N_phaeocystis, & + ratio_Fe2DON_in=config_ratio_Fe_to_DON, & + ratio_Fe2DOC_s_in=config_ratio_Fe_to_DOC_saccharids, & + ratio_Fe2DOC_l_in=config_ratio_Fe_to_DOC_lipids, & + chlabs_diatoms_in=config_chla_absorptivity_of_diatoms, & + chlabs_sp_in=config_chla_absorptivity_of_small_plankton, & + chlabs_phaeo_in=config_chla_absorptivity_of_phaeocystis, & + alpha2max_low_diatoms_in=config_light_attenuation_diatoms, & + alpha2max_low_sp_in=config_light_attenuation_small_plankton, & + alpha2max_low_phaeo_in=config_light_attenuation_phaeocystis, & + beta2max_diatoms_in=config_light_inhibition_diatoms, & + beta2max_sp_in=config_light_inhibition_small_plankton, & + beta2max_phaeo_in=config_light_inhibition_phaeocystis, & + mu_max_diatoms_in=config_maximum_growth_rate_diatoms, & + mu_max_sp_in=config_maximum_growth_rate_small_plankton, & + mu_max_phaeo_in=config_maximum_growth_rate_phaeocystis, & + grow_Tdep_diatoms_in=config_temperature_growth_diatoms, & + grow_Tdep_sp_in=config_temperature_growth_small_plankton, & + grow_Tdep_phaeo_in=config_temperature_growth_phaeocystis, & + fr_graze_diatoms_in=config_grazed_fraction_diatoms, & + fr_graze_sp_in=config_grazed_fraction_small_plankton, & + fr_graze_phaeo_in=config_grazed_fraction_phaeocystis, & + mort_pre_diatoms_in=config_mortality_diatoms, & + mort_pre_sp_in=config_mortality_small_plankton, & + mort_pre_phaeo_in=config_mortality_phaeocystis, & + mort_Tdep_diatoms_in=config_temperature_mortality_diatoms, & + mort_Tdep_sp_in=config_temperature_mortality_small_plankton, & + mort_Tdep_phaeo_in=config_temperature_mortality_phaeocystis, & + k_exude_diatoms_in=config_exudation_diatoms, & + k_exude_sp_in=config_exudation_small_plankton, & + k_exude_phaeo_in=config_exudation_phaeocystis, & + K_Nit_diatoms_in=config_nitrate_saturation_diatoms, & + K_Nit_sp_in=config_nitrate_saturation_small_plankton, & + K_Nit_phaeo_in=config_nitrate_saturation_phaeocystis, & + K_Am_diatoms_in=config_ammonium_saturation_diatoms, & + K_Am_sp_in=config_ammonium_saturation_small_plankton, & + K_Am_phaeo_in=config_ammonium_saturation_phaeocystis, & + K_Sil_diatoms_in=config_silicate_saturation_diatoms, & + K_Sil_sp_in=config_silicate_saturation_small_plankton, & + K_Sil_phaeo_in=config_silicate_saturation_phaeocystis, & + K_Fe_diatoms_in=config_iron_saturation_diatoms, & + K_Fe_sp_in=config_iron_saturation_small_plankton, & + K_Fe_phaeo_in=config_iron_saturation_phaeocystis, & + f_don_protein_in=config_fraction_spilled_to_DON, & + kn_bac_protein_in=config_degredation_of_DON, & + f_don_Am_protein_in=config_fraction_DON_ammonium, & + f_doc_s_in=config_fraction_loss_to_saccharids, & + f_doc_l_in=config_fraction_loss_to_lipids, & + f_exude_s_in=config_fraction_exudation_to_saccharids, & + f_exude_l_in=config_fraction_exudation_to_lipids, & + k_bac_s_in=config_remineralization_saccharids, & + k_bac_l_in=config_remineralization_lipids, & + algaltype_diatoms_in=config_mobility_type_diatoms, & + algaltype_sp_in=config_mobility_type_small_plankton, & + algaltype_phaeo_in=config_mobility_type_phaeocystis, & + doctype_s_in=config_mobility_type_saccharids, & + doctype_l_in=config_mobility_type_lipids, & + dictype_1_in=config_mobility_type_inorganic_carbon, & + dontype_protein_in=config_mobility_type_proteins, & + fedtype_1_in=config_mobility_type_dissolved_iron, & + feptype_1_in=config_mobility_type_particulate_iron, & + zaerotype_bc1_in=config_mobility_type_black_carbon1, & + zaerotype_bc2_in=config_mobility_type_black_carbon2, & + zaerotype_dust1_in=config_mobility_type_dust1, & + zaerotype_dust2_in=config_mobility_type_dust2, & + zaerotype_dust3_in=config_mobility_type_dust3, & + zaerotype_dust4_in=config_mobility_type_dust4, & + ratio_C2N_diatoms_in=config_ratio_C_to_N_diatoms, & + ratio_C2N_sp_in=config_ratio_C_to_N_small_plankton, & + ratio_C2N_phaeo_in=config_ratio_C_to_N_phaeocystis, & + ratio_chl2N_diatoms_in=config_ratio_chla_to_N_diatoms, & + ratio_chl2N_sp_in=config_ratio_chla_to_N_small_plankton, & + ratio_chl2N_phaeo_in=config_ratio_chla_to_N_phaeocystis, & + F_abs_chl_diatoms_in=config_scales_absorption_diatoms, & + F_abs_chl_sp_in=config_scales_absorption_small_plankton, & + F_abs_chl_phaeo_in=config_scales_absorption_phaeocystis, & + ratio_C2N_proteins_in=config_ratio_C_to_N_proteins, & + nitratetype_in=config_mobility_type_nitrate, & + ammoniumtype_in=config_mobility_type_ammonium, & + dmspptype_in=config_mobility_type_DMSPp, & + dmspdtype_in=config_mobility_type_DMSPd, & + silicatetype_in=config_mobility_type_silicate, & + humtype_in=config_mobility_type_humics, & + frazil_scav_in=config_fraction_biotracer_in_frazil, & + initbio_frac_in=config_new_ice_fraction_biotracer, & + tau_min_in=config_rapid_mobile_to_stationary_time, & + tau_max_in=config_long_mobile_to_stationary_time) + + call init_zbgc_tracer_indices(domain, tracerObject, use_nitrogen, nTracers_temp, & + BGCTracerType, initialMobileFraction, retentionTime, & + releaseTime, newIceBGCFraction) + + call icepack_init_zbgc(bgc_tracer_type_in=BGCTracerType, & + zbgc_frac_init_in=initialMobileFraction, & + tau_ret_in=retentionTime, & + tau_rel_in=releaseTime, & + zbgc_init_frac_in=newIceBGCFraction) + + ! check calculated tracer array size + if (nTracers_temp /= tracerObject % nTracers) then + call mpas_log_write(& + "init_column_tracer_object_for_biogeochemistry: nTracers_temp: $i, nTracers: $i", & + messageType=MPAS_LOG_CRIT, intArgs=(/nTracers_temp, tracerObject % nTracers/)) + endif + + call mpas_log_write(" ----- compare values after init_zbgc -----") + + rtmp1 = config_new_ice_fraction_biotracer + call icepack_query_parameters(initbio_frac_out=rtmp2) + if (rtmp1 /= rtmp2) call mpas_log_write('initbio_frac differs $r $r',realArgs=(/rtmp1,rtmp2/)) + + rtmp1 = config_rapid_mobile_to_stationary_time + call icepack_query_parameters(tau_min_out=rtmp2) + if (rtmp1 /= rtmp2) call mpas_log_write('tau_min differs $r $r',realArgs=(/rtmp1,rtmp2/)) + + rtmp1 = config_long_mobile_to_stationary_time + call icepack_query_parameters(tau_max_out=rtmp2) + if (rtmp1 /= rtmp2) call mpas_log_write('tau_max differs $r $r',realArgs=(/rtmp1,rtmp2/)) + + deallocate(BGCTracerType) + deallocate(initialMobileFraction) + deallocate(retentionTime) + deallocate(releaseTime) + deallocate(newIceBGCFraction) + + end subroutine init_column_tracer_object_for_biogeochemistry + +!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +! +! init_zbgc_tracer_indices +! +!> \brief +!> \author Nicole Jeffery, LANL +!> \date 24 May 2024 +!> \details +!> Moves icepack_init_zbgc_tracer_indices to the interface +! +!----------------------------------------------------------------------- + + subroutine init_zbgc_tracer_indices(domain, tracerObject, use_nitrogen, nTracersTemp, & + BGCTracerType, initialMobileFraction, retentionTime, & + releaseTime, newIceBGCFraction) + + type(domain_type), intent(in) :: & + domain + + type(ciceTracerObjectType), intent(inout) :: & + tracerObject + + real(kind=RKIND), dimension(:), intent(inout) :: & + BGCTracerType, & + initialMobileFraction, & + retentionTime, & + releaseTime, & + newIceBGCFraction + + integer, intent(in) :: & + nTracersTemp + + logical, intent(in) :: & + use_nitrogen + + logical, pointer :: & + config_use_brine, & +! config_use_vertical_zsalinity, & !echmod deprecate + config_use_vertical_biochemistry, & + config_use_vertical_tracers, & + config_use_skeletal_biochemistry, & + config_use_shortwave_bioabsorption, & + config_use_nitrate, & + config_use_carbon, & + config_use_chlorophyll, & + config_use_ammonium, & + config_use_silicate, & + config_use_DMS, & + config_use_nonreactive, & + config_use_humics, & + config_use_DON, & + config_use_iron, & + config_use_zaerosols + + real(kind=RKIND), pointer :: & + config_mobility_type_diatoms, & + config_mobility_type_small_plankton, & + config_mobility_type_phaeocystis, & + config_mobility_type_nitrate, & + config_mobility_type_ammonium, & + config_mobility_type_silicate, & + config_mobility_type_DMSPp, & + config_mobility_type_DMSPd, & + config_mobility_type_humics, & + config_mobility_type_saccharids, & + config_mobility_type_lipids, & + config_mobility_type_inorganic_carbon, & + config_mobility_type_proteins, & + config_mobility_type_dissolved_iron, & + config_mobility_type_particulate_iron, & + config_mobility_type_black_carbon1, & + config_mobility_type_black_carbon2, & + config_mobility_type_dust1, & + config_mobility_type_dust2, & + config_mobility_type_dust3, & + config_mobility_type_dust4, & + config_rapid_mobile_to_stationary_time, & + config_long_mobile_to_stationary_time, & + config_fraction_biotracer_in_frazil, & + config_new_ice_fraction_biotracer + + integer, pointer :: & + nIceLayers, & + nSnowLayers, & + nBioLayers, & + nAlgae, & + nDOC, & + nDIC, & + nDON, & + nParticulateIron, & + nDissolvedIron, & + nzAerosols, & + nZBGCTracers, & + maxAerosolType, & + maxAlgaeType, & + maxDOCType, & + maxDICType, & + maxDONType, & + maxIronType + + integer :: & + iAerosols, & + nTracerDependOption, & + nCount, & + nTracerDepend, & + iBioLayer, & + iBioTracer + + real(kind=RKIND) :: & + rtmp1, & + rtmp2 + + real (kind=RKIND), dimension (:), allocatable :: & + algalType, & + docType, & + dicType, & + donType, & + fedType, & + fepType, & + zAeroType + + call MPAS_pool_get_config(domain % configs, "config_use_brine", config_use_brine) +! call MPAS_pool_get_config(domain % configs, "config_use_vertical_zsalinity", config_use_vertical_zsalinity) !echmod deprecate + call MPAS_pool_get_config(domain % configs, "config_use_shortwave_bioabsorption", config_use_shortwave_bioabsorption) + call MPAS_pool_get_config(domain % configs, "config_use_vertical_tracers", config_use_vertical_tracers) + call MPAS_pool_get_config(domain % configs, "config_use_skeletal_biochemistry", config_use_skeletal_biochemistry) + call MPAS_pool_get_config(domain % configs, "config_use_vertical_biochemistry", config_use_vertical_biochemistry) + call MPAS_pool_get_config(domain % configs, "config_use_nitrate", config_use_nitrate) + call MPAS_pool_get_config(domain % configs, "config_use_carbon", config_use_carbon) + call MPAS_pool_get_config(domain % configs, "config_use_chlorophyll", config_use_chlorophyll) + call MPAS_pool_get_config(domain % configs, "config_use_ammonium", config_use_ammonium) + call MPAS_pool_get_config(domain % configs, "config_use_silicate", config_use_silicate) + call MPAS_pool_get_config(domain % configs, "config_use_DMS", config_use_DMS) + call MPAS_pool_get_config(domain % configs, "config_use_nonreactive", config_use_nonreactive) + call MPAS_pool_get_config(domain % configs, "config_use_humics", config_use_humics) + call MPAS_pool_get_config(domain % configs, "config_use_DON", config_use_DON) + call MPAS_pool_get_config(domain % configs, "config_use_iron", config_use_iron) + call MPAS_pool_get_config(domain % configs, "config_use_zaerosols", config_use_zaerosols) + + call MPAS_pool_get_config(domain % configs, "config_mobility_type_diatoms", config_mobility_type_diatoms) + call MPAS_pool_get_config(domain % configs, "config_mobility_type_small_plankton", config_mobility_type_small_plankton) + call MPAS_pool_get_config(domain % configs, "config_mobility_type_phaeocystis", config_mobility_type_phaeocystis) + call MPAS_pool_get_config(domain % configs, "config_mobility_type_nitrate", config_mobility_type_nitrate) + call MPAS_pool_get_config(domain % configs, "config_mobility_type_ammonium", config_mobility_type_ammonium) + call MPAS_pool_get_config(domain % configs, "config_mobility_type_silicate", config_mobility_type_silicate) + call MPAS_pool_get_config(domain % configs, "config_mobility_type_DMSPp", config_mobility_type_DMSPp) + call MPAS_pool_get_config(domain % configs, "config_mobility_type_DMSPd", config_mobility_type_DMSPd) + call MPAS_pool_get_config(domain % configs, "config_mobility_type_humics", config_mobility_type_humics) + call MPAS_pool_get_config(domain % configs, "config_mobility_type_saccharids", config_mobility_type_saccharids) + call MPAS_pool_get_config(domain % configs, "config_mobility_type_lipids", config_mobility_type_lipids) + call MPAS_pool_get_config(domain % configs, "config_mobility_type_inorganic_carbon", config_mobility_type_inorganic_carbon) + call MPAS_pool_get_config(domain % configs, "config_mobility_type_proteins", config_mobility_type_proteins) + call MPAS_pool_get_config(domain % configs, "config_mobility_type_dissolved_iron", config_mobility_type_dissolved_iron) + call MPAS_pool_get_config(domain % configs, "config_mobility_type_particulate_iron", config_mobility_type_particulate_iron) + call MPAS_pool_get_config(domain % configs, "config_mobility_type_black_carbon1", config_mobility_type_black_carbon1) + call MPAS_pool_get_config(domain % configs, "config_mobility_type_black_carbon2", config_mobility_type_black_carbon2) + call MPAS_pool_get_config(domain % configs, "config_mobility_type_dust1", config_mobility_type_dust1) + call MPAS_pool_get_config(domain % configs, "config_mobility_type_dust2", config_mobility_type_dust2) + call MPAS_pool_get_config(domain % configs, "config_mobility_type_dust3", config_mobility_type_dust3) + call MPAS_pool_get_config(domain % configs, "config_mobility_type_dust4", config_mobility_type_dust4) + call MPAS_pool_get_config(domain % configs, "config_rapid_mobile_to_stationary_time", & + config_rapid_mobile_to_stationary_time) + call MPAS_pool_get_config(domain % configs, "config_long_mobile_to_stationary_time", & + config_long_mobile_to_stationary_time) + call MPAS_pool_get_config(domain % configs, "config_fraction_biotracer_in_frazil", & + config_fraction_biotracer_in_frazil) + call MPAS_pool_get_config(domain % configs, "config_new_ice_fraction_biotracer", & + config_new_ice_fraction_biotracer) + call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nIceLayers", nIceLayers) call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nSnowLayers", nSnowLayers) call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nBioLayers",nBioLayers) @@ -14782,6 +13367,7 @@ subroutine init_column_tracer_object_for_biogeochemistry(domain, tracerObject) call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nParticulateIron", nParticulateIron) call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nDissolvedIron", nDissolvedIron) call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nzAerosols", nzAerosols) + call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nZBGCTracers", nZBGCTracers) call MPAS_pool_get_dimension(domain % blocklist % dimensions, "maxAerosolType", maxAerosolType) call MPAS_pool_get_dimension(domain % blocklist % dimensions, "maxAlgaeType", maxAlgaeType) call MPAS_pool_get_dimension(domain % blocklist % dimensions, "maxDOCType", maxDOCType) @@ -14789,238 +13375,631 @@ subroutine init_column_tracer_object_for_biogeochemistry(domain, tracerObject) call MPAS_pool_get_dimension(domain % blocklist % dimensions, "maxDONType", maxDONType) call MPAS_pool_get_dimension(domain % blocklist % dimensions, "maxIronType", maxIronType) - use_nitrogen = .false. - if (config_use_skeletal_biochemistry .or. config_use_vertical_biochemistry) & - use_nitrogen = .true. - - allocate(tracerObject % index_verticalAerosolsConc(maxAerosolType)) - allocate(tracerObject % index_verticalAerosolsConcLayer(maxAerosolType)) - allocate(tracerObject % index_verticalAerosolsConcShortwave(maxAerosolType)) - tracerObject % nzAerosolsIndex = nzAerosols - - allocate(tracerObject % index_algaeConc(maxAlgaeType)) - allocate(tracerObject % index_algaeConcLayer(maxAlgaeType)) - tracerObject % nAlgaeIndex = nAlgae + tracerObject % nTracersNotBio = tracerObject % nTracers + tracerObject % index_brineFraction = 0 + if (config_use_brine) then + tracerObject % index_brineFraction = tracerObject % nTracers + 1 ! ice volume fraction with salt + tracerObject % nTracers = tracerObject % nTracers + 1 + tracerObject % parentIndex(tracerObject % index_brineFraction) = 1 ! volume-weighted + tracerObject % firstAncestorMask (tracerObject % index_brineFraction,1) = 0.0_RKIND ! volume-weighted + tracerObject % firstAncestorMask (tracerObject % index_brineFraction,2) = 1.0_RKIND ! volume-weighted + tracerObject % firstAncestorMask (tracerObject % index_brineFraction,3) = 0.0_RKIND ! volume-weighted + tracerObject % ancestorNumber(tracerObject % index_brineFraction) = 0 + tracerObject % ancestorIndices (tracerObject % index_brineFraction,1) = 0 + tracerObject % ancestorIndices (tracerObject % index_brineFraction,2) = 0 + endif + + nTracerDependOption = 0 ! if tracerObject % index_brineFraction /= 0 then use fbri dependency + if (tracerObject % index_brineFraction == 0) nTracerDependOption = -1 ! otherwise make tracers depend on ice volume + + !----------------------------------------------------------------- + ! biogeochemistry + !----------------------------------------------------------------- + + tracerObject % nBioTracers = 0 + tracerObject % nBioTracersShortwave = 0 + + ! vectors of size maxAlgaeType + tracerObject % index_algaeConcLayer(:) = 0 + tracerObject % index_algalCarbonLayer(:) = 0 + tracerObject % index_algalChlorophyllLayer(:) = 0 + tracerObject % index_algaeConc(:) = 0 + tracerObject % index_algalCarbon(:) = 0 + tracerObject % index_algalChlorophyll(:) = 0 + + ! vectors of size maxDICType + tracerObject % index_DICConcLayer(:) = 0 + tracerObject % index_DICConc(:) = 0 + + ! vectors of size maxDOCType + tracerObject % index_DOCConcLayer(:) = 0 + tracerObject % index_DOCConc(:) = 0 + + ! vectors of size maxDONType + tracerObject % index_DONConcLayer(:) = 0 + tracerObject % index_DONConc(:) = 0 + + ! vectors of size maxIronType + tracerObject % index_dissolvedIronConcLayer(:) = 0 + tracerObject % index_particulateIronConcLayer(:) = 0 + tracerObject % index_dissolvedIronConc(:) = 0 + tracerObject % index_particulateIronConc(:) = 0 + + ! vectors of size maxAerosolType + tracerObject % index_verticalAerosolsConcLayer(:) = 0 + tracerObject % index_verticalAerosolsConcShortwave(:) = 0 + tracerObject % index_verticalAerosolsConc(:) = 0 + + tracerObject % index_nitrateConcLayer = 0 + tracerObject % index_ammoniumConcLayer = 0 + tracerObject % index_silicateConcLayer = 0 + tracerObject % index_DMSPpConcLayer = 0 + tracerObject % index_DMSPdConcLayer = 0 + tracerObject % index_DMSConcLayer = 0 + tracerObject % index_nonreactiveConcLayer = 0 + tracerObject % index_humicsConcLayer = 0 + tracerObject % index_chlorophyllShortwave = 0 + tracerObject % index_LayerIndexToBioIndex(:) = 0 + tracerObject % index_LayerIndexToDataArray(:) = 0 + + tracerObject % index_nitrateConc = 0 + tracerObject % index_ammoniumConc = 0 + tracerObject % index_silicateConc = 0 + tracerObject % index_DMSPpConc = 0 + tracerObject % index_DMSPdConc = 0 + tracerObject % index_DMSConc = 0 + tracerObject % index_nonreactiveConc = 0 + tracerObject % index_humicsConc = 0 + + allocate(algalType(maxAlgaeType)) + allocate(docType(maxDOCType)) + allocate(dicType(maxDICType)) + allocate(donType(maxDONType)) + allocate(fedType(maxIronType)) + allocate(fepType(maxIronType)) + allocate(zAeroType(maxAerosolType)) + + algalType(1) = config_mobility_type_diatoms + algalType(2) = config_mobility_type_small_plankton + algalType(3) = config_mobility_type_phaeocystis + + docType(1) = config_mobility_type_saccharids + docType(2) = config_mobility_type_lipids + + dicType(1) = config_mobility_type_inorganic_carbon + + donType(1) = config_mobility_type_proteins + + fedType(1) = config_mobility_type_dissolved_iron + fepType(1) = config_mobility_type_particulate_iron + + zAeroType(1) = config_mobility_type_black_carbon1 + zAeroType(2) = config_mobility_type_black_carbon2 + zAeroType(3) = config_mobility_type_dust1 + zAeroType(4) = config_mobility_type_dust2 + zAeroType(5) = config_mobility_type_dust3 + zAeroType(6) = config_mobility_type_dust4 + + if (config_use_skeletal_biochemistry) then + + nCount = 1 + nTracerDepend = 0 + + if (config_use_shortwave_bioabsorption) then + tracerObject % index_chlorophyllShortwave = 1 + tracerObject % nBioTracersShortwave = nIceLayers+nSnowLayers+2 ! only the bottom layer + ! will be nonzero + endif + elseif (config_use_vertical_tracers) then ! defined on nBioLayers+1 in ice + ! and 2 snow layers (snow surface + interior) + nCount = nBioLayers + 1 + nTracerDepend = 2 + tracerObject % index_brineFraction + nTracerDependOption + + if (use_nitrogen) then + if (config_use_shortwave_bioabsorption) then + tracerObject % index_chlorophyllShortwave = 1 + tracerObject % nBioTracersShortwave = nIceLayers+nSnowLayers+2 + endif + endif ! use_nitrogen + + endif ! config_use_skeletal_biochemistry or config_use_vertical_tracers + + if (config_use_skeletal_biochemistry .or. config_use_vertical_tracers) then + + !----------------------------------------------------------------- + ! assign tracer indices and dependencies + ! BGCTracerType: < 0 purely mobile , >= 0 stationary + !------------------------------------------------------------------ + + if (use_nitrogen) then + do iBioTracer = 1, nAlgae + call init_bgc_tracer_indices(nCount, tracerObject % index_brineFraction, & + tracerObject % index_algaeConc(iBioTracer), & + tracerObject % index_algaeConcLayer(iBioTracer),& + algalType(iBioTracer), nTracerDepend, & + tracerObject % nTracers, & + tracerObject % nBioTracers, & + BGCTracerType, & + tracerObject % parentIndex, & + tracerObject % firstAncestorMask, & + tracerObject % ancestorNumber, & + tracerObject % ancestorIndices, & + tracerObject % index_LayerIndexToBioIndex) + tracerObject % index_LayerIndexToDataArray(tracerObject % index_algaeConcLayer(iBioTracer)) & + = iBioTracer + enddo ! iBioTracer + endif ! use_nitrogen + + if (config_use_nitrate) then + call init_bgc_tracer_indices(& + nCount, tracerObject % index_brineFraction, & + tracerObject % index_nitrateConc, & + tracerObject % index_nitrateConcLayer, & + config_mobility_type_nitrate, nTracerDepend, & + tracerObject % nTracers, & + tracerObject % nBioTracers, & + BGCTracerType, & + tracerObject % parentIndex, & + tracerObject % firstAncestorMask, & + tracerObject % ancestorNumber, & + tracerObject % ancestorIndices, & + tracerObject % index_LayerIndexToBioIndex) + tracerObject % index_LayerIndexToDataArray(tracerObject % index_nitrateConcLayer) & + = maxAlgaeType + 1 + endif ! config_use_nitrate + + if (config_use_carbon) then + ! + ! Algal C is not yet distinct from algal N + ! * Reqires exudation and/or changing C:N ratios + ! for implementation + ! + ! do iBioTracer = 1,nAlgae + ! call init_bgc_tracer_indices(nCount,tracerObject % index_brineFraction, & + ! tracerObject % index_algalCarbon(iBioTracer), & + ! tracerObject % index_algalCarbonLayer(iBioTracer), & + ! algalType(iBioTracer), nTracerDepend, & + ! tracerObject % nTracers, & + ! tracerObject % nBioTracers, & + ! BGCTracerType, & + ! tracerObject % parentIndex, & + ! tracerObject % firstAncestorMask, & + ! tracerObject % ancestorNumber, & + ! tracerObject % ancestorIndices, & + ! tracerObject % index_LayerIndexToBioIndex) + ! tracerObject % index_LayerIndexToDataArray(tracerObject % index_algalCarbonLayer(iBioTracer)) & + ! = maxAlgaeType + 1 + iBioTracer + ! enddo ! iBioTracer + + do iBioTracer = 1, nDOC + call init_bgc_tracer_indices(& + nCount, tracerObject % index_brineFraction, & + tracerObject % index_DOCConc(iBioTracer), & + tracerObject % index_DOCConcLayer(iBioTracer), & + docType(iBioTracer), nTracerDepend, & + tracerObject % nTracers, & + tracerObject % nBioTracers, & + BGCTracerType, & + tracerObject % parentIndex, & + tracerObject % firstAncestorMask, & + tracerObject % ancestorNumber, & + tracerObject % ancestorIndices, & + tracerObject % index_LayerIndexToBioIndex) + tracerObject % index_LayerIndexToDataArray(tracerObject % index_DOCConcLayer(iBioTracer)) & + = maxAlgaeType + 1 + iBioTracer + enddo ! iBioTracer + do iBioTracer = 1, nDIC + call init_bgc_tracer_indices(nCount, tracerObject % index_brineFraction, & + tracerObject % index_DICConc(iBioTracer), & + tracerObject % index_DICConcLayer(iBioTracer), & + dicType(iBioTracer), nTracerDepend, & + tracerObject % nTracers, & + tracerObject % nBioTracers, & + BGCTracerType, & + tracerObject % parentIndex, & + tracerObject % firstAncestorMask, & + tracerObject % ancestorNumber, & + tracerObject % ancestorIndices, & + tracerObject % index_LayerIndexToBioIndex) + tracerObject % index_LayerIndexToDataArray(tracerObject % index_DICConcLayer(iBioTracer)) & + = maxAlgaeType + maxDOCType + 1 + iBioTracer + enddo ! iBioTracer + endif ! config_use_carbon + + if (config_use_chlorophyll) then + do iBioTracer = 1, nAlgae + call init_bgc_tracer_indices(nCount, tracerObject % index_brineFraction, & + tracerObject % index_algalChlorophyll(iBioTracer), & + tracerObject % index_algalChlorophyllLayer(iBioTracer), & + algalType(iBioTracer), nTracerDepend, & + tracerObject % nTracers, & + tracerObject % nBioTracers, & + BGCTracerType, & + tracerObject % parentIndex, & + tracerObject % firstAncestorMask, & + tracerObject % ancestorNumber, & + tracerObject % ancestorIndices, & + tracerObject % index_LayerIndexToBioIndex) + tracerObject % index_LayerIndexToDataArray(tracerObject % index_algalChlorophyllLayer(iBioTracer)) & + = maxAlgaeType + 1 + maxDOCType + maxDICType + iBioTracer + enddo ! iBioTracer + endif ! config_use_chlorophyll + + if (config_use_ammonium) then + call init_bgc_tracer_indices(nCount, tracerObject % index_brineFraction, & + tracerObject % index_ammoniumConc, & + tracerObject % index_ammoniumConcLayer, & + config_mobility_type_ammonium, & + nTracerDepend, & + tracerObject % nTracers, & + tracerObject % nBioTracers, & + BGCTracerType, & + tracerObject % parentIndex, & + tracerObject % firstAncestorMask, & + tracerObject % ancestorNumber, & + tracerObject % ancestorIndices, & + tracerObject % index_LayerIndexToBioIndex) + tracerObject % index_LayerIndexToDataArray(tracerObject % index_ammoniumConcLayer) & + = 2*maxAlgaeType + maxDOCType + maxDICType + 2 + endif + if (config_use_silicate) then + call init_bgc_tracer_indices(nCount, tracerObject % index_brineFraction, & + tracerObject % index_silicateConc, & + tracerObject % index_silicateConcLayer, & + config_mobility_type_silicate, & + nTracerDepend, & + tracerObject % nTracers, & + tracerObject % nBioTracers, & + BGCTracerType, & + tracerObject % parentIndex, & + tracerObject % firstAncestorMask, & + tracerObject % ancestorNumber, & + tracerObject % ancestorIndices, & + tracerObject % index_LayerIndexToBioIndex) + tracerObject % index_LayerIndexToDataArray(tracerObject % index_silicateConcLayer) & + = 2*maxAlgaeType + maxDOCType + maxDICType + 3 + endif + if (config_use_DMS) then ! all together + call init_bgc_tracer_indices(nCount, tracerObject % index_brineFraction, & + tracerObject % index_DMSPpConc, & + tracerObject % index_DMSPpConcLayer, & + config_mobility_type_DMSPp, nTracerDepend, & + tracerObject % nTracers, & + tracerObject % nBioTracers, & + BGCTracerType, & + tracerObject % parentIndex, & + tracerObject % firstAncestorMask, & + tracerObject % ancestorNumber, & + tracerObject % ancestorIndices, & + tracerObject % index_LayerIndexToBioIndex) + tracerObject % index_LayerIndexToDataArray(tracerObject % index_DMSPpConcLayer) & + = 2*maxAlgaeType + maxDOCType + maxDICType + 4 + + call init_bgc_tracer_indices(nCount, tracerObject % index_brineFraction, & + tracerObject % index_DMSPdConc, & + tracerObject % index_DMSPdConcLayer, & + config_mobility_type_DMSPd, nTracerDepend, & + tracerObject % nTracers, & + tracerObject % nBioTracers, & + BGCTracerType, & + tracerObject % parentIndex, & + tracerObject % firstAncestorMask, & + tracerObject % ancestorNumber, & + tracerObject % ancestorIndices, & + tracerObject % index_LayerIndexToBioIndex) + tracerObject % index_LayerIndexToDataArray(tracerObject % index_DMSPdConcLayer) & + = 2*maxAlgaeType + maxDOCType + maxDICType + 5 + + call init_bgc_tracer_indices(nCount, tracerObject % index_brineFraction, & + tracerObject % index_DMSConc, & + tracerObject % index_DMSConcLayer, & + config_mobility_type_DMSPd, nTracerDepend, & + tracerObject % nTracers, & + tracerObject % nBioTracers, & + BGCTracerType, & + tracerObject % parentIndex, & + tracerObject % firstAncestorMask, & + tracerObject % ancestorNumber, & + tracerObject % ancestorIndices, & + tracerObject % index_LayerIndexToBioIndex) + tracerObject % index_LayerIndexToDataArray(tracerObject % index_DMSConcLayer) & + = 2*maxAlgaeType + maxDOCType + maxDICType + 6 + endif + if (config_use_nonreactive) then + call init_bgc_tracer_indices(nCount, tracerObject % index_brineFraction, & + tracerObject % index_nonreactiveConc, & + tracerObject % index_nonreactiveConcLayer, & + config_mobility_type_nitrate, nTracerDepend,& + tracerObject % nTracers, & + tracerObject % nBioTracers, & + BGCTracerType, & + tracerObject % parentIndex, & + tracerObject % firstAncestorMask, & + tracerObject % ancestorNumber, & + tracerObject % ancestorIndices, & + tracerObject % index_LayerIndexToBioIndex) + tracerObject % index_LayerIndexToDataArray(tracerObject % index_nonreactiveConcLayer) & + = 2*maxAlgaeType + maxDOCType + maxDICType + 7 + endif + if (config_use_DON) then + do iBioTracer = 1, nDON + call init_bgc_tracer_indices(nCount, tracerObject % index_brineFraction, & + tracerObject % index_DONConc(iBioTracer), & + tracerObject % index_DONConcLayer(iBioTracer), & + donType(iBioTracer), nTracerDepend, & + tracerObject % nTracers, & + tracerObject % nBioTracers, & + BGCTracerType, & + tracerObject % parentIndex, & + tracerObject % firstAncestorMask, & + tracerObject % ancestorNumber, & + tracerObject % ancestorIndices, & + tracerObject % index_LayerIndexToBioIndex) + tracerObject % index_LayerIndexToDataArray(tracerObject % index_DONConcLayer(iBioTracer)) & + = 2*maxAlgaeType + maxDOCType + maxDICType + 7 + iBioTracer + enddo ! iBioTracer + endif ! config_use_DON + if (config_use_iron) then + do iBioTracer = 1, nDissolvedIron + call init_bgc_tracer_indices(nCount, tracerObject % index_brineFraction, & + tracerObject % index_dissolvedIronConc(iBioTracer), & + tracerObject % index_dissolvedIronConcLayer(iBioTracer),& + fedType(iBioTracer), nTracerDepend, & + tracerObject % nTracers, & + tracerObject % nBioTracers, & + BGCTracerType, tracerObject % parentIndex, & + tracerObject % firstAncestorMask, & + tracerObject % ancestorNumber, & + tracerObject % ancestorIndices, & + tracerObject % index_LayerIndexToBioIndex) + tracerObject % index_LayerIndexToDataArray(tracerObject % index_dissolvedIronConcLayer(iBioTracer)) & + = 2*maxAlgaeType + maxDOCType + maxDICType + maxDONType + 7 + iBioTracer + enddo ! iBioTracer + do iBioTracer = 1, nParticulateIron + call init_bgc_tracer_indices(nCount, tracerObject % index_brineFraction, & + tracerObject % index_particulateIronConc(iBioTracer), & + tracerObject % index_particulateIronConcLayer(iBioTracer), & + fepType(iBioTracer), nTracerDepend, & + tracerObject % nTracers, & + tracerObject % nBioTracers, & + BGCTracerType, tracerObject % parentIndex, & + tracerObject % firstAncestorMask, & + tracerObject % ancestorNumber, & + tracerObject % ancestorIndices, & + tracerObject % index_LayerIndexToBioIndex) + tracerObject % index_LayerIndexToDataArray(tracerObject % index_particulateIronConcLayer(iBioTracer)) & + = 2*maxAlgaeType + maxDOCType + maxDICType + maxDONType + maxIronType + 7 + iBioTracer + enddo ! iBioTracer + endif ! config_use_iron + + if (config_use_humics) then + call init_bgc_tracer_indices(nCount, tracerObject % index_brineFraction, & + tracerObject % index_humicsConc, & + tracerObject % index_humicsConcLayer, & + config_mobility_type_humics, nTracerDepend, & + tracerObject % nTracers, & + tracerObject % nBioTracers, & + BGCTracerType, & + tracerObject % parentIndex, & + tracerObject % firstAncestorMask, & + tracerObject % ancestorNumber, & + tracerObject % ancestorIndices, & + tracerObject % index_LayerIndexToBioIndex) + tracerObject % index_LayerIndexToDataArray(tracerObject % index_humicsConcLayer) & + = 2*maxAlgaeType + maxDOCType + 8 + maxDICType + maxDONType + 2*maxIronType + maxAerosolType + endif + endif ! config_use_skeletal_biochemistry or config_use_vertical_tracers + + if (config_use_vertical_tracers) then ! defined on nBioLayers+1 in ice + ! and 2 snow layers (snow surface + interior) + nCount = nBioLayers + 1 + nTracerDepend = 2 + tracerObject % index_brineFraction + nTracerDependOption + + ! z layer aerosols + if (config_use_zaerosols) then + do iBioTracer = 1, nzAerosols + if (config_use_shortwave_bioabsorption) then + tracerObject % index_verticalAerosolsConcShortwave(iBioTracer) = & + tracerObject % nBioTracersShortwave + 1 + tracerObject % nBioTracersShortwave = & + tracerObject % nBioTracersShortwave + nIceLayers + nSnowLayers+2 + endif + call init_bgc_tracer_indices(nCount, tracerObject % index_brineFraction, & + tracerObject % index_verticalAerosolsConc(iBioTracer), & + tracerObject % index_verticalAerosolsConcLayer(iBioTracer), & + zAeroType(iBioTracer), nTracerDepend, & + tracerObject % nTracers, & + tracerObject % nBioTracers, & + BGCTracerType, tracerObject % parentIndex, & + tracerObject % firstAncestorMask, & + tracerObject % ancestorNumber, & + tracerObject % ancestorIndices, & + tracerObject % index_LayerIndexToBioIndex) + tracerObject % index_LayerIndexToDataArray(tracerObject % index_verticalAerosolsConcLayer(iBioTracer)) & + = 2*maxAlgaeType + maxDOCType + maxDICType + maxDONType + 2*maxIronType + 7 + iBioTracer + enddo ! iBioTracer + endif ! config_use_zaerosols + + tracerObject % index_mobileFraction = 0 + if (tracerObject % nBioTracers > 0) then + tracerObject % index_mobileFraction = tracerObject % nTracers + 1 + tracerObject % nTracers = tracerObject % nTracers + tracerObject % nBioTracers + do iBioLayer = 1,tracerObject % nBioTracers + initialMobileFraction(iBioLayer) = 1.0_RKIND + tracerObject % parentIndex(tracerObject % index_mobileFraction+iBioLayer-1) & + = 2+tracerObject % index_brineFraction + tracerObject % firstAncestorMask(tracerObject % index_mobileFraction+ iBioLayer - 1,1) = 0.0_RKIND + tracerObject % firstAncestorMask(tracerObject % index_mobileFraction+ iBioLayer - 1,2) = 1.0_RKIND + tracerObject % firstAncestorMask(tracerObject % index_mobileFraction+ iBioLayer - 1,3) = 0.0_RKIND + tracerObject % ancestorNumber(tracerObject % index_mobileFraction+ iBioLayer - 1) = 1 + tracerObject % ancestorIndices(tracerObject % index_mobileFraction+ iBioLayer - 1,1) & + = tracerObject % index_brineFraction + tracerObject % ancestorIndices(tracerObject % index_mobileFraction+ iBioLayer - 1,2) = 0 + retentionTime(iBioLayer) = 1.0_RKIND + releaseTime(iBioLayer) = 1.0_RKIND + + if (BGCTracerType(iBioLayer) >= 0.0_RKIND .and. BGCTracerType(iBioLayer) < 0.5_RKIND) then + retentionTime(iBioLayer) = config_rapid_mobile_to_stationary_time + releaseTime(iBioLayer) = config_long_mobile_to_stationary_time + initialMobileFraction(iBioLayer) = 1.0_RKIND + elseif (BGCTracerType(iBioLayer) >= 0.5_RKIND .and. BGCTracerType(iBioLayer) < 1.0_RKIND) then + retentionTime(iBioLayer) = config_rapid_mobile_to_stationary_time + releaseTime(iBioLayer) = config_rapid_mobile_to_stationary_time + initialMobileFraction(iBioLayer) = 1.0_RKIND + elseif (BGCTracerType(iBioLayer) >= 1.0_RKIND .and. BGCTracerType(iBioLayer) < 2.0_RKIND) then + retentionTime(iBioLayer) = config_long_mobile_to_stationary_time + releaseTime(iBioLayer) = config_rapid_mobile_to_stationary_time + initialMobileFraction(iBioLayer) = 1.0_RKIND + elseif (BGCTracerType(iBioLayer) >= 2.0_RKIND ) then + retentionTime(iBioLayer) = config_long_mobile_to_stationary_time + releaseTime(iBioLayer) = config_long_mobile_to_stationary_time + initialMobileFraction(iBioLayer) = 1.0_RKIND + endif + enddo + endif - allocate(tracerObject % index_algalCarbon(maxAlgaeType)) - allocate(tracerObject % index_algalCarbonLayer(maxAlgaeType)) - tracerObject % nAlgalCarbonIndex = nAlgae + endif ! config_use_vertical_tracers - allocate(tracerObject % index_DOCConc(maxDOCType)) - allocate(tracerObject % index_DOCConcLayer(maxDOCType)) - tracerObject % nDOCIndex = nDOC + do iBioLayer = 1, tracerObject % nBioTracers + newIceBGCFraction(iBioLayer) = config_fraction_biotracer_in_frazil + if (BGCTracerType(iBioLayer) < 0.0_RKIND) & + newIceBGCFraction(iBioLayer) = config_new_ice_fraction_biotracer + enddo - allocate(tracerObject % index_DICConc(maxDICType)) - allocate(tracerObject % index_DICConcLayer(maxDICType)) - tracerObject % nDICIndex = nDIC + if (.NOT.config_use_shortwave_bioabsorption) tracerObject % nBioTracersShortwave = 1 - allocate(tracerObject % index_algalChlorophyll(maxAlgaeType)) - allocate(tracerObject % index_algalChlorophyllLayer(maxAlgaeType)) - tracerObject % nAlgalChlorophyllIndex = nAlgae + !----------------------------------------------------------------- + ! final consistency checks + !----------------------------------------------------------------- - allocate(tracerObject % index_DONConc(maxDONType)) - allocate(tracerObject % index_DONConcLayer(maxDONType)) - tracerObject % nDONIndex = nDON + if (tracerObject % nBioTracers > nZBGCTracers) then + call mpas_log_write(& + "init_zbgc_tracer_indices: nBioTracers $i, greater than max nZBGCTracers: $i", & + messageType=MPAS_LOG_CRIT, intArgs=(/tracerObject % nBioTracers, nZBGCTracers/)) + endif - allocate(tracerObject % index_particulateIronConc(maxIronType)) - allocate(tracerObject % index_particulateIronConcLayer(maxIronType)) - tracerObject % nParticulateIronIndex = nParticulateIron + deallocate(algalType) + deallocate(docType) + deallocate(dicType) + deallocate(donType) + deallocate(fedType) + deallocate(fepType) + deallocate(zAeroType) - allocate(tracerObject % index_dissolvedIronConc(maxIronType)) - allocate(tracerObject % index_dissolvedIronConcLayer(maxIronType)) - tracerObject % nDissolvedIronIndex = nDissolvedIron + end subroutine init_zbgc_tracer_indices - call colpkg_init_zbgc(& - nBioLayers, & - nIceLayers, & - nSnowLayers, & - nAlgae, & - nzAerosols, & - nDOC, & - nDIC, & - nDON, & - nDissolvedIron, & - nParticulateIron, & - tracerObject % firstAncestorMask, & - tracerObject % parentIndex, & - tracerObject % ancestorNumber, & - tracerObject % ancestorIndices, & - tracerObject % nBioTracersShortwave, & - config_use_brine, & - tracerObject % index_brineFraction,& - tracerObject % nTracers, & - tracerObject % nBioTracers, & - tracerObject % index_nitrateConc, & - tracerObject % index_ammoniumConc, & - tracerObject % index_silicateConc, & - tracerObject % index_DMSConc, & - tracerObject % index_nonreactiveConc, & - tracerObject % index_verticalSalinity, & - tracerObject % index_algaeConc, & - tracerObject % index_algalCarbon, & - tracerObject % index_algalChlorophyll, & - tracerObject % index_DOCConc, & - tracerObject % index_DONConc, & - tracerObject % index_DICConc, & - tracerObject % index_verticalAerosolsConc, & - tracerObject % index_DMSPpConc, & - tracerObject % index_DMSPdConc, & - tracerObject % index_dissolvedIronConc, & - tracerObject % index_particulateIronConc, & - tracerObject % index_mobileFraction, & - config_use_nitrate, & - config_use_ammonium, & - config_use_silicate, & - config_use_DMS, & - config_use_nonreactive, & - config_use_vertical_zsalinity, & !echmod deprecate - use_nitrogen, & - config_use_carbon, & - config_use_chlorophyll, & - config_use_DON, & - config_use_iron,& - config_use_zaerosols, & - tracerObject % index_verticalAerosolsConcShortwave, & - tracerObject % index_chlorophyllShortwave, & - tracerObject % index_algaeConcLayer, & - tracerObject % index_nitrateConcLayer, & - tracerObject % index_ammoniumConcLayer, & - tracerObject % index_silicateConcLayer, & - tracerObject % index_DMSConcLayer, & - tracerObject % index_DMSPpConcLayer, & - tracerObject % index_DMSPdConcLayer, & - tracerObject % index_algalCarbonLayer, & - tracerObject % index_algalChlorophyllLayer, & - tracerObject % index_DICConcLayer, & - tracerObject % index_DOCConcLayer, & - tracerObject % index_nonreactiveConcLayer, & - tracerObject % index_DONConcLayer, & - tracerObject % index_dissolvedIronConcLayer, & - tracerObject % index_particulateIronConcLayer, & - tracerObject % index_verticalAerosolsConcLayer, & - tracerObject % index_humicsConc, & - tracerObject % index_humicsConcLayer, & - config_use_humics, & - config_use_vertical_zsalinity, & !echmod deprecate - config_use_skeletal_biochemistry, & - config_use_vertical_tracers, & - config_use_shortwave_bioabsorption, & - config_use_vertical_biochemistry, & - config_fraction_biotracer_in_frazil, & - config_new_ice_fraction_biotracer, & - tracerObject % index_LayerIndexToDataArray, & - tracerObject % index_LayerIndexToBioIndex, & - tracerObject % nTracersNotBio, & - maxAlgaeType, & - maxDOCType, & - maxDICType, & - maxDONType, & - maxIronType, & - config_ratio_Si_to_N_diatoms, & - config_ratio_Si_to_N_small_plankton, & - config_ratio_Si_to_N_phaeocystis, & - config_ratio_S_to_N_diatoms, & - config_ratio_S_to_N_small_plankton, & - config_ratio_S_to_N_phaeocystis, & - config_ratio_Fe_to_C_diatoms, & - config_ratio_Fe_to_C_small_plankton, & - config_ratio_Fe_to_C_phaeocystis, & - config_ratio_Fe_to_N_diatoms, & - config_ratio_Fe_to_N_small_plankton, & - config_ratio_Fe_to_N_phaeocystis, & - config_ratio_Fe_to_DON, & - config_ratio_Fe_to_DOC_saccharids, & - config_ratio_Fe_to_DOC_lipids, & - config_chla_absorptivity_of_diatoms, & - config_chla_absorptivity_of_small_plankton, & - config_chla_absorptivity_of_phaeocystis, & - config_light_attenuation_diatoms, & - config_light_attenuation_small_plankton, & - config_light_attenuation_phaeocystis, & - config_light_inhibition_diatoms, & - config_light_inhibition_small_plankton, & - config_light_inhibition_phaeocystis, & - config_maximum_growth_rate_diatoms, & - config_maximum_growth_rate_small_plankton, & - config_maximum_growth_rate_phaeocystis, & - config_temperature_growth_diatoms, & - config_temperature_growth_small_plankton, & - config_temperature_growth_phaeocystis, & - config_grazed_fraction_diatoms, & - config_grazed_fraction_small_plankton, & - config_grazed_fraction_phaeocystis, & - config_mortality_diatoms, & - config_mortality_small_plankton, & - config_mortality_phaeocystis, & - config_temperature_mortality_diatoms, & - config_temperature_mortality_small_plankton, & - config_temperature_mortality_phaeocystis, & - config_exudation_diatoms, & - config_exudation_small_plankton, & - config_exudation_phaeocystis, & - config_nitrate_saturation_diatoms, & - config_nitrate_saturation_small_plankton, & - config_nitrate_saturation_phaeocystis, & - config_ammonium_saturation_diatoms, & - config_ammonium_saturation_small_plankton, & - config_ammonium_saturation_phaeocystis, & - config_silicate_saturation_diatoms, & - config_silicate_saturation_small_plankton, & - config_silicate_saturation_phaeocystis, & - config_iron_saturation_diatoms, & - config_iron_saturation_small_plankton, & - config_iron_saturation_phaeocystis, & - config_fraction_spilled_to_DON, & - config_degredation_of_DON, & - config_fraction_DON_ammonium, & - config_fraction_loss_to_saccharids, & - config_fraction_loss_to_lipids, & - config_fraction_exudation_to_saccharids, & - config_fraction_exudation_to_lipids, & - config_remineralization_saccharids, & - config_remineralization_lipids, & - config_mobility_type_diatoms, & - config_mobility_type_small_plankton, & - config_mobility_type_phaeocystis, & - config_mobility_type_saccharids, & - config_mobility_type_lipids, & - config_mobility_type_inorganic_carbon, & - config_mobility_type_proteins, & - config_mobility_type_dissolved_iron, & - config_mobility_type_particulate_iron, & - config_mobility_type_black_carbon1, & - config_mobility_type_black_carbon2, & - config_mobility_type_dust1, & - config_mobility_type_dust2, & - config_mobility_type_dust3, & - config_mobility_type_dust4, & - config_ratio_C_to_N_diatoms, & - config_ratio_C_to_N_small_plankton, & - config_ratio_C_to_N_phaeocystis, & - config_ratio_chla_to_N_diatoms, & - config_ratio_chla_to_N_small_plankton, & - config_ratio_chla_to_N_phaeocystis, & - config_scales_absorption_diatoms, & - config_scales_absorption_small_plankton, & - config_scales_absorption_phaeocystis, & - config_ratio_C_to_N_proteins, & - config_mobility_type_nitrate, & - config_mobility_type_ammonium, & - config_mobility_type_DMSPp, & - config_mobility_type_DMSPd, & - config_mobility_type_silicate, & - config_mobility_type_humics, & - config_rapid_mobile_to_stationary_time, & - config_long_mobile_to_stationary_time) +!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +! +! init_bgc_tracer_indices +! +!> \brief +!> \author Nicole Jeffery, LANL +!> \date 24 May 2024 +!> \details +!> +!> Moves icepack_init_bgc_trcr to the interface +! +!----------------------------------------------------------------------- - ! check calculated tracer array size - if (nTracers_temp /= tracerObject % nTracers) then - call mpas_log_write(& - "init_column_tracer_object_for_biogeochemistry: nTracers_temp: $i, nTracers: $i", & - messageType=MPAS_LOG_CRIT, intArgs=(/nTracers_temp, tracerObject % nTracers/)) - endif + subroutine init_bgc_tracer_indices( nCount, iBrineFraction, & + iBGCConc, iBGCConcLayer, & + BGCType, nTracerDepend, & + nTracers, nBioTracers, & + BGCTracerType, parentIndexBGC, & + firstAncestorMaskBGC, & + ancestorNumberBGC, & + ancestorIndicesBGC, & + layerIndexToBioIndex) + + integer, intent(in) :: & + nCount , & ! counter + nTracerDepend , & ! tracer dependency index + iBrineFraction + + integer, intent(inout) :: & + nTracers , & ! number of tracers + nBioTracers , & ! number of bio tracers + iBGCConc , & ! tracer index + iBGCConcLayer ! bio tracer index + + integer, dimension(:), intent(inout) :: & + parentIndexBGC , & ! tracer dependencies + ancestorNumberBGC, & ! number of underlying tracer layers + layerIndexToBioIndex + + integer, dimension(:,:), intent(inout) :: & + ancestorIndicesBGC ! indices of underlying tracer layers + + real (kind=RKIND), dimension(:,:), intent(inout) :: & + firstAncestorMaskBGC ! = 0 or 1 depending on tracer dependency + ! argument 2: (1) aice, (2) vice, (3) vsno + + real (kind=RKIND), intent(in) :: & + BGCType ! bio tracer transport type (mobile vs stationary) + + real (kind=RKIND), dimension(:), intent(inout) :: & + BGCTracerType ! bio tracer transport type array + + ! local variables + + integer :: & + iCount , & ! loop index + nTemp , & ! temporary values + ancestorIndicesBGC1, & ! temporary values + ancestorIndicesBGC2 + + real (kind=RKIND) :: & + firstAncestorMaskBGC1, & ! temporary values + firstAncestorMaskBGC2, & + firstAncestorMaskBGC3 + + iBGCConc = nTracers + 1 + nBioTracers = nBioTracers + 1 + iBGCConcLayer = nBioTracers + BGCTracerType(nBioTracers) = BGCType + + if (nCount > 1) then + ! include vertical bgc in snow + do iCount = nCount, nCount+1 + nTracers = nTracers + 1 + parentIndexBGC (iBGCConc + iCount ) = 2 ! snow volume + firstAncestorMaskBGC (iBGCConc + iCount,1) = 0.0_RKIND + firstAncestorMaskBGC (iBGCConc + iCount,2) = 0.0_RKIND + firstAncestorMaskBGC (iBGCConc + iCount,3) = 1.0_RKIND + ancestorNumberBGC(iBGCConc + iCount ) = 0 + ancestorIndicesBGC (iBGCConc + iCount,1) = 0 + ancestorIndicesBGC (iBGCConc + iCount,2) = 0 + enddo - end subroutine init_column_tracer_object_for_biogeochemistry + firstAncestorMaskBGC1 = 0.0_RKIND + firstAncestorMaskBGC2 = 1.0_RKIND + firstAncestorMaskBGC3 = 0.0_RKIND + nTemp = 1 + ancestorIndicesBGC1 = iBrineFraction + ancestorIndicesBGC2 = 0 + else ! nCount = 1 + firstAncestorMaskBGC1 = 1.0_RKIND + firstAncestorMaskBGC2 = 0.0_RKIND + firstAncestorMaskBGC3 = 0.0_RKIND + nTemp = 0 + ancestorIndicesBGC1 = 0 + ancestorIndicesBGC2 = 0 + endif ! nCount + + do iCount = 1, nCount !in ice + nTracers = nTracers + 1 + parentIndexBGC (iBGCConc + iCount - 1 ) = nTracerDepend + firstAncestorMaskBGC (iBGCConc + iCount - 1,1) = firstAncestorMaskBGC1 + firstAncestorMaskBGC (iBGCConc + iCount - 1,2) = firstAncestorMaskBGC2 + firstAncestorMaskBGC (iBGCConc + iCount - 1,3) = firstAncestorMaskBGC3 + ancestorNumberBGC(iBGCConc + iCount - 1 ) = nTemp + ancestorIndicesBGC (iBGCConc + iCount - 1,1) = ancestorIndicesBGC1 + ancestorIndicesBGC (iBGCConc + iCount - 1,2) = ancestorIndicesBGC2 + enddo + + layerIndexToBioIndex (iBGCConcLayer) = iBGCConc + + end subroutine init_bgc_tracer_indices !||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ! @@ -15036,10 +14015,10 @@ end subroutine init_column_tracer_object_for_biogeochemistry subroutine init_column_biogeochemistry_profiles(domain, tracerObject) - use ice_colpkg, only: & - colpkg_init_bgc, & - colpkg_init_hbrine!, & -! colpkg_init_zsalinity !echmod deprecate + use icepack_intfc, only: & + icepack_init_bgc, & + icepack_init_hbrine, & + icepack_load_ocean_bio_array type(domain_type), intent(inout) :: domain @@ -15057,13 +14036,9 @@ subroutine init_column_biogeochemistry_profiles(domain, tracerObject) logical, pointer :: & config_use_brine, & -! config_use_vertical_zsalinity, & !echmod deprecate config_use_vertical_tracers, & config_use_skeletal_biochemistry, & -! config_do_restart_zsalinity, & !echmod deprecate - config_do_restart_bgc, & - config_do_restart_hbrine, & - config_use_macromolecules + config_do_restart_hbrine real(kind=RKIND), pointer :: & config_dt, & @@ -15082,7 +14057,6 @@ subroutine init_column_biogeochemistry_profiles(domain, tracerObject) biologyGrid, & ! bgrid verticalShortwaveGrid, & ! swgrid interfaceGrid, & ! icgrid - rayleighCriteriaReal, & DOCPoolFractions real(kind=RKIND), dimension(:,:), pointer :: & @@ -15111,27 +14085,13 @@ subroutine init_column_biogeochemistry_profiles(domain, tracerObject) brineFraction integer, pointer :: & - nCellsSolve, & - nIceLayers, & - nBioLayers, & - nBioLayersP1, & - nBioLayersP2, & - nCategories, & - nShortwaveBio, & - nZBGCTracers, & - maxAerosolType, & - maxAlgaeType, & - maxDOCType, & - maxDICType, & - maxDONType, & - maxIronType + nCellsSolve integer :: & iCell logical :: & abortFlag, & - rayleighCriteria, & setGetPhysicsTracers, & setGetBGCTracers @@ -15139,15 +14099,11 @@ subroutine init_column_biogeochemistry_profiles(domain, tracerObject) abortMessage call MPAS_pool_get_config(domain % configs, "config_use_brine", config_use_brine) -! call MPAS_pool_get_config(domain % configs, "config_do_restart_zsalinity", config_do_restart_zsalinity) !echmod deprecate - call MPAS_pool_get_config(domain % configs, "config_do_restart_bgc", config_do_restart_bgc) call MPAS_pool_get_config(domain % configs, "config_do_restart_hbrine", config_do_restart_hbrine) -! call MPAS_pool_get_config(domain % configs, "config_use_vertical_zsalinity", config_use_vertical_zsalinity) !echmod deprecate call MPAS_pool_get_config(domain % configs, "config_use_skeletal_biochemistry", config_use_skeletal_biochemistry) call MPAS_pool_get_config(domain % configs, "config_use_vertical_tracers", config_use_vertical_tracers) call MPAS_pool_get_config(domain % configs, "config_dt", config_dt) call MPAS_pool_get_config(domain % configs, "config_snow_porosity_at_ice_surface", config_snow_porosity_at_ice_surface) - call MPAS_pool_get_config(domain % configs, "config_use_macromolecules", config_use_macromolecules) abortFlag = .false. @@ -15172,7 +14128,6 @@ subroutine init_column_biogeochemistry_profiles(domain, tracerObject) call MPAS_pool_get_array(biogeochemistry, "bioTracerShortwave", bioTracerShortwave) call MPAS_pool_get_array(biogeochemistry, "interfaceBiologyGrid", interfaceBiologyGrid) call MPAS_pool_get_array(biogeochemistry, "interfaceGrid", interfaceGrid) - call MPAS_pool_get_array(biogeochemistry, "rayleighCriteriaReal", rayleighCriteriaReal) call MPAS_pool_get_array(biogeochemistry, "verticalGrid", verticalGrid) call MPAS_pool_get_array(biogeochemistry, "biologyGrid", biologyGrid) call MPAS_pool_get_array(biogeochemistry, "verticalShortwaveGrid", verticalShortwaveGrid) @@ -15200,29 +14155,14 @@ subroutine init_column_biogeochemistry_profiles(domain, tracerObject) call MPAS_pool_get_array(tracers, "brineFraction", brineFraction, 1) call MPAS_pool_get_dimension(block % dimensions, "nCellsSolve", nCellsSolve) - call MPAS_pool_get_dimension(block % dimensions, "nCategories", nCategories) - call MPAS_pool_get_dimension(block % dimensions, "nIceLayers", nIceLayers) - call MPAS_pool_get_dimension(block % dimensions, "nBioLayers", nBioLayers) - call MPAS_pool_get_dimension(block % dimensions, "nBioLayersP1", nBioLayersP1) - call MPAS_pool_get_dimension(block % dimensions, "nBioLayersP2", nBioLayersP2) - call MPAS_pool_get_dimension(block % dimensions, "nShortwaveBio", nShortwaveBio) - call MPAS_pool_get_dimension(block % dimensions, "nZBGCTracers", nZBGCTracers) - call MPAS_pool_get_dimension(block % dimensions, "maxAerosolType", maxAerosolType) - call MPAS_pool_get_dimension(block % dimensions, "maxAlgaeType", maxAlgaeType) - call MPAS_pool_get_dimension(block % dimensions, "maxDOCType", maxDOCType) - call MPAS_pool_get_dimension(block % dimensions, "maxDICType", maxDICType) - call MPAS_pool_get_dimension(block % dimensions, "maxDONType", maxDONType) - call MPAS_pool_get_dimension(block % dimensions, "maxIronType", maxIronType) - - call colpkg_init_hbrine(& - biologyGrid, & - interfaceBiologyGrid, & - verticalGrid, & - interfaceGrid, & - verticalShortwaveGrid, & - nBioLayers, & - nIceLayers, & - config_snow_porosity_at_ice_surface) + + call icepack_init_hbrine(& + bgrid_out=biologyGrid, & + igrid_out=interfaceBiologyGrid, & + cgrid_out=verticalGrid, & + icgrid_out=interfaceGrid, & + swgrid_out=verticalShortwaveGrid, & + phi_snow=config_snow_porosity_at_ice_surface) do iCell = 1, nCellsSolve if (.not. config_do_restart_hbrine) then @@ -15237,65 +14177,33 @@ subroutine init_column_biogeochemistry_profiles(domain, tracerObject) call set_cice_tracer_array_category(block, tracerObject, & tracerArrayCategory, iCell, setGetPhysicsTracers, setGetBGCTracers) -! if (config_use_vertical_zsalinity) then !echmod deprecate -! call colpkg_init_zsalinity(& -! nBioLayers, & -! tracerObject % nTracersNotBio, & -! config_do_restart_zsalinity, & -! rayleighCriteria, & -! rayleighCriteriaReal(iCell), & -! tracerArrayCategory(tracerObject % nTracersNotBio+1:tracerObject % nTracers,:), & -! tracerObject % index_verticalSalinity, & -! nCategories, & -! seaSurfaceSalinity(iCell)) -! endif - if (config_use_vertical_tracers .or. config_use_skeletal_biochemistry) then - call colpkg_init_bgc(& - config_dt, & - nCategories, & - nBioLayers, & - nIceLayers, & - tracerObject % nTracersNotBio, & - verticalGrid, & - interfaceBiologyGrid, & - config_do_restart_bgc, & - tracerObject % nTracers, & - tracerObject % nBiotracers, & - iceSalinity(:,:,iCell), & - tracerArrayCategory(tracerObject % nTracersNotBio+1:tracerObject % nTracers,:), & - seaSurfaceSalinity(iCell), & - oceanNitrateConc(iCell), & - oceanAmmoniumConc(iCell), & - oceanSilicateConc(iCell), & - oceanDMSPConc(iCell), & - oceanDMSConc(iCell), & - oceanAlgaeConc(:,iCell), & - oceanDOCConc(:,iCell), & - oceanDONConc(:,iCell), & - oceanDICConc(:,iCell), & - oceanDissolvedIronConc(:,iCell), & - oceanParticulateIronConc(:,iCell), & - oceanZAerosolConc(:,iCell), & - oceanHumicsConc(iCell), & - oceanBioConcentrations(:,iCell), & - maxAlgaeType, & - maxDOCType, & - maxDICType, & - maxDONType, & - maxIronType, & - nZBGCTracers, & - maxAerosolType, & - DOCPoolFractions, & - config_use_macromolecules, & - abortFlag, & - abortMessage) - - if (abortFlag) then - call mpas_log_write(& - "init_column_biogeochemistry_profiles: colpkg_init_bgc: "//trim(abortMessage), & - messageType=MPAS_LOG_CRIT) - endif + + call icepack_load_ocean_bio_array(& + nit=oceanNitrateConc(iCell), & + amm=oceanAmmoniumConc(iCell), & + sil=oceanSilicateConc(iCell), & + dmsp=oceanDMSPConc(iCell), & + dms=oceanDMSConc(iCell), & + algalN=oceanAlgaeConc(:,iCell), & + doc=oceanDOCConc(:,iCell), & + don=oceanDONConc(:,iCell), & + dic=oceanDICConc(:,iCell), & + fed=oceanDissolvedIronConc(:,iCell), & + fep=oceanParticulateIronConc(:,iCell), & + zaeros=oceanZAerosolConc(:,iCell), & + ocean_bio_all=oceanBioConcentrations(:,iCell), & + hum=oceanHumicsConc(iCell)) + + call icepack_init_bgc(& + sicen=iceSalinity(:,:,iCell), & + trcrn=tracerArrayCategory(tracerObject % nTracersNotBio+1:tracerObject % nTracers,:), & + sss=seaSurfaceSalinity(iCell), & + ocean_bio_all=oceanBioConcentrations(:,iCell), & + DOCPoolFractions=DOCPoolFractions) + + call seaice_icepack_write_warnings(icepack_warnings_aborted()) + endif ! biogeochemistry ! get the category tracer array @@ -15495,10 +14403,10 @@ subroutine seaice_icepack_reinitialize_diagnostics_thermodynamics(domain) pondFreshWaterFlux(:) = 0.0_RKIND - !fresh_ai (:,:,:) = c0 - !fsalt_ai (:,:,:) = c0 - !fhocn_ai (:,:,:) = c0 - !fswthru_ai(:,:,:) = c0 + !fresh_ai (:,:,:) = 0.0_RKIND + !fsalt_ai (:,:,:) = 0.0_RKIND + !fhocn_ai (:,:,:) = 0.0_RKIND + !fswthru_ai(:,:,:) = 0.0_RKIND ! shortwave call MPAS_pool_get_subpool(block % structs, "shortwave", shortwavePool) @@ -15810,8 +14718,9 @@ subroutine seaice_icepack_reinitialize_diagnostics_bgc(domain) config_use_column_biogeochemistry, & config_use_column_shortwave, & config_use_column_physics, & - config_use_vertical_biochemistry!, & -! config_use_vertical_zsalinity !echmod deprecate + config_use_vertical_tracers, & +! config_use_vertical_zsalinity, & + config_use_zaerosols call MPAS_pool_get_config(domain % blocklist % configs, "config_use_column_physics", config_use_column_physics) @@ -15822,15 +14731,16 @@ subroutine seaice_icepack_reinitialize_diagnostics_bgc(domain) ! biogeochemistry call MPAS_pool_get_config(block % configs, "config_use_column_biogeochemistry", config_use_column_biogeochemistry) - call MPAS_pool_get_config(block % configs, "config_use_vertical_biochemistry", config_use_vertical_biochemistry) -! call MPAS_pool_get_config(block % configs, "config_use_vertical_zsalinity", config_use_vertical_zsalinity) !echmod deprecate + call MPAS_pool_get_config(block % configs, "config_use_zaerosols", config_use_zaerosols) + call MPAS_pool_get_config(block % configs, "config_use_vertical_tracers", config_use_vertical_tracers) +! call MPAS_pool_get_config(block % configs, "config_use_vertical_zsalinity", config_use_vertical_zsalinity) - if (config_use_column_biogeochemistry) then + if (config_use_column_biogeochemistry .or. config_use_zaerosols) then call MPAS_pool_get_subpool(block % structs, "biogeochemistry", biogeochemistryPool) call MPAS_pool_get_subpool(block % structs, "diagnostics_biogeochemistry", diagnostics_biogeochemistryPool) - if (config_use_vertical_biochemistry) then + if (config_use_vertical_tracers) then call MPAS_pool_get_array(biogeochemistryPool, "primaryProduction", primaryProduction) call MPAS_pool_get_array(biogeochemistryPool, "totalChlorophyll", totalChlorophyll) call MPAS_pool_get_array(biogeochemistryPool, "netSpecificAlgalGrowthRate", netSpecificAlgalGrowthRate) @@ -15847,15 +14757,6 @@ subroutine seaice_icepack_reinitialize_diagnostics_bgc(domain) end if -! if (config_use_vertical_zsalinity) then !echmod deprecate -! call MPAS_pool_get_array(biogeochemistryPool, "zSalinityFlux", zSalinityFlux) -! call MPAS_pool_get_array(biogeochemistryPool, "zSalinityGDFlux", zSalinityGDFlux) - -! zSalinityFlux = 0.0_RKIND -! zSalinityGDFlux = 0.0_RKIND - -! end if - call MPAS_pool_get_array(biogeochemistryPool, "netBrineHeight", netBrineHeight) call MPAS_pool_get_array(biogeochemistryPool, "oceanBioFluxes", oceanBioFluxes) call MPAS_pool_get_array(biogeochemistryPool, "atmosIceBioFluxes", atmosIceBioFluxes) @@ -15877,7 +14778,7 @@ subroutine seaice_icepack_reinitialize_diagnostics_bgc(domain) call MPAS_pool_get_config(block % configs, "config_use_column_shortwave", config_use_column_shortwave) - if (config_use_column_biogeochemistry .or. config_use_column_shortwave) then + if (config_use_column_biogeochemistry .or. config_use_column_shortwave .or. config_use_zaerosols) then call MPAS_pool_get_subpool(block % structs, "biogeochemistry", biogeochemistryPool) call MPAS_pool_get_array(biogeochemistryPool, "bioTracerShortwave", bioTracerShortwave) @@ -16866,7 +15767,7 @@ end subroutine seaice_ocean_carbon_flux ! !----------------------------------------------------------------------- - subroutine seaice_ocean_carbon_flux_cell(block,oceanCarbonFlux,oceanBioFluxes,iCell) + subroutine seaice_ocean_carbon_flux_cell(block,oceanCarbonFlux,oceanBioFluxes) real(kind=RKIND), intent(out) :: & oceanCarbonFlux @@ -16874,9 +15775,6 @@ subroutine seaice_ocean_carbon_flux_cell(block,oceanCarbonFlux,oceanBioFluxes,iC real(kind=RKIND), dimension(:), intent(in) :: & oceanBioFluxes - integer, intent(in) :: & - iCell - type(block_type), intent(in) :: & block @@ -17274,40 +16172,6 @@ subroutine seaice_total_carbon_content_category(block,totalCarbonContentCategory end subroutine seaice_total_carbon_content_category -!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| -!----------------------------------------------------------------------- -! Warning messages -!----------------------------------------------------------------------- - -!echmod: remove this subroutine and all calls to it - - subroutine column_write_warnings(logAsErrors) - - use ice_colpkg, only: colpkg_get_warnings - - character(len=strKINDWarnings), dimension(:), allocatable :: & - warnings - - logical, intent(in) :: & - logAsErrors - - integer :: & - iWarning - - call colpkg_get_warnings(warnings) - - if (logAsErrors) then - do iWarning = 1, size(warnings) - call mpas_log_write(trim(warnings(iWarning)), messageType=MPAS_LOG_ERR) - enddo ! iWarning - else - do iWarning = 1, size(warnings) - call mpas_log_write(trim(warnings(iWarning)), messageType=MPAS_LOG_WARN) - enddo ! iWarning - endif - - end subroutine column_write_warnings - !----------------------------------------------------------------------- subroutine seaice_icepack_write_warnings(logAsErrors) @@ -17330,12 +16194,12 @@ subroutine seaice_icepack_write_warnings(logAsErrors) if (logAsErrors) then do iWarning = 1, size(warnings) call mpas_log_write(trim(warnings(iWarning)), messageType=MPAS_LOG_ERR) - enddo ! iWarning + enddo ! iWarning call mpas_log_write("icepack aborted", MPAS_LOG_CRIT) else do iWarning = 1, size(warnings) call mpas_log_write(trim(warnings(iWarning)), messageType=MPAS_LOG_WARN) - enddo ! iWarning + enddo ! iWarning endif call icepack_warnings_clear() diff --git a/components/mpas-seaice/src/shared/mpas_seaice_initialize.F b/components/mpas-seaice/src/shared/mpas_seaice_initialize.F index 5611c090e212..69f145881758 100644 --- a/components/mpas-seaice/src/shared/mpas_seaice_initialize.F +++ b/components/mpas-seaice/src/shared/mpas_seaice_initialize.F @@ -784,8 +784,6 @@ subroutine init_ice_state_uniform_1D(& initialSalinityProfile(:,iCell), & initialMeltingTemperatureProfile(:,iCell), & surfaceTemperature(1,1,iCell), & - nIceLayers, & - nSnowLayers, & iceEnthalpy(:,1,iCell), & snowEnthalpy(:,1,iCell)) call seaice_icepack_write_warnings(icepack_warnings_aborted()) @@ -990,8 +988,6 @@ subroutine init_ice_cice_default(& initialSalinityProfile(:,iCell), & initialMeltingTemperatureProfile(:,iCell), & surfaceTemperature(1,iCategory,iCell), & - nIceLayers, & - nSnowLayers, & iceEnthalpy(:,iCategory,iCell), & snowEnthalpy(:,iCategory,iCell)) call seaice_icepack_write_warnings(icepack_warnings_aborted()) @@ -1148,7 +1144,6 @@ subroutine initial_category_areas_and_volumes(& if (trim(config_column_physics_type) == "icepack") then call icepack_init_itd(& - nCategories, & categoryThicknessLimits) call seaice_icepack_write_warnings(icepack_warnings_aborted()) else if (trim(config_column_physics_type) == "column_package") then @@ -1341,8 +1336,6 @@ subroutine init_ice_single_cell(& initialSalinityProfile(:,iCell), & initialMeltingTemperatureProfile(:,iCell), & surfaceTemperature(1,iCategory,iCell), & - nIceLayers, & - nSnowLayers, & iceEnthalpy(:,iCategory,iCell), & snowEnthalpy(:,iCategory,iCell)) call seaice_icepack_write_warnings(icepack_warnings_aborted()) @@ -1562,8 +1555,6 @@ subroutine init_ice_ridging(& initialSalinityProfile(:,iCell), & initialMeltingTemperatureProfile(:,iCell), & surfaceTemperature(1,iCategory,iCell), & - nIceLayers, & - nSnowLayers, & iceEnthalpy(:,iCategory,iCell), & snowEnthalpy(:,iCategory,iCell)) call seaice_icepack_write_warnings(icepack_warnings_aborted()) @@ -2580,11 +2571,12 @@ subroutine initialize_coupler_fields(domain) maxAerosolType, & nZBGCTracers - logical, pointer :: & + logical, pointer :: & config_do_restart, & config_use_column_biogeochemistry, & config_use_column_physics, & - config_use_aerosols + config_use_aerosols, & + config_use_zaerosols integer, pointer :: & nCells @@ -2682,8 +2674,9 @@ subroutine initialize_coupler_fields(domain) endif call MPAS_pool_get_config(block % configs, "config_use_column_biogeochemistry", config_use_column_biogeochemistry) + call MPAS_pool_get_config(block % configs, "config_use_zaerosols", config_use_zaerosols) - if (config_use_column_biogeochemistry) then + if (config_use_column_biogeochemistry .or. config_use_zaerosols) then call MPAS_pool_get_subpool(block % structs, "biogeochemistry", biogeochemistry) @@ -2748,12 +2741,8 @@ subroutine initialize_coupler_fields(domain) oceanNitrateConc(iCell), & oceanSilicateConc(iCell),& oceanZAerosolConc(:,iCell), & - maxDICType, & - maxDONType, & - maxIronType, & - maxAerosolType, & - carbonToNitrogenRatioAlgae, & - carbonToNitrogenRatioDON) + carbonToNitrogenRatioAlgae(:), & + carbonToNitrogenRatioDON(:)) enddo ! iCell else if (trim(config_column_physics_type) == "column_package") then @@ -2777,8 +2766,8 @@ subroutine initialize_coupler_fields(domain) maxDONType, & maxIronType, & maxAerosolType, & - carbonToNitrogenRatioAlgae, & - carbonToNitrogenRatioDON) + carbonToNitrogenRatioAlgae(:), & + carbonToNitrogenRatioDON(:)) enddo ! iCell diff --git a/components/mpas-seaice/src/shared/mpas_seaice_velocity_solver.F b/components/mpas-seaice/src/shared/mpas_seaice_velocity_solver.F index f49ac45a9360..3009b618161b 100644 --- a/components/mpas-seaice/src/shared/mpas_seaice_velocity_solver.F +++ b/components/mpas-seaice/src/shared/mpas_seaice_velocity_solver.F @@ -1431,7 +1431,6 @@ subroutine ice_strength(domain) ! this routine doesnt reset icePressure call icepack_ice_strength(& - nCategories, & iceAreaCell(iCell), & iceVolumeCell(iCell), & openWaterArea(iCell), & diff --git a/docs/dev-guide/adding-grid-support/adding-grid-support-step-by-step-guide/add-grid-config.md b/docs/dev-guide/adding-grid-support/adding-grid-support-step-by-step-guide/add-grid-config.md index b872658db45e..f46a84afa767 100644 --- a/docs/dev-guide/adding-grid-support/adding-grid-support-step-by-step-guide/add-grid-config.md +++ b/docs/dev-guide/adding-grid-support/adding-grid-support-step-by-step-guide/add-grid-config.md @@ -1,3 +1,3 @@ # Add New Grid Configuration to E3SM -[Back to Adding Support for New Grids](../adding-grid-support-step-by-step-guide.md) +Back to step-by-step guide for [Adding Support for New Grids](../adding-grid-support-step-by-step-guide.md) diff --git a/docs/dev-guide/adding-grid-support/adding-grid-support-step-by-step-guide/generate-dry-deposition.md b/docs/dev-guide/adding-grid-support/adding-grid-support-step-by-step-guide/generate-dry-deposition.md index f9dc7ff9eda4..79e6fd017a40 100644 --- a/docs/dev-guide/adding-grid-support/adding-grid-support-step-by-step-guide/generate-dry-deposition.md +++ b/docs/dev-guide/adding-grid-support/adding-grid-support-step-by-step-guide/generate-dry-deposition.md @@ -1,6 +1,40 @@ # Generate a Dry Deposition File -!!!WARNING - This page is still under construction +Atmospheric dry deposition of aerosols at the surface depends on certain surface properties, such as soil type. In some cases these calculations can be handled in the land model and passed to the atmosphere through the coupler. However, with modal areosols this method is not adequate and we must recalculate these fields in the atmosphere (see subroutine `interp_map` in `components/eam/src/chemistry/mozart/mo_drydep.F90`). + +For unstructured grids it was determined to create this offline interpolation tool rather than generalize the subroutine interp_map. + +Be sure to activate the [E3SM unified environment](https://e3sm.org/resources/tools/other-tools/e3sm-unified-environment/) when performing the steps below. + +## Map File Generation + +The destination atmosphere grid file should be on the "pg2" grid. These grid files are easily generated with three TempestRemap commands as follows: + +```shell +NE=30 +GenerateCSMesh --alt --res ${NE} --file ${GRID_ROOT}/ne${NE}.g +GenerateVolumetricMesh --in ${GRID_ROOT}/ne${NE}.g --out ${GRID_ROOT}/ne${NE}pg2.g --np 2 --uniform +ConvertMeshToSCRIP --in ${GRID_ROOT}/ne${NE}pg2.g --out ${GRID_ROOT}/ne${NE}pg2_scrip.nc +``` + +The map file used to generate atmsrf files can be created a few different ways. For a typical E3SM configuration we recommend using a conservative, monotone map. Here is an example command that can be used to generate one (as of NCO version 5.2.2) + +```shell +SRC_GRID=${DIN_LOC_ROOT}/../mapping/grids/1x1d.nc +DST_GRID=${GRID_ROOT}/ne${NE}pg2_scrip.nc +MAP_FILE=${MAP_ROOT}/map_1x1_to_ne${NE}pg2_traave.nc +ncremap -5 -a traave --src_grd=${SRC_GRID} --dst_grd=${DST_GRID} --map_file=${MAP_FILE} +``` + +For RRM grids the last two commands would be used on the exodus file produced by [SQuadGen](https://github.com/ClimateGlobalChange/squadgen) (See the [Adding Support for New Grids](https://docs.e3sm.org/user-guides/adding-grid-support-overview.md) tutorial for more information.). + +## Generating a New Dry Desposition File (atmsrf) + +```shell +VEGE_FILE=${DIN_LOC_ROOT}/atm/cam/chem/trop_mozart/dvel/regrid_vegetation.nc +SOIL_FILE=${DIN_LOC_ROOT}/atm/cam/chem/trop_mozart/dvel/clim_soilw.nc + +python ~/E3SM/mkatmsrffile.py --map_file=${MAP_FILE} --vegetation_file=${VEGE_FILE} --soil_water_file=${SOIL_FILE} --output_root=${atmsrf_root} --dst_grid=ne${NE}pg2 --date-stamp=20240613 +``` Back to step-by-step guide for [Adding Support for New Grids](../adding-grid-support-step-by-step-guide.md) diff --git a/docs/index.md b/docs/index.md index 3dd05a4f62fc..4d979cf0afee 100644 --- a/docs/index.md +++ b/docs/index.md @@ -23,6 +23,7 @@ research problems and Department of Energy mission needs while efficiently using - [MOSART](./MOSART/index.md) - [MPAS-Ocean](./MPAS-Ocean/index.md) - [MPAS-seaice](./MPAS-seaice/index.md) +- [Omega](https://docs.e3sm.org/Omega/omega/) — not yet supported. ## Tools diff --git a/docs/user-guide/index.md b/docs/user-guide/index.md index c2daf519a42d..53fa28d64e25 100644 --- a/docs/user-guide/index.md +++ b/docs/user-guide/index.md @@ -24,7 +24,7 @@ is available. A *fully coupled* compset is one which has active components for at least the atmosphere, ocean, land surface, ocean and sea-ice all interacting. Each compset is associated with a specific forcing condition. -Coupled compsets in E3SM are developed for three science-driven simulation campaigns: `water cycle change and impacts`, `human-earth system feedbacks`, and `polar processes, sea-level rise and coastal impacts`. The standard coupled configurations -- which consist of prognostic atmosphere, land, river, ocean and sea-ice components -- form the base physical coupled system and are mainly designed for `water cycle change and impacts` simulation campaign. +Coupled compsets in E3SM are developed for three science-driven simulation campaigns: **water cycle change and impacts**, **human-earth system feedbacks**, and **polar processes, sea-level rise and coastal impacts**. The standard coupled configurations -- which consist of prognostic atmosphere, land, river, ocean and sea-ice components -- form the base physical coupled system and are mainly designed for `water cycle change and impacts` simulation campaign. Below list the standard configuration compsets supported in the current version of E3SM: |Compset alias | Description | @@ -37,6 +37,35 @@ Below list the standard configuration compsets supported in the current version |`WCYCLSSP245` | Standard configuration with prescribed SSP-245 forcings | |`WCYCLSSP370` | Standard configuration with prescribed SSP-370 forcings | |`WCYCLSSP585` | Standard configuration with prescribed SSP-585 forcings | +| | **Compsets for single-forcings simulations of the historical period (1850-2014)** | +|`WCYCL20TR-GHG` | Greenhouse gases only configuration (`GHGs`)| +|`WCYCL20TR-aer` | Anthropogenic aerosols and precursors only configuration (`aer`)| +|`WCYCL20TR-xGHG-xaer` | All forcings except GHGs and aer (`solar irradiance, stratospheric ozone and volcanic emissions, land use land cover`) | +|`WCYCL20TR-xaer` | All forcings except aer (`GHGs, solar irradiance, stratospheric ozone and volcanic emissions, land use land cover`) | +|`WCYCL20TR-nat` | Natural-only configuration (`solar irradiance, stratospheric volcanic emissions, land use land cover`) | +|`WCYCL20TR-ozone` | Stratospheric ozone only configuration | +|`WCYCL20TR-lulc` | Land use land cover only configuration | +|`WCYCL20TR-volc` | Stratospheric volcanic emissions only configuration | + +The table below specifies which forcing category is fixed at 1850 conditions and which are allowed to vary over the historical period +for each of the historical ("20TR") compsets including the single-forcing compsets. + +|Compset alias | GHGs | Aerosol & precursors | Oxidants | Ozone (CI & Linoz) | Volcano | Solar | Land Use & ndep/popdensa | +|:------------ |:-----: | :---: | :---: | :---: | :---: | :---: | :---: | +|`WCYCL20TR` | varying | varying | varying | varying | varying | varying | varying | +|`WCYCL20TR-GHG`| varying | 1850 | 1850 | 1850 | 1850 | 1850 | 1850 | +|`WCYCL20TR-aer`| 1850 | varying | varying | 1850 | 1850 | 1850 | 1850 | +|`WCYCL20TR-xGHG-xaer`| 1850 | 1850 | 1850 | varying | varying | varying | varying | +|`WCYCL20TR-xaer`| varying | 1850 | 1850 | varying | varying | varying | varying | +|`WCYCL20TR-nat`| 1850 | 1850 | 1850 | 1850 | varying | varying | 1850 | +|`WCYCL20TR-ozone`| 1850 | 1850 | 1850 | varying | 1850 | 1850 | 1850 | +|`WCYCL20TR-lulc`| 1850 | 1850 | 1850 | 1850 | 1850 | 1850 | varying | +|`WCYCL20TR-volc`| 1850 | 1850 | 1850 | 1850 | varying | 1850 | 1850 | + + +- *Volcano* refers to stratospheric volcanic SO2 emissions; *1850* for *Volcano* refers to background (average) stratospheric volcanic emissions used in pre-industrial control experiments + +- *Oxidants* always follow *Aerosol & precursors* for fixed or varying. The compsets for the other two science simulation campaigns are being finalized, with additional components and/or features. The compset naming follows the same convention, e.g., `CRYO1850` and `CRYO1850-4xCO2` are with prognostic ice-shelf melt fluxes for the `polar processes` simulation campaign. diff --git a/driver-mct/cime_config/config_component.xml b/driver-mct/cime_config/config_component.xml index 5b5126af8930..8cddad0abf89 100644 --- a/driver-mct/cime_config/config_component.xml +++ b/driver-mct/cime_config/config_component.xml @@ -1085,7 +1085,7 @@ char - mpas.aisgis20km,mpas.gis20km,mpas.ais20km,mpas.gis1to10km,mpas.gis1to10kmR2,null + mpas.aisgis20km,mpas.ais20km,mpas.ais8to30km,mpas.ais4to20km,mpas.gis20km,mpas.gis1to10km,mpas.gis1to10kmR2,null mpas.gis20km build_grid env_build.xml @@ -2655,16 +2655,16 @@ https://www.unidata.ucar.edu/software/netcdf/docs/data_type.html - 64bit_offset - 64bit_offset - 64bit_offset - 64bit_offset - 64bit_offset - 64bit_offset - 64bit_offset - 64bit_offset - 64bit_offset - 64bit_offset + 64bit_data + 64bit_data + 64bit_data + 64bit_data + 64bit_data + 64bit_data + 64bit_data + 64bit_data + 64bit_data + 64bit_data diff --git a/driver-mct/cime_config/config_component_e3sm.xml b/driver-mct/cime_config/config_component_e3sm.xml index 08758f935313..8fc93b607d46 100755 --- a/driver-mct/cime_config/config_component_e3sm.xml +++ b/driver-mct/cime_config/config_component_e3sm.xml @@ -753,8 +753,13 @@ 312.821 388.717 388.717 - 0.000001 - 0.000001 + 284.317 + 284.317 + 284.317 + 284.317 + 284.317 + 284.317 + 0.000001 284.317 284.317 284.317 @@ -857,6 +862,7 @@ 1 2 + 2 shr_dust_nl env_run.xml diff --git a/driver-moab/cime_config/config_component.xml b/driver-moab/cime_config/config_component.xml index be0ee0fbd776..d3685126c61e 100644 --- a/driver-moab/cime_config/config_component.xml +++ b/driver-moab/cime_config/config_component.xml @@ -1085,7 +1085,7 @@ char - mpas.aisgis20km,mpas.gis20km,mpas.ais20km,mpas.gis1to10km,gis1to10kmR2,null + mpas.aisgis20km,mpas.ais20km,mpas.ais8to30km,mpas.ais4to20km,mpas.gis20km,mpas.gis1to10km,mpas.gis1to10kmR2,null mpas.gis20km build_grid env_build.xml @@ -2647,16 +2647,16 @@ https://www.unidata.ucar.edu/software/netcdf/docs/data_type.html - 64bit_offset - 64bit_offset - 64bit_offset - 64bit_offset - 64bit_offset - 64bit_offset - 64bit_offset - 64bit_offset - 64bit_offset - 64bit_offset + 64bit_data + 64bit_data + 64bit_data + 64bit_data + 64bit_data + 64bit_data + 64bit_data + 64bit_data + 64bit_data + 64bit_data diff --git a/driver-moab/main/component_mod.F90 b/driver-moab/main/component_mod.F90 index 88d152a95685..3e8ba9042a58 100644 --- a/driver-moab/main/component_mod.F90 +++ b/driver-moab/main/component_mod.F90 @@ -748,6 +748,7 @@ subroutine component_init_areacor_moab (comp, mbccid, mbcxid, seq_flds_c2x_fluxe lsize = comp(1)%mblsize allocate(areas (lsize, 3)) ! lsize is along grid; read mask too allocate(factors (lsize, 2)) + factors = 1.0 ! initialize with 1.0 all factors; then maybe correct them ! get areas tagname='area:aream:mask'//C_NULL_CHAR arrsize = 3 * lsize diff --git a/driver-moab/main/prep_lnd_mod.F90 b/driver-moab/main/prep_lnd_mod.F90 index 44ae5490e2c6..7bdb12376a3d 100644 --- a/driver-moab/main/prep_lnd_mod.F90 +++ b/driver-moab/main/prep_lnd_mod.F90 @@ -1,6 +1,6 @@ module prep_lnd_mod - use shr_kind_mod , only: r8 => SHR_KIND_R8 + use shr_kind_mod , only: R8 => SHR_KIND_R8 use shr_kind_mod , only: cs => SHR_KIND_CS use shr_kind_mod , only: cl => SHR_KIND_CL use shr_kind_mod , only: cxx => SHR_KIND_CXX @@ -162,7 +162,7 @@ subroutine prep_lnd_init(infodata, atm_c2_lnd, rof_c2_lnd, glc_c2_lnd, iac_c2_ln integer nrflds ! number of rof fields projected on land integer arrsize ! for setting the r2x fields on land to 0 integer ent_type ! for setting tags - real (kind=r8) , allocatable :: tmparray (:) ! used to set the r2x fields to 0 + real (kind=R8) , allocatable :: tmparray (:) ! used to set the r2x fields to 0 #endif character(*), parameter :: subname = '(prep_lnd_init)' @@ -222,7 +222,6 @@ subroutine prep_lnd_init(infodata, atm_c2_lnd, rof_c2_lnd, glc_c2_lnd, iac_c2_ln call seq_map_init_rcfile(mapper_Fr2l, rof(1), lnd(1), & 'seq_maps.rc','rof2lnd_fmapname:','rof2lnd_fmaptype:',samegrid_lr, & string='mapper_Fr2l initialization',esmf_map=esmf_map_flag) - end if ! symmetric of l2r, from prep_rof #ifdef HAVE_MOAB ! Call moab intx only if land and river are init in moab @@ -370,7 +369,7 @@ subroutine prep_lnd_init(infodata, atm_c2_lnd, rof_c2_lnd, glc_c2_lnd, iac_c2_ln arrsize = nrflds*mlsize allocate (tmparray(arrsize)) ! mlsize is the size of local land ! do we need to zero out others or just river ? - tmparray = 0._r8 + tmparray = 0._R8 ierr = iMOAB_SetDoubleTagStorage(mblxid, tagname, arrsize , ent_type, tmparray) if (ierr .ne. 0) then write(logunit,*) subname,' cant zero out r2x tags on land' @@ -381,6 +380,7 @@ subroutine prep_lnd_init(infodata, atm_c2_lnd, rof_c2_lnd, glc_c2_lnd, iac_c2_ln end if ! if ((mbrxid .ge. 0) .and. (mblxid .ge. 0)) ! endif HAVE_MOAB #endif + end if call shr_sys_flush(logunit) if (atm_c2_lnd) then @@ -693,7 +693,7 @@ subroutine prep_lnd_mrg_moab (infodata) #endif #ifdef MOABCOMP character(CXX) :: tagname, mct_field - real(r8) :: difference + real(R8) :: difference type(mct_list) :: temp_list integer :: size_list, index_list, ent_type type(mct_string) :: mctOStr ! diff --git a/driver-moab/main/prep_ocn_mod.F90 b/driver-moab/main/prep_ocn_mod.F90 index 44ec0c6a3c7a..b13cce62f95d 100644 --- a/driver-moab/main/prep_ocn_mod.F90 +++ b/driver-moab/main/prep_ocn_mod.F90 @@ -1,6 +1,6 @@ module prep_ocn_mod - use shr_kind_mod, only: r8 => SHR_KIND_R8 + use shr_kind_mod, only: R8 => SHR_KIND_R8 use shr_kind_mod, only: cs => SHR_KIND_CS use shr_kind_mod, only: cl => SHR_KIND_CL use shr_kind_mod, only: CX => shr_kind_CX, CXX => shr_kind_CXX @@ -137,7 +137,7 @@ module prep_ocn_mod integer , target :: x2oacc_ox_cnt ! x2oacc_ox: number of time samples accumulated ! accumulation variables for moab data - real (kind=r8) , allocatable, private, target :: x2oacc_om (:,:) ! Ocn import, ocn grid, cpl pes, moab array + real (kind=R8) , allocatable, private, target :: x2oacc_om (:,:) ! Ocn import, ocn grid, cpl pes, moab array integer , target :: x2oacc_om_cnt ! x2oacc_ox: number of time samples accumulated, in moab array integer :: arrSize_x2o_om ! this will be a module variable, size moabLocal_size * nof @@ -154,20 +154,20 @@ module prep_ocn_mod !================================================================================================ - real (kind=r8) , allocatable, private :: fractions_om (:,:) ! will retrieve the fractions from ocean, and use them + real (kind=R8) , allocatable, private :: fractions_om (:,:) ! will retrieve the fractions from ocean, and use them ! they were init with ! character(*),parameter :: fraclist_o = 'afrac:ifrac:ofrac:ifrad:ofrad' in moab, on the fractions - real (kind=r8) , allocatable, private :: x2o_om (:,:) - real (kind=r8) , allocatable, private :: a2x_om (:,:) - real (kind=r8) , allocatable, private :: i2x_om (:,:) - real (kind=r8) , allocatable, private :: r2x_om (:,:) - real (kind=r8) , allocatable, private :: xao_om (:,:) + real (kind=R8) , allocatable, private :: x2o_om (:,:) + real (kind=R8) , allocatable, private :: a2x_om (:,:) + real (kind=R8) , allocatable, private :: i2x_om (:,:) + real (kind=R8) , allocatable, private :: r2x_om (:,:) + real (kind=R8) , allocatable, private :: xao_om (:,:) ! this will be constructed first time, and be used to copy fields for shared indices ! between xao and x2o character(CXX) :: shared_fields_xao_x2o ! will need some array to hold the data for copying - real(r8) , allocatable, save :: shared_values(:) ! will be the size of shared indices * lsize + real(R8) , allocatable, save :: shared_values(:) ! will be the size of shared indices * lsize integer :: size_of_shared_values logical :: iamin_CPLALLICEID ! pe associated with CPLALLICEID @@ -268,7 +268,7 @@ subroutine prep_ocn_init(infodata, atm_c2_ocn, atm_c2_ice, ice_c2_ocn, rof_c2_oc integer arrsize ! for setting the r2x fields on land to 0 integer ent_type ! for setting tags integer noflds ! used for number of fields in allocating moab accumulated array x2oacc_om - real (kind=r8) , allocatable :: tmparray (:) ! used to set the r2x fields to 0 + real (kind=R8) , allocatable :: tmparray (:) ! used to set the r2x fields to 0 !--------------------------------------------------------------- @@ -786,7 +786,7 @@ subroutine prep_ocn_init(infodata, atm_c2_ocn, atm_c2_ice, ice_c2_ocn, rof_c2_oc arrsize = nrflds*mlsize allocate (tmparray(arrsize)) ! mlsize is the size of local land ! do we need to zero out others or just river ? - tmparray = 0._r8 + tmparray = 0._R8 ierr = iMOAB_SetDoubleTagStorage(mboxid, tagname, arrsize , ent_type, tmparray) if (ierr .ne. 0) then write(logunit,*) subname,' cant zero out r2x tags on ocn' @@ -1095,7 +1095,7 @@ subroutine prep_ocn_mrg(infodata, fractions_ox, xao_ox, timer_mrg) ! ! Local Variables integer :: eii, ewi, egi, eoi, eai, eri, exi, efi, emi - real(r8) :: flux_epbalfact ! adjusted precip factor + real(R8) :: flux_epbalfact ! adjusted precip factor type(mct_avect), pointer :: x2o_ox integer :: cnt character(*), parameter :: subname = '(prep_ocn_mrg)' @@ -1177,7 +1177,7 @@ subroutine prep_ocn_mrg_moab(infodata, xao_ox) !--------------------------------------------------------------- - real(r8) :: flux_epbalfact ! adjusted precip factor + real(R8) :: flux_epbalfact ! adjusted precip factor ! will build x2o_om , similar to x2o_ox ! no averages, just one ocn instance @@ -1187,11 +1187,11 @@ subroutine prep_ocn_mrg_moab(infodata, xao_ox) integer :: kof,kif integer :: lsize, arrsize ! for double arrays integer , save :: noflds,naflds,niflds,nrflds,nxflds! ,ngflds,nwflds, no glacier or wave model - real(r8) :: ifrac,ifracr - real(r8) :: afrac,afracr - real(r8) :: frac_sum - real(r8) :: avsdr, anidr, avsdf, anidf ! albedos - real(r8) :: fswabsv, fswabsi ! sw + real(R8) :: ifrac,ifracr + real(R8) :: afrac,afracr + real(R8) :: frac_sum + real(R8) :: avsdr, anidr, avsdf, anidf ! albedos + real(R8) :: fswabsv, fswabsi ! sw character(CL),allocatable :: field_ocn(:) ! string converted to char character(CL),allocatable :: field_atm(:) ! string converted to char character(CL),allocatable :: field_ice(:) ! string converted to char @@ -1289,7 +1289,7 @@ subroutine prep_ocn_mrg_moab(infodata, xao_ox) #endif #ifdef MOABCOMP character(CXX) :: mct_field - real(r8) :: difference + real(R8) :: difference type(mct_list) :: temp_list integer :: size_list, index_list type(mct_string) :: mctOStr ! @@ -1345,7 +1345,7 @@ subroutine prep_ocn_mrg_moab(infodata, xao_ox) allocate(a2x_om (lsize, naflds)) allocate(i2x_om (lsize, niflds)) allocate(r2x_om (lsize, nrflds)) - r2x_om = 0._r8 ! should we zero out all of them ? + r2x_om = 0._R8 ! should we zero out all of them ? allocate(xao_om (lsize, nxflds)) ! allocate fractions too ! use the fraclist fraclist_o = 'afrac:ifrac:ofrac:ifrad:ofrad' @@ -1769,7 +1769,7 @@ subroutine prep_ocn_mrg_moab(infodata, xao_ox) ifrac = fractions_om(n,kif) ! fo_kif_ifrac(n) ! fractions_o%rAttr(kif,n) afrac = fractions_om(n,kof) ! fo_kof_ofrac(n) ! fractions_o%rAttr(kof,n) frac_sum = ifrac + afrac - if ((frac_sum) /= 0._r8) then + if ((frac_sum) /= 0._R8) then ifrac = ifrac / (frac_sum) afrac = afrac / (frac_sum) endif @@ -1777,7 +1777,7 @@ subroutine prep_ocn_mrg_moab(infodata, xao_ox) ifracr = fractions_om(n,kir) ! fo_kir_ifrad(n) ! fractions_o%rAttr(kir,n) afracr = fractions_om(n,kor) ! fo_kor_ofrad(n) ! fractions_o%rAttr(kor,n) frac_sum = ifracr + afracr - if ((frac_sum) /= 0._r8) then + if ((frac_sum) /= 0._R8) then ifracr = ifracr / (frac_sum) afracr = afracr / (frac_sum) endif @@ -1913,7 +1913,7 @@ subroutine prep_ocn_mrg_moab(infodata, xao_ox) ifrac = fractions_om(n,kif) !fo_kif_ifrac(n) ! fractions_o%rAttr(kif) afrac = fractions_om(n,kof) ! fo_kof_ofrac(n) ! fractions_o%rAttr(kof,n) frac_sum = ifrac + afrac - if ((frac_sum) /= 0._r8) then + if ((frac_sum) /= 0._R8) then ifrac = ifrac / (frac_sum) afrac = afrac / (frac_sum) endif @@ -2046,7 +2046,7 @@ subroutine prep_ocn_merge( flux_epbalfact, a2x_o, i2x_o, r2x_o, w2x_o, g2x_o, xa !----------------------------------------------------------------------- ! ! Arguments - real(r8) , intent(in) :: flux_epbalfact + real(R8) , intent(in) :: flux_epbalfact type(mct_aVect), intent(in) :: a2x_o type(mct_aVect), intent(in) :: i2x_o type(mct_aVect), intent(in) :: r2x_o @@ -2061,11 +2061,11 @@ subroutine prep_ocn_merge( flux_epbalfact, a2x_o, i2x_o, r2x_o, w2x_o, g2x_o, xa integer :: kof,kif integer :: lsize integer :: noflds,naflds,niflds,nrflds,nwflds,nxflds,ngflds - real(r8) :: ifrac,ifracr - real(r8) :: afrac,afracr - real(r8) :: frac_sum - real(r8) :: avsdr, anidr, avsdf, anidf ! albedos - real(r8) :: fswabsv, fswabsi ! sw + real(R8) :: ifrac,ifracr + real(R8) :: afrac,afracr + real(R8) :: frac_sum + real(R8) :: avsdr, anidr, avsdf, anidf ! albedos + real(R8) :: fswabsv, fswabsi ! sw character(CL),allocatable :: field_ocn(:) ! string converted to char character(CL),allocatable :: field_atm(:) ! string converted to char character(CL),allocatable :: field_ice(:) ! string converted to char @@ -2584,7 +2584,7 @@ subroutine prep_ocn_merge( flux_epbalfact, a2x_o, i2x_o, r2x_o, w2x_o, g2x_o, xa ifrac = fractions_o%rAttr(kif,n) afrac = fractions_o%rAttr(kof,n) frac_sum = ifrac + afrac - if ((frac_sum) /= 0._r8) then + if ((frac_sum) /= 0._R8) then ifrac = ifrac / (frac_sum) afrac = afrac / (frac_sum) endif @@ -2592,7 +2592,7 @@ subroutine prep_ocn_merge( flux_epbalfact, a2x_o, i2x_o, r2x_o, w2x_o, g2x_o, xa ifracr = fractions_o%rAttr(kir,n) afracr = fractions_o%rAttr(kor,n) frac_sum = ifracr + afracr - if ((frac_sum) /= 0._r8) then + if ((frac_sum) /= 0._R8) then ifracr = ifracr / (frac_sum) afracr = afracr / (frac_sum) endif @@ -2738,7 +2738,7 @@ subroutine prep_ocn_merge( flux_epbalfact, a2x_o, i2x_o, r2x_o, w2x_o, g2x_o, xa ifrac = fractions_o%rAttr(kif,n) afrac = fractions_o%rAttr(kof,n) frac_sum = ifrac + afrac - if ((frac_sum) /= 0._r8) then + if ((frac_sum) /= 0._R8) then ifrac = ifrac / (frac_sum) afrac = afrac / (frac_sum) endif @@ -3068,7 +3068,7 @@ function prep_ocn_get_mapper_Sw2o() prep_ocn_get_mapper_Sw2o => mapper_Sw2o end function prep_ocn_get_mapper_Sw2o function prep_ocn_get_x2oacc_om() - real(r8), DIMENSION(:, :), pointer :: prep_ocn_get_x2oacc_om + real(R8), DIMENSION(:, :), pointer :: prep_ocn_get_x2oacc_om prep_ocn_get_x2oacc_om => x2oacc_om end function prep_ocn_get_x2oacc_om function prep_ocn_get_x2oacc_om_cnt() diff --git a/driver-moab/main/prep_rof_mod.F90 b/driver-moab/main/prep_rof_mod.F90 index 59cc61c58890..83a8e331e916 100644 --- a/driver-moab/main/prep_rof_mod.F90 +++ b/driver-moab/main/prep_rof_mod.F90 @@ -1,7 +1,7 @@ module prep_rof_mod #include "shr_assert.h" - use shr_kind_mod, only: r8 => SHR_KIND_R8 + use shr_kind_mod, only: R8 => SHR_KIND_R8 use shr_kind_mod, only: cs => SHR_KIND_CS use shr_kind_mod, only: cl => SHR_KIND_CL use shr_kind_mod, only: cxx => SHR_KIND_CXX @@ -112,22 +112,22 @@ module prep_rof_mod ! accumulation variables over moab fields character(CXX) :: sharedFieldsLndRof ! used in moab to define l2racc_lm - real (kind=r8) , allocatable, private, target :: l2racc_lm(:,:) ! lnd export, lnd grid, cpl pes - real (kind=r8) , allocatable, private :: l2x_lm2(:,:) ! basically l2x_lm, but in another copy, on rof module + real (kind=R8) , allocatable, private, target :: l2racc_lm(:,:) ! lnd export, lnd grid, cpl pes + real (kind=R8) , allocatable, private :: l2x_lm2(:,:) ! basically l2x_lm, but in another copy, on rof module integer , target :: l2racc_lm_cnt ! l2racc_lm: number of time samples accumulated integer :: nfields_sh_lr ! number of fields in sharedFieldsLndRof integer :: lsize_lm ! size of land in moab, local character(CXX) :: sharedFieldsAtmRof ! used in moab to define a2racc_am - real (kind=r8) , allocatable, private :: a2racc_am(:,:) ! atm export, atm grid, cpl pes - real (kind=r8) , allocatable, private :: a2x_am2(:,:) ! basically a2x_am, but in another copy, on rof module + real (kind=R8) , allocatable, private :: a2racc_am(:,:) ! atm export, atm grid, cpl pes + real (kind=R8) , allocatable, private :: a2x_am2(:,:) ! basically a2x_am, but in another copy, on rof module integer , target :: a2racc_am_cnt ! a2racc_am: number of time samples accumulated integer :: nfields_sh_ar ! number of fields in sharedFieldsAtmRof integer :: lsize_am ! size of atm in moab, local character(CXX) :: sharedFieldsOcnRof ! used in moab to define o2racc_om - real (kind=r8) , allocatable, private, target :: o2racc_om(:,:) ! ocn export, ocn grid, cpl pes - real (kind=r8) , allocatable, private :: o2r_om2(:,:) ! basically o2x_om, but in another copy, on rof module, only shared with rof + real (kind=R8) , allocatable, private, target :: o2racc_om(:,:) ! ocn export, ocn grid, cpl pes + real (kind=R8) , allocatable, private :: o2r_om2(:,:) ! basically o2x_om, but in another copy, on rof module, only shared with rof integer , target :: o2racc_om_cnt ! o2racc_om: number of time samples accumulated integer :: nfields_sh_or ! number of fields in sharedFieldsOcnRof integer :: lsize_om ! size of ocn in moab, local @@ -145,12 +145,12 @@ module prep_rof_mod logical :: samegrid_al ! samegrid atm and lnd ! moab stuff - real (kind=r8) , allocatable, private :: fractions_rm (:,:) ! will retrieve the fractions from rof, and use them + real (kind=R8) , allocatable, private :: fractions_rm (:,:) ! will retrieve the fractions from rof, and use them ! they were init with ! character(*),parameter :: fraclist_r = 'lfrac:lfrin:rfrac' in moab, on the fractions - real (kind=r8) , allocatable, private :: x2r_rm (:,:) ! result of merge - real (kind=r8) , allocatable, private :: a2x_rm (:,:) - real (kind=r8) , allocatable, private :: l2x_rm (:,:) + real (kind=R8) , allocatable, private :: x2r_rm (:,:) ! result of merge + real (kind=R8) , allocatable, private :: a2x_rm (:,:) + real (kind=R8) , allocatable, private :: l2x_rm (:,:) !================================================================================================ @@ -327,6 +327,7 @@ subroutine prep_rof_init(infodata, lnd_c2_rof, atm_c2_rof, ocn_c2_rof) write(logunit,*) subname,' error in defining tags for seq_flds_a2x_fields on rof cpl' call shr_sys_abort(subname//' ERROR in defining tags for seq_flds_a2x_fields on rof cpl') endif + call seq_comm_getData(CPLID ,mpigrp=mpigrp_CPLID) if (samegrid_lr) then ! the same mesh , lnd and rof use the same dofs, but restricted ! we do not compute intersection, so we will have to just send data from lnd to rof and viceversa, by GLOBAL_ID matching @@ -363,7 +364,6 @@ subroutine prep_rof_init(infodata, lnd_c2_rof, atm_c2_rof, ocn_c2_rof) ! we also need to compute the comm graph for the second hop, from the lnd on coupler to the ! lnd for the intx lnd-rof context (coverage) ! - call seq_comm_getData(CPLID ,mpigrp=mpigrp_CPLID) type1 = 3 ! land is FV now on coupler side type2 = 3; @@ -1223,7 +1223,7 @@ subroutine prep_rof_merge(l2x_r, a2x_r, fractions_r, x2r_r, cime_model,o2x_r) integer, save :: index_x2r_coszen_str integer, save :: index_frac - real(r8) :: frac + real(R8) :: frac character(CL) :: fracstr logical, save :: first_time = .true. logical, save :: flds_wiso_rof = .false. @@ -1529,7 +1529,7 @@ subroutine prep_rof_mrg_moab (infodata, cime_model) integer, save :: index_x2r_coszen_str integer, save :: index_frac - real(r8) :: frac + real(R8) :: frac character(CL) :: fracstr logical, save :: first_time = .true. logical, save :: flds_wiso_rof = .false. @@ -1548,7 +1548,7 @@ subroutine prep_rof_mrg_moab (infodata, cime_model) character*32 :: outfile, wopts, lnum #endif #ifdef MOABCOMP - real(r8) :: difference + real(R8) :: difference type(mct_list) :: temp_list integer :: size_list, index_list type(mct_string) :: mctOStr ! @@ -1995,7 +1995,7 @@ function prep_rof_get_o2racc_om_cnt() end function prep_rof_get_o2racc_om_cnt function prep_rof_get_o2racc_om() - real(r8), DIMENSION(:, :), pointer :: prep_rof_get_o2racc_om + real(R8), DIMENSION(:, :), pointer :: prep_rof_get_o2racc_om prep_rof_get_o2racc_om => o2racc_om end function prep_rof_get_o2racc_om @@ -2011,7 +2011,7 @@ function prep_rof_get_l2racc_lm_cnt() end function prep_rof_get_l2racc_lm_cnt function prep_rof_get_l2racc_lm() - real(r8), DIMENSION(:, :), pointer :: prep_rof_get_l2racc_lm + real(R8), DIMENSION(:, :), pointer :: prep_rof_get_l2racc_lm prep_rof_get_l2racc_lm => l2racc_lm end function prep_rof_get_l2racc_lm diff --git a/driver-moab/main/seq_frac_mct.F90 b/driver-moab/main/seq_frac_mct.F90 index a89fc0b9aa4f..031845a102ef 100644 --- a/driver-moab/main/seq_frac_mct.F90 +++ b/driver-moab/main/seq_frac_mct.F90 @@ -180,7 +180,7 @@ module seq_frac_mct use iMOAB, only : iMOAB_DefineTagStorage, iMOAB_SetDoubleTagStorage, & iMOAB_GetMeshInfo, iMOAB_SetDoubleTagStorageWithGid, iMOAB_WriteMesh, & - iMOAB_ApplyScalarProjectionWeights, iMOAB_SendElementTag, iMOAB_ReceiveElementTag, & + iMOAB_SendElementTag, iMOAB_ReceiveElementTag, & iMOAB_FreeSenderBuffers, iMOAB_GetDoubleTagStorage #ifdef MOABDEBUG use seq_comm_mct, only : num_moab_exports diff --git a/driver-moab/main/seq_map_mod.F90 b/driver-moab/main/seq_map_mod.F90 index be47473f444c..82e67b8b195e 100644 --- a/driver-moab/main/seq_map_mod.F90 +++ b/driver-moab/main/seq_map_mod.F90 @@ -355,6 +355,7 @@ subroutine seq_map_map( mapper, av_s, av_d, fldlist, norm, avwts_s, avwtsfld_s, real(r8), dimension(:), allocatable :: wghts real(kind=r8) , allocatable :: targtags(:,:), targtags_ini(:,:) real(kind=r8) :: factor + integer :: filter_type ! used for caas projection #endif ! ! Local Variables @@ -649,7 +650,8 @@ subroutine seq_map_map( mapper, av_s, av_d, fldlist, norm, avwts_s, avwtsfld_s, call shr_sys_flush(logunit) endif #endif - ierr = iMOAB_ApplyScalarProjectionWeights ( mapper%intx_mbid, mapper%weight_identifier, fldlist_moab, fldlist_moab) + filter_type = 0 ! no + ierr = iMOAB_ApplyScalarProjectionWeights ( mapper%intx_mbid, filter_type, mapper%weight_identifier, fldlist_moab, fldlist_moab) if (ierr .ne. 0) then write(logunit,*) subname,' error in applying weights ' call shr_sys_abort(subname//' ERROR in applying weights') diff --git a/externals/ekat b/externals/ekat index b39fd9fbd814..5e9d57c2a4df 160000 --- a/externals/ekat +++ b/externals/ekat @@ -1 +1 @@ -Subproject commit b39fd9fbd81439470e146d7915ed9a22c688ac6a +Subproject commit 5e9d57c2a4df044a5fe4014968f02246d4dcf110 diff --git a/externals/haero b/externals/haero index 8e4c96ded375..e5dfce49ec73 160000 --- a/externals/haero +++ b/externals/haero @@ -1 +1 @@ -Subproject commit 8e4c96ded375bf03bb5e83b0779e45a3aec9659e +Subproject commit e5dfce49ec734d33a42abdc0125da9c7a07ed016 diff --git a/externals/scorpio b/externals/scorpio index 34422f362e9e..804f87c48fc9 160000 --- a/externals/scorpio +++ b/externals/scorpio @@ -1 +1 @@ -Subproject commit 34422f362e9e83b5bc5e013b5992fc2555d02ece +Subproject commit 804f87c48fc9013009307b806d1aff2afa3a0d7c diff --git a/run_e3sm.template.sh b/run_e3sm.template.sh index 623867c01904..49869f5c6f63 100755 --- a/run_e3sm.template.sh +++ b/run_e3sm.template.sh @@ -3,10 +3,7 @@ # E3SM Coupled Model Group run_e3sm script template. # # Bash coding style inspired by: -# http://kfirlavi.herokuapp.com/blog/2012/11/14/defensive-bash-programming - -# TO DO: -# - custom pelayout +# https://web.archive.org/web/20200620202413/http://kfirlavi.herokuapp.com/blog/2012/11/14/defensive-bash-programming main() { @@ -17,8 +14,9 @@ main() { # Machine and project readonly MACHINE=pm-cpu -# BEFORE RUNNING: CHANGE this to your project -readonly PROJECT="e3sm" +# NOTE: The command below will return your default project on SLURM-based systems. +# If you are not using SLURM or need a different project, remove the command and set it directly +readonly PROJECT="$(sacctmgr show user $USER format=DefaultAccount | tail -n1 | tr -d ' ')" # Simulation readonly COMPSET="WCYCL1850" @@ -46,8 +44,8 @@ readonly GET_REFCASE=TRUE #readonly RUN_REFDATE="" # same as MODEL_START_DATE for 'branch', can be different for 'hybrid' # Set paths +readonly CASE_ROOT="${PSCRATCH}/E3SMv3/${CASE_NAME}" readonly CODE_ROOT="${HOME}/E3SMv3/code/${CHECKOUT}" -readonly CASE_ROOT="/pscratch/sd/r/${USER}/e3sm-scratch/${CASE_NAME}" # Sub-directories readonly CASE_BUILD_DIR=${CASE_ROOT}/build @@ -56,6 +54,7 @@ readonly CASE_ARCHIVE_DIR=${CASE_ROOT}/archive # Define type of run # short tests: 'XS_2x5_ndays', 'XS_1x10_ndays', 'S_1x10_ndays', # 'M_1x10_ndays', 'M2_1x10_ndays', 'M80_1x10_ndays', 'L_1x10_ndays' +# * can replace XS, M, etc. with custom-XY with XY being the node count # or 'production' for full simulation readonly run='XS_2x5_ndays' if [ "${run}" != "production" ]; then @@ -118,6 +117,9 @@ fetch_code # Create case create_newcase +# Custom PE layout +custom_pelayout + # Setup case_setup @@ -322,6 +324,14 @@ create_newcase() { echo $'\n----- Starting create_newcase -----\n' + + if [[ ${PELAYOUT} == custom-* ]]; + then + layout="M" # temporary placeholder for create_newcase + else + layout=${PELAYOUT} + fi + if [[ -z "$CASE_GROUP" ]]; then ${CODE_ROOT}/cime/scripts/create_newcase \ --case ${CASE_NAME} \ @@ -333,7 +343,7 @@ create_newcase() { --machine ${MACHINE} \ --project ${PROJECT} \ --walltime ${WALLTIME} \ - --pecount ${PELAYOUT} + --pecount ${layout} else ${CODE_ROOT}/cime/scripts/create_newcase \ --case ${CASE_NAME} \ @@ -346,7 +356,7 @@ create_newcase() { --machine ${MACHINE} \ --project ${PROJECT} \ --walltime ${WALLTIME} \ - --pecount ${PELAYOUT} + --pecount ${layout} fi @@ -398,6 +408,43 @@ case_setup() { popd } +#----------------------------------------------------- +custom_pelayout() { + +if [[ ${PELAYOUT} == custom-* ]]; +then + echo $'\n CUSTOMIZE PROCESSOR CONFIGURATION:' + + # Number of cores per node (machine specific) + if [ "${MACHINE}" == "pm-cpu" ]; then + ncore=128 + elif [ "${MACHINE}" == "chrysalis" ]; then + ncore=64 + elif [ "${MACHINE}" == "compy" ]; then + ncore=40 + elif [ "${MACHINE}" == "anvil" ]; then + ncore=36 + else + echo 'ERROR: MACHINE = '${MACHINE}' is not supported for custom PE layout.' + exit 400 + fi + + # Extract number of nodes + tmp=($(echo ${PELAYOUT} | tr "-" " ")) + nnodes=${tmp[1]} + + # Customize + pushd ${CASE_SCRIPTS_DIR} + ./xmlchange NTASKS=$(( $nnodes * $ncore )) + ./xmlchange NTHRDS=1 + ./xmlchange MAX_MPITASKS_PER_NODE=$ncore + ./xmlchange MAX_TASKS_PER_NODE=$ncore + popd + +fi + +} + #----------------------------------------------------- case_build() { @@ -534,9 +581,10 @@ copy_script() { local script_provenance_dir=${CASE_SCRIPTS_DIR}/run_script_provenance mkdir -p ${script_provenance_dir} - local this_script_name=`basename $0` + local this_script_name=$( basename -- "$0"; ) + local this_script_dir=$( dirname -- "$0"; ) local script_provenance_name=${this_script_name}.`date +%Y%m%d-%H%M%S` - cp -vp ${this_script_name} ${script_provenance_dir}/${script_provenance_name} + cp -vp "${this_script_dir}/${this_script_name}" ${script_provenance_dir}/${script_provenance_name} } diff --git a/share/build/buildlib.kokkos b/share/build/buildlib.kokkos index 035e86b0df2a..81d3e01d80d6 100755 --- a/share/build/buildlib.kokkos +++ b/share/build/buildlib.kokkos @@ -50,6 +50,11 @@ OR ############################################################################### def buildlib(bldroot, installpath, case): ############################################################################### + # If we are using Albany/Trilinos, we must use the Kokkos that comes with it + if case.get_value("USE_ALBANY") or case.get_value("USE_TRILINOS"): + print ("case is using Trilinos and will use its Kokkos") + return + installed_kokkos_dir = os.environ.get("Kokkos_ROOT") if installed_kokkos_dir is not None: # We are trying to use a pre-installed kokkos. Look for the relevant folders/libs, @@ -65,9 +70,10 @@ def buildlib(bldroot, installpath, case): # often arch dependent (e.g., $prefix/lib or $prefix/lib64)... The best thing # would be to run a small cmake script, that calls find_package. But E3SM's # cmake build system will do that soon enough, so any error will be caught there. + print (f"Using pre-installed Kokkos_ROOT: {kokkos_root}") return else: - print ("no value foudn in env for Kokkos_ROOT. building from scratch") + print ("no value found in env for Kokkos_ROOT. building from scratch") srcroot = case.get_value("SRCROOT") ekat_dir = os.path.join(srcroot, "externals", "ekat") diff --git a/share/util/shr_pio_mod.F90 b/share/util/shr_pio_mod.F90 index 0935bce351a5..d500cbc680a2 100644 --- a/share/util/shr_pio_mod.F90 +++ b/share/util/shr_pio_mod.F90 @@ -173,17 +173,24 @@ subroutine shr_pio_init2(comp_id, comp_name, comp_iamin, comp_comm, comp_comm_ia logical, intent(in) :: comp_iamin(:) character(len=*), intent(in) :: comp_name(:) integer, intent(in) :: comp_comm(:), comp_comm_iam(:) + integer(kind=pio_offset_kind) :: cur_buffer_size_limit=-1 integer :: i character(len=shr_kind_cl) :: nlfilename, cname integer :: ret character(*), parameter :: subName = '(shr_pio_init2) ' ! 0 is a valid value of pio_buffer_size_limit - if(pio_buffer_size_limit>=0) then + ! -1 is the value used by CIME to let the library choose the buffer limit + if(pio_buffer_size_limit>=-1) then + call pio_set_buffer_size_limit(pio_buffer_size_limit, prev_limit=cur_buffer_size_limit) if(comp_comm_iam(1)==0) then - write(shr_log_unit,*) 'Setting pio_buffer_size_limit : ',pio_buffer_size_limit + if(pio_buffer_size_limit >= 0) then + write(shr_log_unit,*) 'Set pio_buffer_size_limit to : ', pio_buffer_size_limit, ' (bytes)' + else + ! Default pio_buffer_size_limit + write(shr_log_unit,*) 'Using pio_buffer_size_limit (default): ', cur_buffer_size_limit, ' (bytes)' + end if end if - call pio_set_buffer_size_limit(pio_buffer_size_limit) endif if(pio_blocksize>0) then if(comp_comm_iam(1)==0) then