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 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
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
+
+
+
+
+
+
@@ -1716,7 +1723,7 @@ this mask will have smb calculated over the entire global land surface
+>lnd/clm2/mappingdata/maps/0.5x0.5/map_0.1x0.1_nomask_to_0.5x0.5_nomask_aave_da_c240308.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
+
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"
+ />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\brief Compute MPAS-Seaice analysis member
+!> \author Nicole Jeffery
+!> \date 11 Mar 2024
+!> \details
+!> This routine conducts all computations to verify black carbon conservation
+!
+!-----------------------------------------------------------------------
+
+ subroutine black_carbon_conservation(domain, err)
+
+ type (domain_type), intent(inout) :: &
+ domain
+
+ integer, intent(out) :: &
+ err !< Output: error flag
+
+ type(block_type), pointer :: &
+ blockPtr
+
+ type(MPAS_pool_type), pointer :: &
+ conservationCheckBlackCarbonAMPool, &
+ conservationCheckAMPool, &
+ conservationCheckAreaAMPool
+
+ real(kind=RKIND), dimension(:), pointer :: &
+ initialBlackCarbon, &
+ finalBlackCarbon, &
+ blackCarbonChange, &
+ blackCarbonChangeFlux, &
+ netBlackCarbonFlux, &
+ absoluteBlackCarbonError, &
+ relativeBlackCarbonError, &
+ iceAreaCell, &
+ iceAreaCellInitial, &
+ accumAbsoluteBlackCarbonError, &
+ accumRelativeBlackCarbonError
+
+ real(kind=RKIND), dimension(:), pointer :: &
+ blackCarbonConsAtmBlackCarbonFlux, &
+ blackCarbonConsOceanBlackCarbonFlux, &
+ blackCarbonConsAtmBC1Flux, &
+ blackCarbonConsAtmBC2Flux
+
+ real(kind=RKIND), dimension(:), allocatable :: &
+ sumArray, &
+ sumArrayOut
+
+ type(MPAS_pool_type), pointer :: &
+ meshPool, &
+ tracersAggregatePool, &
+ biogeochemistryPool, &
+ icestatePool
+
+ real(kind=RKIND), dimension(:), pointer :: &
+ areaCell, &
+ totalAtmBlackCarbonFlux, &
+ totalOceanBlackCarbonFlux, &
+ oceanBlackCarbonFluxArea
+
+ real(kind=RKIND), dimension(:,:), pointer :: &
+ atmosBlackCarbonFlux
+
+ integer, dimension(:,:), pointer :: &
+ cellInHemisphere
+
+ real(kind=RKIND), pointer :: &
+ dt, &
+ earthArea
+
+ logical, pointer :: &
+ config_AM_conservationCheck_write_to_logfile
+
+ real(kind=RKIND) :: &
+ totalAtmBlackCarbonCell, &
+ totalAtmBC1Cell, &
+ totalAtmBC2Cell, &
+ totalOceanBlackCarbonCell
+
+ integer, pointer :: &
+ nCellsSolve, &
+ nHemispheres, &
+ nAccumulate
+
+ type (MPAS_Time_Type) :: &
+ currTime, &
+ startTime
+
+ integer :: &
+ iCell, &
+ iHemisphere, &
+ iSumPrev, &
+ ierr
+
+ integer :: &
+ nVars, &
+ nZBGC, &
+ nSums
+
+ real(kind=RKIND) :: &
+ fluxScale
+
+ character(len=strKIND) :: &
+ timeStr, &
+ timeStrStart
+
+ character(len=16) :: &
+ valStr
+
+ err = 0
+
+ call MPAS_pool_get_config(domain % configs, "config_dt", dt)
+ call MPAS_pool_get_config(domain % configs, "config_AM_conservationCheck_write_to_logfile", &
+ config_AM_conservationCheck_write_to_logfile)
+
+ !-------------------------------------------------------------
+ ! Net carbon flux to ice
+ !-------------------------------------------------------------
+
+ call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nHemispheres", nHemispheres)
+
+ nVars = 4
+
+ nSums = nHemispheres * nVars
+
+ allocate(sumArray(nSums))
+ allocate(sumArrayOut(nSums))
+
+ sumArray = 0.0_RKIND
+
+ blockPtr => domain % blocklist
+ do while (associated(blockPtr))
+
+ call MPAS_pool_get_dimension(blockPtr % dimensions, "nCellsSolve", nCellsSolve)
+
+ call MPAS_pool_get_subpool(blockPtr % structs, "mesh", meshPool)
+ call MPAS_pool_get_subpool(blockPtr % structs, "biogeochemistry", biogeochemistryPool)
+ call MPAS_pool_get_subpool(blockPtr % structs, "tracers_aggregate", tracersAggregatePool)
+ call MPAS_pool_get_subpool(blockPtr % structs, "icestate", icestatePool)
+ call MPAS_pool_get_subpool(blockPtr % structs, "conservationCheckAM", conservationCheckAMPool)
+
+
+ call MPAS_pool_get_array(tracersAggregatePool, "iceAreaCell", iceAreaCell)
+ call MPAS_pool_get_array(icestatePool, "iceAreaCellInitial", iceAreaCellInitial)
+ call MPAS_pool_get_array(meshPool, "areaCell", areaCell)
+ call MPAS_pool_get_array(biogeochemistryPool, "totalAtmBlackCarbonFlux", totalAtmBlackCarbonFlux)
+ call MPAS_pool_get_array(biogeochemistryPool, "totalOceanBlackCarbonFlux", totalOceanBlackCarbonFlux)
+ call MPAS_pool_get_array(biogeochemistryPool, "atmosBlackCarbonFlux", atmosBlackCarbonFlux)
+ call MPAS_pool_get_array(biogeochemistryPool, "oceanBlackCarbonFluxArea", oceanBlackCarbonFluxArea)
+ call MPAS_pool_get_array(conservationCheckAMPool, "cellInHemisphere", cellInHemisphere)
+
+ do iCell = 1, nCellsSolve
+
+ ! compute total black carbon flux to ocean from individual fluxes
+
+ nZBGC = 1
+ totalAtmBC1Cell = atmosBlackCarbonFlux(nZBGC,iCell) * areaCell(iCell)* &
+ iceAreaCellInitial(iCell)
+ nZBGC = nZBGC+1
+ totalAtmBC2Cell = atmosBlackCarbonFlux(nZBGC,iCell) * areaCell(iCell)* &
+ iceAreaCellInitial(iCell)
+ totalOceanBlackCarbonCell = oceanBlackCarbonFluxArea(iCell) * areaCell(iCell)
+ totalAtmBlackCarbonCell = totalAtmBC1Cell + totalAtmBC2Cell
+
+ do iHemisphere = 1, nHemispheres
+ iSumPrev = (iHemisphere-1) * nVars
+ if (cellInHemisphere(iHemisphere,iCell) == 1) then
+ sumArray(iSumPrev+1) = sumArray(iSumPrev+1) + totalAtmBlackCarbonCell
+ sumArray(iSumPrev+2) = sumArray(iSumPrev+2) + totalAtmBC1Cell
+ sumArray(iSumPrev+3) = sumArray(iSumPrev+3) + totalAtmBC2Cell
+ sumArray(iSumPrev+4) = sumArray(iSumPrev+4) + totalOceanBlackCarbonCell
+ endif
+ enddo ! iHemisphere
+
+ enddo ! iCell
+
+ blockPtr => blockPtr % next
+ enddo
+
+ ! perform the sums over processors
+ call MPAS_dmpar_sum_real_array(domain % dminfo, nSums, sumArray, sumArrayOut)
+
+ ! accumulate fluxes
+ 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)
+
+ do iHemisphere = 1, nHemispheres
+ iSumPrev = (iHemisphere-1) * nVars
+ blackCarbonConsAtmBlackCarbonFlux(iHemisphere) = blackCarbonConsAtmBlackCarbonFlux(iHemisphere) + sumArrayOut(iSumPrev+1)
+ blackCarbonConsAtmBC1Flux(iHemisphere) = blackCarbonConsAtmBC1Flux(iHemisphere) + sumArrayOut(iSumPrev+2)
+ blackCarbonConsAtmBC2Flux(iHemisphere) = blackCarbonConsAtmBC2Flux(iHemisphere) + sumArrayOut(iSumPrev+3)
+ blackCarbonConsOceanBlackCarbonFlux(iHemisphere) = blackCarbonConsOceanBlackCarbonFlux(iHemisphere) + sumArrayOut(iSumPrev+4)
+ enddo ! iHemisphere
+
+ ! cleanup
+ deallocate(sumArray)
+ deallocate(sumArrayOut)
+
+ !-------------------------------------------------------------
+ ! Black carbon conservation error
+ !-------------------------------------------------------------
+
+ if (MPAS_stream_mgr_ringing_alarms(domain % streamManager, "conservationCheckOutput", ierr=ierr)) then
+
+ ! convert fluxes to fluxes per m2 of whole earth and per second
+ call MPAS_pool_get_subpool(domain % blocklist % structs, "conservationCheckAM", conservationCheckAMPool)
+ call MPAS_pool_get_array(conservationCheckAMPool, "nAccumulate", nAccumulate)
+ call MPAS_pool_get_subpool(domain % blocklist % structs, "conservationCheckAreaAM", conservationCheckAreaAMPool)
+ call MPAS_pool_get_array(conservationCheckAreaAMPool, "earthArea", earthArea)
+ fluxScale = 1.0_RKIND / (earthArea * real(nAccumulate))
+
+ ! get initial black carbon content
+ call MPAS_pool_get_array(conservationCheckBlackCarbonAMPool, "initialBlackCarbon", initialBlackCarbon)
+
+ ! get final black carbon content
+ call MPAS_pool_get_array(conservationCheckBlackCarbonAMPool, "finalBlackCarbon", finalBlackCarbon)
+ call compute_total_black_carbon(domain, finalBlackCarbon)
+
+ ! compute the black carbon content change
+ call MPAS_pool_get_array(conservationCheckBlackCarbonAMPool, "blackCarbonChange", blackCarbonChange)
+ blackCarbonChange(:) = finalBlackCarbon(:) - initialBlackCarbon(:)
+ call MPAS_pool_get_array(conservationCheckBlackCarbonAMPool, "blackCarbonChangeFlux", blackCarbonChangeFlux)
+ blackCarbonChangeFlux(:) = blackCarbonChange(:) * (fluxScale / dt)
+
+ ! calculate the final net black carbon flux to the ice
+ call MPAS_pool_get_array(conservationCheckBlackCarbonAMPool, "netBlackCarbonFlux", netBlackCarbonFlux)
+ netBlackCarbonFlux(:) = blackCarbonConsAtmBlackCarbonFlux(:) &
+ - blackCarbonConsOceanBlackCarbonFlux(:)
+
+ ! absolute error
+ call MPAS_pool_get_array(conservationCheckBlackCarbonAMPool, "absoluteBlackCarbonError", absoluteBlackCarbonError)
+ call MPAS_pool_get_array(conservationCheckBlackCarbonAMPool, "accumAbsoluteBlackCarbonError", accumAbsoluteBlackCarbonError)
+ absoluteBlackCarbonError(:) = netBlackCarbonFlux(:) * dt - blackCarbonChange(:)
+
+ ! rescale fluxes
+ blackCarbonConsOceanBlackCarbonFlux(:) = blackCarbonConsOceanBlackCarbonFlux(:) * fluxScale
+ blackCarbonConsAtmBlackCarbonFlux(:) = blackCarbonConsAtmBlackCarbonFlux(:) * fluxScale
+ blackCarbonConsAtmBC1Flux(:) = blackCarbonConsAtmBC1Flux(:) * fluxScale
+ blackCarbonConsAtmBC2Flux(:) = blackCarbonConsAtmBC2Flux(:) * fluxScale
+ netBlackCarbonFlux(:) = netBlackCarbonFlux(:) * fluxScale
+
+ ! compute the final black carbon error
+ call MPAS_pool_get_array(conservationCheckBlackCarbonAMPool, "relativeBlackCarbonError", relativeBlackCarbonError)
+ call MPAS_pool_get_array(conservationCheckBlackCarbonAMPool, "accumRelativeBlackCarbonError", accumRelativeBlackCarbonError)
+ do iHemisphere = 1, nHemispheres
+ if (abs(finalBlackCarbon(iHemisphere)) > 0.0) then
+ relativeBlackCarbonError(iHemisphere) = absoluteBlackCarbonError(iHemisphere) / finalBlackCarbon(iHemisphere)
+ else
+ relativeBlackCarbonError(iHemisphere) = 0.0_RKIND
+ endif
+ enddo ! iHemisphere
+
+ startTime = mpas_get_clock_time(domain % clock, MPAS_START_TIME, ierr=ierr)
+ currTime = mpas_get_clock_time(domain % clock, MPAS_NOW, ierr=ierr)
+
+ call MPAS_get_time(currTime, dateTimeString=timeStr, ierr=ierr)
+ call MPAS_get_time(startTime, dateTimeString=timeStrStart, ierr=ierr)
+
+ if (trim(timeStr) /= trim(timeStrStart)) then
+ accumRelativeBlackCarbonError(:) = accumRelativeBlackCarbonError(:) + relativeBlackCarbonError(:)
+ accumAbsoluteBlackCarbonError(:) = accumAbsoluteBlackCarbonError(:) + absoluteBlackCarbonError(:)
+ !-------------------------------------------------------------
+ ! Output to log file
+ !-------------------------------------------------------------
+
+ if (config_AM_conservationCheck_write_to_logfile) then
+
+ call mpas_log_write('-----------------------------------------------------------------------------')
+ call mpas_log_write(' Black carbon conservation check')
+ call mpas_log_write(' ')
+ call mpas_log_write(' Initial black carbon (kg) = '//trim(hemisphere_format(initialBlackCarbon)))
+ call mpas_log_write(' Final black carbon (kg) = '//trim(hemisphere_format(finalBlackCarbon)))
+ call mpas_log_write(' Black carbon change (kg) = '//trim(hemisphere_format(blackCarbonChange)))
+ call mpas_log_write(' Black carbon change flux (kg/m2s) = '//trim(hemisphere_format(blackCarbonChangeFlux)))
+ call mpas_log_write(' ')
+ call mpas_log_write(' Ocean black carbon flux (kg/m2s) = '//trim(hemisphere_format(blackCarbonConsOceanBlackCarbonFlux)))
+ call mpas_log_write(' Atmos black carbon flux (kg/m2s) = '//trim(hemisphere_format(blackCarbonConsAtmBlackCarbonFlux)))
+ call mpas_log_write(' Net black carbon flux (kg/m2s) = '//trim(hemisphere_format(netBlackCarbonFlux)))
+ call mpas_log_write(' ')
+ call mpas_log_write(' Individual atmosphere black carbon fluxes :')
+ call mpas_log_write(' Atmos BC1 flux (kg/m2s) = '//trim(hemisphere_format(blackCarbonConsAtmBC1Flux)))
+ call mpas_log_write(' Atmos BC2 flux (kg/m2s) = '//trim(hemisphere_format(blackCarbonConsAtmBC2Flux)))
+ call mpas_log_write(' ')
+
+ call mpas_log_write(' Net black carbon change (kg) = '//trim(hemisphere_format((netBlackCarbonFlux * dt) / fluxScale)))
+ call mpas_log_write(' Net black carbon flux (kg/m2s) = '//trim(hemisphere_format(netBlackCarbonFlux)))
+ call mpas_log_write(' ')
+ call mpas_log_write(' Absolute black carbon error (kg) = '//trim(hemisphere_format(absoluteBlackCarbonError)))
+ call mpas_log_write(' Absolute BC error/s (kg/m2s) = '//trim(hemisphere_format((absoluteBlackCarbonError * fluxScale) / dt)))
+ call mpas_log_write(' Relative black carbon error = '//trim(hemisphere_format(relativeBlackCarbonError)))
+
+ call mpas_log_write(' ')
+ call mpas_log_write(' Total run accumulated error ')
+ call mpas_log_write(' Accum. abs black carbon error(kg) = '//trim(hemisphere_format(accumAbsoluteBlackCarbonError)))
+ call mpas_log_write(' Accum. rel black carbon error = '//trim(hemisphere_format(accumRelativeBlackCarbonError)))
+ endif
+ endif
+ endif
+
+ end subroutine black_carbon_conservation
+
!***********************************************************************
!
! routine compute_total_energy
@@ -2800,6 +3135,100 @@ subroutine compute_total_carbon(domain, totalCarbon)
end subroutine compute_total_carbon
+!***********************************************************************
+!
+! routine compute_total_black_carbon
+!
+!> \brief Compute total black carbon
+!> \author Nicole Jeffery
+!> \date 11 Mar 2024
+!> \details
+!> Calculate the total black carbon
+!
+!-----------------------------------------------------------------------
+
+ subroutine compute_total_black_carbon(domain, totalBlackCarbon)
+
+ type (domain_type), intent(inout) :: &
+ domain
+
+ real(kind=RKIND), dimension(:), intent(out) :: &
+ totalBlackCarbon
+
+ type(block_type), pointer :: &
+ blockPtr
+
+ type(MPAS_pool_type), pointer :: &
+ meshPool, &
+ biogeochemistryPool, &
+ conservationCheckAMPool
+
+ integer, pointer :: &
+ nCellsSolve, &
+ nHemispheres
+
+ real(kind=RKIND), dimension(:), pointer :: &
+ totalBlackCarbonContentCell, &
+ areaCell
+
+ integer, dimension(:,:), pointer :: &
+ cellInHemisphere
+
+ integer :: &
+ iCell, &
+ iHemisphere
+
+ real(kind=RKIND) :: &
+ blackCarbonCell
+
+ real(kind=RKIND), dimension(:), allocatable :: &
+ blackCarbon
+
+ call MPAS_pool_get_dimension(domain % blocklist % dimensions, "nHemispheres", nHemispheres)
+
+ allocate(blackCarbon(nHemispheres))
+ blackCarbon(:) = 0.0_RKIND
+
+ blockPtr => domain % blocklist
+ do while (associated(blockPtr))
+
+ call MPAS_pool_get_subpool(blockPtr % structs, "mesh", meshPool)
+ call MPAS_pool_get_subpool(blockPtr % structs, "biogeochemistry", biogeochemistryPool)
+ call MPAS_pool_get_subpool(blockPtr % structs, "conservationCheckAM", conservationCheckAMPool)
+
+ call MPAS_pool_get_dimension(blockPtr % dimensions, 'nCellsSolve', nCellsSolve)
+ call MPAS_pool_get_dimension(blockPtr % dimensions, 'nHemispheres', nHemispheres)
+
+ call MPAS_pool_get_array(meshPool, "areaCell", areaCell)
+ call MPAS_pool_get_array(biogeochemistryPool, "totalBlackCarbonContentCell", totalBlackCarbonContentCell)
+ call MPAS_pool_get_array(conservationCheckAMPool, "cellInHemisphere", cellInHemisphere)
+
+ call compute_black_carbon_cell(blockPtr,totalBlackCarbonContentCell)
+
+ do iCell = 1, nCellsSolve
+
+ ! black carbon mass (kg)
+ blackCarbonCell = totalBlackCarbonContentCell(iCell) * areaCell(iCell)
+
+ do iHemisphere = 1, nHemispheres
+ if (cellInHemisphere(iHemisphere,iCell) == 1) then
+ blackCarbon(iHemisphere) = blackCarbon(iHemisphere) + blackCarbonCell
+ endif
+ enddo ! iHemisphere
+
+ enddo ! iCell
+
+ blockPtr => 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