diff --git a/.github/workflows/e3sm-gh-ci-cime-tests.yml b/.github/workflows/e3sm-gh-ci-cime-tests.yml index d73e96c6a1d..366fef018f2 100644 --- a/.github/workflows/e3sm-gh-ci-cime-tests.yml +++ b/.github/workflows/e3sm-gh-ci-cime-tests.yml @@ -3,6 +3,18 @@ name: gh on: pull_request: branches: [ master ] + paths: + # first, yes to these + - 'cime_config/**' + - 'components/eam/**' + - 'components/elm/**' + - 'driver-moab/**' + - 'driver-mct/**' + # second, no to these + - '!components/eam/docs/**' + - '!components/eam/mkdocs.yml' + - '!components/elm/docs/**' + - '!components/elm/mkdocs.yml' workflow_dispatch: diff --git a/.github/workflows/e3sm-gh-ci-w-cime-tests.yml b/.github/workflows/e3sm-gh-ci-w-cime-tests.yml new file mode 100644 index 00000000000..595518c326d --- /dev/null +++ b/.github/workflows/e3sm-gh-ci-w-cime-tests.yml @@ -0,0 +1,59 @@ +name: gh + +on: + pull_request: + branches: [ master ] + paths-ignore: + - 'mkdocs.yaml' + - 'docs/**' + - 'components/*/docs/**' + - 'components/*/mkdocs.yml' + + workflow_dispatch: + +jobs: + + ci-w: + 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 + container: + image: ghcr.io/mahf708/e3sm-imgs:v0.0.6 + + steps: + - + name: Checkout + uses: actions/checkout@v4 + with: + show-progress: false + submodules: recursive + - + 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 + uses: actions/upload-artifact@v4 + if: ${{ always() }} + 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 diff --git a/.github/workflows/e3sm-gh-md-linter.yml b/.github/workflows/e3sm-gh-md-linter.yml new file mode 100644 index 00000000000..6484335213d --- /dev/null +++ b/.github/workflows/e3sm-gh-md-linter.yml @@ -0,0 +1,28 @@ +name: markdown + +# if .md files are touched in a PR, lint them! + +on: + pull_request: + branches: ["master"] + paths: + - '**/*.md' + +jobs: + linter: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: tj-actions/changed-files@v44 + id: changed-files + with: + files: '**/*.md' + separator: "," + - uses: DavidAnson/markdownlint-cli2-action@v16 + if: steps.changed-files.outputs.any_changed == 'true' + with: + config: 'docs/.markdownlint.json' + globs: ${{ steps.changed-files.outputs.all_changed_files }} + separator: "," diff --git a/.gitignore b/.gitignore index c4d2a64bc99..8c1fa12b87c 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,13 @@ site # Ignore emacs backup files *~ +#Ignore Mac folder files +.DS_Store + +#Ignore vscode dir +.vscode + + # Ignore mkdocs site-generated files in eamxx components/eamxx/site/* # Ignore auto-generated eamxx_params.md file diff --git a/cime_config/allactive/config_compsets.xml b/cime_config/allactive/config_compsets.xml index 637facc327d..66edcf617c0 100755 --- a/cime_config/allactive/config_compsets.xml +++ b/cime_config/allactive/config_compsets.xml @@ -70,6 +70,12 @@ 1850_EAM%CMIP6_ELM%CNPRDCTCBCTOP_MPASSI_MPASO_MOSART_SGLC_SWAV + + + WCYCL2010NS + 2010_EAM%CMIP6_ELM%CNPRDCTCBCTOP_MPASSI_MPASO_MOSART_SGLC_SWAV + + WCYCL1950 1950SOI_EAM%CMIP6_ELM%CNPRDCTCBCTOP_MPASSI_MPASO_MOSART_SGLC_SWAV @@ -113,12 +119,17 @@ WCYCLSSP585 - SSP585SOI_EAM%CMIP6_ELM%SPBC_MPASSI_MPASO_MOSART_SGLC_SWAV + SSP585SOI_EAM%CMIP6_ELM%CNPRDCTCBCTOP_MPASSI_MPASO_MOSART_SGLC_SWAV WCYCLSSP370 - SSP370SOI_EAM%CMIP6_ELM%SPBC_MPASSI_MPASO_MOSART_SGLC_SWAV + SSP370SOI_EAM%CMIP6_ELM%CNPRDCTCBCTOP_MPASSI_MPASO_MOSART_SGLC_SWAV + + + + WCYCLSSP245 + SSP245SOI_EAM%CMIP6_ELM%CNPRDCTCBCTOP_MPASSI_MPASO_MOSART_SGLC_SWAV @@ -393,7 +404,7 @@ BGWCYCL1850 - 1850_EAM%CMIP6_ELM%SPBC_MPASSI_MPASO_MOSART_MALI%STATIC_SWAV + 1850_EAM%CMIP6_ELM%SPBC_MPASSI_MPASO_MOSART_MALI_SWAV @@ -443,6 +454,7 @@ 1850-01-01 2015-01-01 2015-01-01 + 2015-01-01 diff --git a/cime_config/allactive/config_pesall.xml b/cime_config/allactive/config_pesall.xml index 7bcf72e44e6..0db40bd5798 100644 --- a/cime_config/allactive/config_pesall.xml +++ b/cime_config/allactive/config_pesall.xml @@ -325,7 +325,7 @@ - + "anvil, GPMPAS-JRA compset, 6 nodes" -6 @@ -338,7 +338,7 @@ - + "crusher, GPMPAS-JRA compset, 2 nodes" -4 @@ -351,7 +351,7 @@ - + summit|ascent: GPMPAS-JRA compset on ne30np4 grid -4 @@ -468,7 +468,7 @@ - + -compset A_WCYCL* -res ne30_oEC* on 27 nodes pure-MPI 900 @@ -487,7 +487,7 @@ 0 - + -compset A_WCYCL* -res ne30_oEC* on 40 nodes pure-MPI 1350 @@ -506,7 +506,7 @@ 0 - + -compset A_WCYCL* -res ne30_oEC* on 80 nodes pure-MPI 2700 @@ -525,7 +525,7 @@ 0 - + -compset A_WCYCL* -res ne30_oEC* on 160 nodes pure-MPI 5400 @@ -548,7 +548,7 @@ - + ne120-wcycl on 42 nodes 128x1 ~0.7 sypd 128 @@ -584,7 +584,7 @@ - + ne120-wcycl on 145 nodes, MPI-only 64 64 @@ -609,7 +609,7 @@ 0 - + ne120-wcycl on 145 nodes, threaded 256 64 @@ -644,7 +644,7 @@ 0 - + ne120 coupled-compset on 466 nodes 64 64 @@ -669,7 +669,7 @@ 0 - + ne120-wcycl on 863 nodes, MPI-only 64 64 @@ -694,7 +694,7 @@ 0 - + ne120-wcycl on 863 nodes, threaded 128 64 @@ -729,7 +729,7 @@ 0 - + ne120-wcycl on 825 nodes, threaded, 32 tasks/node 128 32 @@ -764,7 +764,7 @@ 0 - + ne120-wcycl on 800 nodes, threaded, 32 tasks/node 128 32 @@ -801,7 +801,7 @@ - + compy ne120 W-cycle on 310 nodes, 40x1, sypd=1.2 9600 @@ -824,7 +824,7 @@ - + --compset WCYCL* --res ne30pg2_EC30to60E2r2 on 25 nodes pure-MPI, ~5.4 sypd 675 @@ -843,7 +843,7 @@ 0 - + --compset WCYCL* --res ne30pg2_EC30to60E2r2 on 48 nodes pure-MPI, ~9.4 sypd 1350 @@ -862,7 +862,7 @@ 0 - + --compset WCYCL* --res ne30pg2_EC30to60E2r2 on 90 nodes pure-MPI, ~12 sypd 2700 @@ -917,7 +917,7 @@ - + -compset A_WCYCL* -res ne30pg2_EC30to60* on 27 nodes pure-MPI, ~15.5 sypd 2700 @@ -936,7 +936,7 @@ 0 - + -compset A_WCYCL* -res ne30pg2_EC30to60* on 54 nodes pure-MPI, ~25.5 sypd 5400 @@ -957,7 +957,7 @@ - + -compset A_WCYCL* -res ne30pg2_EC30to60* on 11 nodes pure-MPI, ~2.8 sypd 320 @@ -976,7 +976,7 @@ 0 - + -compset A_WCYCL* -res ne30pg2_EC30to60* on 21 nodes pure-MPI, ~5.5 sypd 600 @@ -995,7 +995,7 @@ 0 - + -compset A_WCYCL* -res ne30pg2_EC30to60* on 46 nodes pure-MPI, ~11 sypd 1350 @@ -1014,7 +1014,7 @@ 0 - + -compset A_WCYCL* -res ne30pg2_EC30to60* on 90 nodes pure-MPI, ~18 sypd 2700 @@ -1037,7 +1037,7 @@ - + -compset WCYCL*/CRYO* -res SOwISC12to60E2r4* on 75 nodes pure-MPI, ~5 sypd 900 @@ -1058,7 +1058,7 @@ - + -compset WCYCL*/CRYO* -res ne30pg*SOwISC12to60E2r4* on 105 nodes pure-MPI, ~18.5 sypd 64 @@ -1078,7 +1078,7 @@ 0 - + -compset WCYCL*/CRYO* -res ne30pg*SOwISC12to60E2r4* on 54 nodes pure-MPI, ~11 sypd 64 @@ -1102,7 +1102,7 @@ - + -compset WCYCL*/CRYO* -res ECwISC30to60E2r1* on 48 nodes pure-MPI, ~8.5 sypd 1350 @@ -1123,7 +1123,7 @@ - + -compset WCYCL*/CRYO* -res ne30pg*ECwISC30to60E2r1* on 105 nodes pure-MPI, ~40 sypd 64 @@ -1143,7 +1143,7 @@ 0 - + -compset WCYCL*/CRYO* -res ne30pg*ECwISC30to60E2r1* on 55 nodes pure-MPI, ~25 sypd 64 @@ -1163,7 +1163,7 @@ 0 - + -compset WCYCL*/CRYO* -res ne30pg*ECwISC30to60E2r1* on 28 nodes pure-MPI, ~15 sypd 64 @@ -1187,7 +1187,7 @@ - + gcp12 -compset A_WCYCL* -res ne30pg2_oECv3 with MPASO on 7 nodes 280 @@ -1216,7 +1216,7 @@ - + gcp10 -compset A_WCYCL* -res ne30pg2_oECv3 with MPASO on 11 nodes 240 @@ -1245,7 +1245,7 @@ - + -compset A_WCYCL* -res ne30pg2_oECv3 with MPASO on 7 nodes, 128x1 128 @@ -1273,7 +1273,7 @@ 0 - + -compset A_WCYCL* -res ne30pg2_oECv3 with MPASO on 58 nodes, 128x1, ~20 sypd 128 @@ -1410,7 +1410,7 @@ - + -compset A_WCYCL* -res ne30pg2_oECv3 on 11 nodes pure-MPI, ~2.8 sypd 320 @@ -1429,7 +1429,7 @@ 0 - + -compset A_WCYCL* -res ne30pg2_oECv3 on 21 nodes pure-MPI, ~5.5 sypd 600 @@ -1448,7 +1448,7 @@ 0 - + -compset A_WCYCL* -res ne30pg2_oECv3 on 46 nodes pure-MPI, ~11 sypd 1350 @@ -1467,7 +1467,7 @@ 0 - + -compset A_WCYCL* -res ne30pg2_oECv3 on 90 nodes pure-MPI, ~18 sypd 2700 @@ -1586,9 +1586,70 @@ + + + + --compset WCYCL* --res ne30pg2_r05_IcosXISC30E3r7 on 20 nodes pure-MPI, ~7.25 sypd + + 1024 + 1024 + 256 + 640 + 384 + 385 + + + 0 + 0 + 1024 + 0 + 640 + 640 + + + + --compset WCYCL* --res ne30pg2_r05_IcosXISC30E3r7 on 54 nodes pure-MPI, ~17.5 sypd + + 2752 + 2752 + 704 + 2048 + 704 + 704 + + + 0 + 0 + 2752 + 0 + 2048 + 2048 + + + + --compset WCYCL* --res ne30pg2_r05_IcosXISC30E3r7 on 105 nodes pure-MPI, ~27.7 sypd + + 5440 + 5440 + 1280 + 4352 + 1088 + 1088 + + + 0 + 0 + 5440 + 0 + 4352 + 4352 + + + + - + -compset WCYCL* -res ne30pg2_EC30to60E2r2 on 14 nodes pure-MPI, ~6 sypd 704 @@ -1607,7 +1668,7 @@ 0 - + -compset WCYCL* -res ne30pg2_EC30to60E2r2 on 27 nodes pure-MPI, ~12 sypd 1408 @@ -1626,7 +1687,7 @@ 0 - + -compset WCYCL* -res ne30pg2_EC30to60E2r2 on 53 nodes pure-MPI, ~21 sypd 2752 @@ -1645,7 +1706,7 @@ 0 - + -compset WCYCL* -res ne30pg2_EC30to60E2r2 on 70 nodes pure-MPI, ~24 sypd 3648 @@ -1664,7 +1725,7 @@ 0 - + -compset WCYCL* -res ne30pg2EC30to60E2r2 on 100 nodes pure-MPI, ~30 sypd 5440 @@ -1685,7 +1746,7 @@ - + -compset A_WCYCL* -res ne30pg*EC30to60* on 8 debug Q nodes threaded, 0.8 sypd 384 @@ -1712,7 +1773,7 @@ 0 - + -compset A_WCYCL* -res ne30pg*EC30to60* on 128 default Q nodes pure-MPI, 3.8 sypd 5400 @@ -1735,7 +1796,7 @@ - + -compset WCYCL* -res ne30pg*WCAtl* on 80 nodes pure-MPI, ~8.5 sypd 2700 @@ -1933,7 +1994,7 @@ - + rmod025a 40 40 @@ -1954,7 +2015,7 @@ 0 - + rmod077a 40 40 @@ -1975,7 +2036,7 @@ 0 - + rmod111a 40 40 @@ -1996,7 +2057,7 @@ 0 - + rmod037a 20 40 @@ -2017,7 +2078,7 @@ 2 - + rmod074a 20 40 @@ -2046,7 +2107,7 @@ 0 - + rmod115b 20 40 @@ -2077,7 +2138,7 @@ - + RRM-WCYCL: 64 nodes 2.133 sypd 1800 @@ -2098,7 +2159,7 @@ - + cmod016b64x1 s=2.4 64 128 @@ -2119,7 +2180,7 @@ 0 - + cmod040c64x1 s=5.6 64 128 @@ -2140,7 +2201,7 @@ 0 - + cmod060d64x1 s=8.0 64 128 @@ -2161,7 +2222,7 @@ 0 - + cmod080c64x1 s=10.1 64 128 @@ -2182,7 +2243,7 @@ 0 - + cmod100b64x1 s=12.3 64 128 @@ -2205,7 +2266,7 @@ - + 8 nodes, 128x1 640 @@ -2258,7 +2319,7 @@ - + --compset WCYCL* --res ne30pg2_EC30to60E2r2_wQU225EC30to60E2r2 on 48 nodes pure-MPI, ~8.8 sypd 1350 @@ -2292,7 +2353,7 @@ - + none 924 @@ -2329,7 +2390,7 @@ - + none 2768 @@ -2526,4 +2587,80 @@ + + + + GIS 1-to-10km (high-res) baseline config + 128 + 128 + + 1350 + 960 + 960 + 1350 + 320 + 960 + 2310 + 2310 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + 1350 + 1350 + 0 + 2310 + 1350 + 0 + 0 + + + + + + GIS 1-to-10km (high-res) baseline config + 64 + 64 + + 1350 + 960 + 960 + 1408 + 384 + 960 + 1 + 2368 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + 1408 + 1408 + 0 + 2368 + 1408 + 0 + 0 + + + + diff --git a/cime_config/config_archive.xml b/cime_config/config_archive.xml index 028a11e8439..84de6e0f171 100644 --- a/cime_config/config_archive.xml +++ b/cime_config/config_archive.xml @@ -119,7 +119,6 @@ rst - rst.am.timeSeriesStatsMonthly hist unset @@ -129,9 +128,8 @@ rpointer.glc casename.mali.rst.1976-01-01_00000.nc - casename.mali.rst.am.timeSeriesStatsMonthly.1976-01-01_00000.nc - casename.mali.hist.am.globalStats.1976-01-01.nc - casename.mali.hist.am.highFrequencyOutput.1976-01-01_00.00.00.nc + casename.mali.hist.1976-01-01_00000.nc + casename.mali.hist.am.1976-01-01.nc diff --git a/cime_config/config_files.xml b/cime_config/config_files.xml index 97d73759ac4..71de5196442 100644 --- a/cime_config/config_files.xml +++ b/cime_config/config_files.xml @@ -98,6 +98,7 @@ char $CIMEROOT/CIME/data/config/config_tests.xml + $COMP_ROOT_DIR_OCN/cime_config/config_tests.xml test env_test.xml @@ -321,6 +322,7 @@ char $CIMEROOT/CIME/SystemTests + $COMP_ROOT_DIR_OCN/cime_config/SystemTests test env_test.xml diff --git a/cime_config/config_grids.xml b/cime_config/config_grids.xml index caa87c8222c..ccfb3d908d8 100755 --- a/cime_config/config_grids.xml +++ b/cime_config/config_grids.xml @@ -38,9 +38,6 @@ r05 r05 null - gland5UM - gland4 - gland4 null null null @@ -489,6 +486,36 @@ WC14to60E2r3 + + TL319 + r05 + WC14to60E2r3 + r05 + null + null + WC14to60E2r3 + + + + TL319 + r05 + EC30to60E2r2 + r05 + null + null + EC30to60E2r2 + + + + TL319 + r05 + ARRM10to60E2r1 + r05 + null + null + ARRM10to60E2r1 + + TL319 TL319 @@ -569,6 +596,16 @@ IcoswISC30E3r5 + + TL319 + TL319 + IcosXISC30E3r7 + JRA025 + null + null + IcosXISC30E3r7 + + TL319 TL319 @@ -721,6 +758,16 @@ oEC60to30v3 + + r025 + r025 + r025 + r025 + null + null + oEC60to30v3 + + r0125 r0125 @@ -751,6 +798,16 @@ oRRS18to6v3 + + r025 + r025 + IcoswISC30E3r5 + null + null + null + IcoswISC30E3r5 + + @@ -1023,6 +1080,16 @@ oRRS15to5 + + ne0np4_northamericax4v1.pg2 + r025 + IcoswISC30E3r5 + r025 + null + null + IcoswISC30E3r5 + + ne0np4_northamericax4v1.pg2 r0125 @@ -1426,6 +1493,26 @@ oRRS18to6v3 + + ne120np4.pg2 + r025 + IcoswISC30E3r5 + null + null + null + IcoswISC30E3r5 + + + + ne30np4.pg2 + r025 + IcoswISC30E3r5 + null + null + null + IcoswISC30E3r5 + + ne60np4 ne60np4 @@ -1708,6 +1795,36 @@ oEC60to30v3 + + ne30np4.pg2 + r05 + EC30to60E2r2 + r05 + mpas.gis20km + null + EC30to60E2r2 + + + + ne30np4.pg2 + r05 + IcoswISC30E3r5 + r05 + mpas.gis20km + null + IcoswISC30E3r5 + + + + TL319 + TL319 + IcoswISC30E3r5 + JRA025 + mpas.gis20km + null + IcoswISC30E3r5 + + ne30np4.pg2 r05 @@ -1728,6 +1845,16 @@ oEC60to30v3 + + ne30np4.pg2 + r05 + EC30to60E2r2 + r05 + mpas.gis1to10km + null + EC30to60E2r2 + + ne30np4.pg2 r0125 @@ -1738,6 +1865,36 @@ EC30to60E2r2 + + ne30np4.pg2 + r05 + EC30to60E2r2 + r05 + mpas.gis1to10kmR2 + null + EC30to60E2r2 + + + + ne30np4.pg2 + r05 + IcoswISC30E3r5 + r05 + mpas.gis1to10kmR2 + null + IcoswISC30E3r5 + + + + TL319 + TL319 + IcoswISC30E3r5 + JRA025 + mpas.gis1to10kmR2 + null + IcoswISC30E3r5 + + ne120np4.pg2 r0125 @@ -2104,6 +2261,16 @@ IcoswISC30E3r5 + + ne30np4.pg2 + r05 + IcosXISC30E3r7 + r05 + null + null + IcosXISC30E3r7 + + ne30np4.pg2 r05 @@ -2466,6 +2633,8 @@ $DIN_LOC_ROOT/share/domains/domain.ocn.TL319_ECwISC30to60E2r1.201007.nc $DIN_LOC_ROOT/share/domains/domain.lnd.TL319_IcoswISC30E3r5.231121.nc $DIN_LOC_ROOT/share/domains/domain.ocn.TL319_IcoswISC30E3r5.231121.nc + $DIN_LOC_ROOT/share/domains/domain.lnd.TL319_IcosXISC30E3r7.240326.nc + $DIN_LOC_ROOT/share/domains/domain.ocn.TL319_IcosXISC30E3r7.240326.nc $DIN_LOC_ROOT/share/domains/domain.lnd.TL319_oRRS18to6v3.220124.nc $DIN_LOC_ROOT/share/domains/domain.ocn.TL319_oRRS18to6v3.220124.nc TL319 is JRA lat/lon grid: @@ -2575,6 +2744,8 @@ $DIN_LOC_ROOT/share/domains/domain.ocn.ne30pg2_oRRS18to6v3.211101.nc $DIN_LOC_ROOT/share/domains/domain.lnd.ne30pg2_IcoswISC30E3r5.231121.nc $DIN_LOC_ROOT/share/domains/domain.ocn.ne30pg2_IcoswISC30E3r5.231121.nc + $DIN_LOC_ROOT/share/domains/domain.lnd.ne30pg2_IcosXISC30E3r7.240326.nc + $DIN_LOC_ROOT/share/domains/domain.ocn.ne30pg2_IcosXISC30E3r7.240326.nc $DIN_LOC_ROOT/share/domains/domain.lnd.ne30pg2_gx1v6.190806.nc $DIN_LOC_ROOT/share/domains/domain.ocn.ne30pg2_gx1v6.190806.nc ne30np4.pg2 is Spectral Elem 1-deg grid w/ 2x2 FV physics grid per element: @@ -2877,6 +3048,13 @@ IcoswISC30E3r5 is a MPAS ocean grid generated with the jigsaw/compass process using a dual mesh that is a subdivided icosahedron, resulting in a nearly uniform resolution of 30 km. Additionally, it has ocean in ice-shelf cavities: + + 463013 + 1 + $DIN_LOC_ROOT/share/domains/domain.ocn.IcosXISC30E3r7.240326.nc + IcosXISC30E3r7 is a MPAS ocean grid generated with the jigsaw/compass process using a dual mesh that is a subdivided icosahedron, resulting in a nearly uniform resolution of 30 km.: + + @@ -2909,6 +3087,8 @@ $DIN_LOC_ROOT/share/domains/domain.lnd.r05_WC14to60E2r3.200929.nc $DIN_LOC_ROOT/share/domains/domain.lnd.r05_IcoswISC30E3r5.231121.nc $DIN_LOC_ROOT/share/domains/domain.lnd.r05_IcoswISC30E3r5.231121.nc + $DIN_LOC_ROOT/share/domains/domain.lnd.r05_IcosXISC30E3r7.240326.nc + $DIN_LOC_ROOT/share/domains/domain.lnd.r05_IcosXISC30E3r7.240326.nc $DIN_LOC_ROOT/share/domains/domain.lnd.r05_gx1v6.191014.nc r05 is 1/2 degree river routing grid: @@ -2938,6 +3118,12 @@ r0125 is 1/8 degree river routing grid: + + 1440 + 720 + $DIN_LOC_ROOT/share/domains/domain.lnd.r025_IcoswISC30E3r5.240129.nc + + 28993 1 @@ -2971,6 +3157,12 @@ mpas.gis1to10km is a variable-resolution, from 1- to 10-km, MALI grid of the Greenland Ice Sheet. + + 427386 + 1 + mpas.gis1to10kmR2 is an updated (fewer grid cells; improved optimization) variable-resolution, from 1- to 10-km, MALI grid of the Greenland Ice Sheet. + + 45675 1 @@ -3060,6 +3252,8 @@ $DIN_LOC_ROOT/share/domains/domain.ocn.northamericax4v1pg2_WC14to60E2r3.200929.nc $DIN_LOC_ROOT/share/domains/domain.lnd.northamericax4v1pg2_EC30to60E2r2.220428.nc $DIN_LOC_ROOT/share/domains/domain.ocn.northamericax4v1pg2_EC30to60E2r2.220428.nc + $DIN_LOC_ROOT/share/domains/domain.lnd.northamericax4v1pg2_IcoswISC30E3r5.240416.nc + $DIN_LOC_ROOT/share/domains/domain.ocn.northamericax4v1pg2_IcoswISC30E3r5.240416.nc 1-deg with 1/4-deg over North America (version 1) pg2: @@ -3375,6 +3569,16 @@ cpl/gridmaps/ne30pg2/map_ne30pg2_to_IcoswISC30E3r5_trfvnp2.20231121.nc + + cpl/gridmaps/ne30pg2/map_ne30pg2_to_IcosXISC30E3r7_traave.20240326.nc + cpl/gridmaps/ne30pg2/map_ne30pg2_to_IcosXISC30E3r7_trbilin.20240326.nc + cpl/gridmaps/ne30pg2/map_ne30pg2_to_IcosXISC30E3r7_trbilin.20240326.nc + cpl/gridmaps/IcosXISC30E3r7/map_IcosXISC30E3r7_to_ne30pg2_traave.20240326.nc + cpl/gridmaps/IcosXISC30E3r7/map_IcosXISC30E3r7_to_ne30pg2_traave.20240326.nc + cpl/gridmaps/ne30pg2/map_ne30pg2_to_IcosXISC30E3r7_trfvnp2.20240326.nc + cpl/gridmaps/ne30pg2/map_ne30pg2_to_IcosXISC30E3r7_trfvnp2.20240326.nc + + cpl/gridmaps/ne30pg3/map_ne30pg3_to_oEC60to30v3_mono.200331.nc cpl/gridmaps/ne30pg3/map_ne30pg3_to_oEC60to30v3_bilin.200331.nc @@ -3549,6 +3753,22 @@ cpl/gridmaps/ne120pg2/map_ne120pg2_to_r0125_mono.200707.nc + + cpl/gridmaps/ne120pg2/map_ne120pg2_to_r025_traave.20240206.nc + cpl/gridmaps/ne120pg2/map_ne120pg2_to_r025_trfv2.20240206.nc + cpl/gridmaps/ne120pg2/map_ne120pg2_to_r025_esmfbilin.20240206.nc + cpl/gridmaps/ne120pg2/map_r025_to_ne120pg2_traave.20240206.nc + cpl/gridmaps/ne120pg2/map_r025_to_ne120pg2_traave.20240206.nc + + + + cpl/gridmaps/ne120pg2/map_ne30pg2_to_r025_traave.20240206.nc + cpl/gridmaps/ne120pg2/map_ne30pg2_to_r025_trfv2.20240206.nc + cpl/gridmaps/ne120pg2/map_ne30pg2_to_r025_esmfbilin.20240206.nc + cpl/gridmaps/ne120pg2/map_r025_to_ne30pg2_traave.20240206.nc + cpl/gridmaps/ne120pg2/map_r025_to_ne30pg2_traave.20240206.nc + + cpl/gridmaps/ne120np4/map_ne120np4_to_oRRS18to6v3_mono.20200702.nc cpl/gridmaps/ne120np4/map_ne120np4_to_oRRS18to6v3_mono.20200702.nc @@ -3845,6 +4065,16 @@ cpl/gridmaps/EC30to60E2r2/map_EC30to60E2r2_to_northamericax4v1pg2_mono.220428.nc + + cpl/gridmaps/northamericax4v1np4/map_northamericax4v1pg2_to_IcoswISC30E3r5_traave.20240411.nc + cpl/gridmaps/northamericax4v1np4/map_northamericax4v1pg2_to_IcoswISC30E3r5_trbilin.20240331.nc + cpl/gridmaps/northamericax4v1np4/map_northamericax4v1pg2_to_IcoswISC30E3r5-nomask_trbilin.20240331.nc + cpl/gridmaps/IcoswISC30E3r5/map_IcoswISC30E3r5_to_northamericax4v1pg2_traave.20240331.nc + cpl/gridmaps/IcoswISC30E3r5/map_IcoswISC30E3r5_to_northamericax4v1pg2_traave.20240331.nc + cpl/gridmaps/northamericax4v1np4/map_northamericax4v1pg2_to_IcoswISC30E3r5_trfvnp2.20240331.nc + cpl/gridmaps/northamericax4v1np4/map_northamericax4v1pg2_to_IcoswISC30E3r5_trfvnp2.20240331.nc + + cpl/gridmaps/northamericax4v1np4/map_northamericax4v1pg2_to_r0125_mono.20200401.nc cpl/gridmaps/northamericax4v1np4/map_northamericax4v1pg2_to_r0125_bilin.20200401.nc @@ -3852,6 +4082,14 @@ cpl/gridmaps/r0125/map_r0125_to_northamericax4v1pg2_mono.20200401.nc + + cpl/gridmaps/northamericax4v1np4/map_northamericax4v1pg2_to_r025_traave.20240331.nc + cpl/gridmaps/northamericax4v1np4/map_northamericax4v1pg2_to_r025_trfvnp2.20240331.nc + cpl/gridmaps/northamericax4v1np4/map_northamericax4v1pg2_to_r025_trbilin.20240331.nc + cpl/gridmaps/r025/map_r025_to_northamericax4v1pg2_traave.20240331.nc + cpl/gridmaps/r025/map_r025_to_northamericax4v1pg2_traave.20240331.nc + + cpl/gridmaps/northamericax4v1np4/map_northamericax4v1pg2_to_r0125_mono.20200401.nc cpl/gridmaps/northamericax4v1np4/map_northamericax4v1pg2_to_r0125_bilin.20200401.nc @@ -3862,6 +4100,12 @@ cpl/gridmaps/northamericax4v1np4/map_northamericax4v1pg2_to_r05_bilin.220428.nc + + cpl/gridmaps/northamericax4v1np4/map_northamericax4v1pg2_to_r025_traave.20240331.nc + cpl/gridmaps/northamericax4v1np4/map_northamericax4v1pg2_to_r025_trfvnp2.20240331.nc + cpl/gridmaps/northamericax4v1np4/map_northamericax4v1pg2_to_r025_trbilin.20240331.nc + + cpl/gridmaps/arcticx4v1pg2/map_arcticx4v1pg2_to_oARRM60to10_mono.20210407.nc cpl/gridmaps/arcticx4v1pg2/map_arcticx4v1pg2_to_oARRM60to10_mono.20210407.nc @@ -4230,6 +4474,14 @@ cpl/gridmaps/IcoswISC30E3r5/map_IcoswISC30E3r5_to_TL319_traave.20231121.nc + + cpl/gridmaps/TL319/map_TL319_to_IcosXISC30E3r7_traave.20240326.nc + cpl/gridmaps/TL319/map_TL319_to_IcosXISC30E3r7_trbilin.20240326.nc + cpl/gridmaps/TL319/map_TL319_to_IcosXISC30E3r7_esmfpatch.20240326.nc + cpl/gridmaps/IcosXISC30E3r7/map_IcosXISC30E3r7_to_TL319_traave.20240326.nc + cpl/gridmaps/IcosXISC30E3r7/map_IcosXISC30E3r7_to_TL319_traave.20240326.nc + + cpl/gridmaps/TL319/map_TL319_to_oRRS18to6v3_aave.220124.nc cpl/gridmaps/TL319/map_TL319_to_oRRS18to6v3_bilin.220124.nc @@ -4238,6 +4490,13 @@ cpl/gridmaps/oRRS18to6v3/map_oRRS18to6v3_to_TL319_aave.220124.nc + + cpl/gridmaps/TL319/map_TL319_to_r05_traave.20240212.nc + cpl/gridmaps/TL319/map_TL319_to_r05_trbilin.20240212.nc + cpl/gridmaps/TL319/map_r05_to_TL319_traave.20240212.nc + cpl/gridmaps/TL319/map_r05_to_TL319_traave.20240212.nc + + cpl/cpl6/map_T31_to_gx3v7_aave_da_090903.nc cpl/cpl6/map_T31_to_gx3v7_patch_090903.nc @@ -4353,6 +4612,11 @@ lnd/clm2/mappingdata/maps/ne120np4/map_ne120np4_to_0.125_nomask_aave.160613.nc + + cpl/gridmaps/TL319/map_TL319_to_r05_traave.20240212.nc + cpl/gridmaps/TL319/map_TL319_to_r05_trbilin.20240212.nc + + @@ -4594,10 +4858,18 @@ cpl/gridmaps/IcoswISC30E3r5/map_IcoswISC30E3r5_to_r05_traave.20231121.nc + + cpl/gridmaps/IcosXISC30E3r7/map_IcosXISC30E3r7_to_r05_traave.20240326.nc + + cpl/cpl6/map_EC30to60E2r2_to_r05_neareststod.220728.nc + + cpl/gridmaps/IcoswISC30E3r5/map_IcoswISC30E3r5_to_r025_traave.20240401.nc + + @@ -4780,6 +5052,11 @@ cpl/cpl6/map_JRA025_to_IcoswISC30E3r5_cstmnn.r150e300.20231121.nc + + cpl/cpl6/map_JRA025_to_IcosXISC30E3r7_cstmnn.r150e300.20240326.nc + cpl/cpl6/map_JRA025_to_IcosXISC30E3r7_cstmnn.r150e300.20240326.nc + + cpl/cpl6/map_JRA025_to_oRRS18to6v3_smoothed.r50e100.220124.nc cpl/cpl6/map_JRA025_to_oRRS18to6v3_smoothed.r50e100.220124.nc @@ -4865,6 +5142,16 @@ cpl/cpl6/map_r05_to_IcoswISC30E3r5_cstmnn.r150e300.20231121.nc + + cpl/cpl6/map_r05_to_IcosXISC30E3r7_cstmnn.r150e300.20240326.nc + cpl/cpl6/map_r05_to_IcosXISC30E3r7_cstmnn.r150e300.20240326.nc + + + + cpl/cpl6/map_r025_to_IcoswISC30E3r5_cstmnn.r150e300.20240401.nc + cpl/cpl6/map_r025_to_IcoswISC30E3r5_cstmnn.r150e300.20240401.nc + + cpl/cpl6/map_r0125_to_WC14to60E2r3_smoothed.r150e300.200929.nc cpl/cpl6/map_r0125_to_WC14to60E2r3_smoothed.r150e300.200929.nc @@ -4983,6 +5270,49 @@ cpl/gridmaps/mpas.gis20km/map_mpas.gis20km_to_oEC60to30v3_aave.181115.nc + + cpl/gridmaps/ne30pg2/map_ne30pg2_to_gis20km_traave.20240403.nc + cpl/gridmaps/ne30pg2/map_ne30pg2_to_gis20km_trbilin.20240403.nc + cpl/gridmaps/mpas.gis20km/map_gis20km_to_ne30pg2_traave.20240403.nc + cpl/gridmaps/mpas.gis20km/map_gis20km_to_ne30pg2_traave.20240403.nc + + + + cpl/gridmaps/r05/map_r05_to_gis20km_traave.20240403.nc + cpl/gridmaps/r05/map_r05_to_gis20km_trbilin.20240403.nc + cpl/gridmaps/mpas.gis20km/map_gis20km_to_r05_traave.20240403.nc + cpl/gridmaps/mpas.gis20km/map_gis20km_to_r05_traave.20240403.nc + + + + cpl/gridmaps/TL319/map_TL319_to_gis20km_traave.20240404.nc + cpl/gridmaps/TL319/map_TL319_to_gis20km_trbilin.20240404.nc + cpl/gridmaps/mpas.gis20km/map_gis20km_to_TL319_traave.20240404.nc + cpl/gridmaps/mpas.gis20km/map_gis20km_to_TL319_traave.20240404.nc + + + + cpl/gridmaps/EC30to60E2r2/map_EC30to60E2r2_to_gis20km_aave.230510.nc + cpl/gridmaps/EC30to60E2r2/map_EC30to60E2r2_to_gis20km_bilin.230510.nc + cpl/gridmaps/mpas.gis20km/map_gis20km_to_EC30to60E2r2_aave.230510.nc + cpl/gridmaps/mpas.gis20km/map_gis20km_to_EC30to60E2r2_aave.230510.nc + cpl/gridmaps/mpas.gis20km/map_gis20km_to_EC30to60E2r2_aave.230510.nc + cpl/gridmaps/mpas.gis20km/map_gis20km_to_EC30to60E2r2_aave.230510.nc + cpl/gridmaps/mpas.gis20km/map_gis20km_to_EC30to60E2r2_aave.230510.nc + cpl/gridmaps/mpas.gis20km/map_gis20km_to_EC30to60E2r2_aave.230510.nc + + + + cpl/gridmaps/IcoswISC30E3r5/map_IcoswISC30E3r5_to_gis20km_esmfaave.20240403.nc + cpl/gridmaps/IcoswISC30E3r5/map_IcoswISC30E3r5_to_gis20km_esmfbilin.20240403.nc + cpl/gridmaps/mpas.gis20km/map_gis20km_to_IcoswISC30E3r5_esmfaave.20240403.nc + cpl/gridmaps/mpas.gis20km/map_gis20km_to_IcoswISC30E3r5_esmfaave.20240403.nc + cpl/gridmaps/mpas.gis20km/map_gis20km_to_IcoswISC30E3r5_esmfaave.20240403.nc + cpl/gridmaps/mpas.gis20km/map_gis20km_to_IcoswISC30E3r5_esmfaave.20240403.nc + cpl/gridmaps/mpas.gis20km/map_gis20km_to_IcoswISC30E3r5_esmfaave.20240403.nc + cpl/gridmaps/mpas.gis20km/map_gis20km_to_IcoswISC30E3r5_esmfaave.20240403.nc + + @@ -5030,6 +5360,53 @@ cpl/gridmaps/mpas.gis1to10km/map_gis1to10km_to_EC30to60E2r2_aave.210304.nc + + + + + + cpl/gridmaps/r05/map_r05_to_gis1to10kmR2_traave.20240403.nc + cpl/gridmaps/r05/map_r05_to_gis1to10kmR2_trbilin.20240403.nc + cpl/gridmaps/mpas.gis1to10km/map_gis1to10kmR2_to_r05_traave.20240403.nc + cpl/gridmaps/mpas.gis1to10km/map_gis1to10kmR2_to_r05_traave.20240403.nc + + + + cpl/gridmaps/ne30pg2/map_ne30pg2_to_gis1to10kmR2_traave.20240403.nc + cpl/gridmaps/ne30pg2/map_ne30pg2_to_gis1to10kmR2_trbilin.20240403.nc + cpl/gridmaps/mpas.gis1to10km/map_gis1to10kmR2_to_ne30pg2_traave.20240403.nc + cpl/gridmaps/mpas.gis1to10km/map_gis1to10kmR2_to_ne30pg2_traave.20240403.nc + + + + cpl/gridmaps/TL319/map_TL319_to_gis1to10kmR2_traave.20240404.nc + cpl/gridmaps/TL319/map_TL319_to_gis1to10kmR2_trbilin.20240404.nc + cpl/gridmaps/mpas.gis1to10km/map_gis1to10kmR2_to_TL319_traave.20240404.nc + cpl/gridmaps/mpas.gis1to10km/map_gis1to10kmR2_to_TL319_traave.20240404.nc + + + + cpl/gridmaps/EC30to60E2r2/map_EC30to60E2r2_to_gis1to10r02_aave.230725.nc + cpl/gridmaps/EC30to60E2r2/map_EC30to60E2r2_to_gis1to10r02_bilin.230725.nc + cpl/gridmaps/mpas.gis1to10km/map_gis1to10r02_to_EC30to60E2r2_aave.230725.nc + cpl/gridmaps/mpas.gis1to10km/map_gis1to10r02_to_EC30to60E2r2_aave.230725.nc + cpl/gridmaps/mpas.gis1to10km/map_gis1to10r02_to_EC30to60E2r2_aave.230725.nc + cpl/gridmaps/mpas.gis1to10km/map_gis1to10r02_to_EC30to60E2r2_aave.230725.nc + cpl/gridmaps/mpas.gis1to10km/map_gis1to10r02_to_EC30to60E2r2_aave.230725.nc + cpl/gridmaps/mpas.gis1to10km/map_gis1to10r02_to_EC30to60E2r2_aave.230725.nc + + + + cpl/gridmaps/IcoswISC30E3r5/map_IcoswISC30E3r5_to_gis1to10kmR2_esmfaave.20240403.nc + cpl/gridmaps/IcoswISC30E3r5/map_IcoswISC30E3r5_to_gis1to10kmR2_esmfbilin.20240403.nc + cpl/gridmaps/mpas.gis1to10km/map_gis1to10kmR2_to_IcoswISC30E3r5_esmfaave.20240403.nc + cpl/gridmaps/mpas.gis1to10km/map_gis1to10kmR2_to_IcoswISC30E3r5_esmfaave.20240403.nc + cpl/gridmaps/mpas.gis1to10km/map_gis1to10kmR2_to_IcoswISC30E3r5_esmfaave.20240403.nc + cpl/gridmaps/mpas.gis1to10km/map_gis1to10kmR2_to_IcoswISC30E3r5_esmfaave.20240403.nc + cpl/gridmaps/mpas.gis1to10km/map_gis1to10kmR2_to_IcoswISC30E3r5_esmfaave.20240403.nc + cpl/gridmaps/mpas.gis1to10km/map_gis1to10kmR2_to_IcoswISC30E3r5_esmfaave.20240403.nc + + diff --git a/cime_config/machines/Depends.pm-cpu.nvidia.cmake b/cime_config/machines/Depends.pm-cpu.nvidia.cmake index 2947c73aacc..f3514d11880 100644 --- a/cime_config/machines/Depends.pm-cpu.nvidia.cmake +++ b/cime_config/machines/Depends.pm-cpu.nvidia.cmake @@ -10,6 +10,17 @@ if (NOT DEBUG) endforeach() endif() +list(APPEND NO_STACK_ARRAY_LIST + eam/src/physics/cam/phys_grid_ctem.F90 +) + +# Remove -Mstack_arrays for this one file to avoid error (likely compiler bug) +# As we can't remove flag, try adding -Mnostack_arrays https://github.com/E3SM-Project/E3SM/issues/6350 +# Tried with nvidia/22.7 and 23.9 on pm-cpu +foreach(ITEM IN LISTS NO_STACK_ARRAY_LIST) + e3sm_add_flags("${ITEM}" " -Mnostack_arrays") +endforeach() + # Use -O2 for a few files already found to benefit from increased optimization in Intel Depends file set(PERFOBJS homme/src/share/prim_advection_base.F90 diff --git a/cime_config/machines/cmake_macros/crayclang-scream_frontier-scream-gpu.cmake b/cime_config/machines/cmake_macros/crayclang-scream_frontier-scream-gpu.cmake index 8cc85b92cc6..afcca8f479e 100644 --- a/cime_config/machines/cmake_macros/crayclang-scream_frontier-scream-gpu.cmake +++ b/cime_config/machines/cmake_macros/crayclang-scream_frontier-scream-gpu.cmake @@ -34,5 +34,5 @@ if (COMP_NAME STREQUAL gptl) endif() set(PIO_FILESYSTEM_HINTS "lustre") -string(APPEND KOKKOS_OPTIONS " -DKokkos_ENABLE_HIP=On -DKokkos_ARCH_VEGA90A=On -DCMAKE_CXX_FLAGS='-std=gnu++14'") +string(APPEND KOKKOS_OPTIONS " -DKokkos_ENABLE_HIP=On -DKokkos_ARCH_VEGA90A=On -DCMAKE_CXX_FLAGS='-std=gnu++14' -DKokkos_ENABLE_OPENMP=OFF") set(USE_HIP "TRUE") diff --git a/cime_config/machines/cmake_macros/crayclang_frontier.cmake b/cime_config/machines/cmake_macros/crayclang_frontier.cmake index 6bda90a4187..6c8d4164cb2 100644 --- a/cime_config/machines/cmake_macros/crayclang_frontier.cmake +++ b/cime_config/machines/cmake_macros/crayclang_frontier.cmake @@ -15,3 +15,6 @@ string(APPEND CMAKE_Fortran_FLAGS " -hipa0 -hzero") # -em -ef generates modulename.mod (lowercase files) to support # Scorpio installs string(APPEND CMAKE_Fortran_FLAGS " -em -ef") + +# 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 dbbe7ba2b2e..174f8207d0d 100644 --- a/cime_config/machines/cmake_macros/gnugpu_frontier.cmake +++ b/cime_config/machines/cmake_macros/gnugpu_frontier.cmake @@ -18,7 +18,7 @@ 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-libs -lgfortran -L$ENV{MPICH_DIR}/lib -lmpi -L$ENV{CRAY_MPICH_ROOTDIR}/gtl/lib -lmpi_gtl_hsa ") +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 KOKKOS_OPTIONS " -DKokkos_ENABLE_HIP=On -DKokkos_ARCH_ZEN3=On -DKokkos_ARCH_VEGA90A=On -DKokkos_ENABLE_OPENMP=Off") diff --git a/cime_config/machines/config_batch.xml b/cime_config/machines/config_batch.xml index 33bd48494a4..5ba8e38f2e7 100644 --- a/cime_config/machines/config_batch.xml +++ b/cime_config/machines/config_batch.xml @@ -291,7 +291,6 @@ --job-name={{ job_id }} --nodes={{ num_nodes }} --output={{ job_id }}.%j - --exclusive diff --git a/cime_config/machines/config_machines.xml b/cime_config/machines/config_machines.xml index 87dfacd7fd4..f37cc3266ad 100644 --- a/cime_config/machines/config_machines.xml +++ b/cime_config/machines/config_machines.xml @@ -206,6 +206,7 @@ aocc cudatoolkit climate-utils + matlab craype-accel-nvidia80 craype-accel-host perftools-base @@ -263,8 +264,6 @@ /global/cfs/cdirs/e3sm/perl/lib/perl5-only-switch software MPI_Bcast - $SHELL{if [ -z "$Albany_ROOT" ]; then echo /global/common/software/e3sm/mali_tpls/albany-e3sm-serial-release-gcc; 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} $ENV{CRAY_NETCDF_HDF5PARALLEL_PREFIX} $ENV{CRAY_PARALLEL_NETCDF_PREFIX} 4000MB @@ -275,6 +274,9 @@ $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 "$Kokkos_ROOT" ]; then echo /global/common/software/e3sm/mali_tpls/trilinos-e3sm-serial-release-gcc; else echo "$Kokkos_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} @@ -367,6 +369,7 @@ aocc cudatoolkit climate-utils + matlab craype-accel-nvidia80 craype-accel-host perftools-base @@ -510,6 +513,7 @@ aocc cudatoolkit climate-utils + matlab craype-accel-nvidia80 craype-accel-host perftools-base @@ -672,6 +676,7 @@ aocc cudatoolkit climate-utils + matlab craype-accel-nvidia80 craype-accel-host perftools-base @@ -823,6 +828,7 @@ aocc cudatoolkit climate-utils + matlab craype-accel-nvidia80 craype-accel-host perftools-base @@ -2068,7 +2074,7 @@ ANL CELS General Computing Environment (Linux) workstation (Ubuntu 22.04) - compute-386-01|compute-386-02 + compute-386-(01|02|03|05|07|08)|compute-240-(15) LINUX gnu mpich,openmpi @@ -2129,6 +2135,7 @@ /nfs/gce/projects/climate/software/linux-ubuntu22.04-x86_64/hdf5/1.12.2/mpich-4.1.2/gcc-12.1.0 /nfs/gce/projects/climate/software/linux-ubuntu22.04-x86_64/netcdf/4.8.0c-4.3.1cxx-4.5.3f-parallel/mpich-4.1.2/gcc-12.1.0 /nfs/gce/projects/climate/software/linux-ubuntu22.04-x86_64/pnetcdf/1.12.3/mpich-4.1.2/gcc-12.1.0 + $SHELL{if [ -z "$MOAB_ROOT" ]; then echo /nfs/gce/projects/climate/software/moab/devel/mpich-4.1.2/gcc-12.1.0; else echo "$MOAB_ROOT"; fi} @@ -2138,6 +2145,7 @@ /nfs/gce/projects/climate/software/linux-ubuntu22.04-x86_64/hdf5/1.12.2/openmpi-4.1.6/gcc-12.1.0 /nfs/gce/projects/climate/software/linux-ubuntu22.04-x86_64/netcdf/4.8.0c-4.3.1cxx-4.5.3f-parallel/openmpi-4.1.6/gcc-12.1.0 /nfs/gce/projects/climate/software/linux-ubuntu22.04-x86_64/pnetcdf/1.12.3/openmpi-4.1.6/gcc-12.1.0 + $SHELL{if [ -z "$MOAB_ROOT" ]; then echo /nfs/gce/projects/climate/software/moab/devel/openmpi-4.1.6/gcc-12.1.0; else echo "$MOAB_ROOT"; fi} 64M @@ -2624,6 +2632,7 @@ $SHELL{dirname $(dirname $(which nf-config))} $SHELL{dirname $(dirname $(which pnetcdf_version))} ^lockedfile,individual + ^xpmem 128M @@ -2643,6 +2652,11 @@ $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 "$Kokkos_ROOT" ]; then echo /lcrc/group/e3sm/ac.jwatkins/LandIce/TrilinosBuilds/build-gcc-e3sm/install; else echo "$Kokkos_ROOT"; fi} + @@ -2961,83 +2975,6 @@ - - LLNL Linux Cluster, Linux, 4 V100 GPUs/node, 44 IBM P9 cpu cores/node - lassen.* - LINUX - gnugpu - spectrum-mpi - cbronze - /usr/workspace/$USER/e3sm_scratch - /usr/gdata/e3sm/ccsm3data/inputdata - /usr/gdata/e3sm/ccsm3data/inputdata/atm/datm7 - /usr/workspace/$USER/archive/$CASE - /usr/gdata/e3sm/baselines/$COMPILER - 16 - lsf - donahue5 -at- llnl.gov - 40 - 40 - - - - - jsrun - - -X 1 - $SHELL{if [ {{ total_tasks }} -eq 1 ];then echo --nrs 1 --rs_per_host 1;else echo --nrs $NUM_RS --rs_per_host $RS_PER_NODE;fi} - --tasks_per_rs $SHELL{echo "({{ tasks_per_node }} + $RS_PER_NODE - 1)/$RS_PER_NODE"|bc} - -d plane:$SHELL{echo "({{ tasks_per_node }} + $RS_PER_NODE - 1)/$RS_PER_NODE"|bc} - --cpu_per_rs $ENV{CPU_PER_RS} - --gpu_per_rs $ENV{GPU_PER_RS} - --bind packed:smt:$ENV{OMP_NUM_THREADS} - --latency_priority $ENV{LTC_PRT} - --stdio_mode prepended - $ENV{JSRUN_THREAD_VARS} - $ENV{SMPIARGS} - - - - /usr/share/lmod/lmod/init/env_modules_python.py - /usr/share/lmod/lmod/init/perl - /usr/share/lmod/lmod/init/sh - /usr/share/lmod/lmod/init/csh - module - module - /usr/share/lmod/lmod/libexec/lmod python - /usr/share/lmod/lmod/libexec/lmod perl - - - git - gcc/8.3.1 - cuda/11.8.0 - cmake/3.16.8 - spectrum-mpi - python/3.7.2 - - - /p/gpfs1/$USER/e3sm_scratch/$CASE/run - $CIME_OUTPUT_ROOT/$CASE/bld - - - - - -E OMP_NUM_THREADS=$ENV{OMP_NUM_THREADS} -E OMP_PROC_BIND=spread -E OMP_PLACES=threads -E OMP_STACKSIZE=256M - - - y - /usr/gdata/e3sm/netcdf/bin:$ENV{PATH} - /usr/gdata/e3sm/netcdf/lib:$ENV{LD_LIBRARY_PATH} - /usr/gdata/e3sm/netcdf - 2 - 20 - 2 - gpu-cpu - $SHELL{echo "2*((`./xmlquery --value TOTAL_TASKS` + `./xmlquery --value TASKS_PER_NODE` - 1)/`./xmlquery --value TASKS_PER_NODE`)"|bc} - --smpiargs="-gpu" - - - LLNL Linux Cluster, Linux (pgi), 56 pes/node, batch system is Slurm LINUX @@ -3083,6 +3020,7 @@ netcdf-fortran/4.6.0 parallel-netcdf/1.12.3 screamML-venv/0.0.1 + subversion $CIME_OUTPUT_ROOT/$CASE/run @@ -3138,6 +3076,7 @@ netcdf-fortran/4.6.0 parallel-netcdf/1.12.3 screamML-venv/0.0.1 + subversion $CIME_OUTPUT_ROOT/$CASE/run @@ -4879,12 +4818,12 @@ AMD EPYC 7713 64-Core (Milan) (256GB) and 4 nvidia A100' cli115 /gpfs/alpine/proj-shared/cli115 .* - /gpfs/alpine/$PROJECT/proj-shared/$ENV{USER}/e3sm_scratch - /gpfs/alpine/cli115/world-shared/e3sm/inputdata - /gpfs/alpine/cli115/world-shared/e3sm/inputdata/atm/datm7 + /gpfs/alpine2/$PROJECT/proj-shared/$ENV{USER}/e3sm_scratch + /gpfs/alpine2/atm146/world-shared/e3sm/inputdata + /gpfs/alpine2/atm146/world-shared/e3sm/inputdata/atm/datm7 /gpfs/alpine/$PROJECT/proj-shared/$ENV{USER}/archive/$CASE - /gpfs/alpine/cli115/world-shared/e3sm/baselines/$COMPILER - /gpfs/alpine/cli115/world-shared/e3sm/tools/cprnc.summit/cprnc + /gpfs/alpine2/atm146/world-shared/e3sm/baselines/$COMPILER + /gpfs/alpine2/atm146/world-shared/e3sm/tools/cprnc.summit/cprnc 8 e3sm_developer 4 @@ -4894,7 +4833,7 @@ AMD EPYC 7713 64-Core (Milan) (256GB) and 4 nvidia A100' 18 42 42 - + 84 18 @@ -4928,7 +4867,7 @@ AMD EPYC 7713 64-Core (Milan) (256GB) and 4 nvidia A100' module - DefApps + DefApps-2023 python/3.7-anaconda3 subversion/1.14.0 git/2.31.1 @@ -4976,6 +4915,7 @@ AMD EPYC 7713 64-Core (Milan) (256GB) and 4 nvidia A100' $ENV{OLCF_PARALLEL_NETCDF_ROOT} 0 + True @@ -5039,15 +4979,6 @@ AMD EPYC 7713 64-Core (Milan) (256GB) and 4 nvidia A100' mlx5_3:1,mlx5_0:1 mlx5_0:1,mlx5_3:1 - - $SHELL{if [ -z "$ADIOS2_ROOT" ]; then echo /gpfs/alpine/cli115/world-shared/3rdparty/adios2/2.9.1/spectrum-mpi-10.4.0.3/xl-16.1.1-10; else echo "$ADIOS2_ROOT"; fi} - - - $SHELL{if [ -z "$ADIOS2_ROOT" ]; then echo /gpfs/alpine/cli115/world-shared/3rdparty/adios2/2.9.1/spectrum-mpi-10.4.0.3/nvhpc-21.11; else echo "$ADIOS2_ROOT"; fi} - - - $SHELL{if [ -z "$ADIOS2_ROOT" ]; then echo /gpfs/alpine/cli115/world-shared/3rdparty/adios2/2.9.1/spectrum-mpi-10.4.0.3/gcc-9.1.0; else echo "$ADIOS2_ROOT"; fi} - diff --git a/cime_config/testmods_dirs/allactive/wcprodssp/README b/cime_config/testmods_dirs/allactive/wcprodssp/README index fe36669a02a..66e4a6d06ea 100644 --- a/cime_config/testmods_dirs/allactive/wcprodssp/README +++ b/cime_config/testmods_dirs/allactive/wcprodssp/README @@ -1,5 +1,5 @@ Modifications (in shell_commands) to enable a hybrid run for SSP compsets -(e.g., SSp370 or SSP585), starting from v3 long spinup. +(e.g., SSP370 or SSP585), starting from end of v3 historical run Other modifications (same as for wcprod) should result in a case that has the same namelist settings as the water cycle production sims diff --git a/cime_config/testmods_dirs/allactive/wcprodssp/shell_commands b/cime_config/testmods_dirs/allactive/wcprodssp/shell_commands index 1cb8644c617..91b8f207046 100644 --- a/cime_config/testmods_dirs/allactive/wcprodssp/shell_commands +++ b/cime_config/testmods_dirs/allactive/wcprodssp/shell_commands @@ -6,9 +6,9 @@ ./xmlchange RUN_TYPE="hybrid" ./xmlchange GET_REFCASE="TRUE" - ./xmlchange RUN_REFCASE="20231209.v3.LR.piControl-spinup.chrysalis" - ./xmlchange RUN_REFDATE="1801-01-01" - ./xmlchange RUN_REFDIR=${INPUTDATA_ROOT}"/e3sm_init/V3.SSP370_SSP585.ne30pg2_r05_IcoswISC30E3r5/v3.LR.piControl-spinup/1801-01-01-00000" + ./xmlchange RUN_REFCASE="v3.LR.historical_0101" + ./xmlchange RUN_REFDATE="2015-01-01" + ./xmlchange RUN_REFDIR=${INPUTDATA_ROOT}"/e3sm_init/v3.SSP.ne30pg2_r05_IcoswISC30E3r5/v3.LR.historical_0101/2015-01-01-00000" exit diff --git a/cime_config/testmods_dirs/allactive/wcprodssp/user_nl_eam b/cime_config/testmods_dirs/allactive/wcprodssp/user_nl_eam index b83a8c6ca22..7ef3e3782a3 100644 --- a/cime_config/testmods_dirs/allactive/wcprodssp/user_nl_eam +++ b/cime_config/testmods_dirs/allactive/wcprodssp/user_nl_eam @@ -1,16 +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' -!temporarily remove LINOZ O3 related fields from the list until updated linoz v3 style inputdata is ready -!fexcl1 = 'CFAD_SR532_CAL', 'LINOZ_DO3', 'LINOZ_DO3_PSC', 'LINOZ_O3CLIM', 'LINOZ_O3COL', 'LINOZ_SSO3', 'hstobie_linoz' - fexcl1 = 'CFAD_SR532_CAL', '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. -! Specify an L80 IC to override eam.i from reference case, which is still for L72 - ncdata = '$DIN_LOC_ROOT/atm/cam/inic/homme/eami_mam4_Linoz_ne30np4_L80_c20231010.nc' + empty_htapes = .true. + + avgflag_pertape = 'A','A','A','A','I','I' + nhtfrq = -24,-24,-6,-3,-1,0 + 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:M','TREFHTMX:X','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/allactive/wcprodssp/user_nl_elm b/cime_config/testmods_dirs/allactive/wcprodssp/user_nl_elm index 80bd35a81f0..7bfdbac5c84 100644 --- a/cime_config/testmods_dirs/allactive/wcprodssp/user_nl_elm +++ b/cime_config/testmods_dirs/allactive/wcprodssp/user_nl_elm @@ -2,11 +2,43 @@ CHECK_FINIDAT_FSURDAT_CONSISTENCY = .false. -! flanduse_timeseries not ready for v3.LR.SSP production grid, set not to do transient_pft tentatively until SSP compset fully ready - - do_transient_pfts = .false. 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 diff --git a/cime_config/testmods_dirs/config_pes_tests.xml b/cime_config/testmods_dirs/config_pes_tests.xml index 7e7e531460e..4ef7663c540 100644 --- a/cime_config/testmods_dirs/config_pes_tests.xml +++ b/cime_config/testmods_dirs/config_pes_tests.xml @@ -284,4 +284,34 @@ + + + + + tests+chrysalis: any compset on oQU240 grid, 1x32x2 NODESxMPIxOMP + 32 + 64 + + 32 + 32 + 32 + 32 + 32 + 32 + 32 + 32 + + + 2 + 2 + 2 + 2 + 2 + 2 + 2 + 2 + + + + diff --git a/cime_config/tests.py b/cime_config/tests.py index 3223ae10804..b4b54dceeb9 100644 --- a/cime_config/tests.py +++ b/cime_config/tests.py @@ -54,8 +54,9 @@ "e3sm_land_exenoshare" : { "time" : "0:45:00", "tests" : ( + "ERS.f19_g16.IERA5ELM", + "ERS.f19_g16.IERA56HRELM", "ERS_Ld20.f45_f45.IELMFATES.elm-fates", - "ERS.hcru_hcru.I20TRGSWCNPRDCTCBC.elm-erosion", "ERS.f09_g16.IELMBC.elm-simple_decomp", "ERS.hcru_hcru.IELM.elm-multi_inst", ) @@ -92,7 +93,7 @@ "SMS_Ly2_P1x1.1x1_smallvilleIA.IELMCNCROP.elm-fan", "SMS.r05_r05.IELM.elm-topounit", "ERS.ELM_USRDAT.I1850ELM.elm-usrdat", - "ERS.f09_f09.IELM.elm-lnd_rof_2way", + "ERS.r05_r05.IELM.elm-lnd_rof_2way", "ERS.r05_r05.IELM.elm-V2_ELM_MOSART_features", "ERS.ELM_USRDAT.IELM.elm-surface_water_dynamics" ) @@ -121,6 +122,25 @@ ) }, + "e3sm_cryo_developer" : { + "tests" : ( + "SMS_D_Ld1.TL319_IcoswISC30E3r5.GMPAS-JRA1p5-DIB-PISMF.mpaso-jra_1958", + "ERS_Ld5.T62_oQU240wLI.GMPAS-DIB-IAF-PISMF", + "PEM_Ln5.T62_oQU240wLI.GMPAS-DIB-IAF-PISMF", + "PET_Ln5.T62_oQU240wLI.GMPAS-DIB-IAF-PISMF", + "ERS_Ld5.T62_oQU240wLI.GMPAS-DIB-IAF-DISMF", + "PEM_Ln5.T62_oQU240wLI.GMPAS-DIB-IAF-DISMF", + "PET_Ln5.T62_oQU240wLI.GMPAS-DIB-IAF-DISMF", + ) + }, + + "e3sm_landice_developer" : { + "tests" : ( + "SMS.ne30pg2_r05_EC30to60E2r2_gis20.IGELM_MLI.elm-gis20kmSMS", + "ERS.ne30pg2_r05_EC30to60E2r2_gis20.IGELM_MLI.elm-gis20kmERS", + ) + }, + "eam_condidiag" : { "tests" : ( "SMS_D_Ln5.ne4pg2_oQU480.F2010", @@ -226,6 +246,17 @@ ) }, + #ocean non bit-for-bit test + "e3sm_ocn_nbfb": { + "tests": ( + "MVKO_PS.T62_oQU240.GMPAS-NYF", + ) + }, + + "e3sm_nbfb": { + "inherit": ("e3sm_atm_nbfb", "e3sm_ocn_nbfb") + }, + "e3sm_ocnice_stealth_features" : { "tests" : ( "SMS_D_Ld1.T62_oQU240wLI.GMPAS-IAF-PISMF.mpaso-impl_top_drag", @@ -257,7 +288,7 @@ }, "e3sm_developer" : { - "inherit" : ("e3sm_land_developer", "e3sm_atm_developer", "e3sm_ice_developer"), + "inherit" : ("e3sm_land_developer", "e3sm_atm_developer", "e3sm_ice_developer", "e3sm_cryo_developer"), "time" : "0:45:00", "tests" : ( "ERS.f19_g16_rx1.A", @@ -267,10 +298,8 @@ "NCK.f19_g16_rx1.A", "SMS.ne30_f19_g16_rx1.A", "ERS_Ld5.T62_oQU120.CMPASO-NYF", - "SMS_Ld1.T62_oQU240wLI.GMPAS-IAF-DISMF", "ERS.f09_g16_g.MALISIA", "SMS.T62_oQU120_ais20.MPAS_LISIO_TEST", - "SMS.f09_g16_a.IGELM_MLI", "SMS_P12x2.ne4pg2_oQU480.WCYCL1850NS.allactive-mach_mods", "ERS_Ln9.ne4pg2_ne4pg2.F2010-MMF1.eam-mmf_crmout", ) @@ -304,6 +333,7 @@ "SMS_Ln5.ne30pg2_ne30pg2.F2010-SCREAM-LR-DYAMOND2", "ERS_Ld3.ne30pg2_r05_IcoswISC30E3r5.WCYCL1850.allactive-nlmaps", "SMS_D_Ld1.ne30pg2_r05_IcoswISC30E3r5.CRYO1850-DISMF", + "ERS.hcru_hcru.I20TRGSWCNPRDCTCBC.elm-erosion", ) }, @@ -421,6 +451,7 @@ "ERS_Ld60.f45_g37.IELMFATES.elm-fates_cold_nofire", "ERS_Ld60.f45_g37.IELMFATES.elm-fates_cold_st3", "ERS_Ld60.f45_g37.IELMFATES.elm-fates_cold_pphys", + "SMS_D_Ld15.f45_g37.IELMFATES.elm-fates_cold_twostream", ) }, diff --git a/components/cmake/modules/FindPIO.cmake b/components/cmake/modules/FindPIO.cmake index 7df8a9ba106..0277918ac8e 100644 --- a/components/cmake/modules/FindPIO.cmake +++ b/components/cmake/modules/FindPIO.cmake @@ -18,6 +18,9 @@ endif() if (PIO_VERSION STREQUAL 2) # This is a pio2 library set(PIOLIBS "${PIO_LIBDIR}/libpiof.a;${PIO_LIBDIR}/libpioc.a") + if (DEFINED ENV{ADIOS2_ROOT}) + list(APPEND PIOLIBS "${PIO_LIBDIR}/libadios2pio-nm-lib.a") + endif() else() # This is a pio1 library set(PIOLIBS "${PIO_LIBDIR}/libpio.a") diff --git a/components/data_comps/datm/cime_config/config_component.xml b/components/data_comps/datm/cime_config/config_component.xml index 94b0eab610d..cb982f52fcf 100644 --- a/components/data_comps/datm/cime_config/config_component.xml +++ b/components/data_comps/datm/cime_config/config_component.xml @@ -10,12 +10,14 @@ This file may have atm desc entries. --> - Data driven ATM + Data driven ATM QIAN data set QIAN with water isotopes CRUNCEP data set CLM CRU NCEP v7 data set GSWP3v1 data set + Fifth generation ECMWF reanalysis + Fifth generation ECMWF reanalysis,6 hourly data MOSART test data set using older NLDAS data NLDAS2 regional 0.125 degree data set over the U.S. (25-53N, 235-293E). WARNING: Garbage data will be produced for runs extending beyond this regional domain. Coupler hist data set (in this mode, it is strongly recommended that the model domain and the coupler history forcing are on the same domain) @@ -43,13 +45,13 @@ char - CORE2_NYF,CORE2_IAF,CLM_QIAN,CLM_QIAN_WISO,CLM1PT,CLMCRUNCEP,CLMCRUNCEPv7,CLMGSWP3v1,CLMMOSARTTEST,CLMNLDAS2,CPLHIST,CORE_IAF_JRA,IAF_JRA_1p5,CORE_IAF_JRA_1p4_2018,CORE_RYF8485_JRA,CORE_RYF9091_JRA,CORE_RYF0304_JRA,CFSv2,CFSR + CORE2_NYF,CORE2_IAF,CLM_QIAN,CLM_QIAN_WISO,CLM1PT,CLMCRUNCEP,CLMCRUNCEPv7,CLMGSWP3v1,ELMERA5,ERA56HR,CLMMOSARTTEST,CLMNLDAS2,CPLHIST,CORE_IAF_JRA,IAF_JRA_1p5,CORE_IAF_JRA_1p4_2018,CORE_RYF8485_JRA,CORE_RYF9091_JRA,CORE_RYF0304_JRA,CFSv2,CFSR CORE2_NYF run_component_datm env_run.xml Mode for data atmosphere component. CORE2_NYF (CORE2 normal year forcing) are modes used in forcing prognostic ocean/sea-ice components. - CLM_QIAN, CLMCRUNCEP, CLMCRUNCEPv7, CLMGSWP3v1, CLMMOSARTTEST, CLMNLDAS2 and CLM1PT are modes using observational data for forcing prognostic land components. + CLM_QIAN, CLMCRUNCEP, CLMCRUNCEPv7, CLMGSWP3v1, ELMERA5,ERA56HR, CLMMOSARTTEST, CLMNLDAS2 and CLM1PT are modes using observational data for forcing prognostic land components. WARNING for CLMNLDAS2: This is a regional forcing dataset over the U.S. (25-53N, 235-293E). Garbage data will be produced for runs extending beyond this regional domain. WARNING for CLMGSWP3v1: Humidity is identically zero for last time step in Dec/2013 and all of 2014 so you should NOT use 2014 data (see cime issue #3653 -- https://github.com/ESMCI/cime/issues/3653). @@ -68,6 +70,8 @@ data (see cime issue #3653 -- https://github.com/ESMCI/cime/issues/3653). CLMCRUNCEP CLMCRUNCEPv7 CLMGSWP3v1 + ELMERA5 + ERA56HR CLMMOSARTTEST CLMNLDAS2 CLM1PT @@ -245,6 +249,8 @@ data (see cime issue #3653 -- https://github.com/ESMCI/cime/issues/3653). $DATM_CLMNCEP_YR_START $DATM_CLMNCEP_YR_START $DATM_CLMNCEP_YR_START + $DATM_CLMNCEP_YR_START + $DATM_CLMNCEP_YR_START run_component_datm env_run.xml @@ -288,6 +294,8 @@ data (see cime issue #3653 -- https://github.com/ESMCI/cime/issues/3653). 2005 2002 1958 + 1979 + 1979 run_component_datm env_run.xml @@ -332,6 +340,8 @@ data (see cime issue #3653 -- https://github.com/ESMCI/cime/issues/3653). 2003 2016 2020 + 1979 + 1979 run_component_datm env_run.xml diff --git a/components/data_comps/datm/cime_config/namelist_definition_datm.xml b/components/data_comps/datm/cime_config/namelist_definition_datm.xml index 10d7111d433..529e79a03f6 100644 --- a/components/data_comps/datm/cime_config/namelist_definition_datm.xml +++ b/components/data_comps/datm/cime_config/namelist_definition_datm.xml @@ -36,6 +36,8 @@ CLMCRUNCEP = Run with the CLM CRU NCEP V4 ( default ) forcing valid from 1900 to 2010 (force CLM) CLMCRUNCEPv7 = Run with the CLM CRU NCEP V7 forcing valid from 1900 to 2010 (force CLM) CLMGSWP3v1 = Run with the CLM GSWP3 V1 forcing (force CLM) + ELMERA5 = Run with the ELM fifth generation ECMWF reanalysis from 1979 to present + ERA56HR = Run with the ELM fifth generation ECMWF reanalysis from 1979 to present CLMMOSARTTEST = Run with the CLM NLDAS data (force CLM) for testing MOSART CLMNLDAS2 = Run with the CLM NLDAS2 regional forcing valid from 1980 to 2018 (force CLM) CLM1PT = Run with supplied single point data (force CLM) @@ -103,6 +105,26 @@ CLMGSWP3v1.Solar CLMGSWP3v1.Precip CLMGSWP3v1.TPQW + + ELMERA5.msdrswrf # mean surface direct shortwave radiation flux + ELMERA5.msdfswrf # mean surface diffuse shortwave radiation flux + ELMERA5.mcpr # mean convective precipitation rate + ELMERA5.mlspr # mean large-scale precipitation rate + ELMERA5.t2m # temperature at 2 m + ELMERA5.sp # surface pressure + ELMERA5.d2m # dew point temperature at 2 m + ELMERA5.w10 # wind speed at 10 m + ELMERA5.msdwlwrf # mean surface downward longwave radiation flux + + ERA56HR.msdrswrf # mean surface direct shortwave radiation flux + ERA56HR.msdfswrf # mean surface diffuse shortwave radiation flux + ERA56HR.mcpr # mean convective precipitation rate + ERA56HR.mlspr # mean large-scale precipitation rate + ERA56HR.t2m # temperature at 2 m + ERA56HR.sp # surface pressure + ERA56HR.d2m # dew point temperature at 2 m + ERA56HR.w10 # wind speed at 10 m + ERA56HR.msdwlwrf # mean surface downward longwave radiation flux CLMMOSARTTEST @@ -202,6 +224,8 @@ CLMCRUNCEP.Solar,CLMCRUNCEP.Precip,CLMCRUNCEP.TPQW CLMCRUNCEPv7.Solar,CLMCRUNCEPv7.Precip,CLMCRUNCEPv7.TPQW CLMGSWP3v1.Solar,CLMGSWP3v1.Precip,CLMGSWP3v1.TPQW + ELMERA5.msdrswrf,ELMERA5.msdfswrf,ELMERA5.mcpr,ELMERA5.mlspr,ELMERA5.t2m,ELMERA5.sp,ELMERA5.d2m,ELMERA5.w10,ELMERA5.msdwlwrf + ERA56HR.msdrswrf,ERA56HR.msdfswrf,ERA56HR.mcpr,ERA56HR.mlspr,ERA56HR.t2m,ERA56HR.sp,ERA56HR.d2m,ERA56HR.w10,ERA56HR.msdwlwrf CLMMOSARTTEST CLMNLDAS2.Solar,CLMNLDAS2.Precip,CLMNLDAS2.TPQW CORE2_NYF.GISS,CORE2_NYF.GXGXS,CORE2_NYF.NCEP @@ -234,6 +258,8 @@ $DIN_LOC_ROOT_CLMFORC/atm_forcing.datm7.cruncep_qianFill.0.5d.v7.c160715 $DIN_LOC_ROOT/share/domains/domain.clm $DIN_LOC_ROOT_CLMFORC/atm_forcing.datm7.GSWP3.0.5d.v1.c170516 + $DIN_LOC_ROOT_CLMFORC/atm_forcing.datm7.ERA.0.25d.v5.c180614 + $DIN_LOC_ROOT_CLMFORC/atm_forcing.datm7.ERA.6HRLY.0.25d.v5.c180614 $DIN_LOC_ROOT/share/domains/domain.clm $DIN_LOC_ROOT_CLMFORC/atm_forcing.datm7.cruncep_qianFill.0.5d.V5.c140715 $DIN_LOC_ROOT_CLMFORC/atm_forcing.datm7.GSWP3.0.5d.v1.c170516 @@ -302,6 +328,8 @@ domain.lnd.360x720.130305.nc domain.lnd.360x720_gswp3.0v1.c170606.nc domain.lnd.360x720_gswp3.0v1.c170606.nc + domain.lnd.era5_721x1440_rdrlat_EC30to60E2r2.221115.nc + domain.lnd.era5_721x1440_rdrlat_EC30to60E2r2.221115.nc domain.lnd.nldas2_0224x0464_c110415.nc domain.lnd.0.125nldas2_0.125nldas2.190410.nc nyf.giss.T62.051007.nc @@ -478,6 +506,24 @@ $DIN_LOC_ROOT_CLMFORC/atm_forcing.datm7.GSWP3.0.5d.v1.c170516/Solar3Hrly $DIN_LOC_ROOT_CLMFORC/atm_forcing.datm7.GSWP3.0.5d.v1.c170516/Precip3Hrly $DIN_LOC_ROOT_CLMFORC/atm_forcing.datm7.GSWP3.0.5d.v1.c170516/TPHWL3Hrly + $DIN_LOC_ROOT_CLMFORC/atm_forcing.datm7.ERA.0.25d.v5.c180614/swdn + $DIN_LOC_ROOT_CLMFORC/atm_forcing.datm7.ERA.0.25d.v5.c180614/swdn + $DIN_LOC_ROOT_CLMFORC/atm_forcing.datm7.ERA.0.25d.v5.c180614/prec + $DIN_LOC_ROOT_CLMFORC/atm_forcing.datm7.ERA.0.25d.v5.c180614/prec + $DIN_LOC_ROOT_CLMFORC/atm_forcing.datm7.ERA.0.25d.v5.c180614/tbot + $DIN_LOC_ROOT_CLMFORC/atm_forcing.datm7.ERA.0.25d.v5.c180614/pbot + $DIN_LOC_ROOT_CLMFORC/atm_forcing.datm7.ERA.0.25d.v5.c180614/tdew + $DIN_LOC_ROOT_CLMFORC/atm_forcing.datm7.ERA.0.25d.v5.c180614/wind + $DIN_LOC_ROOT_CLMFORC/atm_forcing.datm7.ERA.0.25d.v5.c180614/lwdn + $DIN_LOC_ROOT_CLMFORC/atm_forcing.datm7.ERA.6HRLY.0.25d.v5.c180614/swdn + $DIN_LOC_ROOT_CLMFORC/atm_forcing.datm7.ERA.6HRLY.0.25d.v5.c180614/swdn + $DIN_LOC_ROOT_CLMFORC/atm_forcing.datm7.ERA.6HRLY.0.25d.v5.c180614/prec + $DIN_LOC_ROOT_CLMFORC/atm_forcing.datm7.ERA.6HRLY.0.25d.v5.c180614/prec + $DIN_LOC_ROOT_CLMFORC/atm_forcing.datm7.ERA.6HRLY.0.25d.v5.c180614/tbot + $DIN_LOC_ROOT_CLMFORC/atm_forcing.datm7.ERA.6HRLY.0.25d.v5.c180614/pbot + $DIN_LOC_ROOT_CLMFORC/atm_forcing.datm7.ERA.6HRLY.0.25d.v5.c180614/tdew + $DIN_LOC_ROOT_CLMFORC/atm_forcing.datm7.ERA.6HRLY.0.25d.v5.c180614/wind + $DIN_LOC_ROOT_CLMFORC/atm_forcing.datm7.ERA.6HRLY.0.25d.v5.c180614/lwdn $DIN_LOC_ROOT/atm/datm7/NLDAS $DIN_LOC_ROOT/atm/datm7/atm_forcing.datm7.NLDAS2.0.125d.v1/Solar $DIN_LOC_ROOT/atm/datm7/atm_forcing.datm7.NLDAS2.0.125d.v1/Precip @@ -553,6 +599,24 @@ clmforc.GSWP3.c2011.0.5x0.5.Solr.%ym.nc clmforc.GSWP3.c2011.0.5x0.5.Prec.%ym.nc clmforc.GSWP3.c2011.0.5x0.5.TPQWL.%ym.nc + elmforc.ERA5.c2018.0.25d.msdrswrf.%ym.nc + elmforc.ERA5.c2018.0.25d.msdfswrf.%ym.nc + elmforc.ERA5.c2018.0.25d.mcpr.%ym.nc + elmforc.ERA5.c2018.0.25d.mlspr.%ym.nc + elmforc.ERA5.c2018.0.25d.t2m.%ym.nc + elmforc.ERA5.c2018.0.25d.sp.%ym.nc + elmforc.ERA5.c2018.0.25d.d2m.%ym.nc + elmforc.ERA5.c2018.0.25d.w10.%ym.nc + elmforc.ERA5.c2018.0.25d.msdwlwrf.%ym.nc + elmforc.ERA5.c2018.0.25d.msdrswrf.%ym.nc + elmforc.ERA5.c2018.0.25d.msdfswrf.%ym.nc + elmforc.ERA5.c2018.0.25d.mcpr.%ym.nc + elmforc.ERA5.c2018.0.25d.mlspr.%ym.nc + elmforc.ERA5.c2018.0.25d.t2m.%ym.nc + elmforc.ERA5.c2018.0.25d.sp.%ym.nc + elmforc.ERA5.c2018.0.25d.d2m.%ym.nc + elmforc.ERA5.c2018.0.25d.w10.%ym.nc + elmforc.ERA5.c2018.0.25d.msdwlwrf.%ym.nc clmforc.nldas.%ym.nc ctsmforc.NLDAS2.0.125d.v1.Solr.%ym.nc ctsmforc.NLDAS2.0.125d.v1.Prec.%ym.nc @@ -1523,6 +1587,60 @@ PSRF pbot FLDS lwdn + + msdrswrf swdndr + + + msdfswrf swdndf + + + mcpr precc + + + mlspr precl + + + t2m tbot + + + sp pbot + + + d2m tdew + + + w10 wind + + + msdwlwrf lwdn + + + msdrswrf swdndr + + + msdfswrf swdndf + + + mcpr precc + + + mlspr precl + + + t2m tbot + + + sp pbot + + + d2m tdew + + + w10 wind + + + msdwlwrf lwdn + TBOT tbot WIND wind @@ -1793,6 +1911,8 @@ $DATM_CLMNCEP_YR_ALIGN $DATM_CLMNCEP_YR_ALIGN $DATM_CLMNCEP_YR_ALIGN + $DATM_CLMNCEP_YR_ALIGN + $DATM_CLMNCEP_YR_ALIGN $DATM_CLMNCEP_YR_ALIGN $DATM_CLMNCEP_YR_ALIGN 1 @@ -1843,6 +1963,8 @@ $DATM_CLMNCEP_YR_START $DATM_CLMNCEP_YR_START $DATM_CLMNCEP_YR_START + $DATM_CLMNCEP_YR_START + $DATM_CLMNCEP_YR_START $DATM_CLMNCEP_YR_START $DATM_CLMNCEP_YR_START 1 @@ -1914,6 +2036,8 @@ $DATM_CLMNCEP_YR_END $DATM_CLMNCEP_YR_END $DATM_CLMNCEP_YR_END + $DATM_CLMNCEP_YR_END + $DATM_CLMNCEP_YR_END $DATM_CLMNCEP_YR_END $DATM_CLMNCEP_YR_END 1 @@ -1988,6 +2112,16 @@ 900 0 0 + -3600 + -3600 + -60 + -60 + -60 + -21600 + -21600 + -60 + -60 + -60 @@ -2054,6 +2188,8 @@ NULL CLMNCEP + CLMNCEP + CLMNCEP CORE2_NYF CORE2_IAF CORE_IAF_JRA @@ -2093,7 +2229,9 @@ valid values: 'copy','spval','nn','nnoni','nnonj' - nn + nn + copy + copy @@ -2248,6 +2386,16 @@ nearest coszen nearest + coszen + coszen + upper + linear + linear + coszen + coszen + upper + linear + linear coszen nearest nearest @@ -2340,6 +2488,25 @@ 3.0 3.0 3.0 + 2.5 + 2.5 + 2.5 + 2.5 + 2.5 + 2.5 + 2.5 + 2.5 + 2.5 + 2.5 + 2.5 + 2.5 + 2.5 + 2.5 + 2.5 + 2.5 + 2.5 + 2.5 + diff --git a/components/data_comps/datm/src/atm_comp_mct.F90 b/components/data_comps/datm/src/atm_comp_mct.F90 index a5f2855ae63..4970ac726d7 100644 --- a/components/data_comps/datm/src/atm_comp_mct.F90 +++ b/components/data_comps/datm/src/atm_comp_mct.F90 @@ -18,6 +18,11 @@ module atm_comp_mct use datm_shr_mod , only: presaero use seq_flds_mod , only: seq_flds_a2x_fields, seq_flds_x2a_fields +#ifdef HAVE_MOAB + use seq_comm_mct, only : mphaid ! iMOAB app id for phys atm; comp atm is 5, phys 5+200 + use iso_c_binding + use iMOAB , only: iMOAB_RegisterApplication +#endif ! !PUBLIC TYPES: implicit none private ! except @@ -80,6 +85,9 @@ subroutine atm_init_mct( EClock, cdata, x2a, a2x, NLFilename ) real(R8) :: orbObliqr ! orb obliquity (radians) real(R8) :: nextsw_cday ! calendar of next atm sw +#ifdef HAVE_MOAB + integer(IN) :: ATM_PHYS_CID ! used to create a new comp id for phys atm; 200+ compid +#endif !--- formats --- character(*), parameter :: F00 = "('(datm_comp_init) ',8a)" integer(IN) , parameter :: master_task=0 ! task number of master task @@ -164,6 +172,18 @@ subroutine atm_init_mct( EClock, cdata, x2a, a2x, NLFilename ) ! Initialize datm !---------------------------------------------------------------------------- + +#ifdef HAVE_MOAB + ATM_PHYS_CID = 200 + compid + ierr = iMOAB_RegisterApplication(trim("DATM")//C_NULL_CHAR, mpicom, ATM_PHYS_CID, mphaid) + if (ierr .ne. 0) then + write(logunit,*) subname,' error in registering data atm comp' + call shr_sys_abort(subname//' ERROR in registering data atm comp') + endif + ! send path of atm domain file to MOAB coupler. Note that here we may have the land domain in some cases? + call seq_infodata_PutData( infodata, atm_mesh=SDATM%domainFile) +#endif + call datm_comp_init(Eclock, x2a, a2x, & seq_flds_x2a_fields, seq_flds_a2x_fields, & SDATM, gsmap, ggrid, mpicom, compid, my_task, master_task, & diff --git a/components/data_comps/datm/src/datm_comp_mod.F90 b/components/data_comps/datm/src/datm_comp_mod.F90 index 3ad18c4a238..6f0adeedcd0 100644 --- a/components/data_comps/datm/src/datm_comp_mod.F90 +++ b/components/data_comps/datm/src/datm_comp_mod.F90 @@ -32,6 +32,9 @@ module datm_comp_mod use datm_shr_mod , only: iradsw ! namelist input use datm_shr_mod , only: nullstr +#ifdef HAVE_MOAB + use iso_c_binding +#endif ! !PUBLIC TYPES: implicit none @@ -212,6 +215,13 @@ subroutine datm_comp_init(Eclock, x2a, a2x, & scmMode, scmlat, scmlon, & orbEccen, orbMvelpp, orbLambm0, orbObliqr, phase, nextsw_cday) +#ifdef HAVE_MOAB + use iMOAB, only: iMOAB_DefineTagStorage, iMOAB_GetDoubleTagStorage, & + iMOAB_SetIntTagStorage, iMOAB_SetDoubleTagStorage, & + iMOAB_ResolveSharedEntities, iMOAB_CreateVertices, & + iMOAB_GetMeshInfo, iMOAB_UpdateMeshInfo, iMOAB_WriteMesh + use seq_comm_mct, only : mphaid ! iMOAB app id for phys atm; comp atm is 5, phys 5+200 +#endif ! !DESCRIPTION: initialize data atm model implicit none @@ -258,6 +268,19 @@ subroutine datm_comp_init(Eclock, x2a, a2x, & character(CL) :: calendar ! calendar type character(CL) :: flds_strm +#ifdef HAVE_MOAB + character*400 tagname + real(R8) latv, lonv + integer iv, tagindex, ilat, ilon, ierr !, arrsize, nfields + real(R8), allocatable, target :: data(:) + integer(IN), pointer :: idata(:) ! temporary + real(r8), dimension(:), allocatable :: moab_vert_coords ! temporary + !real(R8), allocatable, target :: vtags_zero(:, :) +#ifdef MOABDEBUG + character*100 outfile, wopts +#endif +#endif + !--- formats --- character(*), parameter :: F00 = "('(datm_comp_init) ',8a)" character(*), parameter :: F0L = "('(datm_comp_init) ',a, l2)" @@ -347,6 +370,110 @@ subroutine datm_comp_init(Eclock, x2a, a2x, & call shr_dmodel_rearrGGrid(SDATM%grid, ggrid, gsmap, rearr, mpicom) call t_stopf('datm_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(mphaid, lsize*3, 3, moab_vert_coords) + if (ierr .ne. 0) & + call shr_sys_abort('Error: fail to create MOAB vertices in land model') + + tagname='GLOBAL_ID'//C_NULL_CHAR + ierr = iMOAB_DefineTagStorage(mphaid, 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 ( mphaid, tagname, lsize, & + 0, & ! vertex type + idata) + if (ierr .ne. 0) & + call shr_sys_abort('Error: fail to set GLOBAL_ID tag ') + + ierr = iMOAB_ResolveSharedEntities( mphaid, 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( mphaid ) + if (ierr .ne. 0) & + call shr_sys_abort('Error: fail to update mesh info ') + + allocate(data(lsize)) + ierr = iMOAB_DefineTagStorage( mphaid, "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 ( mphaid, 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 ( mphaid, 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 ( mphaid, 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 ( mphaid, 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( mphaid, trim(seq_flds_x2a_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_x2a_fields tags ') + + ierr = iMOAB_DefineTagStorage( mphaid, trim(seq_flds_a2x_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_a2x_fields tags ') + +#endif !---------------------------------------------------------------------------- ! Initialize MCT attribute vectors !---------------------------------------------------------------------------- @@ -479,6 +606,24 @@ subroutine datm_comp_init(Eclock, x2a, a2x, & yc(:) = ggrid%data%rAttr(klat,:) call t_stopf('datm_initmctavs') +#ifdef HAVE_MOAB + ierr = iMOAB_DefineTagStorage( mphaid, trim(flds_strm)//C_NULL_CHAR, & + 1, & ! dense, double + 1, & ! number of components + tagindex ) + if (ierr > 0 ) & + call shr_sys_abort('Error: fail to create flds_strm tags ') +#ifdef MOABDEBUG + ! debug test + outfile = 'AtmDataMesh.h5m'//C_NULL_CHAR + wopts = ';PARALLEL=WRITE_PART'//C_NULL_CHAR ! + ! write out the mesh file to disk + ierr = iMOAB_WriteMesh(mphaid, trim(outfile), trim(wopts)) + if (ierr .ne. 0) then + call shr_sys_abort(subname//' ERROR in writing data mesh atm ') + endif +#endif +#endif !---------------------------------------------------------------------------- ! Read restart @@ -580,7 +725,14 @@ subroutine datm_comp_run(EClock, x2a, a2x, & nextsw_cday, case_name) ! !DESCRIPTION: run method for datm model - +#ifdef HAVE_MOAB + use seq_flds_mod , only: seq_flds_a2x_fields ! this should not be an argument in datm_comp_init + use seq_comm_mct, only : mphaid ! + use seq_flds_mod, only: moab_set_tag_from_av +#ifdef MOABDEBUG + use iMOAB, only: iMOAB_WriteMesh +#endif +#endif implicit none ! !INPUT/OUTPUT PARAMETERS: @@ -627,7 +779,18 @@ subroutine datm_comp_run(EClock, x2a, a2x, & !--- temporaries real(R8) :: uprime,vprime,swndr,swndf,swvdr,swvdf,ratio_rvrf real(R8) :: tbot,pbot,rtmp,vp,ea,e,qsat,frac +#ifdef HAVE_MOAB + real(R8), allocatable, target :: datam(:) + type(mct_list) :: temp_list + integer :: size_list, index_list + type(mct_string) :: mctOStr ! + character*400 tagname, mct_field +#ifdef MOABDEBUG + integer :: cur_datm_stepno, ierr + character*100 outfile, wopts, lnum +#endif +#endif character(*), parameter :: F00 = "('(datm_comp_run) ',8a)" character(*), parameter :: F04 = "('(datm_comp_run) ',2a,2i8,'s')" character(*), parameter :: subName = "(datm_comp_run) " @@ -675,6 +838,8 @@ subroutine datm_comp_run(EClock, x2a, a2x, & allocate(count_av(SDATM%nstreams)) allocate(count_st(SDATM%nstreams)) end if + + do n = 1,SDATM%nstreams if (firstcall) then call shr_dmodel_translate_list(SDATM%avs(n),a2x,& @@ -685,6 +850,7 @@ subroutine datm_comp_run(EClock, x2a, a2x, & ilist_av(n),olist_av(n),rearr) end if enddo + do n = 1,SDATM%nstreams if (firstcall) then call shr_dmodel_translate_list(SDATM%avs(n),avstrm,& @@ -696,7 +862,6 @@ subroutine datm_comp_run(EClock, x2a, a2x, & end if enddo call t_stopf('datm_scatter') - !------------------------------------------------- ! Determine data model behavior based on the mode !------------------------------------------------- @@ -1110,7 +1275,6 @@ subroutine datm_comp_run(EClock, x2a, a2x, & !---------------------------------------------------------- ! bias correction / anomaly forcing ( end block ) !---------------------------------------------------------- - !-------------------- ! Write restart !-------------------- @@ -1145,6 +1309,33 @@ subroutine datm_comp_run(EClock, x2a, a2x, & ! Reset shr logging to original values !---------------------------------------------------------------------------- +#ifdef HAVE_MOAB + lsize = mct_avect_lsize(a2x) ! is it the same as mct_avect_lsize(avstrm) ? + allocate(datam(lsize)) ! + call mct_list_init(temp_list ,seq_flds_a2x_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, a2x, index_list, mphaid, 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_datm_stepno ) + write(lnum,"(I0.2)")cur_datm_stepno + outfile = 'datm_comp_run_'//trim(lnum)//'.h5m'//C_NULL_CHAR + wopts = 'PARALLEL=WRITE_PART'//C_NULL_CHAR + ierr = iMOAB_WriteMesh(mphaid, outfile, wopts) + if (ierr > 0 ) then + write(logunit,*) 'Failed to write data atm component state ' + endif +#endif + +#endif + call t_startf('datm_run2') if (my_task == master_task) then write(logunit,F04) trim(myModelName),': model date ', CurrentYMD,CurrentTOD diff --git a/components/data_comps/docn/src/docn_comp_mod.F90 b/components/data_comps/docn/src/docn_comp_mod.F90 index 03fc4a3459a..e692882c9db 100644 --- a/components/data_comps/docn/src/docn_comp_mod.F90 +++ b/components/data_comps/docn/src/docn_comp_mod.F90 @@ -120,13 +120,11 @@ subroutine docn_comp_init(Eclock, x2o, o2x, & scmMode, scm_multcols, scmlat, scmlon, scm_nx, scm_ny) ! !DESCRIPTION: initialize docn model - use mct_mod use pio , only : iosystem_desc_t use shr_pio_mod, only : shr_pio_getiosys, shr_pio_getiotype #ifdef HAVE_MOAB #include "moab/MOABConfig.h" - use iMOAB, only: iMOAB_RegisterApplication, iMOAB_LoadMesh, & - iMOAB_DefineTagStorage, iMOAB_GetDoubleTagStorage, & + use iMOAB, only: iMOAB_DefineTagStorage, iMOAB_GetDoubleTagStorage, & iMOAB_SetIntTagStorage, iMOAB_SetDoubleTagStorage, & iMOAB_ResolveSharedEntities, iMOAB_CreateVertices, & iMOAB_GetMeshInfo, iMOAB_UpdateMeshInfo @@ -171,13 +169,12 @@ subroutine docn_comp_init(Eclock, x2o, o2x, & type(iosystem_desc_t), pointer :: ocn_pio_subsystem #ifdef HAVE_MOAB - character*100 tagname + character*400 tagname real(R8) latv, lonv integer iv, tagindex real(R8), allocatable, target :: data(:) integer(IN), pointer :: idata(:) ! temporary real(r8), dimension(:), allocatable :: moab_vert_coords ! temporary - integer :: mpigrp ! mpigrp #endif !--- formats --- @@ -522,35 +519,6 @@ subroutine docn_comp_init(Eclock, x2o, o2x, & end subroutine docn_comp_init -#ifdef HAVE_MOAB - !=============================================================================== - - subroutine moab_init_tag(tagname, avx, index, dataarr) - - ! !DESCRIPTION: run method for docn model - use iMOAB, only: iMOAB_SetDoubleTagStorage, & - iMOAB_SetDoubleTagStorageWithGid - implicit none - - integer :: ierr, n, lsize, tagindex - character(len=*), intent(in) :: tagname - type(mct_aVect), intent(in) :: avx - integer, intent(in) :: index - real(R8), intent(inout) :: dataarr(:) - - lsize = mct_avect_lsize(avx) - !write(*,* ) "Setting data for tag: ", tagname, " with size = ", lsize - dataarr(:) = avx%rAttr(index, :) - ierr = iMOAB_SetDoubleTagStorage ( mpoid, tagname, lsize, & - 0, & ! data on vertices - dataarr ) - if (ierr > 0 ) & - call errorout(ierr, 'Error: fail to set tag values for ' // tagname ) - - end subroutine moab_init_tag - -#endif - subroutine docn_comp_run(EClock, x2o, o2x, & SDOCN, gsmap, ggrid, mpicom, compid, my_task, master_task, & inst_suffix, logunit, read_restart, write_restart, & @@ -561,6 +529,7 @@ subroutine docn_comp_run(EClock, x2o, o2x, & use iMOAB, only: iMOAB_GetMeshInfo, & iMOAB_SetDoubleTagStorage, & iMOAB_WriteMesh + use seq_flds_mod, only: moab_set_tag_from_av #endif implicit none @@ -845,63 +814,45 @@ subroutine docn_comp_run(EClock, x2o, o2x, & ! set dense double tags on vertices of the temporary DOCN app ! first set o2x data - call moab_init_tag( 'So_t'//C_NULL_CHAR, o2x, & - kt, data) + call moab_set_tag_from_av('So_t'//C_NULL_CHAR, o2x, kt, mpoid, data, lsize) - call moab_init_tag( 'So_s'//C_NULL_CHAR, o2x, & - ks, data) + call moab_set_tag_from_av('So_s'//C_NULL_CHAR, o2x, ks, mpoid, data, lsize) - call moab_init_tag( 'So_u'//C_NULL_CHAR, o2x, & - ku, data) + call moab_set_tag_from_av( 'So_u'//C_NULL_CHAR, o2x, ku, mpoid, data, lsize) - call moab_init_tag( 'So_v'//C_NULL_CHAR, o2x, & - kv, data) + call moab_set_tag_from_av( 'So_v'//C_NULL_CHAR, o2x, kv, mpoid, data, lsize) - call moab_init_tag( 'So_dhdx'//C_NULL_CHAR, o2x, & - kdhdx, data) + call moab_set_tag_from_av( 'So_dhdx'//C_NULL_CHAR, o2x, kdhdx, mpoid, data, lsize) - call moab_init_tag( 'So_dhdy'//C_NULL_CHAR, o2x, & - kdhdy, data) + call moab_set_tag_from_av( 'So_dhdy'//C_NULL_CHAR, o2x, kdhdy, mpoid, data, lsize) - call moab_init_tag( 'Fioo_q'//C_NULL_CHAR, o2x, & - kq, data) + call moab_set_tag_from_av( 'Fioo_q'//C_NULL_CHAR, o2x, kq, mpoid, data, lsize) if (kswp /= 0) then - call moab_init_tag( 'So_fswpen'//C_NULL_CHAR, o2x, & - kswp, data) + call moab_set_tag_from_av( 'So_fswpen'//C_NULL_CHAR, o2x, kswp, mpoid, data, lsize) endif ! next set x2o data - call moab_init_tag( 'Foxx_swnet'//C_NULL_CHAR, x2o, & - kswnet, data) + call moab_set_tag_from_av( 'Foxx_swnet'//C_NULL_CHAR, x2o, kswnet, mpoid, data, lsize) - call moab_init_tag( 'Foxx_lwup'//C_NULL_CHAR, x2o, & - klwup, data) + call moab_set_tag_from_av( 'Foxx_lwup'//C_NULL_CHAR, x2o, klwup, mpoid, data, lsize) - call moab_init_tag( 'Foxx_sen'//C_NULL_CHAR, x2o, & - ksen, data) + call moab_set_tag_from_av( 'Foxx_sen'//C_NULL_CHAR, x2o, ksen, mpoid, data, lsize) - call moab_init_tag( 'Foxx_lat'//C_NULL_CHAR, x2o, & - klat, data) + call moab_set_tag_from_av( 'Foxx_lat'//C_NULL_CHAR, x2o, klat, mpoid, data, lsize) - call moab_init_tag( 'Foxx_rofi'//C_NULL_CHAR, x2o, & - krofi, data) + call moab_set_tag_from_av( 'Foxx_rofi'//C_NULL_CHAR, x2o, krofi, mpoid, data, lsize) - call moab_init_tag( 'Faxa_lwdn'//C_NULL_CHAR, x2o, & - klwdn, data) + call moab_set_tag_from_av( 'Faxa_lwdn'//C_NULL_CHAR, x2o, klwdn, mpoid, data, lsize) - call moab_init_tag( 'Faxa_snow'//C_NULL_CHAR, x2o, & - ksnow, data) + call moab_set_tag_from_av( 'Faxa_snow'//C_NULL_CHAR, x2o, ksnow, mpoid, data, lsize) - call moab_init_tag( 'Fioi_melth'//C_NULL_CHAR, x2o, & - kmelth, data) + call moab_set_tag_from_av( 'Fioi_melth'//C_NULL_CHAR, x2o, kmelth, mpoid, data, lsize) ! next set avstrm data - call moab_init_tag( 'strm_h'//C_NULL_CHAR, avstrm, & - kh, data) + call moab_set_tag_from_av( 'strm_h'//C_NULL_CHAR, avstrm, kh, mpoid, data, lsize) - call moab_init_tag( 'strm_qbot'//C_NULL_CHAR, avstrm, & - kqbot, data) + call moab_set_tag_from_av( 'strm_qbot'//C_NULL_CHAR, avstrm, kqbot, mpoid, data, lsize) #ifdef MOABDEBUG diff --git a/components/data_comps/docn/src/ocn_comp_mct.F90 b/components/data_comps/docn/src/ocn_comp_mct.F90 index d3d237d1adf..6b029981438 100644 --- a/components/data_comps/docn/src/ocn_comp_mct.F90 +++ b/components/data_comps/docn/src/ocn_comp_mct.F90 @@ -169,8 +169,8 @@ subroutine ocn_init_mct( EClock, cdata, x2o, o2x, NLFilename ) #ifdef HAVE_MOAB ierr = iMOAB_RegisterApplication(trim("DOCN")//C_NULL_CHAR, mpicom, compid, mpoid) if (ierr .ne. 0) then - write(logunit,*) subname,' error in registering atm ocn intx' - call shr_sys_abort(subname//' ERROR in registering atm ocn intx') + write(logunit,*) subname,' error in registering data ocn comp' + call shr_sys_abort(subname//' ERROR in registering data ocn comp') endif ! send path of ocean domain file to MOAB coupler. call seq_infodata_PutData( infodata, ocn_domain=SDOCN%domainFile) diff --git a/components/data_comps/drof/cime_config/namelist_definition_drof.xml b/components/data_comps/drof/cime_config/namelist_definition_drof.xml index 369e2396518..c4139552c70 100644 --- a/components/data_comps/drof/cime_config/namelist_definition_drof.xml +++ b/components/data_comps/drof/cime_config/namelist_definition_drof.xml @@ -205,10 +205,10 @@ RAF_9091.JRA.v1.3.runoff.180404.nc RAF_0304.JRA.v1.3.runoff.180404.nc - JRA.v1.5.runoff.%y.no_rofi_no_rofl.210505.nc + JRA.v1.5.runoff.%y.no_rofi_no_rofl.240411.nc - JRA.v1.5.runoff.%y.210505.nc + JRA.v1.5.runoff.%y.240411.nc JRA.v1.4.runoff.%y.no_rofi.190214.nc diff --git a/components/eam/bld/namelist_files/namelist_defaults_eam.xml b/components/eam/bld/namelist_files/namelist_defaults_eam.xml index 56c816b1753..cfd9bf682c8 100755 --- a/components/eam/bld/namelist_files/namelist_defaults_eam.xml +++ b/components/eam/bld/namelist_files/namelist_defaults_eam.xml @@ -917,6 +917,7 @@ 1.0D0 .false. 100.D6 + 200.D6 0.1D6 -999. -999. diff --git a/components/eam/bld/namelist_files/namelist_definition.xml b/components/eam/bld/namelist_files/namelist_definition.xml index 19e356ca6cc..b3ecb5e9290 100644 --- a/components/eam/bld/namelist_files/namelist_definition.xml +++ b/components/eam/bld/namelist_files/namelist_definition.xml @@ -4726,7 +4726,9 @@ Default: FALSE -Turn off microphysics computation. +Turn off microphysics computation for MG2. For P3 this disables the generation of +liquid precipitation via autoconversion only, to be used for idealized simulations of +warm phase boundary layer clouds. Default: FALSE | | diff --git a/components/eam/bld/namelist_files/use_cases/SSP245_eam_CMIP6_chemUCI-Linoz-mam5-vbs.xml b/components/eam/bld/namelist_files/use_cases/SSP245_eam_CMIP6_chemUCI-Linoz-mam5-vbs.xml new file mode 100644 index 00000000000..120fb939165 --- /dev/null +++ b/components/eam/bld/namelist_files/use_cases/SSP245_eam_CMIP6_chemUCI-Linoz-mam5-vbs.xml @@ -0,0 +1,107 @@ + + + + +.true. + + +atm/cam/solar/Solar_1850-2299_input4MIPS_c20181106.nc +SERIAL + + +atm/cam/ggas/GHG_CMIP_SSP245-1-2-1_Annual_Global_2015-2500_c20200807.nc +RAMPED + + +.true. +.true. +.true. + + +INTERP_MISSING_MONTHS +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/emissions-cmip6_ssp245_e3sm_NO2_aircraft_vertical_2015-2100_1.9x2.5_c20240219.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_so2_volc_elev_2015-2100_c240331.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/emissions-cmip6_ssp245_e3sm_SOAG0_elev_2015-2100_1.9x2.5_c20240219.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_bc_a4_elev_2015-2100_c200716.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_num_a1_elev_2015-2100_c200716.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_num_a2_elev_2015-2100_c200716.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_num_a4_elev_2015-2100_c200716.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_pom_a4_elev_2015-2100_c200716.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_so4_a1_elev_2015-2100_c200716.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_so4_a2_elev_2015-2100_c200716.nc + + +INTERP_MISSING_MONTHS +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/emissions-cmip6_ssp245_e3sm_C2H4_surface_2015-2100_1.9x2.5_c20240219.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/emissions-cmip6_ssp245_e3sm_C2H6_surface_2015-2100_1.9x2.5_c20240219.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/emissions-cmip6_ssp245_e3sm_C3H8_surface_2015-2100_1.9x2.5_c20240219.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/emissions-cmip6_ssp245_e3sm_CH2O_surface_2015-2100_1.9x2.5_c20240219.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/emissions-cmip6_ssp245_e3sm_CH3CHO_surface_2015-2100_1.9x2.5_c20240219.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/emissions-cmip6_ssp245_e3sm_CH3COCH3_surface_2015-2100_1.9x2.5_c20240219.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/emissions-cmip6_ssp245_e3sm_CO_surface_2015-2100_1.9x2.5_c20240219.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/emissions-cmip6_ssp245_e3sm_ISOP_surface_2015-2100_1.9x2.5_c20240219.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/emissions-cmip6_ssp245_e3sm_ISOP_surface_2015-2100_1.9x2.5_c20240219.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/emissions-cmip6_ssp245_e3sm_MTERP_surface_2015-2100_1.9x2.5_c20240219.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/emissions-cmip6_ssp245_e3sm_NO_surface_2015-2100_1.9x2.5_c20240219.nc +atm/cam/chem/trop_mozart_aero/emis/DMSflux.1850-2100.1deg_latlon_conserv.POPmonthlyClimFromACES4BGC_c20160727.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_so2_surf_2015-2100_c200716.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/emissions-cmip6_ssp245_e3sm_SOAG0_surf_2015-2100_1.9x2.5_c20240219.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_bc_a4_surf_2015-2100_c200716.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_num_a1_surf_2015-2100_c200716.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_num_a2_surf_2015-2100_c200716.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_num_a4_surf_2015-2100_c200716.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_pom_a4_surf_2015-2100_c200716.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_so4_a1_surf_2015-2100_c200716.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_so4_a2_surf_2015-2100_c200716.nc +atm/cam/chem/trop_mozart/ub/emissions_E90_surface_1750-2101_1.9x2.5_c20231222.nc + + + + +INTERP_MISSING_MONTHS +atm/cam/chem/trop_mozart_aero/oxid +oxid_SSP245_1.9x2.5_L70_1849-2101_c20240228.nc +'prsd_O3:O3','prsd_NO3:NO3','prsd_OH:OH' +'' + + + + '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_Hist_SSP245_0003-2503_c20200808.nc +SERIAL +linv3_1849-2101_CMIP6_Hist_SSP245_10deg_58km_c20230705.nc +atm/cam/chem/trop_mozart/ub +INTERP_MISSING_MONTHS + + +'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' +'' + + +2015-2100 + + diff --git a/components/eam/bld/namelist_files/use_cases/SSP370_eam_CMIP6.xml b/components/eam/bld/namelist_files/use_cases/SSP370_eam_CMIP6.xml old mode 100755 new mode 100644 diff --git a/components/eam/bld/namelist_files/use_cases/SSP370_eam_CMIP6_chemUCI-Linoz-mam5-vbs.xml b/components/eam/bld/namelist_files/use_cases/SSP370_eam_CMIP6_chemUCI-Linoz-mam5-vbs.xml old mode 100755 new mode 100644 index 60912c54419..e15be0889fd --- a/components/eam/bld/namelist_files/use_cases/SSP370_eam_CMIP6_chemUCI-Linoz-mam5-vbs.xml +++ b/components/eam/bld/namelist_files/use_cases/SSP370_eam_CMIP6_chemUCI-Linoz-mam5-vbs.xml @@ -12,13 +12,6 @@ atm/cam/ggas/GHG_CMIP_SSP370-1-2-1_Annual_Global_2015-2500_c20210509.nc RAMPED - -atm/cam/volc -CMIP_DOE-ACME_radiation_average_1850-2014_v3_c20171204.nc -VOLC_CMIP6 -CYCLICAL -1 - .true. .true. @@ -26,8 +19,9 @@ INTERP_MISSING_MONTHS -atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_so2_elev_2015-2100_c210216.nc -atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_soag_elev_2015-2100_c210216.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_NO2_aircraft_vertical_2015-2100_1.9x2.5_c20240208.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_so2_volc_elev_2015-2100_c240331.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_SOAG0_elev_2015-2100_1.9x2.5_c20240208.nc atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_bc_a4_elev_2015-2100_c210216.nc atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_num_a1_elev_2015-2100_c210216.nc atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_num_a2_elev_2015-2100_c210216.nc @@ -38,8 +32,20 @@ INTERP_MISSING_MONTHS +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_C2H4_surface_2015-2100_1.9x2.5_c20240208.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_C2H6_surface_2015-2100_1.9x2.5_c20240208.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_C3H8_surface_2015-2100_1.9x2.5_c20240208.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_CH2O_surface_2015-2100_1.9x2.5_c20240208.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_CH3CHO_surface_2015-2100_1.9x2.5_c20240208.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_CH3COCH3_surface_2015-2100_1.9x2.5_c20240208.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_CO_surface_2015-2100_1.9x2.5_c20240208.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_ISOP_surface_2015-2100_1.9x2.5_c20240208.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_ISOP_surface_2015-2100_1.9x2.5_c20240208.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_MTERP_surface_2015-2100_1.9x2.5_c20240208.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_NO_surface_2015-2100_1.9x2.5_c20240208.nc atm/cam/chem/trop_mozart_aero/emis/DMSflux.1850-2100.1deg_latlon_conserv.POPmonthlyClimFromACES4BGC_c20160727.nc atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_so2_surf_2015-2100_c210216.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_SOAG0_surf_2015-2100_1.9x2.5_c20240208.nc atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_bc_a4_surf_2015-2100_c210216.nc atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_num_a1_surf_2015-2100_c210216.nc atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_num_a2_surf_2015-2100_c210216.nc @@ -47,14 +53,28 @@ atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_pom_a4_surf_2015-2100_c210216.nc atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_so4_a1_surf_2015-2100_c210216.nc atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_so4_a2_surf_2015-2100_c210216.nc +atm/cam/chem/trop_mozart/ub/emissions_E90_surface_1750-2101_1.9x2.5_c20231222.nc + + INTERP_MISSING_MONTHS atm/cam/chem/trop_mozart_aero/oxid -oxid_SSP370_1.9x2.5_L70_2015-2100_c20211006.nc +oxid_SSP370_1.9x2.5_L70_1849-2101_c20240228.nc +'prsd_O3:O3','prsd_NO3:NO3','prsd_OH:OH' '' - + + + '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 @@ -74,7 +94,12 @@ INTERP_MISSING_MONTHS -'H2O2', 'H2SO4', 'SO2' +'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' +'' 2015-2100 diff --git a/components/eam/bld/namelist_files/use_cases/SSP585_eam_CMIP6.xml b/components/eam/bld/namelist_files/use_cases/SSP585_eam_CMIP6.xml old mode 100755 new mode 100644 diff --git a/components/eam/bld/namelist_files/use_cases/SSP585_eam_CMIP6_chemUCI-Linoz-mam5-vbs.xml b/components/eam/bld/namelist_files/use_cases/SSP585_eam_CMIP6_chemUCI-Linoz-mam5-vbs.xml old mode 100755 new mode 100644 index 98e2dcf7604..f9c45623d5a --- a/components/eam/bld/namelist_files/use_cases/SSP585_eam_CMIP6_chemUCI-Linoz-mam5-vbs.xml +++ b/components/eam/bld/namelist_files/use_cases/SSP585_eam_CMIP6_chemUCI-Linoz-mam5-vbs.xml @@ -12,13 +12,6 @@ atm/cam/ggas/GHG_CMIP_SSP585-1-2-1_Annual_Global_2015-2500_c20190310.nc RAMPED - -atm/cam/volc -CMIP_DOE-ACME_radiation_average_1850-2014_v3_c20171204.nc -VOLC_CMIP6 -CYCLICAL -1 - .true. .true. @@ -26,8 +19,9 @@ INTERP_MISSING_MONTHS -atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/cmip6_ssp585_mam4_so2_elev_2015-2100_c190828.nc -atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/cmip6_ssp585_mam4_soag_elev_2015-2100_c190828.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/emissions-cmip6_ssp585_e3sm_NO2_aircraft_vertical_2015-2100_1.9x2.5_c20240304.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/cmip6_ssp585_mam4_so2_volc_elev_2015-2100_c240331.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/emissions-cmip6_ssp585_e3sm_SOAG0_elev_2015-2100_1.9x2.5_c20240304.nc atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/cmip6_ssp585_mam4_bc_a4_elev_2015-2100_c190828.nc atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/cmip6_ssp585_mam4_num_a1_elev_2015-2100_c190828.nc atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/cmip6_ssp585_mam4_num_a2_elev_2015-2100_c190828.nc @@ -38,8 +32,20 @@ INTERP_MISSING_MONTHS +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/emissions-cmip6_ssp585_e3sm_C2H4_surface_2015-2100_1.9x2.5_c20240304.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/emissions-cmip6_ssp585_e3sm_C2H6_surface_2015-2100_1.9x2.5_c20240304.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/emissions-cmip6_ssp585_e3sm_C3H8_surface_2015-2100_1.9x2.5_c20240304.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/emissions-cmip6_ssp585_e3sm_CH2O_surface_2015-2100_1.9x2.5_c20240304.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/emissions-cmip6_ssp585_e3sm_CH3CHO_surface_2015-2100_1.9x2.5_c20240304.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/emissions-cmip6_ssp585_e3sm_CH3COCH3_surface_2015-2100_1.9x2.5_c20240304.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/emissions-cmip6_ssp585_e3sm_CO_surface_2015-2100_1.9x2.5_c20240304.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/emissions-cmip6_ssp585_e3sm_ISOP_surface_2015-2100_1.9x2.5_c20240304.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/emissions-cmip6_ssp585_e3sm_ISOP_surface_2015-2100_1.9x2.5_c20240304.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/emissions-cmip6_ssp585_e3sm_MTERP_surface_2015-2100_1.9x2.5_c20240304.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/emissions-cmip6_ssp585_e3sm_NO_surface_2015-2100_1.9x2.5_c20240304.nc atm/cam/chem/trop_mozart_aero/emis/DMSflux.1850-2100.1deg_latlon_conserv.POPmonthlyClimFromACES4BGC_c20160727.nc atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/cmip6_ssp585_mam4_so2_surf_2015-2100_c190828.nc +atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/emissions-cmip6_ssp585_e3sm_SOAG0_surf_2015-2100_1.9x2.5_c20240304.nc atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/cmip6_ssp585_mam4_bc_a4_surf_2015-2100_c190828.nc atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/cmip6_ssp585_mam4_num_a1_surf_2015-2100_c190828.nc atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/cmip6_ssp585_mam4_num_a2_surf_2015-2100_c190828.nc @@ -47,14 +53,28 @@ atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/cmip6_ssp585_mam4_pom_a4_surf_2015-2100_c190828.nc atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/cmip6_ssp585_mam4_so4_a1_surf_2015-2100_c190828.nc atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/cmip6_ssp585_mam4_so4_a2_surf_2015-2100_c190828.nc +atm/cam/chem/trop_mozart/ub/emissions_E90_surface_1750-2101_1.9x2.5_c20231222.nc + + INTERP_MISSING_MONTHS atm/cam/chem/trop_mozart_aero/oxid -oxid_1.9x2.5_L70_2015-2100_c20190421.nc +oxid_SSP585_1.9x2.5_L70_2014-2101_c20240228.nc +'prsd_O3:O3','prsd_NO3:NO3','prsd_OH:OH' '' - + + + '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 @@ -74,7 +94,12 @@ INTERP_MISSING_MONTHS -'H2O2', 'H2SO4', 'SO2' +'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' +'' 2015-2100 diff --git a/components/eam/bld/namelist_files/use_cases/scam_generic.xml b/components/eam/bld/namelist_files/use_cases/scam_generic.xml index 395d9a6ec86..2b77e3b630a 100644 --- a/components/eam/bld/namelist_files/use_cases/scam_generic.xml +++ b/components/eam/bld/namelist_files/use_cases/scam_generic.xml @@ -3,7 +3,6 @@ -atm/cam/inic/homme/cami_mam3_Linoz_ne4np4_L72_c160909.nc atm/cam/chem/trop_mozart_aero/emis/aces4bgc_nvsoa_soag_elev_2000_c160427.nc diff --git a/components/eam/cime_config/config_component.xml b/components/eam/cime_config/config_component.xml index 33eaacb36b5..1a961b84aff 100755 --- a/components/eam/cime_config/config_component.xml +++ b/components/eam/cime_config/config_component.xml @@ -53,8 +53,7 @@ -phys default &eamv3_phys_defaults; &eamv3_chem_defaults; &eamv3_phys_defaults; &eamv3_chem_defaults; - &eamv3_phys_defaults; &eamv3_chem_defaults; - &eamv3_phys_defaults; &eamv2_chem_defaults; + &eamv3_phys_defaults; &eamv3_chem_defaults; -bc_dep_to_snow_updates -co2_cycle @@ -129,6 +128,7 @@ 20TR_eam_CMIP6_chemUCI-Linoz-mam5-vbs SSP585_eam_CMIP6_chemUCI-Linoz-mam5-vbs SSP370_eam_CMIP6_chemUCI-Linoz-mam5-vbs + SSP245_eam_CMIP6_chemUCI-Linoz-mam5-vbs SSP585_cam5_CMIP6_bgc 20TR_E3SMv1_superfast_ar5-emis 20TRS_E3SMv1_superfast_ar5-emis @@ -136,7 +136,7 @@ 20TR_eam_chemUCI-Linoz-mam5 scam_arm95 scm_arm97_chemUCI-Linoz-mam5-vbs - scm_generic_chemUCI-Linoz-mam5-vbs + scam_generic 1850-PD_cam5 aquaplanet_EAMv1 RCEMIP_EAMv1 diff --git a/components/eam/cime_config/config_compsets.xml b/components/eam/cime_config/config_compsets.xml index 7c3393b1118..39971fbb094 100644 --- a/components/eam/cime_config/config_compsets.xml +++ b/components/eam/cime_config/config_compsets.xml @@ -51,14 +51,19 @@ 2010_EAM%CMIP6_ELM%CNPRDCTCBCTOP_MPASSI%PRES_DOCN%DOM_MOSART_SGLC_SWAV + + FSSP245 + SSP245_eam_EAM%CMIP6_ELM%CNPRDCTCBCTOP_MPASSI%PRES_DOCN%DOM_MOSART_SGLC_SWAV + + FSSP370 - SSP370_eam_EAM%CMIP6_ELM%SPBC_MPASSI%PRES_DOCN%DOM_MOSART_SGLC_SWAV + SSP370_eam_EAM%CMIP6_ELM%CNPRDCTCBCTOP_MPASSI%PRES_DOCN%DOM_MOSART_SGLC_SWAV FSSP585 - SSP585_eam_EAM%CMIP6_ELM%SPBC_MPASSI%PRES_DOCN%DOM_MOSART_SGLC_SWAV + SSP585_eam_EAM%CMIP6_ELM%CNPRDCTCBCTOP_MPASSI%PRES_DOCN%DOM_MOSART_SGLC_SWAV diff --git a/components/eam/docs/dev-guide/index.md b/components/eam/docs/dev-guide/index.md index 553bf5f3697..6879c32cbe3 100644 --- a/components/eam/docs/dev-guide/index.md +++ b/components/eam/docs/dev-guide/index.md @@ -1 +1,3 @@ -start of the EAM Developer's Guide +# EAM Developer Guide + +coming soon. diff --git a/components/eam/docs/index.md b/components/eam/docs/index.md index 6632c22ca62..55870e3778d 100644 --- a/components/eam/docs/index.md +++ b/components/eam/docs/index.md @@ -1,7 +1,7 @@ # The E3SM Atmosphere Model (EAM) -Some introductory text here +EAM is the state-of-the-art atmospheric component of the E3SM model that uses a Spectral Element Dynamical Core and a suite of parameterizations to represent a range of atmospheric processes, which are described in the Technical Guide (see below). Its nominal resolution is roughly 100km in the horizontal, with a model time step of 1800 seconds, and runs with 80 layers in the vertical (model top of 60km). -* The [EAM User's Guide](user-guide/index.md) explains how to control EAM when its running within E3SM. -* The [EAM Developer's Guide](dev-guide/index.md) explains EAM data structures and how to write new code. -* The [EAM Techincal Guide](tech-guide/index.md) explains the science behind EAM's code +* The [EAM User Guide](user-guide/index.md) explains how to control EAM when its running within E3SM. +* The [EAM Developer Guide](dev-guide/index.md) explains EAM data structures and how to write new code. +* The [EAM Technical Guide](tech-guide/index.md) explains the science behind EAM's code diff --git a/components/eam/docs/tech-guide/armdiags.md b/components/eam/docs/tech-guide/armdiags.md new file mode 100644 index 00000000000..47266db48f2 --- /dev/null +++ b/components/eam/docs/tech-guide/armdiags.md @@ -0,0 +1,56 @@ +# ARM diagnostics + +## Overview + +The ARM data-oriented metrics and diagnostics package (ARM Diags) was developed to facilitate the use of ARM data in climate model evaluation and model intercomparison (Zhang et al., 2020)[@zhang_arm_2020]. It includes ARM data sets, compiled from multiple ARM data products, and a Python-based analysis toolkit for computation ad visualization. It also includes simulation data from models participating the CMIP, which allows climate-modeling groups to compare a new, candidate version of their model to existing CMIP models. The ARM Diags has been applied in several model evaluation studies to help address a range of issues in climate models (Zheng et al., 2023;[@zheng_assessment_2023] Emmenegger et al., 2022;[@emmenegger_evaluating_2022] Zhang et al., 2018[@zhang_causes_2018]). The Majority of ARM Diags sets are ported into E3SM Diags (Zhang et al., 2022)[@zhang_e3sm_2022] for routine evaluation of the model. + +## To enable the use of ARM Diags + +To enable using ARM Diags for a simulation, often, a new tape that output at high-frequency over limited-area (nearest grid box to supported ARM site) needs to be included in the namelist file, an example as follows: + +```fortran +fincl7 = 'PS','Q','T','Z3','CLOUD','CONCLD','CLDICE', + 'CLDLIQ','FREQR','REI','REL','PRECT','TMQ','PRECC', + 'TREFHT','QREFHT','OMEGA','CLDTOT','LHFLX','SHFLX', + 'FLDS','FSDS','FLNS','FSNS','FLNSC','FSDSC','FSNSC', + 'AODVIS','AODABS','LS_FLXPRC','LS_FLXSNW', + 'LS_REFFRAIN','ZMFLXPRC','ZMFLXSNW','CCN1','CCN2', + 'CCN3','CCN4','CCN5','num_a1','num_a2','num_a3', + 'num_a4','so4_a1','so4_a2','so4_a3','AREL','TGCLDLWP', + 'AQRAIN','ANRAIN','FREQR','PRECL','RELHUM' +fincl7lonlat='262.5e_36.6n','203.4e_71.3n','147.4e_2.0s', + '166.9e_0.5s','130.9e_12.4s','331.97e_39.09n' +``` + +Note that in this example fincl7 should set to write output at hourly (`nhtfrq = -1`). And here additional variables are included for ARM simulator analysis. The ARM site information is shown below: + +```fortran + "sgpc1": ["97.5W 36.4N Oklahoma ARM"], + + "nsac1": ["156.6W 71.3N Barrow ARM"], + + "twpc1": ["147.4E 2.1S Manus ARM"], + + "twpc2": ["166.9E 0.5S Nauru ARM"], + + "twpc3": ["130.9E 12.4S Darwin ARM"], + + "enac1": ["28.0E 39.1N Graciosa Island ARM"], +``` + +## Diagnostics and metrics currently implemented in the ARM Diags + +| Statistical Metrics | Variables | Time sampling | +| ------------------------- | --------------------------------------------------------------- | ----------------- | +| Line plots and Taylor diagrams for annual cycle variability of each variable | Precipitation, column water vapor, surface energy budget components, near-surface temperature and specific humidity, surface pressure, total cloud fraction, and aerosol optical depth. | Monthly mean | +| Contour and vertical profiles of annual cycle and diurnal cycle of cloud fraction | Vertical profiles of cloud fraction | Hourly mean | +| Line and harmonic dial plots of diurnal cycle of precipitation | Surface precipitation rate | Hourly mean | +| Probability density function (PDF) plots of precipitation rate | Surface precipitation rate | Hourly mean | +| CCN Annual Cycles | CCN number concentrations at 0.1%, 0.2%, 0.5% and 1.0% supersaturation levels | Hourly mean | +| Aerosol Annual Cycles | Total aerosol number concentration | Hourly mean | +| Aerosol Chemical Annual Cycles | Organic, sulfate, nitrate, ammonium, chloride mass concentration | Hourly mean | + +| Process-oriented metrics | Variables | Time sampling | +| ------------------------- | ------------------------------------------------------------- | ----------------- | +| Convection Onset | 1. Surface precipitation rate
2. Column Precipitable Water Vapor | Hourly mean | +| Aerosol-CCN Activation | 1. Total aerosol number concentration
2. CCN number concentrations at different supersaturation levels (0.1%, 0.2%, 0.5% and 1.0) | Hourly mean | diff --git a/components/eam/docs/tech-guide/chemUCIlinozv3.md b/components/eam/docs/tech-guide/chemUCIlinozv3.md new file mode 100644 index 00000000000..b6b202c00f8 --- /dev/null +++ b/components/eam/docs/tech-guide/chemUCIlinozv3.md @@ -0,0 +1,9 @@ +# chemUCI and Linoz + +## Overview + +Atmospheric interactive chemistry is handled by chemUCI (in the troposphere) and Linoz v3 (in the stratosphere). chemUCI consists of 28 advected tracers for the O3-CH4-HOx-NOx-NMVOCs chemistry. Compared to E3SMv2, the E3SMv3 linearized stratospheric chemistry scheme (Linoz v3) expends the interactive species to include O3, N2O, NOy, and CH4. The boundary between stratosphere and troposphere adopts the e90 tropopause algorithm. + +## Namelist parameters + +[chemUCI and Linoz Namelist Parameters](../user-guide/namelist_parameters.md#chemuci-and-linoz-v3) diff --git a/components/eam/docs/tech-guide/clubb.md b/components/eam/docs/tech-guide/clubb.md new file mode 100644 index 00000000000..2737f753850 --- /dev/null +++ b/components/eam/docs/tech-guide/clubb.md @@ -0,0 +1,9 @@ +# Cloud Layers Unified By Binormals + +## Overview + +The Cloud Layers Unified By Binormals (CLUBB) parameterization is a parameterization of subgrid-scale turbulence and clouds.[@larson_clubb-silhs_2022,@bogenschutz_path_2018,@larson_using_2005,@golaz_pdf-based_2002] It prognoses turbulent fluxes of heat, moisture, and momentum, and it diagnoses the liquid cloud fraction and liquid water mixing ratio. To do so, it prognoses higher-order turbulence moments and closes those prognostic equations by use of an assumed double-Gaussian shape of the subgrid probability density function. CLUBB operates throughout the troposphere, but it contributes especially to the planetary boundary layer and low-cloud regimes, including stratocumulus and shallow cumulus regimes. + +## Namelist parameters + +[CLUBB Namelist Parameters](../user-guide/namelist_parameters.md#cloud-layers-unified-by-binormals) diff --git a/components/eam/docs/tech-guide/cosp.md b/components/eam/docs/tech-guide/cosp.md new file mode 100644 index 00000000000..ef724b12a9f --- /dev/null +++ b/components/eam/docs/tech-guide/cosp.md @@ -0,0 +1,27 @@ +# Cloud Feedback Model Intercomparison Project (CFMIP) Observation Simulator Package + +## Overview + +The Cloud Feedback Model Intercomparison Project (CFMIP) Observation Simulator Package (COSP; Bodas-Salcedo et al., 2011;[@bodas-salcedo_cosp_2011] Swales et al., 2018;[@swales_cloud_2018] Zhang et al., 2019;[@zhang_evaluation_2019] Zhang et al., 2024[@zhang_understanding_2024]) was developed to improve the consistency between model clouds and satellite observations. COSP contains several independent satellite simulators for better comparing model clouds with satellite measurements collected by the International Satellite Cloud Climatology Project (ISCCP), the Moderate Resolution Imaging Spectroradiometer (MODIS), the Multi-angle Imaging SpectroRadiometer (MISR), Cloud-Aerosol Lidar and Infrared Pathfinder Satellite Observation (CALIPSO), and CloudSat. The use of satellite simulators will not only make a fairer comparison between model clouds and satellite data but also allow a more in-depth analysis of clouds. For example, clouds can be assessed in terms of their optical properties and vertical location, which dictate their radiative effects. + +## Namelist parameters + +[COSP Namelist Parameters](../user-guide/namelist_parameters.md#cloud-feedback-model-intercomparison-project-cfmip-observation-simulator-package) + +## To turn on COSP outputs + +Run (add to the run script) the following command before running `./case.setup` + +`./xmlchange --id CAM_CONFIG_OPTS --append --val='-cosp'` + +| Related Outputs | Description | +| ------------------------- | ----------------------------------------------------------------- | +| `FISCCP1_COSP` | Grid-box fraction covered by each ISCCP D level cloud type | +| `CLMODIS` | MODIS Cloud Area Fraction | +| `CLD_MISR` | Cloud Fraction from MISR Simulator | +| `CLDTOT_CAL` | Calipso Total Cloud Fraction | +| `CLDHGH_CAL` | Calipso High-level Cloud Fraction | +| `CLDMED_CAL` | Calipso Mid-level Cloud Fraction | +| `CLDLOW_CAL` | Calipso Low-level Cloud Fraction | +| `CLD_CAL_TMPLIQ` | Calipso Liquid Cloud Fraction as a function of temperature | +| `CLD_CAL_TMPICE` | Calipso Ice Cloud Fraction as a function of temperature | diff --git a/components/eam/docs/tech-guide/dust.md b/components/eam/docs/tech-guide/dust.md new file mode 100644 index 00000000000..59f7cc3a966 --- /dev/null +++ b/components/eam/docs/tech-guide/dust.md @@ -0,0 +1,9 @@ +# Dust aerosol + +## Overview + +Dust-related processes are represented in the E3SM atmosphere and land model components. In E3SMv3, dust deposition will also be coupled with the sea ice and ocean biogeochemistry in the ocean model. Total emission fluxes of dust particles are calculated at each model time step. A new dust emission scheme following Kok et al. (2014)[@kok_improved_2014] is implemented to E3SMv3, replacing the Zender scheme (Zender et al., 2003)[@zender_mineral_2003] in E3SMv1 and v2 as the default option. The new dust emission scheme includes a time-varying soil erodibility factor for dust mobilization, and includes dust sources in high latitudes (e.g., >60 degree N). A manuscript by Feng et al. is in prep to document the performance of the new emission scheme on dust life cycle and radiative effects in E3SMv3. Dust aerosol is represented in the accumulation and coarse aerosol modes of the MAM4 module following emission. Other dust properties such as optical properties and size distribution at emission are documented in Feng et al. (2022).[@feng_global_2022] + +## Namelist parameters + +[Dust Namelist Parameters](../user-guide/namelist_parameters.md#dust-aerosol) diff --git a/components/eam/docs/tech-guide/homme.md b/components/eam/docs/tech-guide/homme.md new file mode 100644 index 00000000000..42561abde98 --- /dev/null +++ b/components/eam/docs/tech-guide/homme.md @@ -0,0 +1,11 @@ +# High-Order Methods Modeling Environment + +## Overview + +EAM uses the a dynamical core (dycore) from the High Order Method Modeling Environment (HOMME).[@taylor_compatible_2010,@guba_spectral_2014,@taylor_energy_2020] The EAM dycore solves the atmospheric primitive equations governing the evolution of velocity, density, pressure and temperature, as well as the transport of water species and related hydrometers, aerosols and other atmospheric constituents. The governing equations are written in a vertically lagrangian terrain following mass coordinate. They are discretized with second order finite differences in the radial direction and spectral finite elements in the horizontal (surface of the sphere) directions, and advanced in time with a 3rd order accurate 5 stage Runge-Kutta method. Dissipation is added through the use of monotoncity contraints on some advectiion terms, explicitly added hyperviscosity, and a Laplacian-based sponge layer in the first few layers at the model top. The transported species makes use of an efficient interpolatory semi-Lagrangian method. EAMv3 uses 80 layers in the vertical. The use of the spectral finite element method allows EAMv3 to run on fully unstructured grids, including the cubed-sphere grid ([SE Atmosphere Grid Overview (EAM & CAM)](https://acme-climate.atlassian.net/wiki/spaces/DOC/pages/34113147)) which provides quasi-uniform resolution over the globe, and regionally refined meshes (RRM) which enhance horizontal resolution in regions of interest ([Library of Regionally-Refined Model (RRM) Grids](https://acme-climate.atlassian.net/wiki/spaces/DOC/pages/3690397775)). + +## Namelist parameters + +Many dynamical core parameters can not be changed independently. For example, increasing the hyperviscosity coefficient may require reducing the hyperviscosity timestep. Dycore timesteps are tuned for each resolution and the defaults are close to the CFL stability limit. For complete details, as well as their interactions, see [EAM's HOMME dycore](https://acme-climate.atlassian.net/wiki/spaces/DOC/pages/1044644202/EAM+s+HOMME+dycore). + +[HOMME Namelist Parameters](../user-guide/namelist_parameters.md#homme) diff --git a/components/eam/docs/tech-guide/index.md b/components/eam/docs/tech-guide/index.md index 44a4f1921e2..437f5636edf 100644 --- a/components/eam/docs/tech-guide/index.md +++ b/components/eam/docs/tech-guide/index.md @@ -1 +1,31 @@ -start of the EAM Technical Guide +# EAM Technical Guide + +This Technical Guide describes the physics of version 3 of the E3SM Atmospheric Model + +## Dynamics and Physics + +- [HOMME](homme.md): Dynamical core. + +- [P3](p3.md): Stratiform cloud microphysics scheme. + +- [CLUBB](clubb.md): Parameterization of subgrid-scale turbulence and clouds. + +- [Zhang-McFarlane](zm.md): Deep convection parameterization. + +- [RRTMG](rrtmg.md): Parameterization of radiation. + +- [MAM](mam.md): Primary parameterization schemes used to represent aerosols. + +- [VBS](vbs.md): Parameterization of secondary organic aerosols. + +- [Dust](dust.md): Parameterization of dust emissions. + +- [OCEANFILMS](oceanfilms.md): Parameterization of sea soray irganic aerosol emissions. + +- [chemUCI + Linoz v3](chemUCIlinozv3.md): Interactive atmospheric chemistry packages. + +## Diagnostic outputs + +- [COSP](cosp.md): Scheme that allows the model to output satellite simulator output. + +- [ARM Diags](armdiags.md): Diagnostic package that allows the model output to be compared against ARM measurements. diff --git a/components/eam/docs/tech-guide/mam.md b/components/eam/docs/tech-guide/mam.md new file mode 100644 index 00000000000..99886682f46 --- /dev/null +++ b/components/eam/docs/tech-guide/mam.md @@ -0,0 +1,17 @@ +# Modal Aerosol Module + +## MAM5 Overview + +The Five-mode Modal Aerosol Model (MAM5) supersedes the MAM4 utilized in previous iterations of E3SM (E3SM-V1 and -V2). MAM5 introduces a fifth mode, specifically designed to represent stratospheric coarse mode aerosols, primarily originating from volcanic eruptions and DMS decomposition. This mode exclusively comprises sulfate aerosols, characterized by a smaller standard deviation (STD) value of 1.2. The STD value denotes the width of the aerosol mode, where a higher STD implies a greater gravitational settling effect (Wang et al., 2020;[@wang_aerosols_2020] Liu et al., 2012[@liu_toward_2012]). By setting the STD to 1.2, the simulated properties of volcanic aerosols align closely with observational findings (Mills et al., 2016).[@mills_global_2016] MAM5 represents a pioneering aerosol model, effectively segregating tropospheric and stratospheric aerosols (Ke et al., in preparation), thereby mitigating the risk of overestimating dust and sea salt aerosols within the stratosphere in previous MAM4 (Visioni et al., 2021).[@visioni_limitations_2022] Volcanic eruptions derived from Neely and Schmidt (2016).[@neely_iii_volcaneesm_2016] + +## MAM4 Overview + +The representation of atmospheric aerosols and their roles in the Earth system by EAMv1/v2/v3 was inherited from the global aerosol-climate model EAMv0 and its four-mode modal aerosol module (MAM4), including Aitken, primary-carbon, accumulation, and coarse modes (Liu et al., 2016).[@liu_description_2016] It treats a combination of processes, controlling the evolution of aerosols that are either directly emitted or converted from precursor gases from a variety of natural and anthropogenic sources. The processes include transport (by grid-scale wind, subgrid turbulence, convection, and sedimentation), aerosol microphysics (i.e., particle nucleation, condensation/evaporation of trace gases, aging, and coagulation), cloud processing (i.e., aqueous chemistry, scavenging by hydrometeors, resuspension from evaporating hydrometeors, and wet deposition), and dry deposition. Aerosol species in the original MAM4 (Liu et al., 2016)[@liu_description_2016] include sulfate, primary organic aerosol (POA) or particulate organic matter (POM), secondary organic aerosol (SOA), black carbon (BC), sea salt, and mineral dust. As described by Wang et al. (2020),[@wang_aerosols_2020] the enhanced MAM4 in EAMv1/v2 added marine organic aerosol (MOA) to all four modes (Burrows et al., 2022).[@burrows_oceanfilms_2022] In MAM4 of EAMv3, the Aitken mode has sulfate, sea salt, SOA and MOA; the primary-carbon mode has BC, POA and MOA; the accumulation and coarse modes include all seven species. Ammonium (NH4) and nitrate (NO3) aerosols are also explicitly treated in EAMv3 (Wu et al., 2022),[@wu_development_2022] as an optional feature for research, in which new species (NH4, NO3, Ca, CO3, Na, Cl) are introduced to the Aitken, accumulation and coarse modes. All aerosol species within each of the four individual modes the MAM4 is assumed to be internally mixed and represented by a single number concentration, while particles are externally mixed among the different modes. + +### Sea salt + +In MAM4, sea salt aerosol is represented in the Aitken, accumulation, and coarse mode with particle emission size (diameter) ranges of 0.02-0.08, 0.08-1.0, and 1.0-10.0 μm, respectively. The emission flux of natural sea salt is first divided into 31 size bins, following the parameterization of Mårtensson et al. (2003)[@martensson_laboratory_2003] and Monahan et al. (1986),[@monahan_model_1986] and then redistributed to the three MAM4 size modes. + +## Namelist parameters + +[MAM Namelist Parameters](../user-guide/namelist_parameters.md#modal-aerosol-module) diff --git a/components/eam/docs/tech-guide/oceanfilms.md b/components/eam/docs/tech-guide/oceanfilms.md new file mode 100644 index 00000000000..1ac45cfd799 --- /dev/null +++ b/components/eam/docs/tech-guide/oceanfilms.md @@ -0,0 +1,9 @@ +# OCEANFILMS + +## Overview + +E3SM (v1-v3) uses the OCEANFILMS (Organic Compounds from Ecosystems to Aerosols: Natural Films and Interfaces via Langmuir Molecular Surfactants) parameterization to represent sea spray organic aerosol emissions. OCEANFILMS is a physically based model that links sea spray chemistry with ocean biogeochemistry using a Langmuir partitioning approach. The underlying physical assumptions and parameterization are described in Burrows et al. (2014);[@burrows_physically_2014] the implementation in E3SM and impact on clouds and climate are documented in Burrows et al. (2022).[@burrows_oceanfilms_2022] + +## Namelist parameters + +[OCEANFILMS Namelist Parameters](../user-guide/namelist_parameters.md#oceanfilms) diff --git a/components/eam/docs/tech-guide/p3.md b/components/eam/docs/tech-guide/p3.md new file mode 100644 index 00000000000..af06aaa6aab --- /dev/null +++ b/components/eam/docs/tech-guide/p3.md @@ -0,0 +1,9 @@ +# Predicted Particle Properties + +## Overview + +The stratiform cloud microphysics scheme in v3 is Predicted Particle Properties (P3; Morrison & Milbrandt, 2015;[@morrison_parameterization_2015] Milbrandt & Morrison, 2016[@milbrandt_parameterization_2016]). P3 offers a new approach to representing the evolution of ice particles that is more physical than the traditional approach of using predefined ice categories. It has been implemented in E3SM (Wang et al., 2021)[@wang_impact_2021] to address the limitations in the original microphysics scheme- the lack of riming particles and the artificial conversion between ice crystals and snow particles. The current version in E3SM is a two-moment scheme with a single ice category (Morrison & Milbrandt, 2015).[@morrison_parameterization_2015] In addition to the total ice number and mass mixing ratios, P3 prognoses the rimed mass and rimed volume mixing ratios, which allows for the prediction of the continuous evolution of the rime fraction and particle density. It is worth noting that the ice nucleation parameterizations are changed to be aerosol-dependent in this study, with the heterogenous ice nucleation parameterizations from the Classical Nucleation Theory (Liu et al., 2012)[@liu_toward_2012] and the homogenous in-situ cirrus formation based on Liu and Penner (2005).[@liu_ice_2005] This differs from the P3 used in WRF and that used in the E3SM v1 in Wang et al. (2021)[@wang_impact_2021] where the heterogeneous ice nucleation parameterizations are temperature dependent only. + +## Namelist parameters + +[P3 Namelist Parameters](../user-guide/namelist_parameters.md#predicted-particle-properties) diff --git a/components/eam/docs/tech-guide/rrtmg.md b/components/eam/docs/tech-guide/rrtmg.md new file mode 100644 index 00000000000..7afa8df6122 --- /dev/null +++ b/components/eam/docs/tech-guide/rrtmg.md @@ -0,0 +1,9 @@ +# Rapid Radiative Transfer Model for GCMs + +## Overview + +The calculation of radiative energy flux through the atmosphere is done using the RRTMG radiation package (Iacono et al., 2008;[@iacono_radiative_2008] Mlawer et al., 1997[@mlawer_radiative_1997]). The details are consistent with the implementation in CAM5 described in Neale et al. (2012).[@neale_description_2012] Radiative fluxes are broadly split into shortwave and longwave and computed by separate codes. The shortwave solver uses the 2-stream approximation, while the longwave is an absorption/emission code. Both shortwave and longwave use the correlated k-distribution method for integration of fluxes. Subgrid cloud overlap is accounted for using the Monte Carlo Independent Column Approximation (MCICA; Pincus and Morcrette, 2003),[@pincus_fast_2003] assuming the cloudy portions of the column are maximally overlapped in vertically contiguous layers and randomly overlapped when two layers are separated by a completely clear layer. Cloud optics are parameterized as described in Neale et al.(2010).[@neale_description_2012] + +## Namelist parameters + +[RRTMG Namelist Parameters](../user-guide/namelist_parameters.md#rapid-radiative-transfer-model-for-gcms) diff --git a/components/eam/docs/tech-guide/vbs.md b/components/eam/docs/tech-guide/vbs.md new file mode 100644 index 00000000000..26535a89308 --- /dev/null +++ b/components/eam/docs/tech-guide/vbs.md @@ -0,0 +1,5 @@ +# Volatility Basis Set (VBS) approach for SOA + +## Overview + +A modified volatility basis set (VBS) approach is used for both SOA precursor gases and particulate SOA that includes gas‐phase functionalization/fragmentation and particle‐phase oligomerization similar to FragNVSOA configuration of Shrivastava et al. (2015).[@shrivastava_global_2015] It includes a detailed treatment of SOA precursor gas chemistry including multigenerational aging via fragmentation and functionalization reactions, particle‐phase oligomerization that generates low “effective volatility” SOA, and particle‐phase loss by photolysis. The sources of SOA include natural biogenic, anthropogenic and biomass burning organic gases that are oxidized to form lower volatility species and undergo dynamic gas-particle partitioning to form SOA. Biogenic SOA is formed by oxidation of isoprene (ISOP_VBS) and monoterpene (C10H16) volatile organic compounds (VOCs). Emissions of anthropogenic and biomass burning organic gases in the range of intermediate volatility organics (IVOCs, referred to as SOAG0) are estimated as total primary organic matter (POM) emitted from these sources multiplied by specified tunable factors. IVOCs undergo multigenerational aging with OH radicals forming SOA corresponding to anthropogenic and biomass burning sources. Photolysis of SOA is included as a chemical sink in the particle phase, in addition to dry and wet removal sinks. The photolysis rate constant of particle-phase SOA is assumed to be 0.04% of typical NO2 photolysis frequencies following Hodzic et al. (2016).[@hodzic_rethinking_2016] The emissions of VBS SOA related gas species and oxidants (prescribed) read from a file are documented in the [User Guide](../user-guide/index.md). diff --git a/components/eam/docs/tech-guide/zm.md b/components/eam/docs/tech-guide/zm.md new file mode 100644 index 00000000000..2e3c5b9b607 --- /dev/null +++ b/components/eam/docs/tech-guide/zm.md @@ -0,0 +1,27 @@ +# Zhang and McFarlane deep convection scheme + +## Overview + +The ZM scheme (Zhang and McFarlane, 1995)[@zhang_sensitivity_1995] used in E3SMv3 is a bulk mass flux-type scheme; it has three components: a trigger for convection initiation, a cloud model including both updrafts and downdrafts, and a closure. The original CAPE-based trigger for convection was replaced by a trigger function based on dynamic CAPE generation by Xie et al. (2019)[@xie_improved_2019] (see dCAPE-ULL description below for more details). The closure predicts cloud base mass flux using dilute CAPE (Neale et al., 2008).[@neale_impact_2008] The updraft model is a bulk entraining plume model. Both updrafts and downdrafts are assumed saturated, with downdraft mass flux at the downdraft initiation level set proportional to the updraft cloud base mass flux. The microphysical processes inside the updrafts are represented by a convective microphysics scheme (see ZM convective microphysics description below). An additional adjustment is made to cloud base mass flux to incorporate the effect of large-scale circulation (see mass flux adjustment description below). + +### dCAPE-ULL + +A notable update related to clouds and precipitation in E3SMv2 is the use of a new convective trigger function described by Xie et al. (2019)[@xie_improved_2019] in ZM to improve the simulation of precipitation and its diurnal cycle. The new convective trigger named as dCAPE-ULL uses the dynamic CAPE (dCAPE) trigger developed by Xie and Zhang (2000)[@xie_impact_2000] with an unrestricted air parcel launch level (ULL) approach used by Wang et al. (2015).[@wang_impacts_2015] It was designed to address the unrealistically strong coupling of convection to the surface heating in ZM that often results in unrealistically too active model convection during the day in summer season over lands and improve the model capability to capture mid-level convection for nocturnal precipitation. + +### ZM convective microphysics + +The convective microphysics scheme is based on the work of Song and Zhang (2011)[@song_microphysics_2011] to improve the representation of microphysical processes in convective clouds and their interaction with aerosol and stratiform clouds in GCMs. It explicitly treats the mass mixing ratio and number concentration of five hydrometeor species (cloud water, cloud ice, rain, snow, and graupel). The scheme is linked to stratiform cloud microphysics parameterization through convective detrainment of cloud liquid/ice water content and droplet/crystal number concentration, and to aerosols through cloud droplet activation and ice nucleation processes. Previous evaluations of the scheme showed that it improved the simulation of convective cloud properties and cloud hydrological cycle (Song et al., 2012;[@song_evaluation_2012] Storer et al., 2015[@storer_effects_2015]). The assessment demonstrates that the convective microphysics scheme not only significantly improves the simulation of tropical variability across multiple scales but also enhances the simulation of climatological mean states. + +### Mass flux adjustment + +The convective mass flux adjustment (MAdj) is designed to represent the dynamical effects of large-scale vertical motion on convection. With MAdj, convection is enhanced (suppressed) when there is large-scale ascending (descending) motion at the planetary boundary layer top. The coupling of convection with the large-scale circulation significantly improves the simulation of climate variability across multiple scales from diurnal cycle, convectively coupled equatorial waves, to Madden-Julian oscillations (Song et al., 2023).[@song_incorporating_2023] + +### MCSP + +Due to inadequate model resolution, organized mesoscale convection cannot be resolved in general circulation models and thus needs to be parameterized. The Multiscale Coherent Structure Parameterization (MCSP) aims at representing the dynamical and physical effects of organized mesoscale convection. + +MCSP applies a sinusoidal baroclinic profile in the temperature, moisture, and momentum fields to represent the impact. Moncrieff et al. (2017)[@moncrieff_simulation_2017] and Chen et al. (2021)[@chen_effects_2021] have found that by adding MCSP, the both the representation of large-scale precipitation systems and the modes of variability from Tropical waves are improved. + +## Namelist parameters + +[ZM Namelist Parameters](../user-guide/namelist_parameters.md#zhang-and-mcfarlane-deep-convection-scheme) diff --git a/components/eam/docs/user-guide/aerosol_phys_prop.md b/components/eam/docs/user-guide/aerosol_phys_prop.md new file mode 100644 index 00000000000..6d80565d971 --- /dev/null +++ b/components/eam/docs/user-guide/aerosol_phys_prop.md @@ -0,0 +1,111 @@ + +# Aerosol physical properties + +## Description + +Key information + +- Original physical properties of aerosols are documented in Liu et al. (2012).[@liu_toward_2012] Detailed information is included in the supplement. + +- Physical properties of aerosols used in E3SMv1 are documented in Wang et al. (2020).[@wang_aerosols_2020] + +- Marine organic aerosol properties are defined in Burrows et al. (2022).[@burrows_oceanfilms_2022] + +- Dust refractive index and longwave absorption coefficients are updated by Feng et al. (2022).[@feng_global_2022] + +- BC and POM hygroscopicity values are updated by Shan et al. (2024). + +- Physical properties of the fifth mode aerosols are documented by Ke et al. (2024). + +## Included fields + +### Mode properties + +- Geometric standard deviation of each lognormal mode + +- Nominal geometric mean diameter and its lower/upper bound of values for each mode + +- Coefficients of polynomial expression (lookup-table) for extinction, absorption, and asymmetry parameter calculations + +- Aerosol refractive index table needed for interpolation (lookup-table) calculation (for different wavelengths) + +- Crystalization and deliquesence relative humidity thresholds for aerosol wateruptake calculations + +### Species properties + +- Aerosol refractive index for each species + +- Density for each species + +- Aerosol hygroscopicity for each species + +- Note that some of variables in the species property file are for bulk aerosols, so we ignore the description for them. + +## Files + +Species properties + +```fortran +/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/sulfate_rrtmg_c080918.nc +/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/ocpho_rrtmg_c130709_kPOM0.04.nc +/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/ocphi_rrtmg_c100508.nc +/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/bcpho_rrtmg_c100508.nc +/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/dust_aeronet_rrtmg_c141106.nc +/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/ssam_rrtmg_c100508.nc +/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/poly_rrtmg_c130816.nc +``` + +Mode properties + +```fortran +/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/mam4_mode1_rrtmg_aeronetdust_c141106.nc', +/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/mam4_mode2_rrtmg_c130628.nc', +/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/mam4_mode3_rrtmg_aeronetdust_c141106.nc', +/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/mam4_mode4_rrtmg_c130628.nc', +/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/mam5_mode5_rrtmg_sig1.2_dgnl.40_c03072023.nc' +``` + +## Namelist + +```fortran + mode_defs = 'mam5_mode1:accum:=', + 'A:num_a1:N:num_c1:num_mr:+', + 'A:so4_a1:N:so4_c1:sulfate:/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/sulfate_rrtmg_c080918.nc:+', + 'A:pom_a1:N:pom_c1:p-organic:/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/ocpho_rrtmg_c130709_kPOM0.04.nc:+', + 'A:soa_a1:N:soa_c1:s-organic:/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/ocphi_rrtmg_c100508.nc:+', + 'A:bc_a1:N:bc_c1:black-c:/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/bcpho_rrtmg_c100508.nc:+', + 'A:dst_a1:N:dst_c1:dust:/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/dust_aeronet_rrtmg_c141106.nc:+', + 'A:ncl_a1:N:ncl_c1:seasalt:/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/ssam_rrtmg_c100508.nc:+', + 'A:mom_a1:N:mom_c1:m-organic:/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/poly_rrtmg_c130816.nc', + 'mam5_mode2:aitken:=', + 'A:num_a2:N:num_c2:num_mr:+', + 'A:so4_a2:N:so4_c2:sulfate:/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/sulfate_rrtmg_c080918.nc:+', + 'A:soa_a2:N:soa_c2:s-organic:/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/ocphi_rrtmg_c100508.nc:+', + 'A:ncl_a2:N:ncl_c2:seasalt:/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/ssam_rrtmg_c100508.nc:+', + 'A:mom_a2:N:mom_c2:m-organic:/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/poly_rrtmg_c130816.nc', + 'mam5_mode3:coarse:=', + 'A:num_a3:N:num_c3:num_mr:+', + 'A:dst_a3:N:dst_c3:dust:/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/dust_aeronet_rrtmg_c141106.nc:+', + 'A:ncl_a3:N:ncl_c3:seasalt:/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/ssam_rrtmg_c100508.nc:+', + 'A:so4_a3:N:so4_c3:sulfate:/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/sulfate_rrtmg_c080918.nc:+', + 'A:bc_a3:N:bc_c3:black-c:/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/bcpho_rrtmg_c100508.nc:+', + 'A:pom_a3:N:pom_c3:p-organic:/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/ocpho_rrtmg_c130709_kPOM0.04.nc:+', + 'A:soa_a3:N:soa_c3:s-organic:/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/ocphi_rrtmg_c100508.nc:+', + 'A:mom_a3:N:mom_c3:m-organic:/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/poly_rrtmg_c130816.nc', + 'mam5_mode4:primary_carbon:=', + 'A:num_a4:N:num_c4:num_mr:+', + 'A:pom_a4:N:pom_c4:p-organic:/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/ocpho_rrtmg_c130709_kPOM0.04.nc:+', + 'A:bc_a4:N:bc_c4:black-c:/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/bcpho_rrtmg_c100508.nc:+', + 'A:mom_a4:N:mom_c4:m-organic:/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/poly_rrtmg_c130816.nc', + 'mam5_mode5:strat_coarse:=', + 'A:num_a5:N:num_c5:num_mr:+', + 'A:so4_a5:N:so4_c5:sulfate:/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/sulfate_rrtmg_c080918.nc' + rad_climate = '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:/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/mam4_mode1_rrtmg_aeronetdust_c141106.nc', + 'M:mam5_mode2:/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/mam4_mode2_rrtmg_c130628.nc', + 'M:mam5_mode3:/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/mam4_mode3_rrtmg_aeronetdust_c141106.nc', + 'M:mam5_mode4:/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/mam4_mode4_rrtmg_c130628.nc', + 'M:mam5_mode5:/lcrc/group/e3sm/data/inputdata/atm/cam/physprops/mam5_mode5_rrtmg_sig1.2_dgnl.40_c03072023.nc' + +``` diff --git a/components/eam/docs/user-guide/emission_oxidant_files.md b/components/eam/docs/user-guide/emission_oxidant_files.md new file mode 100644 index 00000000000..72868b6b845 --- /dev/null +++ b/components/eam/docs/user-guide/emission_oxidant_files.md @@ -0,0 +1,196 @@ + +# Emission files for EAMv3 gas and aerosol species and oxidant file for VBS SOA and stratosphere sulfate formation + +## Overview + +This page documents emissions data for all required aerosols and precursor gases as well as oxidants input data for running EAMv3, mostly for the MAM4 aerosol scheme, from anthropogenic (i.e., industrial, energy, transportation, domestic, and agriculture activity sectors) and natural (i.e., sea spray, vegetation, fire smoke, volcano) sources. Sulfur from agriculture, domestic, transportation, waste, and shipping sectors is emitted at the surface while sulfur from energy and industry sectors is emitted at 100-300 m above the surface, and sulfur from forest fire and grass fire is emitted at higher elevations (0-6 km). POM and BC from forest fire and grass fire are emitted at 0-6 km, while those from other sources (domestic, energy, industry, transportation, waste, and shipping) are emitted at the surface. Injection height profiles for fire emissions are derived from the corresponding AeroCom profiles (Dentener et al., 2006)[@dentener_emissions_2006], which give emissions in 6 altitude ranges (0-0.1, 0.1-0.5, 0.5-1, 1-2, 2-3, and 3-6 km). Otherwise, species emissions are assumed to be at the surface (bottom layer). Number emission fluxes each mode are calculated from mass emission fluxes based on AeroCom prescribed lognormal size distributions. + +## Aerosols and gas precursors (common for EAMv1/v2/v3) + +* Species: SO2, SOAG0, DMS, bc_a4, pom_a4, so4_a1, so4_a2, num_a1, num_a2, num_a4 +* Data sources + * Most of the original data are directly from input4MIPs with the following exceptions (E3SM specific treatments) + * SO2 takes 97.5% from the input4MIPs data (all SO2-em-anthro_input4MIPs sectors) + * SO4_a1 surf takes 2.5% from the corresponding surface sectors of input4MIPs data (SO2-em-anthro_input4MIPs sectors: AGR, SLV, WST, SHP) + * SO4_a2 surf takes 2.5% from the corresponding surface sectors of input4MIPs data (SO2-em-anthro_input4MIPs sectors: TRA, RCO) + * SO4_a1 elev takes 2.5% from the corresponding elevated sectors of input4MIPs data (SO2-em-anthro_input4MIPs sectors: ENE, IND) + * SO2 (97.5%) and SO4_a1 (2.5%) also take emissions from AR5 input file for sector contvolc (constant volcanic degassing) + * SOAG0 emissions are obtained by scaling OC (POM) emissions with a tunable factor. + * num_a1, num_a2 and num_a4 are determined by mass concentration of aerosols species in the corresponding sectors and modes. + +## Marine organic sea spray + +Marine organic sea spray aerosol contributions are parameterized following the OCEANFILMS parameterization (E3SMv1; Burrows et al., 2014;[@burrows_physically_2014] 2022[@burrows_oceanfilms_2022]). The input file for this parameterization provides a climatology of the ocean surface concentrations of several groups of organic macromolecules. Briefly, the Parallel Ocean Program (POP; Maltrud et al., 1998)[@maltrud_global_1998] and its biogeochemical elemental cycling (BEC) routines (Moore et al., 2004)[@moore_upper_2004] were used to simulate marine biogeochemistry fields, including particulate organic matter (POC), chlorophyll, and zooplankton concentrations; these fields were used to generate maps of the estimated surface distributions of classes of macromolecules following the methods described in Burrows et al. (2014).[@burrows_physically_2014] The scripts used to accomplish this translation are available [here](https://github.com/E3SM-Project/PreAndPostProcessingScripts/blob/devel/prepare_model_inputfiles/emis/marine_organic_aerosol/JAN_1850_MASTERLANG.jnl). + +The file used as an input to E3SM is available here: +[https://web.lcrc.anl.gov/public/e3sm/inputdata/atm/cam/chem/trop_mam/marine_BGC/monthly_macromolecules_0.1deg_bilinear_latlon_year01_merge_date.nc](https://web.lcrc.anl.gov/public/e3sm/inputdata/atm/cam/chem/trop_mam/marine_BGC/monthly_macromolecules_0.1deg_bilinear_latlon_year01_merge_date.nc) + +And is also published as a citeable dataset on Zenodo: + +Elliott, S. M., Maltrud, M., & Burrows, S. M. (2015). Macromolecule distributions input file for the OCEANFILMS parameterization (Version v1) [Data set]. [Zenodo](https://doi.org/10.5281/zenodo.6320812). + +## Oceanic dimethyl sulfide concentrations + +Dimethyl sulfide (DMS) fluxes to the atmosphere are calculated in E3SM as a function of prescribed surface oceanic DMS concentrations, and an air-sea flux piston velocity that is a function of wind speed. + +E3SM uses a DMS surface concentration dataset developed from a dynamic ocean biogeochemistry simulation; the methods and underlying assumptions used to produce this dataset are documented in Wang, et al. (2015). The resolution in the DMS dataset is 1.9x2.5 degrees. + +## New gas species for chemUCI in EAMv3 + +* Species: C2H4, C2H6, C3H8, CH2O, CH3CHO, CH3COCH3, CO, E90, ISOP, NO, NO2 +* Data sources + * anthropogenic, biomass burning, and aircraft emissions (NO2) are regridded from NCAR CESM2 emission files. They are time-dependent during historical period and in the future scenarios. + * biogenic emissions (C2H4, C2H6, C3H8, CH2O, CH3CHO, CH3COCH3, CO, ISOP) are from MEGAN-MACC offline data + * 1850-1979: monthly input cycled yearly from 30-year mean (1980-2009) + * 1980-2014: time-varying MEGAN-MACC data (historical) + * 2015-2100: monthly input cycled yearly from 30-year mean (1980-2009) + * natural emissions from oceans (C2H4, C2H6, C3H8, CO) and soil (NO) are regridded from NCAR CESM2 emission files. Just cycled yearly during the historical period and in the future scenarios. + * E90 emissions? + +## Oxidants file needed for VBS SOA and stratosphere sulfate formation + +* Species: prsd_O3, prsd_NO3, prsd_OH +* Data sources + * the file for historical simulation is the same as v1 and v2, inherited from CESM + * files for SSPs are regridded from NCAR CESM2 tracer files + +## Namelist setting for emissions input + +### Historical (WCYCL20TR)/AMIP (F20TR) + +```fortran + ext_frc_specifier = 'NO2 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_NO2_aircraft_vertical_1750-2015_1.9x2.5_c20170608.nc', + 'SO2 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so2_elev_1850-2014_c180205_kzm_1850_2014_volcano.nc', + 'SOAG0 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/emissions-cmip6_e3sm_SOAG0_elev_1850-2014_1.9x2.5_c20230201.nc', + 'bc_a4 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_bc_a4_elev_1850-2014_c180205.nc', + 'num_a1 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a1_elev_1850-2014_c180205.nc', + 'num_a2 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a2_elev_1850-2014_c180205.nc', + 'num_a4 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a4_elev_1850-2014_c180205.nc', + 'pom_a4 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_pom_a4_elev_1850-2014_c180205.nc', + 'so4_a1 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a1_elev_1850-2014_c180205.nc', + 'so4_a2 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a2_elev_1850-2014_c180205.nc' + + srf_emis_specifier = 'C10H16 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_MTERP_surface_1850-2014_1.9x2.5_c20230126.nc', + 'C2H4 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C2H4_surface_1850-2014_1.9x2.5_c20210323.nc', + 'C2H6 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C2H6_surface_1850-2014_1.9x2.5_c20210323.nc', + 'C3H8 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C3H8_surface_1850-2014_1.9x2.5_c20210323.nc', + 'CH2O -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH2O_surface_1850-2014_1.9x2.5_c20210323.nc', + 'CH3CHO -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH3CHO_surface_1850-2014_1.9x2.5_c20210323.nc', + 'CH3COCH3 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH3COCH3_surface_1850-2014_1.9x2.5_c20210323.nc', + 'CO -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CO_surface_1850-2014_1.9x2.5_c20210323.nc', + 'DMS -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DMSflux.1850-2100.1deg_latlon_conserv.POPmonthlyClimFromACES4BGC_c20160727.nc', + 'E90 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions_E90_surface_1750-2015_1.9x2.5_c20210408.nc', + 'ISOP -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_ISOP_surface_1850-2014_1.9x2.5_c20210323.nc', + 'ISOP_VBS -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_ISOP_surface_1850-2014_1.9x2.5_c20210323.nc', + 'NO -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_NO_surface_1850-2014_1.9x2.5_c20220425.nc', + 'SO2 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so2_surf_1850-2014_c180205.nc', + 'SOAG0 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/emissions-cmip6_e3sm_SOAG0_surf_1850-2014_1.9x2.5_c20230201.nc', + 'bc_a4 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_bc_a4_surf_1850-2014_c180205.nc', + 'num_a1 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a1_surf_1850-2014_c180205.nc', + 'num_a2 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a2_surf_1850-2014_c180205.nc', + 'num_a4 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a4_surf_1850-2014_c180205.nc', + 'pom_a4 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_pom_a4_surf_1850-2014_c180205.nc', + 'so4_a1 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a1_surf_1850-2014_c180205.nc', + 'so4_a2 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a2_surf_1850-2014_c180205.nc' + + tracer_cnst_datapath = '\$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/oxid' + tracer_cnst_file = 'oxid_1.9x2.5_L26_1850-2015_c20181106.nc' + tracer_cnst_filelist = '' + tracer_cnst_specifier = 'prsd_O3:O3','prsd_NO3:NO3','prsd_OH:OH' + tracer_cnst_type = 'INTERP_MISSING_MONTHS' +``` + +### F2010 + +```fortran + ext_frc_cycle_yr = 2010 + ext_frc_specifier = 'NO2 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_NO2_aircraft_vertical_2010_clim_1.9x2.5_c20230213.nc', + 'SO2 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so2_elev_1x1_2010_clim_c20190821.nc', + 'SOAG0 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/emissions-cmip6_e3sm_SOAG0_elev_2010_clim_1.9x2.5_c20230213.nc', + 'bc_a4 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_bc_a4_elev_1x1_2010_clim_c20190821.nc', + 'num_a1 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a1_elev_1x1_2010_clim_c20190821.nc', + 'num_a2 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a2_elev_1x1_2010_clim_c20190821.nc', + 'num_a4 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a4_elev_1x1_2010_clim_c20190821.nc', + 'pom_a4 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_pom_a4_elev_1x1_2010_clim_c20190821.nc', + 'so4_a1 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a1_elev_1x1_2010_clim_c20190821.nc', + 'so4_a2 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a2_elev_1x1_2010_clim_c20190821.nc' + ext_frc_type = 'CYCLICAL' + + srf_emis_cycle_yr = 2010 + srf_emis_specifier = 'C10H16 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_MTERP_surface_2010_clim_1.9x2.5_c20230213.nc', + 'C2H4 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C2H4_surface_2010_clim_1.9x2.5_c20230213.nc', + 'C2H6 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C2H6_surface_2010_clim_1.9x2.5_c20230213.nc', + 'C3H8 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_C3H8_surface_2010_clim_1.9x2.5_c20230213.nc', + 'CH2O -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH2O_surface_2010_clim_1.9x2.5_c20230213.nc', + 'CH3CHO -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH3CHO_surface_2010_clim_1.9x2.5_c20230213.nc', + 'CH3COCH3 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CH3COCH3_surface_2010_clim_1.9x2.5_c20230213.nc', + 'CO -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_CO_surface_2010_clim_1.9x2.5_c20230213.nc', + 'DMS -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DMSflux.2010.1deg_latlon_conserv.POPmonthlyClimFromACES4BGC_c20190220.nc', + 'E90 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions_E90_surface_2010_clim_1.9x2.5_c20230213.nc', + 'ISOP -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_ISOP_surface_2010_clim_1.9x2.5_c20230213.nc', + 'ISOP_VBS -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_ISOP_surface_2010_clim_1.9x2.5_c20230213.nc', + 'NO -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/chem_gases/2degrees/emissions-cmip6_e3sm_NO_surface_2010_clim_1.9x2.5_c20230213.nc', + 'SO2 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so2_surf_1x1_2010_clim_c20190821.nc', + 'SOAG0 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/emissions-cmip6_e3sm_SOAG0_surf_2010_clim_1.9x2.5_c20230213.nc', + 'bc_a4 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_bc_a4_surf_1x1_2010_clim_c20190821.nc', + 'num_a1 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a1_surf_1x1_2010_clim_c20190821.nc', + 'num_a2 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a2_surf_1x1_2010_clim_c20190821.nc', + 'num_a4 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_num_a4_surf_1x1_2010_clim_c20190821.nc', + 'pom_a4 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_pom_a4_surf_1x1_2010_clim_c20190821.nc', + 'so4_a1 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a1_surf_1x1_2010_clim_c20190821.nc', + 'so4_a2 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DECK_ne30/cmip6_mam4_so4_a2_surf_1x1_2010_clim_c20190821.nc' + srf_emis_type = 'CYCLICAL' + + tracer_cnst_cycle_yr = 2015 + tracer_cnst_datapath = '\$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/oxid' + tracer_cnst_file = 'oxid_1.9x2.5_L26_1850-2015_c20181106.nc' + tracer_cnst_filelist = '' + tracer_cnst_specifier = 'prsd_O3:O3','prsd_NO3:NO3','prsd_OH:OH' + tracer_cnst_type = 'CYCLICAL' + ``` + +### Future Scenarios + +#### SSP370 + +```fortran +ext_frc_specifier = 'NO2 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_NO2_aircraft_vertical_2015-2100_1.9x2.5_c20240208.nc', + 'SO2 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_so2_elev_2015-2100_c210216.nc', + 'SOAG0 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_SOAG0_elev_2015-2100_1.9x2.5_c20240208.nc', + 'bc_a4 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_bc_a4_elev_2015-2100_c210216.nc', + 'num_a1 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_num_a1_elev_2015-2100_c210216.nc', + 'num_a2 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_num_a2_elev_2015-2100_c210216.nc', + 'num_a4 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_num_a4_elev_2015-2100_c210216.nc', + 'pom_a4 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_pom_a4_elev_2015-2100_c210216.nc', + 'so4_a1 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_so4_a1_elev_2015-2100_c210216.nc', + 'so4_a2 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_so4_a2_elev_2015-2100_c210216.nc' + +srf_emis_specifier = 'C10H16 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_MTERP_surface_2015-2100_1.9x2.5_c20240208.nc', + 'C2H4 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_C2H4_surface_2015-2100_1.9x2.5_c20240208.nc', + 'C2H6 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_C2H6_surface_2015-2100_1.9x2.5_c20240208.nc', + 'C3H8 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_C3H8_surface_2015-2100_1.9x2.5_c20240208.nc', + 'CH2O -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_CH2O_surface_2015-2100_1.9x2.5_c20240208.nc', + 'CH3CHO -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_CH3CHO_surface_2015-2100_1.9x2.5_c20240208.nc', + 'CH3COCH3 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_CH3COCH3_surface_2015-2100_1.9x2.5_c20240208.nc', + 'CO -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_CO_surface_2015-2100_1.9x2.5_c20240208.nc ', + 'DMS -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DMSflux.1850-2100.1deg_latlon_conserv.POPmonthlyClimFromACES4BGC_c20160727.nc', + 'E90 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart/ub/emissions_E90_surface_1750-2101_1.9x2.5_c20231222.nc', + 'ISOP -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_ISOP_surface_2015-2100_1.9x2.5_c20240208.nc', + 'ISOP_VBS -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_ISOP_surface_2015-2100_1.9x2.5_c20240208.nc', + 'NO -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_NO_surface_2015-2100_1.9x2.5_c20240208.nc', + 'SO2 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_so2_surf_2015-2100_c210216.nc', + 'SOAG0 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_SOAG0_surf_2015-2100_1.9x2.5_c20240208.nc', + 'bc_a4 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_bc_a4_surf_2015-2100_c210216.nc', + 'num_a1 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_num_a1_surf_2015-2100_c210216.nc', + 'num_a2 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_num_a2_surf_2015-2100_c210216.nc', + 'num_a4 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_num_a4_surf_2015-2100_c210216.nc', + 'pom_a4 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_pom_a4_surf_2015-2100_c210216.nc', + 'so4_a1 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_so4_a1_surf_2015-2100_c210216.nc', + 'so4_a2 -> \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_so4_a2_surf_2015-2100_c210216.nc' + + tracer_cnst_datapath = '\$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/oxid' + tracer_cnst_file = 'oxid_SSP370_1.9x2.5_L70_1849-2101_c20240228.nc' + tracer_cnst_filelist = '' + tracer_cnst_specifier = 'prsd_O3:O3','prsd_NO3:NO3','prsd_OH:OH' + tracer_cnst_type = 'INTERP_MISSING_MONTHS' +``` diff --git a/components/eam/docs/user-guide/index.md b/components/eam/docs/user-guide/index.md index 81084e869cd..c2bd7f06538 100644 --- a/components/eam/docs/user-guide/index.md +++ b/components/eam/docs/user-guide/index.md @@ -1 +1,175 @@ -start of the EAM User's Guide + +# EAM User Guide + +This User Guide describes how to set up and run EAM. + +## Steps to build and run EAM + +EAM is not available as a standalone model. Instead, EAM can be run in an atmosphere-only configuration. +The difference when running in atmosphere-only mode (without an interactive ocean or sea-ice) would be to +change the *compset* and *grid*. +See the +[Case Control System Basic Usage](https://esmci.github.io/cime/versions/master/html/users_guide/index.html#case-control-system-part-1-basic-usage) for general descriptions of compsets and grids. + +Certain namelist paramaters, input data files, and output file specifcations can also be modified. +These are described below as ways to customize runs. + +Step-by-step instructions on how to run and analyze E3SM with a script can be found at +[E3SM step-by-step guide](https://docs.e3sm.org/running-e3sm-guide/) + +## Scientifically supported compsets and grids + +### Compsets + +All of the compsets below run with the complete set of E3SM atmospheric configuration of EAMV3. For more information on the schemes in EAMv3, see the [Technical Guide](../tech-guide/index.md) + +`F2010` - Climatological present day climate (year 2010) + +`F1850` - Climatological pre-industrial-day climate (year 1850) + +`F20TR` - Historical EAM simulation with time varying sea-surface temperatures, aerosol emissions, and greenhouse gas forcings (year 1850-2014) + +### Grids + +Only one grid combination is currently supported for the above compsets: + +`ne30pg2_r05_IcoswISC30E3r5` - ne30pg2 atmosphere, 0.5deg x 0.5deg land grid, and Icosahedral 30 km mesh with ice shelves cavities (wISC), E3SMv3 (E3) revision r5 + +## Customizing runs + +### Compile-time options + +Some customizations require making changes before the model is built. + +### Run-time options + +Run-time customization is enabled by a Fortran namelist. + +Namelist parameters can be changed from default values by putting them in the `user_nl_eam` file in the case directory +with the desired new value. + +This [Table of Namelist Parameters](namelist_parameters.md) includes many of the paramaters that control +physics schemes described in the [tech-guide](../tech-guide/index.md) + +#### History File Namelist Parameters + +By default, EAM will output a set of monthly-averaged variables. Additional output files can be specified using the following flags in the `user_nl_eam` file: + +`finclX` - List of variables (in single quotes and separated by commas) that are added to tape X. + +`fexclX` - List of variables (in single quotes and separated by commas) that will be excluded in tape X. + +`nhtfrq` - List of write frequencies for each of the history files. A value of 0 denotes a monthly frequency. Negative values denote hourly frequencies (e.g., `-3` will write an output every 3 hours). Positive values denotes the frequency in model timesteps (e.g., `4` will write an output every 4 timesteps). + +`mfilt` - List that sets the number of timesteps to write in a single file before starting a new file. + +`avgflag_pertape` - List that sets the type of output to write. Choices are `'A'` for time-averaged output, `'A'` for instantaneous output, `'M'` for time-minimum output, and `'X'` for time-maximum output. + +#### Example output specification + +```fortran +nhtfrq = 0,-24,-6,-3 +mfilt = 1,30,120,24 +avgflag_pertape = 'A','A','A','I' + +fexcl1 = 'U10' # Removes U10 output from monthly files +fincl2 = 'PS','FLUT','PRECT','U200','V200','U850', + 'V850','TCO','SCO','TREFHT','QREFHT' # Output files of daily-averaged output, which includes 30 days of output in each file +fincl3 = 'PS', 'PSL','PRECT','TUQ','TVQ','UBOT', + 'VBOT','TREFHT','FLUT','OMEGA500','TBOT', + 'U850','V850','U200','V200','T200','T500', + 'Z700' # Output files of 6-hour-averaged output, which includes 30 days of output in each file +fincl4 = 'PRECT' # Output files of 3-hourly output with 3 days of output in every file +``` + +## Input datasets + +Many properties of the simulated atmosphere are controlled by data sets read in by the model during initialization. +Changing the content of these files is another way to customize a run. + +### Greenhouse gases (non-reacting) + +Greenhouse gas concentration inputs of non-reacting species are taken from CMIP6 Forcing Datasets provided from the input4MIPs data collection. In addition to what is provided by the input4MIPS, 2015 and 2016 have been added by extrapolating from 2013 and 2014. + +```fortran +inputdata/atm/cam/ggas/GHG_CMIP-1-2-0_Annual_Global_0000-2014_c20180105.nc +``` + +### [Aerosol physical properties](aerosol_phys_prop.md) + +The aerosol properties files provide aerosol refractive index, density, and aerosol hygroscopicty information for +each aerosol species, as well as information about lognormal mode definition and lookup tables of polynomial +expression coefficients for aerosol optics calculation for each mode. These aerosol physical and chemical properties +are used by the radiation, aerosol microphysics and other related source and sink processes, and droplet +activation/ice nucleation schemes. + +### [Aerosol and gas emission and oxidant files](emission_oxidant_files.md) + +Details of the aerosol and gas emission and oxidant files used in various historical, present-day, and future scenarios. + +### Linoz v3 input files + +Linozv3 uses the ozone tendency, (net production minus loss) calculated from its climatological mean state (function of month, latitude, altitude) and a first-order Taylor series expansion about the local ozone, temperature, and overhead ozone column. For historical simulation, Linozv3 uses the linozv3 data files with monthly resolution, spanning the dates 1849-01 -- 2014-12. + +#### Historical files + +```fortran + linoz_data_file = ‘linv3_1849-2101_CMIP6_Hist_10deg_58km_c20231207.nc’ + linoz_data_path = '/lcrc/group/e3sm/data/inputdata/atm/cam/chem/trop_mozart/ub' + linoz_data_type = 'INTERP_MISSING_MONTHS' +``` + +Refer to [this page](https://acme-climate.atlassian.net/wiki/spaces/DOC/pages/3764486280/Production+of+the+Linoz+v3+data) for more details on Linoz v3 input files. + +### Topography + +The global elevation on the atmosphere grid is a key input dataset. The dataset is grid dependent. It contains the geopotential data (on both the GLL dynamics and PG2 physics grids) and two surface roughness quantities, `SGH` and `SGH30`. + +EAMv3 NE30 data: + +```fortran +inputdata/atm/cam/topo/USGS-gtopo30_ne30np4pg2_x6t-SGH.c20210614.nc' +``` + +This file is computed via a complex procedure that starts with high resolution dataset (for EAMv3, we use the GTOPO30, a 30 arc-second resolution data set on a lat-lon grid) that is then downsampled to a 3km cubed-sphere grid (cube3000) and then downsampled to the atmosphere grid on the (GLL nodes), and then smoothed with the same viscosity operator used by the dycore. The smoothed GLL topography is then mapped to the PG2 grid. Finally, two different surface roughness fields are computed: + +- `SGH30`: the variance between GTOPO30 and GTOPO30-downsampled-to-PG2 (independent of any dycore specific smoothing). (used by CLUBB, TMS, vertical_diffusion) +- `SGH`: the variance between the cube3000 data and the smoothed PG2 data. (used by GWD parameterizations) + +### Land-use / land cover change + +Info needed on land-use land cover change / land surface data + +Refer to [ELM documentation](https://docs.e3sm.org/E3SM/ELM/). + +### Ocean/sea ice + +The sea surface temperature and sea-ice coverage data used in F-case simulations are based on CMIP6 Forcing Datasets provided from the input4MIPs data collection. The file for the `F2010` compset is created from taking a monthly climatology of years 2005-2014. The file for the `F1850` compset is created from taking a monthly climatology of years 1870-1879.* + +*[Provenenance for F1850 file](https://acme-climate.atlassian.net/wiki/spaces/ATM/pages/201525378/Provenance+for+CMIP6+DECK+SST+Sea-Ice+input+data+for+E3SM) + +`F20TR` + +```fortran +inputdata/ocn/docn7/SSTDATA/sst_ice_CMIP6_DECK_E3SM_1x1_c20180213.nc +``` + +`F2010` + +```fortran +inputdata/ocn/docn7/SSTDATA/sst_ice_CMIP6_DECK_E3SM_1x1_2010_clim_c20190821.nc +``` + +`F1850` + +```fortran +inputdata/ocn/docn7/SSTDATA/sst_ice_CMIP6_DECK_E3SM_1x1_1850_clim_c20190125.nc +``` + +### Solar input + +As with greenhouse gas emissions, solar input files are taken from the input4MIPs data collection that were prepared for CMIP6 Forcing Datasets. + +```fortran +inputdata/atm/cam/solar/Solar_1850-2299_input4MIPS_c20181106.nc +``` diff --git a/components/eam/docs/user-guide/namelist_parameters.md b/components/eam/docs/user-guide/namelist_parameters.md new file mode 100644 index 00000000000..b09e8c44ffd --- /dev/null +++ b/components/eam/docs/user-guide/namelist_parameters.md @@ -0,0 +1,158 @@ + +# Namelist parameters associated with atmosphere schemes + +## chemUCI and Linoz v3 + +| Parameter | Description | Default value* | +| ---------------------------- | ------------------------------------------------------------------------ | ---------------------- | +| `airpl_emis_file` | Aviation emission | | +| `chlorine_loading_file` | Chlorine loading | | +| `chlorine_loading_fixed_ymd` | | | +| `chlorine_loading_type` | | | +| `ext_frc_specifier` | 3-D emissions | | +| `ext_frc_cycle_yr` | | | +| `ext_frc_type` | | | +| `srf_emis_specifier` | Surface emissions | | +| `srf_emis_cycle_yr` | | | +| `srf_emis_type` | Upper bound of mean raindrop diameter | | +| `linoz_data_file` | Linoz data file | | +| `linoz_data_cycle_yr` | | | +| `linoz_data_path` | | | +| `linoz_data_type` | | | +| `lght_no_prd_factor` | Lightning NOx emission factor | `5.0` | +| `fstrat_efold_list` | Tracer (from troposphere) list with e-folding decay in the stratosphere | | + +* Many of these namelist parameters specify input data files. Check the `atm_in` file for examples or refer to the [Users' Guide](../user-guide/index.md). + +## Cloud Layers Unified By Binormals + +| Parameter | Description | Default value | +| -------------- | ------------------------------------------------------------------------------------------- | -------------- | +| `gamma_coef` | Width of vertical velocity within a Gaussian PDF component at low skewness | `0.12` | +| `gamma_coefb` | Width of vertical velocity within a Gaussian PDF component at high skewness | `0.28` | +| `C8` | Coefficient of damping of third moment of vertical velocity, w’3 | `5.2` | +| `C1` | Coefficient of damping of second vertical moment of vertical velocity, w’2, at low skewness | `2.4` | +| `C14` | Coefficient of damping of second horizontal moments of vertical velocity, u’2 and v’2 | `2.0` | +| `c_k10` | Ratio of diffusivity of momentum to heat | `0.35` | + +## Dust aerosol + +| Parameter | Description | Default value | +| ------------------------- | ---------------------------------------------- | ------------------------------------------------- | +| `dust_emis_scheme`* | The v3 dust emission scheme (Kok et al., 2014) | `2`
(set to 1 to switch to the v1/v2 scheme) | + +*This parameter is set in `user_nl_drv` + +## HOMME + +| Parameter | Description | Default value | +| ---------------- | ------------------------------------------------------------------------------------------- | -------------- | +| `se_tstep` | Main dycore timestep. Additional parameters control the hyper viscsosity, trancer and vertical remap timesteps, which are derived from se_tstep.
units = seconds | Scales linearly with horizontal resolution.
NE30 default: `300` | +| `nu` | Tensor hyperviscosity coefficient, independent of spatial resolution.
units = 1/s | `3.4e-8` | +| `nu_top` | Scalar viscosity at model top.
units = m^2/s | Horizontal resolution dependent
NE30 default: `2.5e5` | +| `transport_alg` | Select between semi-lagrangian and Eulerian based transport schemes | `12` = semi-lagranian method with monotinicity and mass preservation | +| `statefreq` | print a varieity of dycore metrics to the atm.log file every “statefreq” timesteps | `480` | +| `vert_remap_alg` | Algorithm used to remap the vertically lagrangian levels back to the reference levels | `10` = strict monotonicity applied on top of a 2nd order accurate PPM method | +| `se_ftype` | Controls how physics tendencies are applied. 0=”dribbled” in during dynamics timesteps. 1=”hard adjustment” after each physics timestep. 2=hybrid approach: hard adjustment for tracers, dribbled for remaining tendencies | `2` | + +## Modal Aerosol Module + +| Parameter | Description | Default value | +| ------------------------ | ----------------------------------------------------------------------------------- | --------------------------- | +| `is_output_interactive_volc` | Switch for diagnostic output of the stratospheric aerosol optics | `.false.` | +| `mam_amicphys_optaa` | Recommended option of the new time-splitting treatment of H2SO4 production and loss | `1`
(0 to turn it off) | +| `n_so4_monolayers_pcage` | Number of monolayers required to age primary-carbon mode particles | `3` | +| `seasalt_emis_scale` | Tuning parameter for sea salt emission | `0.55` | + +## OCEANFILMS + +| Parameter | Description | Default value | +| ------------------------- | ----------------------------------------------------------------- | ---------------------- | +| `mam_mom_cycle_yr` | | `1` | +| `mam_mom_datapath` | Full pathname of the directory that contains the files specified in mam_mom_filelist | `'atm/cam/chem/trop_mam/marine_BGC/'` | +| `mam_mom_filename` | Filename of file that contains a sequence of filenames for prescribed marine organic matter ocean concentrations. The filenames in this file are relative to the directory specified by mam_mom_datapath.| `'monthly_macromolecules_0.1deg_bilinear_latlon_year01_merge_date.nc'` | +| `mam_mom_rmfile` | Remove the file containing prescribed aerosol deposition fluxes from local disk when no longer needed. | `FALSE` | +| `mam_mom_specifier` | Names of variables containing aerosol data in the prescribed aerosol datasets. | `'chla:CHL1','mpoly:TRUEPOLYC','mprot:TRUEPROTC','mlip:TRUELIPC'` | +| `mam_mom_datatype` | Type of time interpolation for data in mam_mom files. Can be set to `'CYCLICAL'`, `'SERIAL'`, `'INTERP_MISSING_MONTHS'`, or `'FIXED'`. | `'CYCLICAL'` | +| `mam_mom_cycle_yr` | The cycle year of the prescribed aerosol flux data if mam_mom_type is `'CYCLICAL'`. Format: YYYY | `1` | +| `mam_mom_fixed_ymd` | The date at which the prescribed aerosol flux data is fixed if mam_mom_type is `'FIXED'`. Format: YYYYMMDD | `0` | +| `mam_mom_fixed_tod` | The time of day (seconds) corresponding to mam_mom_fixed_ymd at which the prescribed aerosol flux data is fixed if mam_mom_type is 'FIXED'. | `0` | +| `mam_mom_bubble_thickness` | Bubble film thickness (in m) for marine organic aerosol emission mechanism. The physically reasonable range is approximately (0.1 - 1) x 10^ -6. | `0.1e-6` | +| `mam_mom_mixing_state` | Switch to select mixing state assumption in marine organic aerosol code. Currently implemented options: 0 : total external mixture, add to mass; 1 : total external mixture, replace mass; 2 : total internal mixture, add to mass; 3 : total internal mixture, replace mass. | `0` [Note: set to 3 in the atm_in namelist] | +| `mam_mom_parameterization` | Selection of alternate parameterizations for marine organic matter emissions. Set fmoa=1 for Burrows et al. (2014) [@burrows_physically_2014] parameterization; fmoa=2 for Gantt et al. (2011) [@gantt_wind_2011] parameterization; fmoa=3 for simple parameterization based on Quinn et al., 2014; [@quinn_contribution_2014] fmoa=4 for Rinaldi et al. (JGR, 2013).* [@rinaldi_is_2013] | `1` | + +*Note: non-default values have not been carefully tested and may not work as expected. + +## Predicted Particle Properties + +| Parameter | Description | Default value | +| ------------------------- | ----------------------------------------------------------------- | ---------------------- | +| `do_prescribed_ccn` | Turn on the prescribed CCN if true | `false` | +| `micro_aerosolactivation` | Turn on aerosol activation if true | `true` | +| `micro_p3_lookup_dir` | Directory of P3 look-up tables | `inputdata/atm/cam/physprops` | +| `micro_p3_tableversion` | P3 look-up table Version | `4.1.2` | +| `micro_subgrid_cloud` | Sub-grid cloud properties | `true` | +| `micro_tend_output` | Output of P3 microphysical process rates | `false` | +| `p3_accret_coeff` | Tunable parameter for adjusting rain accretion efficiency | `117.25` | +| `p3_autocon_coeff` | Tunable parameter for adjusting droplet autoconversion efficiency | `30500` | +| `p3_embryonic_rain_size` | Radius of embryomic raindrops from auto-conversion | `0.000025` (m) | +| `p3_max_mean_rain_size` | Upper bound of mean raindrop diameter | `0.005` (m) | +| `p3_mincdnc` | Lower bound of droplet number concentration | `20.d6` (# m-3) | +| `p3_nc_autocon_expon` | Nc exponent in droplet auto-conversion | `-1.1` | +| `p3_qc_accret_expon` | Qc exponent in rain accretion | `1.15` | +| `p3_qc_autocon_expon` | Qc exponeent in droplet autoconversion | `3.19` | +| `p3_wbf_coeff` | Tunable parameter for adjusting WBF efficiency | `1.0` | +| `do_cooper_inp3` | Turn on Cooper ice nucleation scheme if true | `false` | + +## Rapid Radiative Transfer Model for GCMs + +| Parameter | Description | Default value | +| ------------------------- | ----------------------------------------------------------------- | ---------------------- | +| `iradsw` | Frequency for updating shortwave fluxes and heating rate; iradsw > 0 interpreted as number of timesteps, iradsw < 0 interpreted as hours; iradsw = 0 disables shortwave radiation entirely | `-1` | +| `iradlw` | Frequency for updating longwave fluxes and heating rate; iradlw > 0 interpreted as number of timesteps, iradlw < 0 interpreted as hours; iradlw = 0 disables longwave radiation entirely | `-1` | +| `irad_always` | Length of time in timesteps (irad_always > 0) or in hours (irad_always < 0) SW/LW radiation will be run continuously from the start of an initial or restart run | `0` | +| `use_rad_dt_cosz` | If true, use the radiation dt for all cosz calculations; calculates solar zenith angle averaged over a time step. In default model solar zenith angle is held constant over time | `.true.`
(set by namelist_defaults_eam.xml for default physics) | +| `spectralflux` | Calculate fluxes (up and down) per band | `.false.` | +| `liqcldoptics` | Choice of cloud optical property parameterization for liquid clouds. Valid options are ‘slingo’ or ‘gammadist’ | `gammadist` | +| `icecldoptics` | Choice of cloud optical property parameterization for ice clouds. Valid options are ‘ebertcurry’ or ‘mitchell’ | `mitchell` | + +## Zhang and McFarlane deep convection scheme + +| ZM Parameters | Description | Default value | +| ------------------------- | ----------------------------------------------------------------- | ---------------------- | +| `zmconv_ke` | Tunable evaporation efficiency in ZM deep convection scheme | `2.5E-6` | +| `zmconv_tau` | Relaxation time in ZM deep convection scheme | `3600` | +| `zmconv_dmpdz` | Parcel fractional mass entrainment rate | `-0.7E-3` | +| `zmconv_alfa` | Initial downdraft mass flux fraction | `0.14D0` | +| `zmconv_tiedke_add` | Temperature perturbation of an air parcel | `0.8D0` | +| `zmconv_cape_cin` | Number of negative buoyancy regions that are allowed | `1` | + +| dCAPE-ULL Parameters | Description | Default value | +| ------------------------- | ----------------------------------------------------------------- | ---------------------- | +| `zmconv_trigdcape_ull` | DCAPE trigger along with unrestricted launching level for ZM deep convection scheme | `.true.` | +| `zmconv_trig_dcape_only` | DCAPE only trigger for ZM deep convection scheme | `.false.`
If true, zmconv_trigdcape_ull must be false to use the dcape only trigger. | +| `zmconv_trig_ull_only` | Use unrestricted launching level (ULL) only trigger for ZM deep convection scheme | `.false.`
If true, zmconv_trigdcape_ull must be false to use the ull only trigger. | + +| Conv. micro. Parameters | Description | Default value | +| ------------------------- | ----------------------------------------------------------------- | ---------------------- | +| `zmconv_microp` | Convective microphysics option in ZM convection scheme | `true` | +| `zmconv_auto_fac` | Cloud droplet-rain autoconversion enhancement factor in the convective microphysics scheme | `7.0` | +| `zmconv_accr_fac` | Cloud droplet-rain accretion enhancement factor in the convective microphysics scheme | `1.5` | +| `zmconv_micro_dcs` | Autoconversion size threshold for cloud ice to snow (m) | `150.E-6` | + +| Mass flux adj. Parameters | Description | Default value | +| ------------------------- | ----------------------------------------------------------------- | ---------------------- | +| `zmconv_clos_dyn_adj` | Apply mass flux adjustment to ZM convection scheme | `true` | + +| MCSP Parameters | Description | Default value | +| ---------------------------- | ----------------------------------------------------------------- | ---------------------- | +| `zmconv_mcsp_heat_coeff` | MCSP heating coefficient | `0.3` | +| `zmconv_mcsp_moisture_coeff` | MCSP moisture coefficient | `0.0` | +| `zmconv_mcsp_uwind_coeff` | MCSP zonal wind coefficient | `0.0` | +| `zmconv_mcsp_vwind_coeff` | MCSP meridional wind coefficient | `0.0` | + +## Cloud Feedback Model Intercomparison Project (CFMIP) Observation Simulator Package + +| Parameter | Description | Default value | +| ------------------------- | ----------------------------------------------------------------- | ---------------------- | +| `cosp_lite` | This namelist sets cosp_ncolumns=10 and cosp_nradsteps=3 (appropriate for COSP statistics derived from seasonal averages), and runs MISR, ISCCP, MODIS, and CALIPSO lidar simulators (cosp_lmisr_sim=.true.,cosp_lisccp_sim=.true., cosp_lmodis_sim=.true.,cosp_llidar_sim=.true.). | `false` | diff --git a/components/eam/mkdocs.yml b/components/eam/mkdocs.yml index f64ab33620f..c310e410285 100644 --- a/components/eam/mkdocs.yml +++ b/components/eam/mkdocs.yml @@ -2,6 +2,23 @@ site_name: EAM nav: - Introduction: 'index.md' - - Users's Guide: user-guide/index.md - - Developers's Guide: dev-guide/index.md - - Technical Guide: tech-guide/index.md + - User Guide: + - user-guide/index.md + - Namelist Parameters: user-guide/namelist_parameters.md + - Aerosol Properties: user-guide/aerosol_phys_prop.md + - Emission Oxidants: user-guide/emission_oxidant_files.md + - Developer Guide: dev-guide/index.md + - Technical Guide: + - tech-guide/index.md + - tech-guide/homme.md + - tech-guide/p3.md + - tech-guide/clubb.md + - tech-guide/zm.md + - RRTMG: tech-guide/rrtmg.md + - tech-guide/mam.md + - tech-guide/vbs.md + - tech-guide/dust.md + - tech-guide/oceanfilms.md + - tech-guide/chemUCIlinozv3.md + - COSP: tech-guide/cosp.md + - tech-guide/armdiags.md diff --git a/components/eam/src/chemistry/mozart/chemistry.F90 b/components/eam/src/chemistry/mozart/chemistry.F90 index 57412d8f818..f78ceda1dea 100644 --- a/components/eam/src/chemistry/mozart/chemistry.F90 +++ b/components/eam/src/chemistry/mozart/chemistry.F90 @@ -1574,44 +1574,43 @@ subroutine chem_timestep_tend( state, ptend, cam_in, cam_out, dt, pbuf, fh2o, f end if ! HHLEE 20210923 if (history_gaschmbudget_2D_levels .or. history_chemdyg_summary) then - ftem_layers = 0.0_r8 - gas_ac_layers = 0.0_r8 - - gas_ac_idx = pbuf_get_index(gas_ac_name(n)) - call pbuf_get_field(pbuf, gas_ac_idx, gas_ac ) + ftem_layers = 0.0_r8 + gas_ac_layers = 0.0_r8 + if( nstep /= 0 ) then + gas_ac_idx = pbuf_get_index(gas_ac_name(n)) + call pbuf_get_field(pbuf, gas_ac_idx, gas_ac ) - if (gaschmbudget_2D_L1_e .lt. gaschmbudget_2D_L1_s .or. gaschmbudget_2D_L2_e .lt. gaschmbudget_2D_L2_s .or. & - gaschmbudget_2D_L3_e .lt. gaschmbudget_2D_L3_s .or. gaschmbudget_2D_L4_e .lt. gaschmbudget_2D_L4_s ) then - call endrun('chem_readnl: ERROR 2D chem diags layers, layer ending index is less than starting index') - end if + if (gaschmbudget_2D_L1_e .lt. gaschmbudget_2D_L1_s .or. gaschmbudget_2D_L2_e .lt. gaschmbudget_2D_L2_s .or. & + gaschmbudget_2D_L3_e .lt. gaschmbudget_2D_L3_s .or. gaschmbudget_2D_L4_e .lt. gaschmbudget_2D_L4_s ) then + call endrun('chem_readnl: ERROR 2D chem diags layers, layer ending index is less than starting index') + end if - do k= gaschmbudget_2D_L1_s, gaschmbudget_2D_L1_e ! 0-90 hPa - ftem_layers(:ncol,1) = ftem_layers(:ncol,1) + ftem(:ncol,k) - gas_ac_layers(:ncol,1) = gas_ac_layers(:ncol,1) + gas_ac(:ncol,k) - end do - do k= gaschmbudget_2D_L2_s, gaschmbudget_2D_L2_e ! 90-300 hPa - ftem_layers(:ncol,2) = ftem_layers(:ncol,2) + ftem(:ncol,k) - gas_ac_layers(:ncol,2) = gas_ac_layers(:ncol,2) + gas_ac(:ncol,k) - end do - do k= gaschmbudget_2D_L3_s, gaschmbudget_2D_L3_e ! 300-850 hPa - ftem_layers(:ncol,3) = ftem_layers(:ncol,3) + ftem(:ncol,k) - gas_ac_layers(:ncol,3) = gas_ac_layers(:ncol,3) + gas_ac(:ncol,k) - end do - do k= gaschmbudget_2D_L4_s, gaschmbudget_2D_L4_e ! 850 hPa - surface - ftem_layers(:ncol,4) = ftem_layers(:ncol,4) + ftem(:ncol,k) - gas_ac_layers(:ncol,4) = gas_ac_layers(:ncol,4) + gas_ac(:ncol,k) - end do + do k= gaschmbudget_2D_L1_s, gaschmbudget_2D_L1_e ! 0-90 hPa + ftem_layers(:ncol,1) = ftem_layers(:ncol,1) + ftem(:ncol,k) + gas_ac_layers(:ncol,1) = gas_ac_layers(:ncol,1) + gas_ac(:ncol,k) + end do + do k= gaschmbudget_2D_L2_s, gaschmbudget_2D_L2_e ! 90-300 hPa + ftem_layers(:ncol,2) = ftem_layers(:ncol,2) + ftem(:ncol,k) + gas_ac_layers(:ncol,2) = gas_ac_layers(:ncol,2) + gas_ac(:ncol,k) + end do + do k= gaschmbudget_2D_L3_s, gaschmbudget_2D_L3_e ! 300-850 hPa + ftem_layers(:ncol,3) = ftem_layers(:ncol,3) + ftem(:ncol,k) + gas_ac_layers(:ncol,3) = gas_ac_layers(:ncol,3) + gas_ac(:ncol,k) + end do + do k= gaschmbudget_2D_L4_s, gaschmbudget_2D_L4_e ! 850 hPa - surface + ftem_layers(:ncol,4) = ftem_layers(:ncol,4) + ftem(:ncol,k) + gas_ac_layers(:ncol,4) = gas_ac_layers(:ncol,4) + gas_ac(:ncol,k) + end do + endif if (history_gaschmbudget_2D_levels ) then - call outfld(trim(solsym(n))//'_2DMSB_L1', ftem_layers(:ncol,1), pcols, lchnk) - call outfld(trim(solsym(n))//'_2DMSB_L2', ftem_layers(:ncol,2), pcols, lchnk) - call outfld(trim(solsym(n))//'_2DMSB_L3', ftem_layers(:ncol,3), pcols, lchnk) - call outfld(trim(solsym(n))//'_2DMSB_L4', ftem_layers(:ncol,4), pcols, lchnk) + call outfld(trim(solsym(n))//'_2DMSB_L1', ftem_layers(:ncol,1), pcols, lchnk) + call outfld(trim(solsym(n))//'_2DMSB_L2', ftem_layers(:ncol,2), pcols, lchnk) + call outfld(trim(solsym(n))//'_2DMSB_L3', ftem_layers(:ncol,3), pcols, lchnk) + call outfld(trim(solsym(n))//'_2DMSB_L4', ftem_layers(:ncol,4), pcols, lchnk) endif - if( nstep == 0 ) then - Diff_layers(:ncol,:) = 0.0_r8 - else - Diff_layers(:ncol,:) = 0.0_r8 + Diff_layers(:ncol,:) = 0.0_r8 + if( nstep /= 0 ) then Diff_layers(:ncol,1) = (ftem_layers(:ncol,1) - gas_ac_layers(:ncol,1))/dt Diff_layers(:ncol,2) = (ftem_layers(:ncol,2) - gas_ac_layers(:ncol,2))/dt Diff_layers(:ncol,3) = (ftem_layers(:ncol,3) - gas_ac_layers(:ncol,3))/dt @@ -1629,18 +1628,18 @@ subroutine chem_timestep_tend( state, ptend, cam_in, cam_out, dt, pbuf, fh2o, f trim(solsym(n))=='N2OLNZ' .or. trim(solsym(n))=='CH4LNZ') then ftem_layers = 0.0_r8 gas_ac_layers = 0.0_r8 - do k=1,pver - ftem_layers(:ncol,1) = ftem_layers(:ncol,1) + ftem(:ncol,k) * tropFlagInt(:ncol,k) - gas_ac_layers(:ncol,1) = gas_ac_layers(:ncol,1) + gas_ac(:ncol,k) * tropFlagInt(:ncol,k) - end do + if( nstep /= 0 ) then + do k=1,pver + ftem_layers(:ncol,1) = ftem_layers(:ncol,1) + ftem(:ncol,k) * tropFlagInt(:ncol,k) + gas_ac_layers(:ncol,1) = gas_ac_layers(:ncol,1) + gas_ac(:ncol,k) * tropFlagInt(:ncol,k) + end do + endif if (history_gaschmbudget_2D_levels ) then - call outfld(trim(solsym(n))//'_2DMSB_trop', ftem_layers(:ncol,1), pcols, lchnk ) + call outfld(trim(solsym(n))//'_2DMSB_trop', ftem_layers(:ncol,1), pcols, lchnk ) endif - - if( nstep == 0 ) then - Diff_layers(:ncol,:) = 0.0_r8 - else - Diff_layers(:ncol,:) = 0.0_r8 + + Diff_layers(:ncol,:) = 0.0_r8 + if( nstep /= 0 ) then Diff_layers(:ncol,1) = (ftem_layers(:ncol,1) - gas_ac_layers(:ncol,1))/dt end if diff --git a/components/eam/src/dynamics/se/se_iop_intr_mod.F90 b/components/eam/src/dynamics/se/se_iop_intr_mod.F90 index 0798a0a79f5..ae29e5734a9 100644 --- a/components/eam/src/dynamics/se/se_iop_intr_mod.F90 +++ b/components/eam/src/dynamics/se/se_iop_intr_mod.F90 @@ -56,7 +56,7 @@ subroutine iop_setinitial(elem) integer i, j, k, cix, ie, thelev integer inumliq, inumice, icldliq, icldice - if (.not. use_replay .and. get_nstep() .eq. 0 .and. par%dynproc) then + if (get_nstep() .eq. 0 .and. par%dynproc) then call cnst_get_ind('NUMLIQ', inumliq, abrtf=.false.) call cnst_get_ind('NUMICE', inumice, abrtf=.false.) call cnst_get_ind('CLDLIQ', icldliq) @@ -215,8 +215,7 @@ subroutine iop_setfield(elem,iop_update_phase1) integer i, j, k, ie do ie=1,nelemd - if (have_ps .and. use_replay .and. .not. iop_update_phase1) elem(ie)%state%ps_v(:,:,:) = psobs - if (have_ps .and. .not. use_replay) elem(ie)%state%ps_v(:,:,:) = psobs + if (have_ps) elem(ie)%state%ps_v(:,:,:) = psobs do i=1, PLEV ! If DP CRM mode do NOT write over dycore vertical velocity if ((have_omega .and. iop_update_phase1) .and. .not. dp_crm) elem(ie)%derived%omega_p(:,:,i)=wfld(i) ! set t to tobs at first diff --git a/components/eam/src/dynamics/se/stepon.F90 b/components/eam/src/dynamics/se/stepon.F90 index 38a376935ee..783122d3147 100644 --- a/components/eam/src/dynamics/se/stepon.F90 +++ b/components/eam/src/dynamics/se/stepon.F90 @@ -526,9 +526,10 @@ subroutine stepon_run3(dtime, cam_out, phys_state, dyn_in, dyn_out) use hycoef, only: hyam, hybm use dimensions_mod, only: nlev, nelemd, np, npsq use se_iop_intr_mod, only: iop_setfield, iop_setinitial - use dyn_comp, only: TimeLevel + use dyn_comp, only: TimeLevel, hvcoord use cam_history, only: outfld use cam_logfile, only: iulog + use element_ops, only: get_temperature use mpishorthand real(r8), intent(in) :: dtime ! Time-step real(r8) :: ftmp_temp(np,np,nlev,nelemd), ftmp_q(np,np,nlev,pcnst,nelemd) @@ -542,6 +543,7 @@ subroutine stepon_run3(dtime, cam_out, phys_state, dyn_in, dyn_out) type (dyn_export_t), intent(inout) :: dyn_out ! Dynamics export container type (element_t), pointer :: elem(:) integer :: rc, i, j, k, p, ie, tl_f + real(r8) :: temperature(np,np,nlev) ! Temperature from dynamics #if defined (E3SM_SCM_REPLAY) real(r8) :: forcing_temp(npsq,nlev), forcing_q(npsq,nlev,pcnst) #endif @@ -554,7 +556,10 @@ subroutine stepon_run3(dtime, cam_out, phys_state, dyn_in, dyn_out) ! Save ftmp stuff to get state before dynamics is called do ie=1,nelemd - ftmp_temp(:,:,:,ie) = dyn_in%elem(ie)%state%T(:,:,:,tl_f) + + call get_temperature(dyn_in%elem(ie),temperature,hvcoord,tl_f) + + ftmp_temp(:,:,:,ie) = temperature(:,:,:) ftmp_q(:,:,:,:,ie) = dyn_in%elem(ie)%state%Q(:,:,:,:) enddo @@ -599,6 +604,10 @@ subroutine stepon_run3(dtime, cam_out, phys_state, dyn_in, dyn_out) tl_f = TimeLevel%n0 do ie=1,nelemd + + ! Get temperature from dynamics state + call get_temperature(dyn_in%elem(ie),temperature,hvcoord,tl_f) + do k=1,nlev do j=1,np do i=1,np @@ -606,9 +615,9 @@ subroutine stepon_run3(dtime, cam_out, phys_state, dyn_in, dyn_out) ! Note that this calculation will not provide b4b results with ! an E3SM because the dynamics tendency is not computed in the exact ! same way as an E3SM run, introducing error with roundoff - forcing_temp(i+(j-1)*np,k) = (dyn_in%elem(ie)%state%T(i,j,k,tl_f) - & + forcing_temp(i+(j-1)*np,k) = (temperature(i,j,k) - & ftmp_temp(i,j,k,ie))/dtime - dyn_in%elem(ie)%derived%FT(i,j,k) - out_temp(i+(j-1)*np,k) = dyn_in%elem(ie)%state%T(i,j,k,tl_f) + out_temp(i+(j-1)*np,k) = temperature(i,j,k) out_u(i+(j-1)*np,k) = dyn_in%elem(ie)%state%v(i,j,1,k,tl_f) out_v(i+(j-1)*np,k) = dyn_in%elem(ie)%state%v(i,j,2,k,tl_f) out_q(i+(j-1)*np,k) = dyn_in%elem(ie)%state%Q(i,j,k,1) diff --git a/components/eam/src/physics/cam/co2_diagnostics.F90 b/components/eam/src/physics/cam/co2_diagnostics.F90 index c24c908a524..81fdb3e9d76 100644 --- a/components/eam/src/physics/cam/co2_diagnostics.F90 +++ b/components/eam/src/physics/cam/co2_diagnostics.F90 @@ -433,16 +433,24 @@ subroutine print_global_carbon_diags(state, dtime, nstep) ( co2_print_diags_monthly .and. is_end_curr_month() ) .or. & ( co2_print_diags_total .and. is_last_step() ) ) then call gmean(tc, tc_glob, c_num_var) + else + tc_glob(:) = 1.e36 end if if ( co2_print_diags_timestep) then call gmean(flux_ts, flux_ts_glob, f_ts_num_var) + else + flux_ts_glob(:) = 0._r8 end if if ( co2_print_diags_monthly .and. is_end_curr_month() ) then call gmean(flux_mon, flux_mon_glob, f_mon_num_var) + else + flux_mon_glob(:) = 0._r8 end if if ( co2_print_diags_total .and. is_last_step() ) then call gmean(flux_run, flux_run_glob, f_run_num_var) + else + flux_run_glob(:) = 0._r8 end if ! assign global means to readable variables diff --git a/components/eam/src/physics/cam/ndrop.F90 b/components/eam/src/physics/cam/ndrop.F90 index b4dc999309b..6ffe89fa730 100644 --- a/components/eam/src/physics/cam/ndrop.F90 +++ b/components/eam/src/physics/cam/ndrop.F90 @@ -58,6 +58,10 @@ module ndrop (/ 0.02_r8, 0.05_r8, 0.1_r8, 0.2_r8, 0.5_r8, 1.0_r8 /) character(len=8) :: ccn_name(psat)= & (/'CCN1','CCN2','CCN3','CCN4','CCN5','CCN6'/) +! The following additional fields output CCN in units of 1/kg, +! which could be handy for appplications such as SCREAM-SPA. +character(len=8) :: ccnmair_name(psat)= & + (/'CCN1MAIR','CCN2MAIR','CCN3MAIR','CCN4MAIR','CCN5MAIR','CCN6MAIR'/) ! indices in state and pbuf structures integer :: numliq_idx = -1 @@ -274,6 +278,12 @@ subroutine ndrop_init call addfld('CCN5',(/ 'lev' /), 'A','1/cm3','CCN concentration at S=0.5%') call addfld('CCN6',(/ 'lev' /), 'A','1/cm3','CCN concentration at S=1.0%') + call addfld('CCN1MAIR',(/ 'lev' /), 'A','1/kg','CCN concentration at S=0.02%') + call addfld('CCN2MAIR',(/ 'lev' /), 'A','1/kg','CCN concentration at S=0.05%') + call addfld('CCN3MAIR',(/ 'lev' /), 'A','1/kg','CCN concentration at S=0.1%') + call addfld('CCN4MAIR',(/ 'lev' /), 'A','1/kg','CCN concentration at S=0.2%') + call addfld('CCN5MAIR',(/ 'lev' /), 'A','1/kg','CCN concentration at S=0.5%') + call addfld('CCN6MAIR',(/ 'lev' /), 'A','1/kg','CCN concentration at S=1.0%') call addfld('WTKE', (/ 'lev' /), 'A', 'm/s', 'Standard deviation of updraft velocity') call addfld('NDROPMIX', (/ 'lev' /), 'A', '1/kg/s', 'Droplet number mixing') @@ -435,7 +445,8 @@ subroutine dropmixnuc( & real(r8), allocatable :: coltend(:,:) ! column tendency for diagnostic output real(r8), allocatable :: coltend_cw(:,:) ! column tendency - real(r8) :: ccn(pcols,pver,psat) ! number conc of aerosols activated at supersat + real(r8) :: ccn(pcols,pver,psat) ! number conc [1/m3] of aerosols activated at supersat + real(r8) :: ccnmair(pcols,pver,psat) ! number conc [1/kg] of aerosols activated at supersat integer :: ccn3d_idx real(r8), pointer :: ccn3d(:, :) @@ -1105,9 +1116,10 @@ subroutine dropmixnuc( & call outfld('NDROPMIX', ndropmix, pcols, lchnk) call outfld('WTKE ', wtke, pcols, lchnk) - call ccncalc(state, pbuf, cs, ccn) + call ccncalc(state, pbuf, cs, ccn, ccnmair) do l = 1, psat call outfld(ccn_name(l), ccn(1,1,l), pcols, lchnk) + call outfld(ccnmair_name(l), ccnmair(1,1,l), pcols, lchnk) enddo if(do_aerocom_ind3) then @@ -1704,7 +1716,7 @@ end subroutine maxsat !=============================================================================== -subroutine ccncalc(state, pbuf, cs, ccn) +subroutine ccncalc(state, pbuf, cs, ccn, ccnmair) ! calculates number concentration of aerosols activated as CCN at ! supersaturation supersat. @@ -1721,6 +1733,7 @@ subroutine ccncalc(state, pbuf, cs, ccn) real(r8), intent(in) :: cs(pcols,pver) ! air density (kg/m3) real(r8), intent(out) :: ccn(pcols,pver,psat) ! number conc of aerosols activated at supersat (#/m3) + real(r8), intent(out) :: ccnmair(pcols,pver,psat) ! number conc of aerosols activated at supersat (#/kg) ! local @@ -1770,6 +1783,7 @@ subroutine ccncalc(state, pbuf, cs, ccn) end do ccn = 0._r8 + ccnmair = 0._r8 do k=top_lev,pver do i=1,ncol @@ -1796,6 +1810,7 @@ subroutine ccncalc(state, pbuf, cs, ccn) do i=1,ncol arg(i)=argfactor(m)*log(sm(i)/super(l)) ccn(i,k,l)=ccn(i,k,l)+naerosol(i)*0.5_r8*(1._r8-erf(arg(i))) + ccnmair(i,k,l)=ccn(i,k,l)/cs(i,k) ! convert from #/m3 to #/kg enddo enddo enddo diff --git a/components/eam/src/physics/cam/physpkg.F90 b/components/eam/src/physics/cam/physpkg.F90 index f711bc8eaa6..5ece6725279 100644 --- a/components/eam/src/physics/cam/physpkg.F90 +++ b/components/eam/src/physics/cam/physpkg.F90 @@ -526,10 +526,6 @@ subroutine phys_inidat( cam_out, pbuf2d ) end do deallocate(tptr) - do lchnk=begchunk,endchunk - cam_out(lchnk)%tbot(:) = posinf - end do - ! ! 3-D fields ! diff --git a/components/eam/src/physics/p3/eam/micro_p3.F90 b/components/eam/src/physics/p3/eam/micro_p3.F90 index 730736a2dbf..e668cbaa494 100644 --- a/components/eam/src/physics/p3/eam/micro_p3.F90 +++ b/components/eam/src/physics/p3/eam/micro_p3.F90 @@ -56,7 +56,7 @@ module micro_p3 use phys_control, only: use_hetfrz_classnuc ! physical and mathematical constants - use micro_p3_utils, only: rho_1000mb,rho_600mb,ar,br,f1r,f2r,rho_h2o,kr,kc,aimm,mi0,nccnst, & + use micro_p3_utils, only: rho_1000mb,rho_600mb,ar,br,f1r,f2r,rho_h2o,kr,kc,aimm,mi0, & eci,eri,bcn,cpw,cons1,cons3,cons4,cons5,cons6,cons7, & inv_rho_h2o,inv_dropmass,qsmall,nsmall,cp,g,rd,rv,ep_2,inv_cp, & thrd,sxth,piov6,rho_rimeMin, & @@ -441,7 +441,7 @@ SUBROUTINE p3_main_part1(kts, kte, kbot, ktop, kdir, do_predict_nc, do_prescribe t_atm, rho, inv_rho, qv_sat_l, qv_sat_i, qv_supersat_i, rhofacr, rhofaci, acn, qv, th_atm, & qc, nc, qr, nr, & qi, ni, qm, bm, qc_incld, qr_incld, qi_incld, qm_incld, & - nc_incld, nr_incld, ni_incld, bm_incld, is_nucleat_possible, is_hydromet_present) + nc_incld, nr_incld, ni_incld, bm_incld, is_nucleat_possible, is_hydromet_present, nccnst) implicit none @@ -449,7 +449,7 @@ SUBROUTINE p3_main_part1(kts, kte, kbot, ktop, kdir, do_predict_nc, do_prescribe integer, intent(in) :: kts, kte, kbot, ktop, kdir logical(btype), intent(in) :: do_predict_nc - real(rtype), intent(in) :: dt + real(rtype), intent(in) :: dt, nccnst real(rtype), intent(in), dimension(kts:kte) :: pres, dpres, dz, nc_nuceat_tend, exner, inv_exner, & inv_cld_frac_l, inv_cld_frac_i, inv_cld_frac_r, latent_heat_vapor, latent_heat_sublim, latent_heat_fusion, nccn_prescribed @@ -561,15 +561,15 @@ SUBROUTINE p3_main_part2(kts, kte, kbot, ktop, kdir, do_predict_nc, do_prescribe qm, bm, latent_heat_vapor, latent_heat_sublim, latent_heat_fusion, qc_incld, qr_incld, qi_incld, qm_incld, nc_incld, nr_incld, & ni_incld, bm_incld, mu_c, nu, lamc, cdist, cdist1, cdistr, mu_r, lamr, logn0r, qv2qi_depos_tend, precip_total_tend, & nevapr, qr_evap_tend, vap_liq_exchange, vap_ice_exchange, liq_ice_exchange, pratot, & - prctot, frzimm, frzcnt, frzdep, p3_tend_out, is_hydromet_present) + prctot, frzimm, frzcnt, frzdep, p3_tend_out, is_hydromet_present, do_precip_off, nccnst) implicit none ! args integer, intent(in) :: kts, kte, kbot, ktop, kdir - logical(btype), intent(in) :: do_predict_nc, do_prescribed_CCN - real(rtype), intent(in) :: dt, inv_dt + logical(btype), intent(in) :: do_predict_nc, do_prescribed_CCN, do_precip_off + real(rtype), intent(in) :: dt, inv_dt, nccnst real(rtype), intent(in) :: p3_autocon_coeff, p3_accret_coeff, p3_qc_autocon_expon, p3_nc_autocon_expon, p3_qc_accret_expon, & p3_wbf_coeff, p3_embryonic_rain_size, p3_max_mean_rain_size @@ -875,7 +875,7 @@ SUBROUTINE p3_main_part2(kts, kte, kbot, ktop, kdir, do_predict_nc, do_prescribe ! NOTE: cloud_water_autoconversion must be called before droplet_self_collection call cloud_water_autoconversion(rho(k),qc_incld(k),nc_incld(k),inv_qc_relvar(k),& p3_autocon_coeff,p3_qc_autocon_expon,p3_nc_autocon_expon,p3_embryonic_rain_size,& - qc2qr_autoconv_tend,nc2nr_autoconv_tend,ncautr) + do_precip_off,qc2qr_autoconv_tend,nc2nr_autoconv_tend,ncautr) !............................ ! self-collection of droplets @@ -978,7 +978,7 @@ SUBROUTINE p3_main_part2(kts, kte, kbot, ktop, kdir, do_predict_nc, do_prescribe !-- warm-phase only processes: call update_prognostic_liquid(qc2qr_accret_tend, nc_accret_tend, qc2qr_autoconv_tend, nc2nr_autoconv_tend, ncautr, & nc_selfcollect_tend, qr2qv_evap_tend, nr_evap_tend, nr_selfcollect_tend, & - do_predict_nc, do_prescribed_CCN, inv_rho(k), exner(k), latent_heat_vapor(k), dt, & + do_predict_nc, nccnst, do_prescribed_CCN, inv_rho(k), exner(k), latent_heat_vapor(k), dt, & th_atm(k), qv(k), qc(k), nc(k), qr(k), nr(k)) !== @@ -1259,7 +1259,7 @@ SUBROUTINE p3_main(qc,nc,qr,nr,th_atm,qv,dt,qi,qm,ni,bm, p3_wbf_coeff,p3_mincdnc,p3_max_mean_rain_size,p3_embryonic_rain_size, & dpres,exner,qv2qi_depos_tend,precip_total_tend,nevapr,qr_evap_tend,precip_liq_flux,precip_ice_flux,rflx,sflx,cflx,cld_frac_r,cld_frac_l,cld_frac_i, & p3_tend_out,mu_c,lamc,liq_ice_exchange,vap_liq_exchange, & - vap_ice_exchange,qv_prev,t_prev,col_location,diag_equiv_reflectivity,diag_ze_rain,diag_ze_ice & + vap_ice_exchange,qv_prev,t_prev,col_location,do_precip_off,nccnst,diag_equiv_reflectivity,diag_ze_rain,diag_ze_ice & #ifdef SCREAM_CONFIG_IS_CMAKE ,elapsed_s & #endif @@ -1337,6 +1337,10 @@ SUBROUTINE p3_main(qc,nc,qr,nr,th_atm,qv,dt,qi,qm,ni,bm, ! INPUT for prescribed CCN option logical(btype), intent(in) :: do_prescribed_CCN + ! INPUT for idealization options + logical(btype), intent(in) :: do_precip_off + real(rtype), intent(in) :: nccnst + ! INPUT for p3 tuning parameters real(rtype), intent(in) :: p3_autocon_coeff ! autconversion coefficient real(rtype), intent(in) :: p3_accret_coeff ! accretion coefficient @@ -1517,7 +1521,7 @@ SUBROUTINE p3_main(qc,nc,qr,nr,th_atm,qv,dt,qi,qm,ni,bm, rhofaci(i,:), acn(i,:), qv(i,:), th_atm(i,:), qc(i,:), nc(i,:), qr(i,:), nr(i,:), & qi(i,:), ni(i,:), qm(i,:), bm(i,:), qc_incld(i,:), qr_incld(i,:), & qi_incld(i,:), qm_incld(i,:), nc_incld(i,:), nr_incld(i,:), & - ni_incld(i,:), bm_incld(i,:), is_nucleat_possible, is_hydromet_present) + ni_incld(i,:), bm_incld(i,:), is_nucleat_possible, is_hydromet_present, nccnst) if (debug_ON) then tmparr1(i,:) = th_atm(i,:)*inv_exner(i,:)!(pres(i,:)*1.e-5)**(rd*inv_cp) @@ -1541,7 +1545,8 @@ SUBROUTINE p3_main(qc,nc,qr,nr,th_atm,qv,dt,qi,qm,ni,bm, bm_incld(i,:), mu_c(i,:), nu(i,:), lamc(i,:), cdist(i,:), cdist1(i,:), & cdistr(i,:), mu_r(i,:), lamr(i,:), logn0r(i,:), qv2qi_depos_tend(i,:), precip_total_tend(i,:), & nevapr(i,:), qr_evap_tend(i,:), vap_liq_exchange(i,:), vap_ice_exchange(i,:), & - liq_ice_exchange(i,:), pratot(i,:), prctot(i,:), frzimm(i,:), frzcnt(i,:), frzdep(i,:), p3_tend_out(i,:,:), is_hydromet_present) + liq_ice_exchange(i,:), pratot(i,:), prctot(i,:), frzimm(i,:), frzcnt(i,:), frzdep(i,:), p3_tend_out(i,:,:), is_hydromet_present, & + do_precip_off, nccnst) ! measure microphysics processes tendency output @@ -2950,7 +2955,7 @@ end subroutine rain_self_collection subroutine cloud_water_autoconversion(rho,qc_incld,nc_incld,inv_qc_relvar, & p3_autocon_coeff,p3_qc_autocon_expon,p3_nc_autocon_expon,p3_embryonic_rain_size, & - qc2qr_autoconv_tend,nc2nr_autoconv_tend,ncautr) + do_precip_off,qc2qr_autoconv_tend,nc2nr_autoconv_tend,ncautr) implicit none @@ -2963,6 +2968,8 @@ subroutine cloud_water_autoconversion(rho,qc_incld,nc_incld,inv_qc_relvar, real(rtype), intent(in) :: p3_nc_autocon_expon real(rtype), intent(in) :: p3_embryonic_rain_size + logical(btype), intent(in) :: do_precip_off + real(rtype), intent(out) :: qc2qr_autoconv_tend real(rtype), intent(out) :: nc2nr_autoconv_tend real(rtype), intent(out) :: ncautr @@ -2981,8 +2988,9 @@ subroutine cloud_water_autoconversion(rho,qc_incld,nc_incld,inv_qc_relvar, ncautr = qc2qr_autoconv_tend*cons3*(1._rtype/bfb_pow(p3_embryonic_rain_size,3._rtype)) nc2nr_autoconv_tend = qc2qr_autoconv_tend*nc_incld/qc_incld - if (qc2qr_autoconv_tend .eq.0._rtype) nc2nr_autoconv_tend = 0._rtype - if (nc2nr_autoconv_tend.eq.0._rtype) qc2qr_autoconv_tend = 0._rtype + if (qc2qr_autoconv_tend .eq.0._rtype .or. do_precip_off) nc2nr_autoconv_tend = 0._rtype + if (nc2nr_autoconv_tend.eq.0._rtype .or. do_precip_off) qc2qr_autoconv_tend = 0._rtype + if (do_precip_off) ncautr = 0._rtype endif qc_not_small @@ -3502,7 +3510,7 @@ end subroutine update_prognostic_ice subroutine update_prognostic_liquid(qc2qr_accret_tend,nc_accret_tend,qc2qr_autoconv_tend,nc2nr_autoconv_tend, & ncautr,nc_selfcollect_tend, qr2qv_evap_tend,nr_evap_tend,nr_selfcollect_tend, & - do_predict_nc, do_prescribed_CCN, inv_rho,exner,latent_heat_vapor,dt, & + do_predict_nc, nccnst, do_prescribed_CCN, inv_rho,exner,latent_heat_vapor,dt, & th_atm,qv,qc,nc,qr,nr) !-- warm-phase only processes: @@ -3520,6 +3528,7 @@ subroutine update_prognostic_liquid(qc2qr_accret_tend,nc_accret_tend,qc2qr_autoc logical(btype), intent(in) :: do_predict_nc, do_prescribed_CCN + real(rtype), intent(in) :: nccnst real(rtype), intent(in) :: inv_rho real(rtype), intent(in) :: exner real(rtype), intent(in) :: latent_heat_vapor diff --git a/components/eam/src/physics/p3/eam/micro_p3_interface.F90 b/components/eam/src/physics/p3/eam/micro_p3_interface.F90 index 9d53e95fc17..bb6e164b4a1 100644 --- a/components/eam/src/physics/p3/eam/micro_p3_interface.F90 +++ b/components/eam/src/physics/p3/eam/micro_p3_interface.F90 @@ -42,6 +42,7 @@ module micro_p3_interface use ncdio_atm, only: infld use ppgrid, only: begchunk, endchunk, pcols, pver, pverp,psubcols use cam_history_support, only: add_hist_coord + use iop_data_mod, only: precip_off implicit none save @@ -131,8 +132,8 @@ module micro_p3_interface p3_wbf_coeff = huge(1.0_rtype), & p3_mincdnc = huge(1.0_rtype), & p3_max_mean_rain_size = huge(1.0_rtype), & - p3_embryonic_rain_size = huge(1.0_rtype) - + p3_embryonic_rain_size = huge(1.0_rtype), & + micro_nccons = huge(1.0_rtype) integer :: ncnst @@ -165,7 +166,7 @@ subroutine micro_p3_readnl(nlfile) micro_p3_tableversion, micro_p3_lookup_dir, micro_aerosolactivation, micro_subgrid_cloud, & micro_tend_output, p3_autocon_coeff, p3_qc_autocon_expon, p3_nc_autocon_expon, p3_accret_coeff, & p3_qc_accret_expon, p3_wbf_coeff, p3_max_mean_rain_size, p3_embryonic_rain_size, & - do_prescribed_CCN, do_Cooper_inP3, p3_mincdnc + do_prescribed_CCN, do_Cooper_inP3, p3_mincdnc, micro_nccons !----------------------------------------------------------------------------- @@ -220,6 +221,7 @@ subroutine micro_p3_readnl(nlfile) call mpibcast(p3_embryonic_rain_size, 1 , mpir8, 0, mpicom) call mpibcast(do_prescribed_CCN, 1, mpilog, 0, mpicom) call mpibcast(do_Cooper_inP3, 1, mpilog, 0, mpicom) + call mpibcast(micro_nccons, 1, mpir8, 0, mpicom) #endif @@ -1363,6 +1365,8 @@ subroutine micro_p3_tend(state, ptend, dtime, pbuf) qv_prev(its:ite,kts:kte), & ! IN qv at end of prev p3_main call kg kg-1 t_prev(its:ite,kts:kte), & ! IN t at end of prev p3_main call K col_location(its:ite,:3), & ! IN column locations + precip_off, & ! IN Option to turn precip (liquid) off + micro_nccons, & ! IN Option for constant droplet concentration diag_equiv_reflectivity(its:ite,kts:kte), & !OUT equivalent reflectivity (rain + ice) [dBz] diag_ze_rain(its:ite,kts:kte),diag_ze_ice(its:ite,kts:kte)) !OUT equivalent reflectivity for rain and ice [dBz] diff --git a/components/eam/src/physics/p3/eam/micro_p3_utils.F90 b/components/eam/src/physics/p3/eam/micro_p3_utils.F90 index dab1c475132..c2182a14206 100644 --- a/components/eam/src/physics/p3/eam/micro_p3_utils.F90 +++ b/components/eam/src/physics/p3/eam/micro_p3_utils.F90 @@ -33,9 +33,6 @@ module micro_p3_utils ! maximum total ice concentration (sum of all categories) real(rtype), public, parameter :: max_total_ni = 500.e+3_rtype ! (m) - ! droplet concentration (m-3) - real(rtype), public, parameter :: nccnst = 200.e+6_rtype - ! parameters for Seifert and Beheng (2001) autoconversion/accretion real(rtype), public, parameter :: kc = 9.44e+9_rtype real(rtype), public, parameter :: kr = 5.78e+3_rtype diff --git a/components/eamxx/mkdocs.yml b/components/eamxx/mkdocs.yaml similarity index 100% rename from components/eamxx/mkdocs.yml rename to components/eamxx/mkdocs.yaml diff --git a/components/eamxx/src/share/util/scream_utils.hpp b/components/eamxx/src/share/util/scream_utils.hpp index 28a9b3af9d9..dbb315fc4b9 100644 --- a/components/eamxx/src/share/util/scream_utils.hpp +++ b/components/eamxx/src/share/util/scream_utils.hpp @@ -11,6 +11,7 @@ #include #include #include +#include namespace scream { diff --git a/components/eamxx/tests/multi-process/dynamics_physics/homme_shoc_cld_p3_rrtmgp/output.yaml b/components/eamxx/tests/multi-process/dynamics_physics/homme_shoc_cld_p3_rrtmgp/output.yaml index 97648fbd82f..11de905dd65 100644 --- a/components/eamxx/tests/multi-process/dynamics_physics/homme_shoc_cld_p3_rrtmgp/output.yaml +++ b/components/eamxx/tests/multi-process/dynamics_physics/homme_shoc_cld_p3_rrtmgp/output.yaml @@ -3,7 +3,9 @@ filename_prefix: homme_shoc_cld_p3_rrtmgp_output iotype: default Averaging Type: Instant -Max Snapshots Per File: 1 +Max Snapshots Per File: 744 # One output every 31 days +#remap_file: /g/g17/donahue5/Code/e3sm/scream-docs/regional_output_sites/20221123_ARM_sites_map.nc +remap_file: /usr/gdata/e3sm/ccsm3data/inputdata/atm/scream/maps/map_ne30np4_to_ne4pg2_mono.20220714.nc Fields: Physics GLL: Field Names: diff --git a/components/elm/bld/configure b/components/elm/bld/configure index 01cc15f9d20..e0a13f30be7 100755 --- a/components/elm/bld/configure +++ b/components/elm/bld/configure @@ -477,6 +477,7 @@ sub write_filepath_cesmbld "external_models/fates/biogeochem", "external_models/fates/fire", "external_models/fates/parteh", + "external_models/fates/radiation", "external_models/mpp/src/mpp/dtypes", "external_models/mpp/src/mpp/thermal", "external_models/mpp/src/mpp/util", diff --git a/components/elm/bld/namelist_files/namelist_defaults.xml b/components/elm/bld/namelist_files/namelist_defaults.xml index 7c8b7c6e7c9..8294fdeeb5a 100644 --- a/components/elm/bld/namelist_files/namelist_defaults.xml +++ b/components/elm/bld/namelist_files/namelist_defaults.xml @@ -310,6 +310,8 @@ lnd/clm2/surfdata_map/surfdata_ne256pg2_simyr2010_c230207.nc lnd/clm2/surfdata_map/surfdata_ne1024pg2_simyr2010_c211021.nc lnd/clm2/surfdata_map/surfdata_ne1024np4_simyr2010_c220523.nc + +lnd/clm2/surfdata_map/surfdata_0.25x0.25_simyr2010_c240206_TOP.nc @@ -446,6 +448,8 @@ lnd/clm2/surfdata_map/surfdata_0.5x0.5_simyr1850_c211019.nc lnd/clm2/surfdata_map/surfdata_0.125x0.125_simyr1850_c190730.nc lnd/clm2/surfdata_map/surfdata_0.125x0.125_simyr1950_c210924.nc + +lnd/clm2/surfdata_map/surfdata_0.25x0.25_simyr1850_c240125_TOP.nc lnd/clm2/surfdata_map/surfdata_conusx4v1_simyr1850_c160503.nc @@ -597,22 +601,10 @@ this mask will have smb calculated over the entire global land surface lnd/clm2/griddata/glcmaskdata_0.9x1.25_GIS_AIS.nc lnd/clm2/griddata/glcmaskdata_ne30np4_GIS_AIS_171002.nc - -glc/cism/griddata/glcmaskdata_48x96_Gland20km.nc -glc/cism/griddata/glcmaskdata_48x96_Gland10km.nc -glc/cism/griddata/glcmaskdata_48x96_Gland5km.nc -glc/cism/griddata/glcmaskdata_48x96_Gland5km.nc -glc/cism/griddata/glcmaskdata_0.9x1.25_Gland20km.nc -glc/cism/griddata/glcmaskdata_0.9x1.25_Gland10km.nc -glc/cism/griddata/glcmaskdata_0.9x1.25_Gland5km.nc -glc/cism/griddata/glcmaskdata_0.9x1.25_Gland5km.nc -glc/cism/griddata/glcmaskdata_1.9x2.5_Gland20km.nc -glc/cism/griddata/glcmaskdata_1.9x2.5_Gland10km.nc -glc/cism/griddata/glcmaskdata_1.9x2.5_Gland5km.nc -glc/cism/griddata/glcmaskdata_1.9x2.5_Gland5km.nc - + glc/cism/griddata/glcmaskdata_0.9x1.25_Gland5km.nc lnd/clm2/griddata/glcmaskdata_0.9x1.25_60S.nc +lnd/clm2/griddata/glcmaskdata_0.5x0.5_GIS_AIS.nc lnd/clm2/griddata/glcmaskdata_0.5x0.5_GIS_AIS.nc lnd/clm2/griddata/glcmaskdata_r0125_GIS_AIS.210407.nc lnd/clm2/griddata/glcmaskdata_ne30pg2_GIS_AIS.210407.nc @@ -2082,6 +2074,39 @@ this mask will have smb calculated over the entire global land surface +lnd/clm2/mappingdata/maps/0.25x0.25/map_0.5x0.5_AVHRR_to_0.25x0.25_nomask_aave_da_c240123.nc +lnd/clm2/mappingdata/maps/0.25x0.25/map_0.5x0.5_MODIS_to_0.25x0.25_nomask_aave_da_c240123.nc +lnd/clm2/mappingdata/maps/0.25x0.25/map_0.9x1.25_GRDC_to_0.25x0.25_nomask_aave_da_c240124.nc +lnd/clm2/mappingdata/maps/0.25x0.25/map_10x10min_IGBPmergeICESatGIS_to_0.25x0.25_nomask_aave_da_c240123.nc +lnd/clm2/mappingdata/maps/0.25x0.25/map_10x10min_nomask_to_0.25x0.25_nomask_aave_da_c240123.nc +lnd/clm2/mappingdata/maps/0.25x0.25/map_1km-merge-10min_HYDRO1K-merge-nomask_to_0.25x0.25_nomask_aave_da_c240123.nc +lnd/clm2/mappingdata/maps/0.25x0.25/map_360x720cru_cruncep_to_0.25x0.25_nomask_aave_da_c240124.nc +lnd/clm2/mappingdata/maps/0.25x0.25/map_3x3min_GLOBE-Gardner-mergeGIS_to_0.25x0.25_nomask_aave_da_c240123.nc +lnd/clm2/mappingdata/maps/0.25x0.25/map_3x3min_GLOBE-Gardner_to_0.25x0.25_nomask_aave_da_c240123.nc +lnd/clm2/mappingdata/maps/0.25x0.25/map_3x3min_LandScan2004_to_0.25x0.25_nomask_aave_da_c240123.nc +lnd/clm2/mappingdata/maps/0.25x0.25/map_3x3min_MODIS_to_0.25x0.25_nomask_aave_da_c240123.nc +lnd/clm2/mappingdata/maps/0.25x0.25/map_3x3min_USGS_to_0.25x0.25_nomask_aave_da_c240123.nc +lnd/clm2/mappingdata/maps/0.25x0.25/map_5x5min_IGBP-GSDP_to_0.25x0.25_nomask_aave_da_c240123.nc +lnd/clm2/mappingdata/maps/0.25x0.25/map_5x5min_ISRIC-WISE_to_0.25x0.25_nomask_aave_da_c240123.nc +lnd/clm2/mappingdata/maps/0.25x0.25/map_5x5min_nomask_to_0.25x0.25_nomask_aave_da_c240123.nc +lnd/clm2/mappingdata/maps/0.25x0.25/map_0.5x0.5_GSDTG2000_to_0.25x0.25_nomask_aave_da_c240123.nc + lnd/clm2/mappingdata/maps/antarcticax4v1/map_0.5x0.5_AVHRR_to_antarcticax4v1_nomask_aave_da_c210130.nc none -gland5UM +mpas.gis20km .false. .true. 0 diff --git a/components/elm/bld/namelist_files/namelist_definition.xml b/components/elm/bld/namelist_files/namelist_definition.xml index c08951338d7..0f8b03dfec3 100644 --- a/components/elm/bld/namelist_files/namelist_definition.xml +++ b/components/elm/bld/namelist_files/namelist_definition.xml @@ -215,12 +215,11 @@ Normally this is ONLY used when running CESM with the active glacier model. + group="elm_inparm" valid_values="mpas.gis20km,mpas.gis1to10km,mpas.gis1to10kmR2" > Glacier model grid - gland20 = Greenland at 20km resolution - gland10 = Greenland at 10km resolution - gland5 = Greenland at 5km resolution - gland5UM = Greenland at 5km resolution, using new UMontana ice sheet data for present day Greenland + mpas.gis20km = Greenland at 20km resolution + mpas.gis1to10km = Greenland at 1-to-10km variable resolution (v1, kept for backwards compatibility) + mpas.gis1to10kmR2 = Greenland at 1-to-10km variable resolution (v2, improved init. cond., fewer total grid cells) +"512x1024,360x720cru,128x256,64x128,48x96,32x64,8x16,94x192,0.23x0.31,0.9x1.25,1.9x2.5,2.5x3.33,4x5,10x15,5x5_amazon,1x1_tropicAtl,1x1_camdenNJ,1x1_vancouverCAN,1x1_mexicocityMEX,1x1_asphaltjungleNJ,1x1_brazil,1x1_urbanc_alpha,1x1_numaIA,1x1_smallvilleIA,0.1x0.1,0.5x0.5,3x3min,5x5min,10x10min,0.33x0.33,ne4np4,ne4np4.pg2,ne11np4,ne16np4,ne30np4,ne30np4.pg2,ne60np4,ne120np4,ne120np4.pg2,ne240np4,ne256np4,ne256np4.pg2,ne1024np4,ne1024np4.pg2,1km-merge-10min,ne0np4_arm_x8v3_lowcon,ne0np4_conus_x4v1_lowcon,ne0np4_enax4v1,ne0np4_twpx4v1,r2,r05,r0125,NLDAS,ne0np4_northamericax4v1.pg2,ne0np4_arcticx4v1.pg2,r025"> Horizontal resolutions Note: 0.1x0.1, 0.5x0.5, 5x5min, 10x10min, 3x3min and 0.33x0.33 are only used for CLM tools @@ -1424,7 +1423,7 @@ Representative concentration pathway for future scenarios [radiative forcing at + valid_values="USGS,gx3v7,gx1v6,navy,test,tx0.1v2,tx1v1,T62,TL319,cruncep,oEC60to30v3,oEC60to30v3wLI,ECwISC30to60E1r2,EC30to60E2r2,WC14to60E2r3,WCAtl12to45E2r4,SOwISC12to60E2r4,ECwISC30to60E2r1,oRRS18to6,oRRS18to6v3,oRRS15to5,oARRM60to10,oARRM60to6,ARRM10to60E2r1,oQU480,oQU240,oQU240wLI,oQU120,oRRS30to10v3,oRRS30to10v3wLI,360x720cru,NLDASww3a,NLDAS,tx0.1v2,ICOS10,IcoswISC30E3r5,IcosXISC30E3r7"> Land mask description 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 new file mode 100755 index 00000000000..e313dab6b16 --- /dev/null +++ b/components/elm/bld/namelist_files/use_cases/2015-2100_SSP245_transient.xml @@ -0,0 +1,45 @@ + + + + +Simulate transient land-use, and aerosol deposition changes from 2015 to 2100 +Simulate transient land-use, aerosol deposition, and Nitrogen deposition changes from 2015 to 2100 +Simulate transient land-use, aerosol deposition, and Nitrogen deposition changes from 2015 to 2100 +Simulate transient land-use, aerosol deposition, and Nitrogen deposition changes from 2015 to 2100 + + + +2015-2100 + +arb_ic + +flanduse_timeseries + + + +1850 +2005 +1850 + +2000 +2000 +2000 + +1850 +2010 +1850 + + + + +lnd/clm2/surfdata_map/surfdata_0.5x0.5_simyr1850_c200609_with_TOP.nc +lnd/clm2/surfdata_map/landuse.timeseries_0.5x0.5_ssp2_rcp45_simyr2015-2100_c240408.nc + + + +.false. +.true. +.true. +.false. + + 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 cc708a828c9..0e8415d3c1a 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 @@ -15,7 +15,8 @@ flanduse_timeseries - + 1850 2005 1850 @@ -27,8 +28,6 @@ 1850 2010 1850 ---> - @@ -36,8 +35,7 @@ lnd/clm2/surfdata_map/landuse.timeseries_ne30pg2_SSP3_RCP70_simyr2015-2100_c211015.nc - -lnd/clm2/surfdata_map/landuse.timeseries_ne30pg2_SSP3_RCP70_simyr2015-2100_c211015.nc +lnd/clm2/surfdata_map/landuse.timeseries_0.5x0.5_ssp3_rcp70_simyr2015-2100_c240308.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 bd62af24858..2db3549ce5f 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 @@ -15,7 +15,8 @@ flanduse_timeseries - + 1850 2005 1850 @@ -27,8 +28,6 @@ 1850 2010 1850 ---> - @@ -36,8 +35,7 @@ lnd/clm2/surfdata_map/landuse.timeseries_ne30pg2_SSP5_RCP85_simyr2015-2100_c220310.nc - -lnd/clm2/surfdata_map/landuse.timeseries_ne30pg2_SSP3_RCP70_simyr2015-2100_c211015.nc +lnd/clm2/surfdata_map/landuse.timeseries_0.5x0.5_ssp5_rcp85_simyr2015-2100_c240408.nc diff --git a/components/elm/cime_config/config_component.xml b/components/elm/cime_config/config_component.xml index 513805d1cfb..94fac9ab939 100755 --- a/components/elm/cime_config/config_component.xml +++ b/components/elm/cime_config/config_component.xml @@ -83,6 +83,7 @@ 2015-2100_SSP585_transient 2015-2100_SSP585_CMIP6bgc_transient 2015-2100_SSP370_transient + 2015-2100_SSP245_transient 2010_CMIP6LR_control 2010_CMIP6HR_control diff --git a/components/elm/cime_config/config_compsets.xml b/components/elm/cime_config/config_compsets.xml index 01366aa71dd..1e38dc81277 100644 --- a/components/elm/cime_config/config_compsets.xml +++ b/components/elm/cime_config/config_compsets.xml @@ -24,6 +24,16 @@ 1850_DATM%QIA_ELM%SPBC_SICE_SOCN_MOSART_SGLC_SWAV + + IERA5ELM + 2000_DATM%ERA5_ELM%SP_SICE_SOCN_MOSART_SGLC_SWAV + + + + IERA56HRELM + 2000_DATM%ERA56HR_ELM%SP_SICE_SOCN_MOSART_SGLC_SWAV + + IELM 2000_DATM%QIA_ELM%SP_SICE_SOCN_MOSART_SGLC_SWAV @@ -129,6 +139,11 @@ 1850_DATM%QIA_ELM%CNPRDCTCBC_SICE_SOCN_MOSART_SGLC_SWAV + + I1850CNPRDCTCBCTOP + 1850_DATM%QIA_ELM%CNPRDCTCBCTOP_SICE_SOCN_MOSART_SGLC_SWAV + + ICB1850CRDCTCBC 1850_SATM_ELM%CRDCTCBC_SICE_SOCN_MOSART_SGLC_SWAV @@ -532,6 +547,11 @@ 2000_DATM%GSWP3v1_ELM%CNPRDCTCBC_SICE_SOCN_MOSART_SGLC_SWAV + + IGSWCNPRDCTCBCTOP + 2000_DATM%GSWP3v1_ELM%CNPRDCTCBCTOP_SICE_SOCN_MOSART_SGLC_SWAV + + IGSWCNECACTCBC 2000_DATM%GSWP3v1_ELM%CNECACTCBC_SICE_SOCN_MOSART_SGLC_SWAV @@ -627,6 +647,11 @@ 1850_DATM%GSWP3v1_ELM%CNPRDCTCBC_SICE_SOCN_MOSART_SGLC_SWAV + + I1850GSWCNPRDCTCBCTOP + 1850_DATM%GSWP3v1_ELM%CNPRDCTCBCTOP_SICE_SOCN_MOSART_SGLC_SWAV + + I20TRGSWCNRDCTCBC 20TR_DATM%GSWP3v1_ELM%CNRDCTCBC_SICE_SOCN_MOSART_SGLC_SWAV @@ -637,6 +662,11 @@ 20TR_DATM%GSWP3v1_ELM%CNPRDCTCBC_SICE_SOCN_MOSART_SGLC_SWAV + + I20TRGSWCNPRDCTCBCTOP + 20TR_DATM%GSWP3v1_ELM%CNPRDCTCBCTOP_SICE_SOCN_MOSART_SGLC_SWAV + + @@ -773,7 +803,7 @@ IGELM_MLI - 2000_DATM%QIA_ELM%SP_SICE_SOCN_MOSART_MALI%SIA_SWAV + 2000_DATM%QIA_ELM%SP_SICE_SOCN_MOSART_MALI_SWAV diff --git a/components/elm/cime_config/config_pes.xml b/components/elm/cime_config/config_pes.xml index acf6c6911b9..51a0a735525 100644 --- a/components/elm/cime_config/config_pes.xml +++ b/components/elm/cime_config/config_pes.xml @@ -552,4 +552,80 @@ + + + + GIS 20km (low-res) testing config + 128 + 128 + + 128 + 128 + 128 + 128 + 128 + 128 + 128 + 128 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + + + + + GIS 1-to-10km (high-res) config + 128 + 128 + + 512 + 512 + 512 + 512 + 512 + 512 + 512 + 512 + + + 1 + 1 + 1 + 1 + 1 + 1 + 1 + 1 + + + 0 + 0 + 0 + 0 + 0 + 0 + 0 + + + + diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold/shell_commands b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold/shell_commands index 5c5dc3a9118..c2771ff61c4 100644 --- a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold/shell_commands +++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold/shell_commands @@ -1,2 +1,8 @@ ./xmlchange TEST_MEMLEAK_TOLERANCE=0.75 ./xmlchange NTHRDS=1 + +# Change PIO settings as temporary fix for #6316 +if [ `./xmlquery --value LND_GRID` == 1.9x2.5 ]; then + ./xmlchange PIO_NUMTASKS=4 + ./xmlchange PIO_STRIDE=-999 +fi diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_allvars/user_nl_elm b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_allvars/user_nl_elm index 67f363bb0a3..2aff9c0b3c2 100644 --- a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_allvars/user_nl_elm +++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_allvars/user_nl_elm @@ -14,8 +14,7 @@ hist_fincl1 = 'FATES_CROWNAREA_PF', 'FATES_CANOPYCROWNAREA_PF', 'FATES_LAISHA_TOP_CL', 'FATES_FABD_SUN_CLLLPF', 'FATES_FABD_SHA_CLLLPF', 'FATES_FABI_SUN_CLLLPF', 'FATES_FABI_SHA_CLLLPF', 'FATES_FABD_SUN_CLLL', 'FATES_FABD_SHA_CLLL', 'FATES_FABI_SUN_CLLL', 'FATES_FABI_SHA_CLLL', -'FATES_PARPROF_DIR_CLLLPF', 'FATES_PARPROF_DIF_CLLLPF', -'FATES_PARPROF_DIR_CLLL', 'FATES_PARPROF_DIF_CLLL', 'FATES_FABD_SUN_TOPLF_CL', +'FATES_PARPROF_DIR_CLLLPF', 'FATES_PARPROF_DIF_CLLLPF','FATES_FABD_SUN_TOPLF_CL', 'FATES_FABD_SHA_TOPLF_CL', 'FATES_FABI_SUN_TOPLF_CL', 'FATES_FABI_SHA_TOPLF_CL', 'FATES_NET_C_UPTAKE_CLLL', 'FATES_CROWNAREA_CLLL', 'FATES_NPLANT_CANOPY_SZAP', 'FATES_NPLANT_USTORY_SZAP', 'FATES_DDBH_CANOPY_SZAP', 'FATES_DDBH_USTORY_SZAP', diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_twostream/README b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_twostream/README new file mode 100644 index 00000000000..8211a863c35 --- /dev/null +++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_twostream/README @@ -0,0 +1,19 @@ +Testing FATES two-stream radiation scheme is activated by switching the fates_rad_model +parameter from 1 to 2. This is all that is needed, both radiation schemes +1) Norman and 2) two-stream use the same optical parameters. + +fates_rad_model + +Note that to avoid exceeding the filename string length maximum, the parameter +file generated on the fly is placed in the $SRCROOT/src/fates/parameter_files +directory. This may still run into problems is the $SRCROOT string is too long. + +Like the test with seed dispersal activation, the main downside of this method is +that this file will require a custom update for every fates parameter file API update. +Allowing the HLM to generate the file at runtime via buildnamelist step +will provide the capability to build the fates parameter file on +the fly which with the appropriate values for this test. + +Note that the test as currently designed is not machine agnostic as it requires +specific shell commands for enabling the workflow to have access to ncgen. Currently +this test is only usable on perlmutter. diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_twostream/include_user_mods b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_twostream/include_user_mods new file mode 100644 index 00000000000..45e8af32d22 --- /dev/null +++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_twostream/include_user_mods @@ -0,0 +1 @@ +../fates_cold diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_twostream/shell_commands b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_twostream/shell_commands new file mode 100644 index 00000000000..e3f2fa482d6 --- /dev/null +++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_twostream/shell_commands @@ -0,0 +1,15 @@ +module load e4s +spack env activate gcc +spack load nco + +SRCDIR=`./xmlquery SRCROOT --value` +CASEDIR=`./xmlquery CASEROOT --value` +FATESDIR=$SRCDIR/components/elm/src/external_models/fates +FATESPARAMFILE=$CASEDIR/fates_params_twostream.nc + +ncgen -o $FATESPARAMFILE $FATESDIR/parameter_files/fates_params_default.cdl + +$FATESDIR/tools/modify_fates_paramfile.py --O --fin $FATESPARAMFILE --fout $FATESPARAMFILE --var fates_rad_model --val 2 --allpfts + +spack unload nco +module unload e4s diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_twostream/user_nl_elm b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_twostream/user_nl_elm new file mode 100644 index 00000000000..cae5fc2112d --- /dev/null +++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/fates_cold_twostream/user_nl_elm @@ -0,0 +1 @@ +fates_paramfile = '$CASEROOT/fates_params_twostream.nc' diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/gis20kmERS/shell_commands b/components/elm/cime_config/testdefs/testmods_dirs/elm/gis20kmERS/shell_commands new file mode 100644 index 00000000000..4547393d872 --- /dev/null +++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/gis20kmERS/shell_commands @@ -0,0 +1,10 @@ +./xmlchange STOP_OPTION=ndays +./xmlchange STOP_N=1 +./xmlchange REST_OPTION=ndays +./xmlchange REST_N=1 +./xmlchange NCPL_BASE_PERIOD=year +./xmlchange ATM_NCPL=17520 +./xmlchange LND_NCPL=17520 +./xmlchange OCN_NCPL=8760 +./xmlchange GLC_NCPL=365 +./xmlchange ROF_NCPL=17520 diff --git a/components/elm/cime_config/testdefs/testmods_dirs/elm/gis20kmSMS/shell_commands b/components/elm/cime_config/testdefs/testmods_dirs/elm/gis20kmSMS/shell_commands new file mode 100644 index 00000000000..adec2de2665 --- /dev/null +++ b/components/elm/cime_config/testdefs/testmods_dirs/elm/gis20kmSMS/shell_commands @@ -0,0 +1,11 @@ +./xmlchange STOP_OPTION=ndays +./xmlchange STOP_N=2 +./xmlchange REST_OPTION=ndays +./xmlchange REST_N=2 +./xmlchange NCPL_BASE_PERIOD=year +./xmlchange ATM_NCPL=17520 +./xmlchange LND_NCPL=17520 +./xmlchange OCN_NCPL=8760 +./xmlchange GLC_NCPL=365 +./xmlchange ROF_NCPL=17520 + diff --git a/components/elm/docs/index.md b/components/elm/docs/index.md index 27c44c3cac1..3c9b7edd07b 100644 --- a/components/elm/docs/index.md +++ b/components/elm/docs/index.md @@ -2,6 +2,6 @@ Some introductory text here -* The [ELM User's Guide](user-guide/index.md) explains how to control ELM when its running within E3SM and how to run in Coupler-bypass mode -* The [ELM Developer's Guide](dev-guide/index.md) explains ELM data structures and how to develop new code. -* The [ELM Techincal Guide](tech-guide/index.md) explains the science behind ELM's code +* The [ELM User Guide](user-guide/index.md) explains how to control ELM when its running within E3SM and how to run in Coupler-bypass mode +* The [ELM Developer Guide](dev-guide/index.md) explains ELM data structures and how to develop new code. +* The [ELM Technical Guide](tech-guide/index.md) explains the science behind ELM's code diff --git a/components/elm/docs/user-guide/fates.md b/components/elm/docs/user-guide/fates.md new file mode 100644 index 00000000000..390f714ee0c --- /dev/null +++ b/components/elm/docs/user-guide/fates.md @@ -0,0 +1,21 @@ +# FATES + +FATES (Functionally Assembled Terrestrial Ecosystem Simulator) is a numerical terrestrial ecosystem model +hat can be utilized as a component with various host land models such as ELM. It is incorporated as an +external module, the development of which is primarily supported by the Department of Energy’s Office of +Science, through the [Next Generation Ecosystem Experiment - Tropics (NGEE-T) project](https://ngee-tropics.lbl.gov/). + +The FATES code is hosted online through a github repository at [https://github.com/NGEET/fates](https://github.com/NGEET/fates). + +## Technical Document + +The full FATES documentation detailing the scientific underpinnings of the model can be found in the +[FATES Technical Document](https://fates-users-guide.readthedocs.io/projects/tech-doc/en/stable/) +hosted on ReadTheDocs. + +## User's and Developer's Guide + +The FATES team also provides a [User's guide](https://fates-users-guide.readthedocs.io/en/latest/user/users-guide.html) +and a [Developer's guide](https://fates-users-guide.readthedocs.io/en/latest/developer/developer-guide.html) +also hosted on ReadTheDocs. Both guides and the technical documentation can be reached from the top level +[User's Guide](https://fates-users-guide.readthedocs.io/en/latest/index.html) diff --git a/components/elm/docs/user-guide/index.md b/components/elm/docs/user-guide/index.md index 0ec3b413c3f..7995e54acb3 100644 --- a/components/elm/docs/user-guide/index.md +++ b/components/elm/docs/user-guide/index.md @@ -1 +1,78 @@ -start of the ELM User's Guide +# ELM User's Guide + +This User's Guide describes how to set up and run ELM. + +## Steps to build and run ELM + +A step-by-step instruction on how to run fully coupled E3SM can be found [here](https://acme-climate.atlassian.net/wiki/spaces/DOC/pages/2309226536). Here we describe running ELM driven by atmospheric forcings provided via the data atmosphere (DATM) model for configurations that are used in the E3SM water cycle v3 campaign. + +The water cycle campaigns of E3SM v1 and v2 used ELM's satellite phenology mode (SP-mode) in which a prescribed leaf area index is used in ELM. However, the E3SM v3 water cycle campaign uses an interactive phenology by including an active biogeochemistry (BGC) cycle in ELM. Additionally, a parameterization of sub-grid topographical effects on solar radiation is included within ELM. + +### Scientifically supported compsets + +The land-only compsets are referred to as "I"-compset and are supported for the following time periods: pre-industrial (1850) and historical transient (20TR). Additionally, multiple atmospheric forcing datasets can be used to drive the ELM simulations. The supported compsets are: + +1. `I1850GSWCNPRDCTCBCTOP`: Pre-industrial ELM simulation using atmospheric forcings from GSWP3 reanalysis dataset +2. `I20TRGSWCNPRDCTCBCTOP`: Historical ELM simulation using GSWP atmospheric forcings with time varying greenhouse gas forcing and land use, land cover dataset (year 1850-2014). + +The E3SM coupler output forcings are most commonly used as an offline land model spinup step, in preparation for a fully-coupled E3SM experiment. + +### Supported grid + +The `r05_r05` is the supported grid resolution for performing offline ELM simulation. + +## Customizing runs + +Few useful changes to `user_nl_elm` + +### Changing monthly output file + +ELM by default outputs monthly history file in `*elm.h0.**.nc` files +that include many variables (>200). At times, many of the default output +variables may not be of interest, thus one could remove all default variables +(via `hist_empty_htapes`) and only include select variables (via `hist_fincl1`) +to the monthly history files by + +```fortran + &elm_inparm + hist_empty_htapes = .true. + hist_fincl1 = 'TG', 'TV', 'FSA' + / +``` + +#### Saving additional output files + +ELM can output additional history files (such as `*elm.h1.*.nc`, `*elm.h2.*.nc`) +that have different temporal averaging (e.g. daily, hourly, every model timestep) via +`hist_nhtfrq` where + +- `-24` corresponds to daily average +- `-1` corresponds to hourly average +- `0` corresponds to monthly average +- `1` corresponds to each model time step + +The number of time slices in these additional files can be controlled +vai `hist_mfilt`. + +```fortran + &elm_inparm + hist_fincl2 = 'TG' + hist_fincl3 = 'TV' + hist_fincl4 = 'TG', 'TV', 'FSA' + hist_nhtfrq = 0, -24, -1, 1 + hist_mfilt = 12, 30, 24, 48 + / +``` + +Using the above-mentioned settings: + +- Each `*.elm.h1.*.nc` will include 30 daily average values of `TG` +- Each `*.elm.h2.*.nc` will include 24 hourly average values of `TV` +- Each `*.elm.h3.*.nc` will include 48 values of `TG`, `TV`, and `FSA` at + each model time step, which is typically is 30 min. + +## Running with FATES + +[FATES](fates.md) can be run in various modes with ELM through the use of namelist settings. +The [FATES User's Guide section on namelist options](https://fates-users-guide.readthedocs.io/en/latest/user/Namelist-Options-and-Run-Time-Modes.html) +provides guidance on enabling these different FATES run modes. diff --git a/components/elm/mkdocs.yml b/components/elm/mkdocs.yml index 900934e3494..55a1c82b2a4 100644 --- a/components/elm/mkdocs.yml +++ b/components/elm/mkdocs.yml @@ -2,6 +2,6 @@ site_name: ELM nav: - Introduction: 'index.md' - - Users's Guide: user-guide/index.md - - Developers's Guide: dev-guide/index.md + - User Guide: user-guide/index.md + - Developer Guide: dev-guide/index.md - Technical Guide: tech-guide/index.md diff --git a/components/elm/src/biogeophys/SnowHydrologyMod.F90 b/components/elm/src/biogeophys/SnowHydrologyMod.F90 index 62f2ba24242..6354dd598b0 100644 --- a/components/elm/src/biogeophys/SnowHydrologyMod.F90 +++ b/components/elm/src/biogeophys/SnowHydrologyMod.F90 @@ -571,14 +571,14 @@ subroutine SnowCompaction(bounds, num_snowc, filter_snowc, & ! parameters real(r8), parameter :: c2 = 23.e-3_r8 ! [m3/kg] real(r8), parameter :: c3 = 2.777e-6_r8 ! [1/s] - real(r8), parameter :: c3_ams = 5.8e-7_r8 ! Schneider et al., 2020 [1/s] + real(r8), parameter :: c3_ams = 0.83e-6_r8 ! Schneider et al.,(2021),Table 2 [1/s] real(r8), parameter :: c4 = 0.04_r8 ! [1/K] real(r8), parameter :: c5 = 2.0_r8 ! real(r8), parameter :: dm = 100.0_r8 ! Upper Limit on Destructive Metamorphism Compaction [kg/m3] - real(r8), parameter :: rho_dm = 150.0_r8 ! Upper limit on destructive metamorphism compaction [kg/m3] (Anderson, 1976; Schneider et al., 2020) + real(r8), parameter :: rho_dm = 150.0_r8 ! Upper limit on destructive metamorphism compaction [kg/m3] (Anderson, 1976;Schneider et al., 2021) real(r8), parameter :: eta0 = 9.e+5_r8 ! The Viscosity Coefficient Eta0 [kg-s/m2] - real(r8), parameter :: k_creep_snow = 1.4e-9_r8 ! Creep coefficient for snow (bi < 550 kg / m3) [m3-s/kg] - real(r8), parameter :: k_creep_firn = 1.2e-9_r8 ! Creep coefficient for firn (bi > 550 kg / m3) + real(r8), parameter :: k_creep_snow = 9.2e-9_r8 ! Creep coefficient for snow (bi < 550 kg / m3) [m3-s/kg] + real(r8), parameter :: k_creep_firn = 3.7e-9_r8 ! Creep coefficient for firn (bi > 550 kg / m3) [m3-s/kg] ! real(r8) :: p_gls ! grain load stress [kg / m-s2] real(r8) :: burden(bounds%begc:bounds%endc) ! pressure of overlying snow [kg/m2] @@ -693,12 +693,12 @@ subroutine SnowCompaction(bounds, num_snowc, filter_snowc, & ddz2 = (-k_creep_snow * (max(denice / bi, 1._r8) - 1._r8) * & exp(-60.e6_r8 / (rgas * t_soisno(c,j))) * p_gls) / & (snw_rds(c,j) * 1.e-6_r8 * snw_rds(c,j) * 1.e-6_r8) - & - 2.02e-10_r8 + 1.0e-10_r8 else ! High density, i.e. firn ddz2 = (-k_creep_firn * (max(denice / bi, 1._r8) - 1._r8) * & exp(-60.e6_r8 / (rgas * t_soisno(c,j))) * p_gls) / & (snw_rds(c,j) * 1.e-6_r8 * snw_rds(c,j) * 1.e-6_r8) - & - 2.7e-11_r8 + 1.0e-10_r8 endif endif diff --git a/components/elm/src/biogeophys/SnowSnicarMod.F90 b/components/elm/src/biogeophys/SnowSnicarMod.F90 index fae56d8927d..d6d6de75ffa 100644 --- a/components/elm/src/biogeophys/SnowSnicarMod.F90 +++ b/components/elm/src/biogeophys/SnowSnicarMod.F90 @@ -80,7 +80,7 @@ module SnowSnicarMod integer, parameter :: snw_rds_max_tbl = 1500 ! maximum effective radius defined in Mie lookup table [microns] integer, parameter :: snw_rds_min_tbl = 30 ! minimium effective radius defined in Mie lookup table [microns] real(r8), parameter :: snw_rds_max = 1500._r8 ! maximum allowed snow effective radius [microns] - real(r8), parameter :: snw_rds_refrz = 1000._r8 ! effective radius of re-frozen snow [microns] + real(r8) :: snw_rds_refrz = 1000._r8 ! effective radius of re-frozen snow [microns] !$acc declare copyin(snw_rds_max_tbl) !$acc declare copyin(snw_rds_min_tbl) !$acc declare copyin(snw_rds_max ) @@ -1441,6 +1441,12 @@ subroutine SnowAge_grain(bounds, & newsnow = max(0._r8, (qflx_snow_grnd_col(c_idx)*dtime)) endif + if (use_extrasnowlayers) then + snw_rds_refrz = 1500._r8 + else + snw_rds_refrz = 1000._r8 + endif + ! snow that has re-frozen [kg/m2] refrzsnow = max(0._r8, (qflx_snofrz_lyr(c_idx,i)*dtime)) diff --git a/components/elm/src/data_types/ColumnDataType.F90 b/components/elm/src/data_types/ColumnDataType.F90 index bc6c935efa5..2d79412e568 100644 --- a/components/elm/src/data_types/ColumnDataType.F90 +++ b/components/elm/src/data_types/ColumnDataType.F90 @@ -18,7 +18,7 @@ module ColumnDataType use elm_varpar , only : nlevdecomp_full, crop_prog, nlevdecomp use elm_varpar , only : i_met_lit, i_cel_lit, i_lig_lit, i_cwd use elm_varcon , only : spval, ispval, zlnd, snw_rds_min, denice, denh2o, tfrz, pondmx - use elm_varcon , only : watmin, bdsno, zsoi, zisoi, dzsoi_decomp + use elm_varcon , only : watmin, bdsno, bdfirn, zsoi, zisoi, dzsoi_decomp use elm_varcon , only : c13ratio, c14ratio, secspday use elm_varctl , only : use_fates, use_fates_planthydro, create_glacier_mec_landunit use elm_varctl , only : use_hydrstress, use_crop @@ -28,6 +28,7 @@ module ColumnDataType use elm_varctl , only : hist_wrtch4diag, use_century_decomp use elm_varctl , only : get_carbontag, override_bgc_restart_mismatch_dump use elm_varctl , only : pf_hmode, nu_com + use elm_varctl , only : use_extrasnowlayers use elm_varctl , only : use_fan use ch4varcon , only : allowlakeprod use pftvarcon , only : VMAX_MINSURF_P_vr, KM_MINSURF_P_vr, pinit_beta1, pinit_beta2 @@ -1742,8 +1743,20 @@ subroutine col_ws_init(this, begc, endc, h2osno_input, snow_depth_input, watsat_ end do do j = -nlevsno+1, 0 if (j > col_pp%snl(c)) then - this%h2osoi_ice(c,j) = col_pp%dz(c,j)*250._r8 - this%h2osoi_liq(c,j) = 0._r8 + if (use_extrasnowlayers) then + ! amschnei@uci.edu: Initialize "deep firn" on glacier columns + if (lun_pp%itype(l) == istice .or. lun_pp%itype(l) == istice_mec) then + this%h2osoi_ice(c,j) = col_pp%dz(c,j)*bdfirn + this%h2osoi_liq(c,j) = 0._r8 + else + this%h2osoi_ice(c,j) = col_pp%dz(c,j)*bdsno + this%h2osoi_liq(c,j) = 0._r8 + end if + else ! no firn model (default in v2) + ! Below, "250._r8" should instead be "bdsno", which is 250 kg m^3 by default + this%h2osoi_ice(c,j) = col_pp%dz(c,j)*250._r8 + this%h2osoi_liq(c,j) = 0._r8 + end if end if end do end if @@ -5830,26 +5843,20 @@ subroutine col_wf_init(this, begc, endc) avgflag='A', long_name='column-integrated snow freezing rate', & ptr_col=this%qflx_snofrz, set_lake=spval, c2l_scale_type='urbanf', default='inactive') - if (create_glacier_mec_landunit) then - this%qflx_glcice(begc:endc) = spval - call hist_addfld1d (fname='QICE', units='mm/s', & - avgflag='A', long_name='ice growth/melt', & - ptr_col=this%qflx_glcice, l2g_scale_type='ice') - end if - - if (create_glacier_mec_landunit) then - this%qflx_glcice_frz(begc:endc) = spval - call hist_addfld1d (fname='QICE_FRZ', units='mm/s', & - avgflag='A', long_name='ice growth', & - ptr_col=this%qflx_glcice_frz, l2g_scale_type='ice') - end if + this%qflx_glcice(begc:endc) = spval + call hist_addfld1d (fname='QICE', units='mm/s', & + avgflag='A', long_name='ice growth/melt', & + ptr_col=this%qflx_glcice, l2g_scale_type='ice') - if (create_glacier_mec_landunit) then - this%qflx_glcice_melt(begc:endc) = spval - call hist_addfld1d (fname='QICE_MELT', units='mm/s', & - avgflag='A', long_name='ice melt', & - ptr_col=this%qflx_glcice_melt, l2g_scale_type='ice') - end if + this%qflx_glcice_frz(begc:endc) = spval + call hist_addfld1d (fname='QICE_FRZ', units='mm/s', & + avgflag='A', long_name='ice growth', & + ptr_col=this%qflx_glcice_frz, l2g_scale_type='ice') + + this%qflx_glcice_melt(begc:endc) = spval + call hist_addfld1d (fname='QICE_MELT', units='mm/s', & + avgflag='A', long_name='ice melt', & + ptr_col=this%qflx_glcice_melt, l2g_scale_type='ice') ! As defined here, snow_sources - snow_sinks will equal the change in h2osno at any ! given time step but only if there is at least one snow layer (for all landunits diff --git a/components/elm/src/external_models/fates b/components/elm/src/external_models/fates index 698a8df848e..42d804ba54d 160000 --- a/components/elm/src/external_models/fates +++ b/components/elm/src/external_models/fates @@ -1 +1 @@ -Subproject commit 698a8df848ecdb81aa72fee6c86be2c41b2545e9 +Subproject commit 42d804ba54d0cf013a9737018ff9920e0c9808ea diff --git a/components/elm/src/main/elm_instMod.F90 b/components/elm/src/main/elm_instMod.F90 index ce5fb9bda4e..b8afca87e24 100644 --- a/components/elm/src/main/elm_instMod.F90 +++ b/components/elm/src/main/elm_instMod.F90 @@ -262,7 +262,7 @@ subroutine elm_inst_biogeophys(bounds_proc) ! use shr_scam_mod , only : shr_scam_getCloseLatLon use landunit_varcon , only : istice, istice_mec, istsoil - use elm_varcon , only : h2osno_max, bdsno + use elm_varcon , only : h2osno_max, bdsno, bdfirn use domainMod , only : ldomain use elm_varpar , only : nlevsno, numpft use elm_varctl , only : single_column, fsurdat, scmlat, scmlon, use_extrasnowlayers @@ -318,8 +318,18 @@ subroutine elm_inst_biogeophys(bounds_proc) else h2osno_col(c) = 0._r8 endif - else ! With a deeper firn model, we can no longer depend on "h2osno_max," because this will - ! potentially be large, resulting in a lot of artificial firn at initialization. + snow_depth_col(c) = h2osno_col(c) / bdsno + else! With a deeper firn model, we can no longer depend on "h2osno_max," because this will + ! potentially be large, resulting in a lot of artificial firn at initialization. ! + ! amschnei@uci.edu: UPDATE - By including a new parameter, bdfirn, we can + ! initialize a dense (e.g, 730 kd m^-3) "deep firn" layer for glacier + ! land units. This deep firn layer can be set to half of the total + ! maximum allotted snowpack mass (i.e., "h2osno_max"), which effectively + ! sets the Greenland and Antarctic ice sheets' (and mountain glaciers') + ! climatic (aka surface) mass balance (SMB) initial condition to 0. With this + ! cold start condition, a multi-decadal (100 to 300 years or more) + ! spin up is first required to prognose nonzero SMB. + ! ! However... (below docstring from CLMv5) ! In areas that should be snow-covered, it can be problematic to start with 0 snow ! cover, because this can affect the long-term state through soil heating, albedo @@ -328,14 +338,18 @@ subroutine elm_inst_biogeophys(bounds_proc) ! feedback may not activate on time (or at all). So, as a compromise, we start with ! a small amount of snow in places that are likely to be snow-covered for much or ! all of the year. + ! amschnei@uci.edu: Initializing "deep firn" for glacier columns if (lun_pp%itype(l)==istice .or. lun_pp%itype(l)==istice_mec) then ! land ice (including multiple elevation classes, i.e. glacier_mec) - h2osno_col(c) = 50._r8 + h2osno_col(c) = 0.5_r8*h2osno_max ! start with half full snow column, representing deep firn + snow_depth_col(c) = h2osno_col(c) / bdfirn else if (lun_pp%itype(l)==istsoil .and. grc_pp%latdeg(g) >= 44._r8) then ! Northern hemisphere seasonal snow h2osno_col(c) = 50._r8 + snow_depth_col(c) = h2osno_col(c) / bdsno else h2osno_col(c) = 0._r8 + snow_depth_col(c) = h2osno_col(c) / bdsno endif endif snow_depth_col(c) = h2osno_col(c) / bdsno diff --git a/components/elm/src/main/elm_varcon.F90 b/components/elm/src/main/elm_varcon.F90 index 3a95fc05c52..01df6ce0afd 100644 --- a/components/elm/src/main/elm_varcon.F90 +++ b/components/elm/src/main/elm_varcon.F90 @@ -67,6 +67,7 @@ module elm_varcon real(r8) :: oneatm = 1.01325e5_r8 ! one standard atmospheric pressure [Pa] real(r8) :: bdsno = 250._r8 ! bulk density snow (kg/m**3) + real(r8) :: bdfirn = 730._r8 ! bulk density of deep firn (kg/m**3) real(r8) :: alpha_aero = 1.0_r8 ! constant for aerodynamic parameter weighting real(r8) :: tlsai_crit = 2.0_r8 ! critical value of elai+esai for which aerodynamic parameters are maximum real(r8) :: watmin = 0.01_r8 ! minimum soil moisture (mm) @@ -248,7 +249,7 @@ subroutine elm_varcon_init() allocate( dzsoifl(1:nlevsoifl )) if (use_extrasnowlayers) then - h2osno_max = 10000._r8 + h2osno_max = 30000._r8 end if end subroutine elm_varcon_init diff --git a/components/elm/src/main/elmfates_interfaceMod.F90 b/components/elm/src/main/elmfates_interfaceMod.F90 index edcdd01f1ed..9b9fbc6e390 100644 --- a/components/elm/src/main/elmfates_interfaceMod.F90 +++ b/components/elm/src/main/elmfates_interfaceMod.F90 @@ -149,7 +149,8 @@ module ELMFatesInterfaceMod use EDInitMod , only : init_patches use EDInitMod , only : set_site_properties use EDPftVarcon , only : EDpftvarcon_inst - use EDSurfaceRadiationMod , only : ED_SunShadeFracs, ED_Norman_Radiation + use FatesRadiationDriveMod, only : FatesSunShadeFracs + use FatesRadiationDriveMod, only : FatesNormalizedCanopyRadiation use EDBtranMod , only : btran_ed, & get_active_suction_layers use EDCanopyStructureMod , only : canopy_summarization, update_hlm_dynamics @@ -519,7 +520,7 @@ subroutine ELMFatesGlobals2() call set_fates_ctrlparms('num_lu_harvest_cats',ival=pass_num_lu_harvest_types) call set_fates_ctrlparms('use_logging',ival=pass_logging) - if(use_fates_luh) then + if (use_fates_luh) then pass_use_luh = 1 pass_num_luh_states = num_landuse_state_vars pass_num_luh_transitions = num_landuse_transition_vars @@ -2055,7 +2056,7 @@ subroutine wrap_sunfrac(this,bounds_clump,top_af_inst,canopystate_inst) ! as well as total patch sun/shade fraction output boundary condition ! ------------------------------------------------------------------------------- - call ED_SunShadeFracs(this%fates(nc)%nsites, & + call FatesSunShadeFracs(this%fates(nc)%nsites, & this%fates(nc)%sites, & this%fates(nc)%bc_in, & this%fates(nc)%bc_out) @@ -2563,7 +2564,7 @@ subroutine wrap_canopy_radiation(this, bounds_clump, & end do end do - call ED_Norman_Radiation(this%fates(nc)%nsites, & + call FatesNormalizedCanopyRadiation(this%fates(nc)%nsites, & this%fates(nc)%sites, & this%fates(nc)%bc_in, & this%fates(nc)%bc_out) diff --git a/components/homme/CMakeLists.txt b/components/homme/CMakeLists.txt index c016182e3bf..fdb996fa17a 100644 --- a/components/homme/CMakeLists.txt +++ b/components/homme/CMakeLists.txt @@ -447,18 +447,22 @@ if(HOMME_BUILD_EXECS AND NOT BUILD_HOMME_WITHOUT_PIOLIBRARY) ENDIF () ENDIF () -# If we don't need kokkos we don't need EKAT, and if -# Homme is built in EAMxx EKAT is already built -IF (HOMME_USE_KOKKOS AND HOMME_STANDALONE) - # Add ekat's cmake/pkg_build folder to cmake path +IF (HOMME_USE_KOKKOS) + # Add ekat's cmake scripts folders to cmake path set (EKAT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../externals/ekat) set (EKAT_CMAKE_PATH ${EKAT_SOURCE_DIR}/cmake) list(APPEND CMAKE_MODULE_PATH - ${EKAT_CMAKE_PATH} - ${EKAT_CMAKE_PATH}/pkg_build - ${EKAT_CMAKE_PATH}/tpls + ${EKAT_CMAKE_PATH} + ${EKAT_CMAKE_PATH}/tpls ) - include (EkatBuildKokkos) + + # We first try to use find_package. If that doesn't work, build from EKAT's submodule + include (EkatFindKokkos) + if (NOT Kokkos_FOUND) + # The following script checks if Kokkos is already available as a target, and if so does nothing. + # For instance, if HOMME is built inside EAMxx, Kokkos will already be available + include (EkatBuildKokkos) + endif() ENDIF () # This folder contains the CMake macro used to build cxx unit tests diff --git a/components/homme/cmake/SetCompilerFlags.cmake b/components/homme/cmake/SetCompilerFlags.cmake index 49e79a463c4..9a37c6a36bd 100644 --- a/components/homme/cmake/SetCompilerFlags.cmake +++ b/components/homme/cmake/SetCompilerFlags.cmake @@ -68,12 +68,6 @@ IF (${HOMME_USE_CXX}) SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g") INCLUDE(CheckCXXCompilerFlag) - CHECK_CXX_COMPILER_FLAG("-std=c++14" CXX14_SUPPORTED) - IF (CXX14_SUPPORTED) - SET (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") - ELSEIF (${HOMME_USE_KOKKOS}) - MESSAGE (FATAL_ERROR "Kokkos needs C++14, but the C++ compiler does not support it.") - ENDIF () CHECK_CXX_COMPILER_FLAG("-cxxlib" CXXLIB_SUPPORTED) IF (CXXLIB_SUPPORTED) SET(CXXLIB_SUPPORTED_CACHE TRUE CACHE BOOL "") diff --git a/components/homme/src/preqx_kokkos/CMakeLists.txt b/components/homme/src/preqx_kokkos/CMakeLists.txt index 425e7c34da7..dff42bb97c6 100644 --- a/components/homme/src/preqx_kokkos/CMakeLists.txt +++ b/components/homme/src/preqx_kokkos/CMakeLists.txt @@ -168,6 +168,8 @@ MACRO(PREQX_KOKKOS_SETUP) ${SRC_SHARE_DIR}/cxx/EulerStepFunctor.cpp ${SRC_SHARE_DIR}/cxx/ExecSpaceDefs.cpp ${SRC_SHARE_DIR}/cxx/FunctorsBuffersManager.cpp + ${SRC_SHARE_DIR}/cxx/GllFvRemap.cpp + ${SRC_SHARE_DIR}/cxx/GllFvRemapImpl.cpp ${SRC_SHARE_DIR}/cxx/Hommexx_Session.cpp ${SRC_SHARE_DIR}/cxx/HybridVCoord.cpp ${SRC_SHARE_DIR}/cxx/HyperviscosityFunctor.cpp diff --git a/components/homme/src/preqx_kokkos/config.h.cmake.in b/components/homme/src/preqx_kokkos/config.h.cmake.in index c0bc4c311c3..119844f3def 100644 --- a/components/homme/src/preqx_kokkos/config.h.cmake.in +++ b/components/homme/src/preqx_kokkos/config.h.cmake.in @@ -58,9 +58,8 @@ /* ZOLTAN2 SUBPACKAGE OF TRILINOS library */ #cmakedefine01 TRILINOS_HAVE_ZOLTAN2 -/* When doing BFB testing, we occasionally must use modified code. */ -/* Use this flag to protect such code. */ -#cmakedefine HOMMEXX_BFB_TESTING +/* Detect whether this is a kokkos target */ +#cmakedefine01 KOKKOS_TARGET /* Whether to use OpenMP4 */ #cmakedefine OMP4 diff --git a/components/homme/src/share/compose/cedr_util.hpp b/components/homme/src/share/compose/cedr_util.hpp index 52a1a4d77b5..6d5ca7fecf5 100644 --- a/components/homme/src/share/compose/cedr_util.hpp +++ b/components/homme/src/share/compose/cedr_util.hpp @@ -4,11 +4,12 @@ #ifndef INCLUDE_CEDR_UTIL_HPP #define INCLUDE_CEDR_UTIL_HPP -#include - #include "cedr_kokkos.hpp" #include "cedr_mpi.hpp" +#include // For std::stringstream +#include // For std::cerr + namespace cedr { namespace util { diff --git a/components/homme/src/share/compose/compose_slmm.cpp b/components/homme/src/share/compose/compose_slmm.cpp index b8277b5423c..27ab1e1a7d0 100644 --- a/components/homme/src/share/compose/compose_slmm.cpp +++ b/components/homme/src/share/compose/compose_slmm.cpp @@ -276,8 +276,6 @@ extern "C" { // Interface for Homme, through compose_mod.F90. void kokkos_init () { amb::dev_init_threads(); - Kokkos::InitArguments args; - args.disable_warnings = true; initialize_kokkos(); // Test these initialize correctly. Kokkos::View v("hi"); diff --git a/components/homme/src/share/compose/compose_slmm_siqk.cpp b/components/homme/src/share/compose/compose_slmm_siqk.cpp index 5f8c4474df1..628c023090c 100644 --- a/components/homme/src/share/compose/compose_slmm_siqk.cpp +++ b/components/homme/src/share/compose/compose_slmm_siqk.cpp @@ -75,7 +75,7 @@ class TestSphereToRefKernel { } KOKKOS_INLINE_FUNCTION - void join (volatile value_type& dst, volatile value_type const& src) const { + void join (value_type& dst, value_type const& src) const { dst.max_nits = max(dst.max_nits, src.max_nits); dst.sum_nits += src.sum_nits; dst.nfails += src.nfails; diff --git a/components/homme/src/share/cxx/ExecSpaceDefs.cpp b/components/homme/src/share/cxx/ExecSpaceDefs.cpp index 784d37b65d2..8d496bff5d1 100644 --- a/components/homme/src/share/cxx/ExecSpaceDefs.cpp +++ b/components/homme/src/share/cxx/ExecSpaceDefs.cpp @@ -187,7 +187,7 @@ team_num_threads_vectors (const int num_parallel_iterations, #elif defined(KOKKOS_ENABLE_HIP) // Use 64 wavefronts per CU and 120 CUs. const int num_warps_device = 120*64; // no such thing Kokkos::Impl::hip_internal_maximum_warp_count(); - const int num_threads_warp = Kokkos::Experimental::Impl::HIPTraits::WarpSize; + const int num_threads_warp = Kokkos::Impl::HIPTraits::WarpSize; #else // I want thread-distribution rules to be unit-testable even when GPU spaces // are off. Thus, make up a GPU-like machine: diff --git a/components/homme/src/share/cxx/ExecSpaceDefs.hpp b/components/homme/src/share/cxx/ExecSpaceDefs.hpp index 8c18d8bcbb9..fbcd314cb2b 100644 --- a/components/homme/src/share/cxx/ExecSpaceDefs.hpp +++ b/components/homme/src/share/cxx/ExecSpaceDefs.hpp @@ -143,11 +143,7 @@ struct DefaultThreadsDistribution { team_num_threads_vectors(const int num_parallel_iterations, const ThreadPreferences tp = ThreadPreferences()) { return Parallel::team_num_threads_vectors_from_pool( -#ifdef KOKKOS_ENABLE_DEPRECATED_CODE - ExecSpaceType::thread_pool_size() -#else - ExecSpaceType::impl_thread_pool_size() -#endif + ExecSpaceType().impl_thread_pool_size() , num_parallel_iterations, tp); } }; diff --git a/components/eam/src/dynamics/se/semoab_mod.F90 b/components/homme/src/share/semoab_mod.F90 similarity index 92% rename from components/eam/src/dynamics/se/semoab_mod.F90 rename to components/homme/src/share/semoab_mod.F90 index 984b9793df4..2d8bb099ade 100644 --- a/components/eam/src/dynamics/se/semoab_mod.F90 +++ b/components/homme/src/share/semoab_mod.F90 @@ -12,12 +12,10 @@ module semoab_mod use dimensions_mod, only: nelem, ne, np, nelemd, nlev use element_mod, only : element_t - use parallel_mod, only : parallel_t + use parallel_mod, only : parallel_t, abortmp use m_MergeSorts, only: IndexSet, IndexSort - use cam_grid_support, only: iMap - use cam_abortutils, only : endrun use edgetype_mod, only: edgedescriptor_t use gridgraph_mod, only: gridvertex_t @@ -209,8 +207,10 @@ subroutine create_moab_meshes(par, elem) if ( nelemd > 0 ) then allocate(moab_vert_coords(3*nverts) ) allocate(vdone(nverts)) - vdone = 0; + else + allocate(vdone(1)) ! will be passed to iMOAB_ResolveSharedEnts, and compilers are complaining about non-allocated arrays endif + vdone = 0; if ( nelemd > 0 ) currentval = gdofv( indx(1)) ! start over to identify coordinates of the vertices do ix=1,moab_dim_cquads @@ -251,7 +251,7 @@ subroutine create_moab_meshes(par, elem) if ( nelemd > 0 ) then ierr = iMOAB_CreateVertices(MHFID, dimcoord, dimen, moab_vert_coords) if (ierr > 0 ) & - call endrun('Error: fail to create MOAB vertices ') + call abortmp('Error: fail to create MOAB vertices ') endif !!num_el = nelemd2 mbtype = 3 ! quadrilateral @@ -261,7 +261,7 @@ subroutine create_moab_meshes(par, elem) if ( nelemd > 0 ) then ierr = iMOAB_CreateElements( MHFID, nelemd2, mbtype, nve, moabconn, block_ID ); if (ierr > 0 ) & - call endrun('Error: fail to create MOAB elements') + call abortmp('Error: fail to create MOAB elements') endif ! nverts: num vertices; vdone will store now the markers used in global resolve ! for this particular problem, markers are the global dofs at corner nodes @@ -272,18 +272,19 @@ subroutine create_moab_meshes(par, elem) numco = 1 ierr = iMOAB_DefineTagStorage(MHFID, tagname, tagtype, numco, tagindex ) if (ierr > 0 ) & - call endrun('Error: fail to retrieve global id tag') + call abortmp('Error: fail to retrieve global id tag') ! now set the values ent_type = 0 ! vertex type if ( nverts > 0 ) then ierr = iMOAB_SetIntTagStorage ( MHFID, tagname, nverts , ent_type, vdone) if (ierr > 0 ) & - call endrun('Error: fail to set marker id tag for vertices') + call abortmp('Error: fail to set marker id tag for vertices') endif + ! we need to call this even when no mesh locally, it involves a collective ierr = iMOAB_ResolveSharedEntities( MHFID, nverts, vdone ); if (ierr > 0 ) & - call endrun('Error: fail to resolve shared entities') + call abortmp('Error: fail to resolve shared entities') if ( nelemd > 0) then vdone = -1 ! reuse vdone for the new tag, GLOBAL_ID (actual tag that we want to store global dof ) @@ -294,7 +295,7 @@ subroutine create_moab_meshes(par, elem) newtagg='GLOBAL_ID'//C_NULL_CHAR ierr = iMOAB_DefineTagStorage(MHFID, newtagg, tagtype, numco, tagindex ) if (ierr > 0 ) & - call endrun('Error: fail to create new GDOF tag') + call abortmp('Error: fail to create new GDOF tag') do ie=1,nelemd do ii=1,elem(ie)%idxp%NumUniquePts i=elem(ie)%idxp%ia(ii) @@ -310,19 +311,19 @@ subroutine create_moab_meshes(par, elem) if ( nverts > 0 ) then ierr = iMOAB_SetIntTagStorage ( MHFID, newtagg, nverts , ent_type, vdone) if (ierr > 0 ) & - call endrun('Error: fail to set global dof tag for vertices') + call abortmp('Error: fail to set global dof tag for vertices') endif ierr = iMOAB_ReduceTagsMax ( MHFID, tagindex, ent_type) if (ierr > 0 ) & - call endrun('Error: fail to reduce max tag') + call abortmp('Error: fail to reduce max tag') ! set global id tag for elements ent_type = 1 ! now set the global id tag on elements if ( nelemd2 > 0 ) then ierr = iMOAB_SetIntTagStorage ( MHFID, newtagg, nelemd2 , ent_type, elemids) if (ierr > 0 ) & - call endrun('Error: fail to set global id tag for elements') + call abortmp('Error: fail to set global id tag for elements') endif ! now, after reduction, we can get the actual global ids for each vertex in the fine mesh @@ -333,18 +334,18 @@ subroutine create_moab_meshes(par, elem) allocate(vgids(nverts)) ierr = iMOAB_GetIntTagStorage ( MHFID, newtagg, nverts , ent_type, vgids) if (ierr > 0 ) & - call endrun('Error: fail to retrieve GLOBAL ID on each task') + call abortmp('Error: fail to retrieve GLOBAL ID on each task') endif ierr = iMOAB_UpdateMeshInfo(MHFID) if (ierr > 0 ) & - call endrun('Error: fail to update mesh info') + call abortmp('Error: fail to update mesh info') #ifdef MOABDEBUG ! write out the mesh file to disk, in parallel outfile = 'wholeFineATM.h5m'//C_NULL_CHAR wopts = 'PARALLEL=WRITE_PART'//C_NULL_CHAR ierr = iMOAB_WriteMesh(MHFID, outfile, wopts) if (ierr > 0 ) & - call endrun('Error: fail to write the mesh file') + call abortmp('Error: fail to write the mesh file') #endif @@ -422,7 +423,7 @@ subroutine create_moab_meshes(par, elem) if ( nverts_c > 0 ) then ierr = iMOAB_CreateVertices(MHID, dimcoord, dimen, moab_vert_coords) if (ierr > 0 ) & - call endrun('Error: fail to create MOAB vertices ') + call abortmp('Error: fail to create MOAB vertices ') endif ! num_el = nelemd mbtype = 3 ! quadrilateral @@ -432,7 +433,7 @@ subroutine create_moab_meshes(par, elem) if ( nelemd > 0 ) then ierr = iMOAB_CreateElements( MHID, nelemd, mbtype, nve, moabconn_c, block_ID ); if (ierr > 0 ) & - call endrun('Error: fail to create MOAB elements') + call abortmp('Error: fail to create MOAB elements') endif ! idx: num vertices; vdone will store now the markers used in global resolve ! for this particular problem, markers are the global dofs at corner nodes @@ -443,28 +444,28 @@ subroutine create_moab_meshes(par, elem) numco = 1 ierr = iMOAB_DefineTagStorage(MHID, tagname, tagtype, numco, tagindex ) if (ierr > 0 ) & - call endrun('Error: fail to retrieve GDOFV id tag') + call abortmp('Error: fail to retrieve GDOFV id tag') ierr = iMOAB_DefineTagStorage(MHID, newtagg, tagtype, numco, tagindex ) if (ierr > 0 ) & - call endrun('Error: fail to retrieve GLOBAL_ID tag on coarse mesh') + call abortmp('Error: fail to retrieve GLOBAL_ID tag on coarse mesh') ! now set the values ent_type = 0 ! vertex type if ( nverts_c > 0 ) then ierr = iMOAB_SetIntTagStorage ( MHID, tagname, nverts_c , ent_type, vdone_c) if (ierr > 0 ) & - call endrun('Error: fail to set GDOFV tag for vertices') + call abortmp('Error: fail to set GDOFV tag for vertices') endif ! set global id tag for coarse elements, too; they will start at nets=1, end at nete=nelemd ent_type = 1 ! now set the global id tag on elements if ( nelemd > 0 ) then ierr = iMOAB_SetIntTagStorage ( MHID, newtagg, nelemd , ent_type, elemids) if (ierr > 0 ) & - call endrun('Error: fail to set global id tag for vertices') + call abortmp('Error: fail to set global id tag for vertices') endif ierr = iMOAB_ResolveSharedEntities( MHID, idx, vdone_c ); if (ierr > 0 ) & - call endrun('Error: fail to resolve shared entities') + call abortmp('Error: fail to resolve shared entities') ! global dofs are the GLL points are set for each element tagname='GLOBAL_DOFS'//C_NULL_CHAR @@ -472,7 +473,7 @@ subroutine create_moab_meshes(par, elem) numco = np*np ! usually, it is 16; each element will have the dofs in order ierr = iMOAB_DefineTagStorage(MHID, tagname, tagtype, numco, tagindex ) if (ierr > 0 ) & - call endrun('Error: fail to create global DOFS tag') + call abortmp('Error: fail to create global DOFS tag') ! now set the values ! set global dofs tag for coarse elements, too; they will start at nets=1, end at nete=nelemd ent_type = 1 ! now set the global id tag on elements @@ -499,7 +500,7 @@ subroutine create_moab_meshes(par, elem) if ( nelemd > 0 ) then ierr = iMOAB_SetIntTagStorage ( MHID, tagname, numvals, ent_type, gdofel) if (ierr > 0 ) & - call endrun('Error: fail to set globalDOFs tag for coarse elements') + call abortmp('Error: fail to set globalDOFs tag for coarse elements') endif ! set the global ids for coarse vertices the same as corresponding fine vertices @@ -507,19 +508,19 @@ subroutine create_moab_meshes(par, elem) if ( nverts_c > 0 ) then ierr = iMOAB_SetIntTagStorage ( MHID, newtagg, nverts_c , ent_type, vdone_c) if (ierr > 0 ) & - call endrun('Error: fail to set GLOBAL_DOFS tag values') + call abortmp('Error: fail to set GLOBAL_DOFS tag values') endif ierr = iMOAB_UpdateMeshInfo(MHID) if (ierr > 0 ) & - call endrun('Error: fail to update mesh info') + call abortmp('Error: fail to update mesh info') #ifdef MOABDEBUG ! write out the mesh file to disk, in parallel outfile = 'wholeATM.h5m'//C_NULL_CHAR wopts = 'PARALLEL=WRITE_PART'//C_NULL_CHAR ierr = iMOAB_WriteMesh(MHID, outfile, wopts) if (ierr > 0 ) & - call endrun('Error: fail to write the mesh file') + call abortmp('Error: fail to write the mesh file') #endif if (fv_nphys > 0 ) then @@ -629,6 +630,8 @@ subroutine create_moab_meshes(par, elem) ! reuse moab_vert_coords for coordinates of pg mesh ! the first nverts_c coords are the same as coarse mesh; but we do create new allocate(vdone_pg(nverts_pg)) + else + allocate(vdone_pg(1)) endif do iv = 1, nverts_c vdone_pg(iv) = vdone_c(iv) ! also the coordinates will be the same !! @@ -737,7 +740,7 @@ subroutine create_moab_meshes(par, elem) if ( nverts_pg > 0 ) then ierr = iMOAB_CreateVertices(MHPGID, dimcoord, dimen, moab_vert_coords) if (ierr > 0 ) & - call endrun('Error: fail to create MOAB vertices ') + call abortmp('Error: fail to create MOAB vertices ') endif ! num_el = nelem_pg * mbtype = 3 ! quadrilateral @@ -747,44 +750,45 @@ subroutine create_moab_meshes(par, elem) if ( nelem_pg > 0 ) then ierr = iMOAB_CreateElements( MHPGID, nelem_pg, mbtype, nve, moabconn_pg, block_ID ); if (ierr > 0 ) & - call endrun('Error: fail to create MOAB elements') + call abortmp('Error: fail to create MOAB elements') endif tagname='GLOBAL_ID'//C_NULL_CHAR tagtype = 0 ! dense, integer numco = 1 ierr = iMOAB_DefineTagStorage(MHPGID, tagname, tagtype, numco, tagindex ) if (ierr > 0 ) & - call endrun('Error: fail to retrieve GLOBAL id tag') + call abortmp('Error: fail to retrieve GLOBAL id tag') ! now set the values ent_type = 0 ! vertex type if ( nverts_pg > 0 ) then ierr = iMOAB_SetIntTagStorage ( MHPGID, tagname, nverts_pg , ent_type, vdone_pg) if (ierr > 0 ) & - call endrun('Error: fail to set global id tag for vertices') + call abortmp('Error: fail to set global id tag for vertices') endif ! set global id tag for pg2 elements, too; they will start at nets=1, end at nete=nelemd*4 ent_type = 1 ! now set the global id tag on elements if ( nelem_pg > 0 ) then ierr = iMOAB_SetIntTagStorage ( MHPGID, tagname, nelem_pg , ent_type, elemids) if (ierr > 0 ) & - call endrun('Error: fail to set global id tag for edges') + call abortmp('Error: fail to set global id tag for edges') endif + ! this involves a collective, vdone_pg can be empty ierr = iMOAB_ResolveSharedEntities( MHPGID, nverts_pg, vdone_pg ); if (ierr > 0 ) & - call endrun('Error: fail to resolve shared ents for pg2 mesh') + call abortmp('Error: fail to resolve shared ents for pg2 mesh') ierr = iMOAB_UpdateMeshInfo(MHPGID) if (ierr > 0 ) & - call endrun('Error: fail to update mesh info for pg2 mesh') + call abortmp('Error: fail to update mesh info for pg2 mesh') #ifdef MOABDEBUG ! write out the mesh file to disk, in parallel outfile = 'wholeATM_PG2.h5m'//C_NULL_CHAR wopts = 'PARALLEL=WRITE_PART'//C_NULL_CHAR ierr = iMOAB_WriteMesh(MHPGID, outfile, wopts) if (ierr > 0 ) & - call endrun('Error: fail to write the mesh file') + call abortmp('Error: fail to write the mesh file') #endif endif ! only valid for pg == 2 if ( nelemd > 0 ) then @@ -792,16 +796,14 @@ subroutine create_moab_meshes(par, elem) deallocate (indx_cell) deallocate (edge) ! deallocate(moabconn_pg) ! connectivity - deallocate(vdone_pg) endif - + deallocate(vdone_pg) ! this is now always allocated/deallocated, even for no mesh here endif ! deallocate if ( nelemd > 0 ) then deallocate(moabvh) deallocate(moabconn) ! do not keep it anymore, we are not setting another tag on fine mesh - deallocate(vdone) deallocate(gdofel) deallocate(indx) deallocate(elemids) @@ -810,6 +812,7 @@ subroutine create_moab_meshes(par, elem) deallocate(moabconn_c) deallocate(vdone_c) endif + deallocate(vdone) ! we are always allocating this now ! end copy end subroutine create_moab_meshes diff --git a/components/homme/test_execs/preqx_kokkos_ut/remap_preqx_ut.cpp b/components/homme/test_execs/preqx_kokkos_ut/remap_preqx_ut.cpp index 480c3782931..771376e959f 100644 --- a/components/homme/test_execs/preqx_kokkos_ut/remap_preqx_ut.cpp +++ b/components/homme/test_execs/preqx_kokkos_ut/remap_preqx_ut.cpp @@ -10,6 +10,7 @@ #include "utilities/TestUtils.hpp" #include +#include TEST_CASE("remap_interface", "vertical remap") { diff --git a/components/homme/test_execs/share_kokkos_ut/boundary_exchange_ut.cpp b/components/homme/test_execs/share_kokkos_ut/boundary_exchange_ut.cpp index 12a7e9a1673..ad15a1c10bd 100644 --- a/components/homme/test_execs/share_kokkos_ut/boundary_exchange_ut.cpp +++ b/components/homme/test_execs/share_kokkos_ut/boundary_exchange_ut.cpp @@ -11,6 +11,7 @@ #include #include +#include using namespace Homme; diff --git a/components/homme/test_execs/share_kokkos_ut/col_ops_ut.cpp b/components/homme/test_execs/share_kokkos_ut/col_ops_ut.cpp index b27b3f3281b..85368cd6ab0 100644 --- a/components/homme/test_execs/share_kokkos_ut/col_ops_ut.cpp +++ b/components/homme/test_execs/share_kokkos_ut/col_ops_ut.cpp @@ -1,15 +1,17 @@ #include -#include - #include "ColumnOps.hpp" -#include "Types.hpp" #include "utilities/TestUtils.hpp" #include "utilities/SubviewUtils.hpp" #include "utilities/SyncUtils.hpp" #include "utilities/ViewUtils.hpp" +#include "Types.hpp" + +#include +#include + using namespace Homme; diff --git a/components/homme/test_execs/share_kokkos_ut/ppm_remap_ut.cpp b/components/homme/test_execs/share_kokkos_ut/ppm_remap_ut.cpp index 5fe4a9c2163..401a029607f 100644 --- a/components/homme/test_execs/share_kokkos_ut/ppm_remap_ut.cpp +++ b/components/homme/test_execs/share_kokkos_ut/ppm_remap_ut.cpp @@ -8,6 +8,7 @@ #include "utilities/TestUtils.hpp" #include +#include using namespace Homme; diff --git a/components/homme/test_execs/share_kokkos_ut/sphere_op_ml.cpp b/components/homme/test_execs/share_kokkos_ut/sphere_op_ml.cpp index e4cbb4ec459..e261b60b390 100644 --- a/components/homme/test_execs/share_kokkos_ut/sphere_op_ml.cpp +++ b/components/homme/test_execs/share_kokkos_ut/sphere_op_ml.cpp @@ -13,6 +13,7 @@ #include #include #include +#include using namespace Homme; diff --git a/components/homme/test_execs/share_kokkos_ut/sphere_op_sl.cpp b/components/homme/test_execs/share_kokkos_ut/sphere_op_sl.cpp index 26cec000976..fd2f79fabae 100644 --- a/components/homme/test_execs/share_kokkos_ut/sphere_op_sl.cpp +++ b/components/homme/test_execs/share_kokkos_ut/sphere_op_sl.cpp @@ -13,6 +13,7 @@ #include #include #include +#include using namespace Homme; diff --git a/components/homme/test_execs/thetal_kokkos_ut/elem_ops_ut.cpp b/components/homme/test_execs/thetal_kokkos_ut/elem_ops_ut.cpp index 8cccddb5118..9627b0d6d61 100644 --- a/components/homme/test_execs/thetal_kokkos_ut/elem_ops_ut.cpp +++ b/components/homme/test_execs/thetal_kokkos_ut/elem_ops_ut.cpp @@ -1,14 +1,15 @@ #include -#include - #include "ElementOps.hpp" -#include "Types.hpp" #include "utilities/TestUtils.hpp" #include "utilities/SubviewUtils.hpp" #include "utilities/SyncUtils.hpp" #include "utilities/ViewUtils.hpp" +#include "Types.hpp" + +#include +#include using namespace Homme; diff --git a/components/mosart/bld/namelist_files/namelist_defaults_mosart.xml b/components/mosart/bld/namelist_files/namelist_defaults_mosart.xml index 9a7c5e4eeae..1f7e4472212 100644 --- a/components/mosart/bld/namelist_files/namelist_defaults_mosart.xml +++ b/components/mosart/bld/namelist_files/namelist_defaults_mosart.xml @@ -42,12 +42,14 @@ for the CLM data in the CESM distribution rof/mosart/MOSART_global_8th_20180211c.nc +rof/mosart/MOSART_global_qd_20240212.v3.nc rof/mosart/MOSART_global_half_20180721a.nc rof/mosart/MOSART_Global_2deg_antarctica_flowing_to_north_c09162020.nc rof/mosart/MOSART_NLDAS_8th_20160426.nc share/meshes/rof/MOSART_global_8th.scrip.20180211c.nc +share/meshes/rof/SCRIPgrid_0.25x0.25_nomask_c200309.nc share/meshes/rof/SCRIPgrid_0.5x0.5_nomask_c110308.nc share/meshes/rof/SCRIPgrid_2x2_nomask_c210211.nc diff --git a/components/mosart/cime_config/buildnml b/components/mosart/cime_config/buildnml index ba015b01f6a..90b3b3bb379 100755 --- a/components/mosart/cime_config/buildnml +++ b/components/mosart/cime_config/buildnml @@ -46,8 +46,8 @@ def buildnml(case, caseroot, compname): # Verify rof grid is supported #-------------------------------------------------------------------- - rof_grid_supported = ("null", "r2", "r05", "r0125", "r01", "NLDAS", "ELM_USRDAT") - expect(rof_grid in rof_grid_supported, "ROF_GRID '{}' is not supported in mosart. Choose from: null, r2, r05, r0125, r01, NLDAS, ELM_USRDAT".format(rof_grid)) + rof_grid_supported = ("null", "r2", "r05", "r025", "r0125", "r01", "NLDAS", "ELM_USRDAT") + expect(rof_grid in rof_grid_supported, "ROF_GRID '{}' is not supported in mosart. Choose from: null, r2, r05, r025, r0125, r01, NLDAS, ELM_USRDAT".format(rof_grid)) #-------------------------------------------------------------------- # Invoke mosart build-namelist - output will go in $CASEBUILD/mosartconf diff --git a/components/mosart/docs/dev-guide/index.md b/components/mosart/docs/dev-guide/index.md index 82f7444f45f..5d490290063 100644 --- a/components/mosart/docs/dev-guide/index.md +++ b/components/mosart/docs/dev-guide/index.md @@ -1 +1,5 @@ -Please refer to the [ELM's Developer Guide](../../ELM/dev-guide/index.md) for MOSART development. +# MOSART Developer's Guide + +This guide provides MOSART data structures and how to develop new code for MOSART. + +Coming soon... diff --git a/components/mosart/docs/figures/mosart_concept.png b/components/mosart/docs/figures/mosart_concept.png new file mode 100644 index 00000000000..beeb742ca4a Binary files /dev/null and b/components/mosart/docs/figures/mosart_concept.png differ diff --git a/components/mosart/docs/index.md b/components/mosart/docs/index.md index c1ac0ac3b47..b784fbd5e35 100644 --- a/components/mosart/docs/index.md +++ b/components/mosart/docs/index.md @@ -1,7 +1,7 @@ -#Model for Scale Adaptive River Transport (MOSART) +# Model for Scale Adaptive River Transport (MOSART) -Some introductory text here +MOSART is the river model of E3SM. It routes the runoff genrated by ELM and provides freshwater input to the ocean model. -* The [MOSART User's Guide](user-guide/index.md) explains how to control MOSART when its running within E3SM -* The [MOSART Developer's Guide](dev-guide/index.md) explains MOSART data structures and how to develop new code. -* The [MOSART Techincal Guide](tech-guide/index.md) explains the science behind MOSART's code +* The [MOSART User Guide](user-guide/index.md) explains how to control MOSART when its running within E3SM +* The [MOSART Developer Guide](dev-guide/index.md) explains MOSART data structures and how to develop new code. +* The [MOSART Technical Guide](tech-guide/index.md) explains the science behind MOSART's code diff --git a/components/mosart/docs/tech-guide/index.md b/components/mosart/docs/tech-guide/index.md index ff73bc070c0..73903f405de 100644 --- a/components/mosart/docs/tech-guide/index.md +++ b/components/mosart/docs/tech-guide/index.md @@ -1 +1,47 @@ -start of the MOSART Technical Guide +# MOSART Technical Guide + +This guide provides scientific and technical details about MOSART. + +## Physics + +MOSART is a one-dimension river transport model that is designed for river routing at local, regional, and global scales ([Li et al., 2013](https://doi.org/10.1175/JHM-D-12-015.1)). Its primary function is to supply freshwater inputs to ocean models within coupled Earth System Models. + +MOSART divides each spatial unit, such as a latitude/longitude grid or a sub-basin, into three hydrologic categories: hillslopes, tributaries, and a main channel (see figure below). The hillslopes receive runoff and send into tributaries, which then converge into a single main channel. This main channel connects adjacent upstream and downstream units through the river network. MOSART simplifies the multiple tributaries within a spatial unit into a single hypothetical sub-network channel, which has a transport capacity equivalent to all combined tributaries. + +![alt text](../figures/mosart_concept.png) + +- Hillslope Routing: Within each spatial unit, surface runoff is directed as overland flow to the sub-network channel, while subsurface runoff enters the sub-network channel directly. + +- Sub-network Channel Routing: This channel aggregates water from the hillslopes, routes it through the channel system, and discharges it into the main channel. + +- Main Channel Routing: The main channel collects water from the sub-network channel and any inflow from upstream spatial units, eventually discharging the accumulated water downstream to the next spatial unit or directly to the ocean. + +## Parameters + +### Main parameters required in the MOSART parameter file + +| Variable Name | Description [unit] | +|-------------------|--------------------------------------------------------------------------------| +| fdir | Flow direction [unitless] | +| lat | Latitude at cell center [degree] | +| lon | Longitude at cell center [degree] | +| frac | fraction of the unit draining to the outlet [0-1] | +| rslp | main channel slope [unitless] | +| rlen | main channel length [m] | +| tslp | mean tributary channel slope averaged through the unit [unitless] | +| area | local drainage area [m^2] | +| areaTotal | total upstream drainage area, local unit included; multi flow direction [m^2] | +| areaTotal2 | total upstream drainage area, local unit included; single flow direction [m^2] | +| rdep | bankfull depth of main channel [m] | +| rwid | bankfull width of main channel [m] | +| rwid0 | floodplain width linked to main channel [m] | +| gxr | drainage density [m^-1] | +| hslp | topographic slope [unitless] | +| twid | bankfull width of local tributaries [m] | +| nr | Manning''s roughness coefficient for main channel flow [unitless] | +| nt | Manning''s roughness coefficient for tributary channel flow [unitless] | +| nh | Manning''s roughness coefficient for overland flow [unitless] | + +### Parameters required by additional MOSART features + +Coming soon. diff --git a/components/mosart/docs/user-guide/index.md b/components/mosart/docs/user-guide/index.md index 858bd73b9a4..f6098382728 100644 --- a/components/mosart/docs/user-guide/index.md +++ b/components/mosart/docs/user-guide/index.md @@ -1 +1,128 @@ -start of the MOSART User's Guide +# MOSART User's Guide + +This guide describes how to set up and run MOSART. + +## Steps to build and run MOSART + +A step-by-step instruction on how to run fully coupled E3SM can be found [here](https://acme-climate.atlassian.net/wiki/spaces/DOC/pages/2309226536). Here we describe running MOSART driven by runoff forcings provided via the data land mode(DLND). Although the default runoff forcing is predefined by the DLND compsets, the users is able to use other runoff forcing to drive MOSART. + +MOSART in the water cycle campaigns of E3SM v1, v2, and v3 was. + +### Scientifically supported compsets + +The mosart-only compsets are supported for multiple runoff forcing datasets that covers different domains and time periods: + +1. `RMOSQIAN`: A 57-year (1948-2004, no leap year) global Qian runoff forcings. The native resolutions are 192*288 at daily time scale. The path to the stream file is `$input_data_dir/lnd/dlnd7/hcru_hcru/QIAN.daily.1948-2004.nc` +2. `RMOSGPCC`: A one-year (1979) global GPCC runoff forcing. The native resoultions are 192*288 at daily time scale. The path to the stream file is `$input_data_dir/lnd/dlnd7/hcru_hcru/GPCC.daily.nc` +3. `RMOSNLDAS`: A one-year (1975) CLM runoff forcing for [NLDAS](https://ldas.gsfc.nasa.gov/nldas) domain (North America between 25N and 53N) and spatial resolution (1/8th degree). The time scale is 3-hourly. The path to the stream file is `$input_data_dir/lnd/dlnd7/NLDAS/mosart_nldas_hist_1975.clm2.h1.1975-01-01-00000.nc`. + +### Supported grid + +The `r05_r05`, `NLDAS_NLDAS`, and `MOS_USRDAT` are the supported grid resolutions for performing offline MOSART simulations. + +### User-defined runoff forcing + +Once the case is created based on the above compsets. The users can create a `user_dlnd.streams.txt` file in the `case_scripts` directory following the format below: + +```xml + + + + GENERIC + + + + time time + lon lon + lat lat + + + /path/to/forcing/file + + + Runoff_forcing.nc + + + + + QDRAI rofsub + QOVER rofsur + + + /path/to/forcing/file + + + Runoff_forcing.nc + + + 0 + + + +``` + +## Customizing runs + +For default river routing simulation in MOSART (i.e. natural flow routing), one [parameter file](../tech-guide/index.md#parameters) defined by `frivinp_rtm` is required. The geographic domain and spatial resolution must match the domain defined in the simulation case. Additional parameter/input files will be needed for some extra features. + +### Output variables and frequency + +MOSART by default outputs monthly history file in `*mosart.h0.**.nc` files that include all key variables. User could choose to output additional history files (such as `*mosart.h1.*.nc`, `*mosart.h2.*.nc`) that have different temporal averaging (e.g. daily, hourly, every model timestep) via `rtmhist_nhtfrq` where + +- `-24` corresponds to daily average +- `-1` corresponds to hourly average +- `0` corresponds to monthly average +- `1` corresponds to each model time step + +The number of time slices in these additional files can be controlled +vai `rtmhist_mfilt`. + +```fortran + &mosart_inparm + rtmhist_fincl2 = 'FLOODPLAIN_FRACTION' + rtmhist_fincl3 = 'RIVER_DISCHARGE_OVER_LAND_LIQ' + rtmhist_nhtfrq = 0, -24, -1 + rtmhist_mfilt = 12, 30, 24 + / +``` + +Using the above-mentioned settings: + +- Each `*.mosart.h1.*.nc` will include 30 daily average values of `FLOODPLAIN_FRACTION` +- Each `*.mosart.h2.*.nc` will include 24 hourly average values of `RIVER_DISCHARGE_OVER_LAND_LIQ` + +### Additional options + +The table below lists avaiable options defined by users through `user_nl_mosart`. + +| Flag Name | Description | +|-------------------|---------------------------------------------------------------------------------------| +| `routingmethod` | `1` for kenematic wave routing (default); `2` for diffusion wave routing | +| `wrmflag` | `.true.` for active water management; `.false.` for no water management (default) | +| `inundflag` | `.true.` for active flood inundation; `.false.` for no flood inundation (default) | +| `sediflag` | `.true.` for active sediment transport; `.false.` for no sediment transport (default) | +| `heatflag` | `.true.` for active heat transport; `.false.` for no heat transport (default) | + +## Additional MOSART features + +There are some options only made available for specific features. They can be defined through `user_nl_mosart`. + +### Water management + +- Parameter file: when water management is active, one additional parameter file `parafile` is required. This file defines the location and specifics for the dams/reservoirs simulated in this scheme. + +- `damconstructionflag`: `0` - dam always exist; `1` - dam construction year is considered. + +- `externaldemandflag`: `0` - no external water demand for the WM scheme; `1` - external water demand files are required. + + - Note if `externaldemandflag` is set to `1`, paths to monthly water demand files are requried in the `usr_nl_mosart` file through `demandpath = '/path/to/demand/files/`. + +### Flood inundation + +- `opt_eleprof`: `1` - use actural elevation profiles derived from DEM; `2` - use hypothetical elevation profile. + + - Note if `opt_eleprof` is set to `1`, the elevation profile data must be included in the MOSART parameter file. + +### Sediment transport + +- If sediment feature is activated, D50 data must be included in the MOSART parameter file. In addition, `rof_sed = .true.` has to be defined in `./user_nl_cpl` to allow sediment flux passing into the river model through the coupler. diff --git a/components/mosart/mkdocs.yml b/components/mosart/mkdocs.yml index 6d80ef7c93d..cae190f0302 100644 --- a/components/mosart/mkdocs.yml +++ b/components/mosart/mkdocs.yml @@ -2,6 +2,6 @@ site_name: MOSART nav: - Introduction: 'index.md' - - Users's Guide: user-guide/index.md - - Developers's Guide: dev-guide/index.md + - User Guide: user-guide/index.md + - Developer Guide: dev-guide/index.md - Technical Guide: tech-guide/index.md diff --git a/components/mosart/src/riverroute/MOSART_physics_mod.F90 b/components/mosart/src/riverroute/MOSART_physics_mod.F90 index 912014904e9..cad978577cd 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,*) 'Warning: Negative channel storage found! ',negchan -! call shr_sys_abort('mosart: negative channel storage') + write(iulog,*) 'Error: 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/namelist_files/albany_input.yaml b/components/mpas-albany-landice/bld/namelist_files/albany_input.yaml index 89df18322ef..478ed9dd658 100644 --- a/components/mpas-albany-landice/bld/namelist_files/albany_input.yaml +++ b/components/mpas-albany-landice/bld/namelist_files/albany_input.yaml @@ -3,9 +3,25 @@ ANONYMOUS: Build Type: Tpetra + Problem: + 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 + Effective Pressure Type: Hydrostatic Computed At Nodes + Zero Effective Pressure On Floating Ice At Nodes: true + Zero Beta On Floating Ice: false + Use Pressurized Bed Above Sea Level: false # Discretization Description Discretization: -# Exodus Output File Name: albany_output.exo + #Exodus Output File Name: albany_output.exo Piro: # Nonlinear Solver Information @@ -22,13 +38,21 @@ ANONYMOUS: Combo Type: OR Number of Tests: 2 Test 0: - Test Type: NormF - Norm Type: Two Norm - Scale Type: Scaled - Tolerance: 1.0e-05 + 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: 50 + Maximum Iterations: 100 Printing: Output Precision: 3 Output Processor: 0 @@ -46,7 +70,7 @@ ANONYMOUS: Direction: Method: Newton Newton: - Forcing Term Method: Constant + Forcing Term Method: Type 2 Rescue Bad Newton Solve: true Linear Solver: Write Linear System: false @@ -230,4 +254,3 @@ ANONYMOUS: Coordinates: myRebalanceProlongatorFact Importer: myRepartitionFact - diff --git a/components/mpas-albany-landice/cime_config/buildnml b/components/mpas-albany-landice/cime_config/buildnml index edc88f09ffc..0a3b35df93e 100755 --- a/components/mpas-albany-landice/cime_config/buildnml +++ b/components/mpas-albany-landice/cime_config/buildnml @@ -77,6 +77,11 @@ def buildnml(case, caseroot, compname): grid_prefix += 'gis_1to10km_r01' decomp_date += '051920' decomp_prefix += 'mpasli.graph.info.' + elif glc_grid == 'mpas.gis1to10kmR2': + grid_date += '20230202' + grid_prefix += 'gis_1to10km_r02' + decomp_date += '020223' + decomp_prefix += 'mpasli.graph.info.' else: expect(False, "ERROR: mali buildnml encountered unknown GLC_GRID: " + glc_grid) @@ -205,7 +210,7 @@ def buildnml(case, caseroot, compname): lines.append(' filename_template="{}.mali.hist.$Y-$M-$D_$S.nc"'.format(casename)) lines.append(' filename_interval="0001-00-00_00:00:00"') lines.append(' clobber_mode="truncate"') - lines.append(' output_interval="0001-00-00_00:00:00">') + lines.append(' output_interval="0000-00-01_00:00:00">') # Note: if output_interval is less than dt, then multiples of that interval will be checked. # There is some performance hit for making this too small. For now making it 1 day. lines.append('') diff --git a/components/mpas-albany-landice/cime_config/config_compsets.xml b/components/mpas-albany-landice/cime_config/config_compsets.xml index 8aa3687893c..f3124b78494 100644 --- a/components/mpas-albany-landice/cime_config/config_compsets.xml +++ b/components/mpas-albany-landice/cime_config/config_compsets.xml @@ -3,7 +3,7 @@ - Compset format is explained in cime/config/e3sm/allactive/config_compsets.xml + Compset format is explained in cime_config/allactive/config_compsets.xml or in the CIME documenation diff --git a/components/mpas-albany-landice/driver/glc_comp_mct.F b/components/mpas-albany-landice/driver/glc_comp_mct.F index 957422fc859..ac33d17b1f3 100644 --- a/components/mpas-albany-landice/driver/glc_comp_mct.F +++ b/components/mpas-albany-landice/driver/glc_comp_mct.F @@ -886,12 +886,23 @@ subroutine glc_run_mct( EClock, cdata_g, x2g_g, g2x_g)!{{{ ! will allow that. ! Finally, set whence to latest_before so we have piecewise-constant forcing. ! Could add, e.g., linear interpolation later. -! In coupled mode, we don't want to use forcing from a file - that should come from the coupler! -! call mpas_stream_mgr_read(stream_manager, whence=MPAS_STREAM_LATEST_BEFORE, ierr=err_tmp) -! err = ior(err, err_tmp) -! call mpas_stream_mgr_reset_alarms(stream_manager, direction=MPAS_STREAM_INPUT, ierr=err_tmp) -! err = ior(err, err_tmp) + ! NOTE: If any input ("forcing") files here contain fields that the coupler also passes, + ! the input file versions here will clobber the fields passed from the coupler. + + call mpas_stream_mgr_read(domain % streamManager, whence=MPAS_STREAM_LATEST_BEFORE, saveActualWhen = .true., ierr=err_tmp) + err = ior(err, err_tmp) + call mpas_stream_mgr_reset_alarms(domain % streamManager, direction=MPAS_STREAM_INPUT, ierr=err_tmp) + err = ior(err, err_tmp) + + ! call analysis driver compute, restart, write subroutines + ! (note: alarms and timers are handled by the analysis member code) + call li_analysis_compute(domain, err_tmp) + err = ior(err, err_tmp) + call li_analysis_restart(domain, err_tmp) + err = ior(err, err_tmp) + call li_analysis_write(domain, err_tmp) + err = ior(err, err_tmp) ! === ! === Write Output and/or Restart, if needed diff --git a/components/mpas-framework/src/framework/mpas_pool_routines.F b/components/mpas-framework/src/framework/mpas_pool_routines.F index 9611129c8ea..7c01125bf7f 100644 --- a/components/mpas-framework/src/framework/mpas_pool_routines.F +++ b/components/mpas-framework/src/framework/mpas_pool_routines.F @@ -930,22 +930,36 @@ end subroutine mpas_pool_clone_pool!}}} !> \details !> This routine assumes srcPool and destPool have identical members. It will !> copy the data from the members of srcPool into the members of destPool. +!> The overrideTimeLevels argument enables a given time level of a srcPool +!> with >1 time level to be copied into a destPool with a single time level. ! !----------------------------------------------------------------------- - recursive subroutine mpas_pool_copy_pool(srcPool, destPool)!{{{ + recursive subroutine mpas_pool_copy_pool(srcPool, destPool, overrideTimeLevels)!{{{ implicit none type (mpas_pool_type), pointer :: srcPool type (mpas_pool_type), pointer :: destPool + integer, intent(in), optional :: overrideTimeLevels integer :: i, j, threadNum + integer :: timeLevels type (mpas_pool_member_type), pointer :: ptr type (mpas_pool_data_type), pointer :: dptr type (mpas_pool_data_type), pointer :: mem threadNum = mpas_threading_get_thread_num() + timeLevels = -1 + + if (present(overrideTimeLevels)) then + timeLevels = overrideTimeLevels + + if (timeLevels < 1) then + call mpas_pool_set_error_level(MPAS_POOL_FATAL) + call pool_mesg('ERROR in mpas_pool_copy_pool: Input time levels cannot be less than 1.') + end if + end if if ( threadNum == 0 ) then do i=1,srcPool % size @@ -985,8 +999,14 @@ recursive subroutine mpas_pool_copy_pool(srcPool, destPool)!{{{ dptr => ptr % data - ! Do this through brute force... mem => pool_get_member(destPool, ptr % key, MPAS_POOL_FIELD) + + ! Allow for overrideTimeLevels + if (timeLevels == -1) then + timeLevels = mem % contentsTimeLevs + endif + + ! Do this through brute force... if (associated(dptr % r0)) then call mpas_duplicate_field(dptr % r0, mem % r0, copy_array_only=.true.) else if (associated(dptr % r1)) then @@ -1014,83 +1034,135 @@ recursive subroutine mpas_pool_copy_pool(srcPool, destPool)!{{{ else if (associated(dptr % l0)) then call mpas_duplicate_field(dptr % l0, mem % l0, copy_array_only=.true.) else if (associated(dptr % r0a)) then - do j=1,mem % contentsTimeLevs - mem % r0 => mem % r0a(j) - call mpas_duplicate_field(dptr % r0a(j), mem % r0, copy_array_only=.true.) - nullify(mem % r0) - end do + if (timeLevels > 1) then + do j=1,timeLevels + mem % r0 => mem % r0a(j) + call mpas_duplicate_field(dptr % r0a(j), mem % r0, copy_array_only=.true.) + nullify(mem % r0) + end do + else + call mpas_duplicate_field(dptr % r0a(1), mem % r0, copy_array_only=.true.) + end if else if (associated(dptr % r1a)) then - do j=1,mem % contentsTimeLevs - mem % r1 => mem % r1a(j) - call mpas_duplicate_field(dptr % r1a(j), mem % r1, copy_array_only=.true.) - nullify(mem % r1) - end do + if (timeLevels > 1) then + do j=1,timeLevels + mem % r1 => mem % r1a(j) + call mpas_duplicate_field(dptr % r1a(j), mem % r1, copy_array_only=.true.) + nullify(mem % r1) + end do + else + call mpas_duplicate_field(dptr % r1a(1), mem % r1, copy_array_only=.true.) + end if else if (associated(dptr % r2a)) then - do j=1,mem % contentsTimeLevs - mem % r2 => mem % r2a(j) - call mpas_duplicate_field(dptr % r2a(j), mem % r2, copy_array_only=.true.) - nullify(mem % r2) - end do + if (timeLevels > 1) then + do j=1,timeLevels + mem % r2 => mem % r2a(j) + call mpas_duplicate_field(dptr % r2a(j), mem % r2, copy_array_only=.true.) + nullify(mem % r2) + end do + else + call mpas_duplicate_field(dptr % r2a(1), mem % r2, copy_array_only=.true.) + end if else if (associated(dptr % r3a)) then - do j=1,mem % contentsTimeLevs - mem % r3 => mem % r3a(j) - call mpas_duplicate_field(dptr % r3a(j), mem % r3, copy_array_only=.true.) - nullify(mem % r3) - end do + if (timeLevels > 1) then + do j=1,timeLevels + mem % r3 => mem % r3a(j) + call mpas_duplicate_field(dptr % r3a(j), mem % r3, copy_array_only=.true.) + nullify(mem % r3) + end do + else + call mpas_duplicate_field(dptr % r3a(1), mem % r3, copy_array_only=.true.) + end if else if (associated(dptr % r4a)) then - do j=1,mem % contentsTimeLevs - mem % r4 => mem % r4a(j) - call mpas_duplicate_field(dptr % r4a(j), mem % r4, copy_array_only=.true.) - nullify(mem % r4) - end do + if (timeLevels > 1) then + do j=1,timeLevels + mem % r4 => mem % r4a(j) + call mpas_duplicate_field(dptr % r4a(j), mem % r4, copy_array_only=.true.) + nullify(mem % r4) + end do + else + call mpas_duplicate_field(dptr % r4a(1), mem % r4, copy_array_only=.true.) + end if else if (associated(dptr % r5a)) then - do j=1,mem % contentsTimeLevs - mem % r5 => mem % r5a(j) - call mpas_duplicate_field(dptr % r5a(j), mem % r5, copy_array_only=.true.) - nullify(mem % r5) - end do + if (timeLevels > 1) then + do j=1,timeLevels + mem % r5 => mem % r5a(j) + call mpas_duplicate_field(dptr % r5a(j), mem % r5, copy_array_only=.true.) + nullify(mem % r5) + end do + else + call mpas_duplicate_field(dptr % r5a(1), mem % r5, copy_array_only=.true.) + end if else if (associated(dptr % i0a)) then - do j=1,mem % contentsTimeLevs - mem % i0 => mem % i0a(j) - call mpas_duplicate_field(dptr % i0a(j), mem % i0, copy_array_only=.true.) - nullify(mem % i0) - end do + if (timeLevels > 1) then + do j=1,timeLevels + mem % i0 => mem % i0a(j) + call mpas_duplicate_field(dptr % i0a(j), mem % i0, copy_array_only=.true.) + nullify(mem % i0) + end do + else + call mpas_duplicate_field(dptr % i0a(1), mem % i0, copy_array_only=.true.) + end if else if (associated(dptr % i1a)) then - do j=1,mem % contentsTimeLevs - mem % i1 => mem % i1a(j) - call mpas_duplicate_field(dptr % i1a(j), mem % i1, copy_array_only=.true.) - nullify(mem % i1) - end do + if (timeLevels > 1) then + do j=1,timeLevels + mem % i1 => mem % i1a(j) + call mpas_duplicate_field(dptr % i1a(j), mem % i1, copy_array_only=.true.) + nullify(mem % i1) + end do + else + call mpas_duplicate_field(dptr % i1a(1), mem % i1, copy_array_only=.true.) + end if else if (associated(dptr % i2a)) then - do j=1,mem % contentsTimeLevs - mem % i2 => mem % i2a(j) - call mpas_duplicate_field(dptr % i2a(j), mem % i2, copy_array_only=.true.) - nullify(mem % i2) - end do + if (timeLevels > 1) then + do j=1,timeLevels + mem % i2 => mem % i2a(j) + call mpas_duplicate_field(dptr % i2a(j), mem % i2, copy_array_only=.true.) + nullify(mem % i2) + end do + else + call mpas_duplicate_field(dptr % i2a(1), mem % i2, copy_array_only=.true.) + end if else if (associated(dptr % i3a)) then - do j=1,mem % contentsTimeLevs - mem % i3 => mem % i3a(j) - call mpas_duplicate_field(dptr % i3a(j), mem % i3, copy_array_only=.true.) - nullify(mem % i3) - end do + if (timeLevels > 1) then + do j=1,timeLevels + mem % i3 => mem % i3a(j) + call mpas_duplicate_field(dptr % i3a(j), mem % i3, copy_array_only=.true.) + nullify(mem % i3) + end do + else + call mpas_duplicate_field(dptr % i3a(1), mem % i3, copy_array_only=.true.) + end if else if (associated(dptr % c0a)) then - do j=1,mem % contentsTimeLevs - mem % c0 => mem % c0a(j) - call mpas_duplicate_field(dptr % c0a(j), mem % c0, copy_array_only=.true.) - nullify(mem % c0) - end do + if (timeLevels > 1) then + do j=1,timeLevels + mem % c0 => mem % c0a(j) + call mpas_duplicate_field(dptr % c0a(j), mem % c0, copy_array_only=.true.) + nullify(mem % c0) + end do + else + call mpas_duplicate_field(dptr % c0a(1), mem % c0, copy_array_only=.true.) + end if else if (associated(dptr % c1a)) then - do j=1,mem % contentsTimeLevs - mem % c1 => mem % c1a(j) - call mpas_duplicate_field(dptr % c1a(j), mem % c1, copy_array_only=.true.) - nullify(mem % c1) - end do + if (timeLevels > 1) then + do j=1,timeLevels + mem % c1 => mem % c1a(j) + call mpas_duplicate_field(dptr % c1a(j), mem % c1, copy_array_only=.true.) + nullify(mem % c1) + end do + else + call mpas_duplicate_field(dptr % c1a(1), mem % c1, copy_array_only=.true.) + end if else if (associated(dptr % l0a)) then - do j=1,mem % contentsTimeLevs - mem % l0 => mem % l0a(j) - call mpas_duplicate_field(dptr % l0a(j), mem % l0, copy_array_only=.true.) - nullify(mem % l0) - end do + if (timeLevels > 1) then + do j=1,timeLevels + mem % l0 => mem % l0a(j) + call mpas_duplicate_field(dptr % l0a(j), mem % l0, copy_array_only=.true.) + nullify(mem % l0) + end do + else + call mpas_duplicate_field(dptr % l0a(1), mem % l0, copy_array_only=.true.) + end if else call pool_mesg('While copying pool, member '//trim(ptr % key)//' has no valid field pointers.') end if diff --git a/components/mpas-ocean/bld/build-namelist b/components/mpas-ocean/bld/build-namelist index 19418582863..c8e1c1e3a7a 100755 --- a/components/mpas-ocean/bld/build-namelist +++ b/components/mpas-ocean/bld/build-namelist @@ -616,6 +616,8 @@ add_default($nl, 'config_use_cvmix'); add_default($nl, 'config_cvmix_prandtl_number'); add_default($nl, 'config_cvmix_background_scheme'); add_default($nl, 'config_cvmix_background_diffusion'); +add_default($nl, 'config_cvmix_background_diffusion_passive'); +add_default($nl, 'config_cvmix_background_diffusion_passive_enable'); add_default($nl, 'config_cvmix_background_viscosity'); add_default($nl, 'config_cvmix_BryanLewis_bl1'); add_default($nl, 'config_cvmix_BryanLewis_bl2'); @@ -1005,6 +1007,12 @@ add_default($nl, 'config_manufactured_solution_wavelength_x'); add_default($nl, 'config_manufactured_solution_wavelength_y'); add_default($nl, 'config_manufactured_solution_amplitude'); +##################################### +# Namelist group: init_mode_subgrid # +##################################### + +add_default($nl, 'config_subgrid_table_levels'); + ################################################ # Namelist group: tracer_forcing_activeTracers # ################################################ @@ -1775,6 +1783,7 @@ my @groups = qw(run_modes transport_tests init_mode_vert_levels manufactured_solution + init_mode_subgrid tracer_forcing_activetracers tracer_forcing_debugtracers tracer_forcing_ecosystracers diff --git a/components/mpas-ocean/bld/build-namelist-group-list b/components/mpas-ocean/bld/build-namelist-group-list index 11864939025..c109ba9990e 100644 --- a/components/mpas-ocean/bld/build-namelist-group-list +++ b/components/mpas-ocean/bld/build-namelist-group-list @@ -40,6 +40,7 @@ my @groups = qw(run_modes transport_tests init_mode_vert_levels manufactured_solution + init_mode_subgrid tracer_forcing_activetracers tracer_forcing_debugtracers tracer_forcing_ecosystracers diff --git a/components/mpas-ocean/bld/build-namelist-section b/components/mpas-ocean/bld/build-namelist-section index 0c834f05cec..b202284f300 100644 --- a/components/mpas-ocean/bld/build-namelist-section +++ b/components/mpas-ocean/bld/build-namelist-section @@ -155,6 +155,8 @@ add_default($nl, 'config_use_cvmix'); add_default($nl, 'config_cvmix_prandtl_number'); add_default($nl, 'config_cvmix_background_scheme'); add_default($nl, 'config_cvmix_background_diffusion'); +add_default($nl, 'config_cvmix_background_diffusion_passive'); +add_default($nl, 'config_cvmix_background_diffusion_passive_enable'); add_default($nl, 'config_cvmix_background_viscosity'); add_default($nl, 'config_cvmix_BryanLewis_bl1'); add_default($nl, 'config_cvmix_BryanLewis_bl2'); @@ -522,6 +524,12 @@ add_default($nl, 'config_manufactured_solution_wavelength_x'); add_default($nl, 'config_manufactured_solution_wavelength_y'); add_default($nl, 'config_manufactured_solution_amplitude'); +##################################### +# Namelist group: init_mode_subgrid # +##################################### + +add_default($nl, 'config_subgrid_table_levels'); + ################################################ # Namelist group: tracer_forcing_activeTracers # ################################################ 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 6541b9a5a2b..248654ef10f 100644 --- a/components/mpas-ocean/bld/namelist_files/namelist_defaults_mpaso.xml +++ b/components/mpas-ocean/bld/namelist_files/namelist_defaults_mpaso.xml @@ -49,6 +49,7 @@ '00:10:00' '00:30:00' '00:30:00' +'00:30:00' '00:08:00' '00:04:00' '00:02:00' @@ -77,6 +78,7 @@ .true. .true. .true. +.true. .true. .true. .true. @@ -97,6 +99,7 @@ .true. .true. .true. +.true. .true. .true. .true. @@ -111,6 +114,7 @@ 462.0 1000.0 1000.0 +1000.0 308.0 154.0 77.0 @@ -140,6 +144,7 @@ 1.18e10 1.2e11 1.2e11 +1.2e11 3.50e09 4.37e08 5.46e07 @@ -175,6 +180,7 @@ 'RossbyRadius' 'RossbyRadius' 'ramp' +'ramp' 'RossbyRadius' 'RossbyRadius' 'RossbyRadius' @@ -204,6 +210,7 @@ 'N2_dependent' 'N2_dependent' 'constant' +'constant' 'N2_dependent' 'N2_dependent' 'N2_dependent' @@ -217,6 +224,7 @@ 600.0 600.0 600.0 +600.0 600.0 600.0 600.0 @@ -229,6 +237,7 @@ 1.0 1.0 3.0 +3.0 1.0 1.0 1.0 @@ -243,6 +252,7 @@ 'RossbyRadius' 'RossbyRadius' 'ramp' +'ramp' 'RossbyRadius' 'RossbyRadius' 'RossbyRadius' @@ -265,6 +275,8 @@ 1.0 'constant' 0.0 +0.0 +.false. 1.0e-4 8.0e-5 1.05E-4 @@ -383,6 +395,7 @@ 'pressure_only' 'pressure_only' 'pressure_only' +'pressure_only' 'pressure_only' 'pressure_only' 'pressure_only' @@ -400,6 +413,7 @@ 4.48e-3 4.48e-3 4.48e-3 +4.48e-3 4.48e-3 4.48e-3 4.48e-3 @@ -412,6 +426,7 @@ 0.00295 0.00295 0.00295 +0.00295 0.00295 0.00295 0.00295 @@ -422,6 +437,7 @@ 8.42e-5 8.42e-5 8.42e-5 +8.42e-5 8.42e-5 8.42e-5 8.42e-5 @@ -449,6 +465,7 @@ 4.48e-3 4.48e-3 4.48e-3 +4.48e-3 4.48e-3 4.48e-3 4.48e-3 @@ -531,6 +548,7 @@ '0000_00:00:15' '0000_00:01:15' '0000_00:01:00' +'0000_00:01:00' '0000_00:00:10' '0000_00:00:05' '0000_00:00:02.5' @@ -576,6 +594,7 @@ .false. .false. .false. +.false. .false. .false. .false. @@ -629,6 +648,9 @@ 2000000.0 1 + +-1 + .true. .true. @@ -1097,6 +1119,7 @@ .true. .true. .true. +.true. .true. .true. .true. @@ -1183,6 +1206,7 @@ .true. .true. .true. +.true. .true. .true. .true. @@ -1193,6 +1217,7 @@ .true. .true. .true. +.true. .true. .true. .true. @@ -1201,6 +1226,7 @@ .true. .true. .true. +.true. .true. .true. .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 e01c2b9716f..cd8535a4158 100644 --- a/components/mpas-ocean/bld/namelist_files/namelist_definition_mpaso.xml +++ b/components/mpas-ocean/bld/namelist_files/namelist_definition_mpaso.xml @@ -747,6 +747,22 @@ Valid values: Any positive real value. Default: Defined in namelist_defaults.xml + +Background vertical diffusion applied to passive tracer quantities + +Valid values: Any positive real value. +Default: Defined in namelist_defaults.xml + + + +flag to enable using a different background vertical diffusion for passive tracers + +Valid values: .true. or .false. +Default: Defined in namelist_defaults.xml + + Background vertical viscosity applied to horizontal velocity @@ -2640,6 +2656,17 @@ Default: Defined in namelist_defaults.xml + + + +Number of levels in subgrid lookup tables + +Valid values: Any positive non-zero integer. A value of -1 causes this to be overwritten with the configurations subgrid table levels definition. +Default: Defined in namelist_defaults.xml + + + 0: + # This is here because the comparison is run for each submission + # and we only want to compare once the whole run is finished. We + # need to return a pass here to continue the submission process. + self._test_status.set_status( + CIME.test_status.BASELINE_PHASE, CIME.test_status.TEST_PEND_STATUS + ) + return + + self._test_status.set_status( + CIME.test_status.BASELINE_PHASE, CIME.test_status.TEST_FAIL_STATUS + ) + + run_dir = self._case.get_value("RUNDIR") + case_name = self._case.get_value("CASE") + base_dir = os.path.join( + self._case.get_value("BASELINE_ROOT"), + self._case.get_value("BASECMP_CASE"), + ) + + test_name = str(case_name.split(".")[-1]) + evv_config = { + test_name: { + "module": os.path.join(evv_lib_dir, "extensions", "kso.py"), + "test-case": "Test", + "test-dir": run_dir, + "ref-case": "Baseline", + "ref-dir": base_dir, + "var-set": "default", + "ninst": NINST, + "critical": 0, + "component": self.ocn_component, + "alpha": 0.05, + "hist-name": "hist.am.timeSeriesStatsClimatology", + } + } + + json_file = os.path.join(run_dir, ".".join([case_name, "json"])) + with open(json_file, "w", encoding="utf-8") as config_file: + json.dump(evv_config, config_file, indent=4) + + evv_out_dir = os.path.join(run_dir, ".".join([case_name, "evv"])) + evv(["-e", json_file, "-o", evv_out_dir]) + + with open( + os.path.join(evv_out_dir, "index.json"), encoding="utf-8" + ) as evv_f: + evv_status = json.load(evv_f) + + comments = "" + for evv_ele in evv_status["Page"]["elements"]: + if "Table" in evv_ele: + comments = "; ".join( + f"{key}: {val[0]}" + for key, val in evv_ele["Table"]["data"].items() + ) + if evv_ele["Table"]["data"]["Test status"][0].lower() == "pass": + self._test_status.set_status( + CIME.test_status.BASELINE_PHASE, + CIME.test_status.TEST_PASS_STATUS, + ) + break + + status = self._test_status.get_status(CIME.test_status.BASELINE_PHASE) + mach_name = self._case.get_value("MACH") + mach_obj = Machines(machine=mach_name) + htmlroot = CIME.utils.get_htmlroot(mach_obj) + urlroot = CIME.utils.get_urlroot(mach_obj) + if htmlroot is not None: + with CIME.utils.SharedArea(): + dir_util.copy_tree( + evv_out_dir, + os.path.join(htmlroot, "evv", case_name), + preserve_mode=False, + ) + if urlroot is None: + urlroot = f"[{mach_name.capitalize()}_URL]" + viewing = f"{urlroot}/evv/{case_name}/index.html" + else: + viewing = ( + f"{evv_out_dir}\n" + " EVV viewing instructions can be found at: " + " https://github.com/E3SM-Project/E3SM/blob/master/cime/scripts/" + "climate_reproducibility/README.md#test-passfail-and-extended-output" + ) + comments = ( + f"{CIME.test_status.BASELINE_PHASE} {status} for test '{test_name}'.\n" + f" {comments}\n" + " EVV results can be viewed at:\n" + f" {viewing}" + ) + + CIME.utils.append_testlog(comments, self._orig_caseroot) diff --git a/components/mpas-ocean/cime_config/buildnml b/components/mpas-ocean/cime_config/buildnml index 048e621fafa..47076dee726 100755 --- a/components/mpas-ocean/cime_config/buildnml +++ b/components/mpas-ocean/cime_config/buildnml @@ -134,6 +134,8 @@ def buildnml(case, caseroot, compname): if ocn_ic_mode == 'spunup': logger.warning("WARNING: The specified compset is requesting ocean ICs spunup from a G-case") logger.warning(" But no file available for this grid.") + if ocn_ismf == 'data': + data_ismf_file = 'prescribed_ismf_paolo2023.oQU240wLI.20240404.nc' elif ocn_grid == 'oQU120': decomp_date = '230424' @@ -352,6 +354,17 @@ def buildnml(case, caseroot, compname): if ocn_ismf == 'data': data_ismf_file = 'prescribed_ismf_paolo2023.IcoswISC30E3r5.20240227.nc' + elif ocn_grid == 'IcosXISC30E3r7': + decomp_date = '20240314' + decomp_prefix = 'partitions/mpas-o.graph.info.' + restoring_file = 'sss.PHC2_monthlyClimatology.IcosXISC30E3r7.20240314.nc' + analysis_mask_file = 'IcosXISC30E3r7_mocBasinsAndTransects20210623.nc' + ic_date = '20240314' + ic_prefix = 'mpaso.IcosXISC30E3r7' + if ocn_ic_mode == 'spunup': + ic_date = '20240314' + ic_prefix = 'mpaso.IcosXISC30E3r7.rstFromPiControlSpinup-chrysalis' + #-------------------------------------------------------------------- # Set OCN_FORCING = datm_forced_restoring if restoring file is available #-------------------------------------------------------------------- @@ -586,6 +599,8 @@ def buildnml(case, caseroot, compname): lines.append(' ') lines.append(' ') lines.append(' ') + lines.append(' ') + lines.append(' ') lines.append(' ') lines.append(' ') if ocn_bgc in ['eco_only', 'eco_and_dms', 'eco_and_macromolecules', 'eco_and_dms_and_macromolecules']: @@ -862,7 +877,7 @@ def buildnml(case, caseroot, compname): lines.append(' ') lines.append(' ') lines.append(' ') - lines.append(' ') + lines.append(' ') lines.append(' ') lines.append(' ') if ocn_bgc in ['eco_only', 'eco_and_dms', 'eco_and_macromolecules', 'eco_and_dms_and_macromolecules']: @@ -1286,6 +1301,8 @@ def buildnml(case, caseroot, compname): lines.append(' ') lines.append(' ') lines.append(' ') + lines.append(' ') + lines.append(' ') lines.append(' ') lines.append(' ') lines.append(' ') @@ -1464,6 +1481,8 @@ def buildnml(case, caseroot, compname): lines.append(' ') lines.append(' ') lines.append(' ') + lines.append(' ') + lines.append(' ') lines.append(' ') lines.append(' ') lines.append(' ') @@ -1526,6 +1545,8 @@ def buildnml(case, caseroot, compname): lines.append(' ') lines.append(' ') lines.append(' ') + lines.append(' ') + lines.append(' ') lines.append(' ') lines.append(' ') lines.append(' ') diff --git a/components/mpas-ocean/cime_config/config_compsets.xml b/components/mpas-ocean/cime_config/config_compsets.xml index b15f9111be4..fa87ed02e7a 100644 --- a/components/mpas-ocean/cime_config/config_compsets.xml +++ b/components/mpas-ocean/cime_config/config_compsets.xml @@ -62,6 +62,26 @@ 2000_DATM%JRA-1p5_SLND_MPASSI_MPASO%DATMFORCED_DROF%JRA-1p5_SGLC_SWAV + + GMPAS-OECO-JRA1p4 + 2000_DATM%JRA-1p4-2018_SLND_MPASSI_MPASO%OECODATMFORCED_DROF%JRA-1p4-2018_SGLC_SWAV + + + + GMPAS-OIECO-JRA1p4 + 2000_DATM%JRA-1p4-2018_SLND_MPASSI%BGC_MPASO%OIECODATMFORCED_DROF%JRA-1p4-2018_SGLC_SWAV + + + + GPMPAS-OECO-JRA1p4 + 2000_DATM%JRA-1p4-2018_ELM%SPBC_MPASSI_MPASO%OECODATMFORCED_MOSART_SGLC_SWAV + + + + GPMPAS-OIECO-JRA1p4 + 2000_DATM%JRA-1p4-2018_ELM%SPBC_MPASSI%BGC_MPASO%OIECODATMFORCED_MOSART_SGLC_SWAV + + GMPAS-JRA1p5-DIB-PISMF 2000_DATM%JRA-1p5_SLND_MPASSI%DIB_MPASO%IBPISMFDATMFORCED_DROF%JRA-1p5-AIS0ROF_SGLC_SWAV diff --git a/components/mpas-ocean/cime_config/config_tests.xml b/components/mpas-ocean/cime_config/config_tests.xml new file mode 100644 index 00000000000..a89986257e8 --- /dev/null +++ b/components/mpas-ocean/cime_config/config_tests.xml @@ -0,0 +1,23 @@ + + + + + + + + climate reproducibility test using the multivariate K-S test + 1 + FALSE + FALSE + nmonths + 24 + $STOP_OPTION + $STOP_N + $STOP_OPTION + $STOP_N + 0 + + + diff --git a/components/mpas-ocean/docs/ccase.template.v3LR.anvil.sh b/components/mpas-ocean/docs/ccase.template.v3LR.anvil.sh new file mode 100755 index 00000000000..ed9af711058 --- /dev/null +++ b/components/mpas-ocean/docs/ccase.template.v3LR.anvil.sh @@ -0,0 +1,498 @@ +#!/bin/bash -fe + +# E3SM Coupled Model Group run_e3sm script template. +# +# Bash coding style inspired by: +# http://kfirlavi.herokuapp.com/blog/2012/11/14/defensive-bash-programming + +main() { + +# For debugging, uncomment libe below +#set -x + +# --- Configuration flags ---- + +# Machine and project +readonly MACHINE=anvil +readonly PROJECT="condo" + +# Simulation +readonly COMPSET="CMPASO-JRA1p4" +readonly RESOLUTION="TL319_IcoswISC30E3r5" +readonly CASE_NAME="test.CMPAS-JRA.TL319_IcoswISC30E3r5.anvil" # MODIFY +#readonly CASE_GROUP="" + +# Code and compilation +readonly CHECKOUT="20240304" +readonly BRANCH="399d430" # master as of 2024-03-04 E3Sm v3.0.0 tag +#readonly CHERRY=() +readonly DEBUG_COMPILE=false + +# Run options +readonly MODEL_START_TYPE="initial" # 'initial', 'continue', 'branch', 'hybrid' +readonly START_DATE="0001-01-01" + +# Additional options for 'branch' and 'hybrid' +# readonly GET_REFCASE=TRUE +# readonly RUN_REFDIR="" +# readonly RUN_REFCASE="" +# readonly RUN_REFDATE="0301-01-01" + +# Set paths +readonly CODE_ROOT="/lcrc/group/e3sm/${USER}/E3SM/code/${CHECKOUT}" +readonly CASE_ROOT="/lcrc/group/e3sm/${USER}/e3sm_scratch/${MACHINE}/${CASE_NAME}" + +# Sub-directories +readonly CASE_BUILD_DIR=${CASE_ROOT}/build +readonly CASE_ARCHIVE_DIR=${CASE_ROOT}/archive + +# Define type of run +# short tests: 'S_2x5_ndays', 'M_1x10_ndays', 'M80_1x10_ndays' +# or 'production' for full simulation + +#readonly run='S_1x1_nmonth' +readonly run='production' +if [ "${run}" != "production" ]; then + + # Short test simulations + tmp=($(echo $run | tr "_" " ")) + layout=${tmp[0]} + units=${tmp[2]} + resubmit=$(( ${tmp[1]%%x*} -1 )) + length=${tmp[1]##*x} + + readonly CASE_SCRIPTS_DIR=${CASE_ROOT}/tests/${run}/case_scripts + readonly CASE_RUN_DIR=${CASE_ROOT}/tests/${run}/run + readonly PELAYOUT=${layout} + readonly WALLTIME="2:00:00" + readonly STOP_OPTION=${units} + readonly STOP_N=${length} + readonly REST_OPTION=${STOP_OPTION} + readonly REST_N=${STOP_N} + readonly RESUBMIT=${resubmit} + readonly DO_SHORT_TERM_ARCHIVING=false + +else + + # Production simulation + readonly CASE_SCRIPTS_DIR=${CASE_ROOT}/case_scripts + readonly CASE_RUN_DIR=${CASE_ROOT}/run + readonly PELAYOUT="L" + readonly WALLTIME="02:00:00" + readonly STOP_OPTION="nmonths" + readonly STOP_N="1" + readonly REST_OPTION="nmonths" + readonly REST_N="1" + readonly RESUBMIT="0" + readonly DO_SHORT_TERM_ARCHIVING=false +fi + +# Coupler history +readonly HIST_OPTION="nmonths" +readonly HIST_N="1" + +# Leave empty (unless you understand what it does) +readonly OLD_EXECUTABLE="" + +# --- Toggle flags for what to do ---- +do_fetch_code=false +do_create_newcase=true +do_modify_pelayout=false +do_case_setup=true +do_case_build=true +do_case_submit=true + +# --- Now, do the work --- + +# Make directories created by this script world-readable +umask 022 + +# Fetch code from Github +fetch_code + +# Create case +create_newcase + +# Custom PE layout +modify_pelayout + +# Setup +case_setup + +# Build +case_build + +# Configure runtime options +runtime_options + +# Copy script into case_script directory for provenance +copy_script + +# Submit +case_submit + +# All done +echo $'\n----- All done -----\n' + +} + +# ======================= +# Custom user_nl settings +# ======================= + +user_nl() { + +cat << EOF >> user_nl_eam +EOF + +cat << EOF >> user_nl_elm +EOF + +cat << EOF >> user_nl_mpaso +EOF + +cat << EOF >> user_nl_mpassi +EOF + +} + +# ===================================== +# Customize MPAS stream files if needed +# ===================================== + +patch_mpas_streams() { + +echo + +} + +# ===================================================== +# Custom PE layout: +# ===================================================== + +modify_pelayout() { + + if [ "${do_modify_pelayout,,}" != "true" ]; then + echo $'\n----- Skipping changing PE-layout -----\n' + return + fi + + echo $'\n----- changing PE layout to custom -----\n' + pushd ${CASE_SCRIPTS_DIR} + + ./xmlchange MAX_MPITASKS_PER_NODE=32 + ./xmlchange MAX_TASKS_PER_NODE=256 + ./xmlchange NTASKS_ATM=1024 + ./xmlchange NTASKS_CPL=1024 + ./xmlchange NTASKS_OCN=1024 + ./xmlchange NTASKS_WAV=1024 + ./xmlchange NTASKS_GLC=1024 + ./xmlchange NTASKS_ICE=1024 + ./xmlchange NTASKS_ROF=1024 + ./xmlchange NTASKS_LND=1024 + ./xmlchange NTASKS_ESP=1 + ./xmlchange NTASKS_IAC=1 + + ./xmlchange NTHRDS_ATM=8 + ./xmlchange NTHRDS_CPL=8 + ./xmlchange NTHRDS_OCN=8 + ./xmlchange NTHRDS_WAV=8 + ./xmlchange NTHRDS_GLC=1 + ./xmlchange NTHRDS_ICE=8 + ./xmlchange NTHRDS_ROF=8 + ./xmlchange NTHRDS_LND=8 + ./xmlchange NTHRDS_ESP=1 + ./xmlchange NTHRDS_IAC=1 + + ./xmlchange ROOTPE_ATM=0 + ./xmlchange ROOTPE_CPL=0 + ./xmlchange ROOTPE_OCN=0 + ./xmlchange ROOTPE_WAV=0 + ./xmlchange ROOTPE_GLC=0 + ./xmlchange ROOTPE_ICE=0 + ./xmlchange ROOTPE_ROF=0 + ./xmlchange ROOTPE_LND=0 + ./xmlchange ROOTPE_ESP=0 + ./xmlchange ROOTPE_IAC=0 + + popd + + } +###################################################### +### Most users won't need to change anything below ### +###################################################### + +#----------------------------------------------------- +fetch_code() { + + if [ "${do_fetch_code,,}" != "true" ]; then + echo $'\n----- Skipping fetch_code -----\n' + return + fi + + echo $'\n----- Starting fetch_code -----\n' + local path=${CODE_ROOT} + local repo=E3SM + + echo "Cloning $repo repository branch $BRANCH under $path" + if [ -d "${path}" ]; then + echo "ERROR: Directory already exists. Not overwriting" + exit 20 + fi + mkdir -p ${path} + pushd ${path} + + # This will put repository, with all code + git clone git@github.com:E3SM-Project/${repo}.git . + + # Check out desired branch + git checkout ${BRANCH} + + # Custom addition + if [ "${CHERRY}" != "" ]; then + echo ----- WARNING: adding git cherry-pick ----- + for commit in "${CHERRY[@]}" + do + echo ${commit} + git cherry-pick ${commit} + done + echo ------------------------------------------- + fi + + # Bring in all submodule components + git submodule update --init --recursive + + popd +} + +#----------------------------------------------------- +create_newcase() { + + if [ "${do_create_newcase,,}" != "true" ]; then + echo $'\n----- Skipping create_newcase -----\n' + return + fi + + echo $'\n----- Starting create_newcase -----\n' + + if [[ ${PELAYOUT} == custom-* ]]; + then + layout="M" # temporary placeholder for create_newcase + else + layout=${PELAYOUT} + + fi + ${CODE_ROOT}/cime/scripts/create_newcase \ + --case ${CASE_NAME} \ + --output-root ${CASE_ROOT} \ + --script-root ${CASE_SCRIPTS_DIR} \ + --handle-preexisting-dirs u \ + --compset ${COMPSET} \ + --res ${RESOLUTION} \ + --machine ${MACHINE} ${COMPILER} \ + --project ${PROJECT} \ + --walltime ${WALLTIME} \ + --pecount ${layout} \ + + if [ $? != 0 ]; then + echo $'\nNote: if create_newcase failed because sub-directory already exists:' + echo $' * delete old case_script sub-directory' + echo $' * or set do_newcase=false\n' + exit 35 + fi + +} + +#----------------------------------------------------- +case_setup() { + + if [ "${do_case_setup,,}" != "true" ]; then + echo $'\n----- Skipping case_setup -----\n' + return + fi + + echo $'\n----- Starting case_setup -----\n' + pushd ${CASE_SCRIPTS_DIR} + + # Setup some CIME directories + ./xmlchange EXEROOT=${CASE_BUILD_DIR} + ./xmlchange RUNDIR=${CASE_RUN_DIR} + + # Short term archiving + ./xmlchange DOUT_S=${DO_SHORT_TERM_ARCHIVING^^} + ./xmlchange DOUT_S_ROOT=${CASE_ARCHIVE_DIR} + + # Build with COSP, except for a data atmosphere (datm) + if [ `./xmlquery --value COMP_ATM` == "datm" ]; then + echo $'\nThe specified configuration uses a data atmosphere, so cannot activate COSP simulator\n' + else + echo $'\nConfiguring E3SM to use the COSP simulator\n' + ./xmlchange --id CAM_CONFIG_OPTS --append --val='-cosp' + fi + + # Extracts input_data_dir in case it is needed for user edits to the namelist later + local input_data_dir=`./xmlquery DIN_LOC_ROOT --value` + + # Custom user_nl + user_nl + + # Finally, run CIME case.setup + ./case.setup --reset + + popd +} + +#----------------------------------------------------- +case_build() { + + pushd ${CASE_SCRIPTS_DIR} + + # do_case_build = false + if [ "${do_case_build,,}" != "true" ]; then + + echo $'\n----- case_build -----\n' + + if [ "${OLD_EXECUTABLE}" == "" ]; then + # Ues previously built executable, make sure it exists + if [ -x ${CASE_BUILD_DIR}/e3sm.exe ]; then + echo 'Skipping build because $do_case_build = '${do_case_build} + else + echo 'ERROR: $do_case_build = '${do_case_build}' but no executable exists for this case.' + exit 297 + fi + else + # If absolute pathname exists and is executable, reuse pre-exiting executable + if [ -x ${OLD_EXECUTABLE} ]; then + echo 'Using $OLD_EXECUTABLE = '${OLD_EXECUTABLE} + cp -fp ${OLD_EXECUTABLE} ${CASE_BUILD_DIR}/ + else + echo 'ERROR: $OLD_EXECUTABLE = '$OLD_EXECUTABLE' does not exist or is not an executable file.' + exit 297 + fi + fi + echo 'WARNING: Setting BUILD_COMPLETE = TRUE. This is a little risky, but trusting the user.' + ./xmlchange BUILD_COMPLETE=TRUE + + # do_case_build = true + else + + echo $'\n----- Starting case_build -----\n' + + # Turn on debug compilation option if requested + if [ "${DEBUG_COMPILE^^}" == "TRUE" ]; then + ./xmlchange DEBUG=${DEBUG_COMPILE^^} + fi + + # Run CIME case.build + ./case.build + + fi + + # Some user_nl settings won't be updated to *_in files under the run directory + # Call preview_namelists to make sure *_in and user_nl files are consistent. + echo $'\n----- Preview namelists -----\n' + ./preview_namelists + + popd +} + +#----------------------------------------------------- +runtime_options() { + + echo $'\n----- Starting runtime_options -----\n' + pushd ${CASE_SCRIPTS_DIR} + + # Set simulation start date + ./xmlchange RUN_STARTDATE=${START_DATE} + + # Segment length + ./xmlchange STOP_OPTION=${STOP_OPTION,,},STOP_N=${STOP_N} + + # Restart frequency + ./xmlchange REST_OPTION=${REST_OPTION,,},REST_N=${REST_N} + + # Coupler history + ./xmlchange HIST_OPTION=${HIST_OPTION,,},HIST_N=${HIST_N} + + # Coupler budgets (always on) + ./xmlchange BUDGETS=TRUE + + # Set resubmissions + if (( RESUBMIT > 0 )); then + ./xmlchange RESUBMIT=${RESUBMIT} + fi + + # Run type + # Start from default of user-specified initial conditions + if [ "${MODEL_START_TYPE,,}" == "initial" ]; then + ./xmlchange RUN_TYPE="startup" + ./xmlchange CONTINUE_RUN="FALSE" + + # Continue existing run + elif [ "${MODEL_START_TYPE,,}" == "continue" ]; then + ./xmlchange CONTINUE_RUN="TRUE" + + elif [ "${MODEL_START_TYPE,,}" == "branch" ] || [ "${MODEL_START_TYPE,,}" == "hybrid" ]; then + ./xmlchange RUN_TYPE=${MODEL_START_TYPE,,} + ./xmlchange GET_REFCASE=${GET_REFCASE} + ./xmlchange RUN_REFDIR=${RUN_REFDIR} + ./xmlchange RUN_REFCASE=${RUN_REFCASE} + ./xmlchange RUN_REFDATE=${RUN_REFDATE} + echo 'Warning: $MODEL_START_TYPE = '${MODEL_START_TYPE} + echo '$RUN_REFDIR = '${RUN_REFDIR} + echo '$RUN_REFCASE = '${RUN_REFCASE} + echo '$RUN_REFDATE = '${START_DATE} + else + echo 'ERROR: $MODEL_START_TYPE = '${MODEL_START_TYPE}' is unrecognized. Exiting.' + exit 380 + fi + + # Patch mpas streams files + patch_mpas_streams + + popd +} + +#----------------------------------------------------- +case_submit() { + + if [ "${do_case_submit,,}" != "true" ]; then + echo $'\n----- Skipping case_submit -----\n' + return + fi + + echo $'\n----- Starting case_submit -----\n' + pushd ${CASE_SCRIPTS_DIR} + + # Run CIME case.submit + ./case.submit + + popd +} + +#----------------------------------------------------- +copy_script() { + + echo $'\n----- Saving run script for provenance -----\n' + + local script_provenance_dir=${CASE_SCRIPTS_DIR}/run_script_provenance + mkdir -p ${script_provenance_dir} + local this_script_name=`basename $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} + +} + +#----------------------------------------------------- +# Silent versions of popd and pushd +pushd() { + command pushd "$@" > /dev/null +} +popd() { + command popd "$@" > /dev/null +} + +# Now, actually run the script +#----------------------------------------------------- +main + diff --git a/components/mpas-ocean/docs/dev-guide/index.md b/components/mpas-ocean/docs/dev-guide/index.md new file mode 100644 index 00000000000..c7665da944c --- /dev/null +++ b/components/mpas-ocean/docs/dev-guide/index.md @@ -0,0 +1,5 @@ +# MPAS-Ocean Developer Guide + +The E3SM developer guide may be found at [https://e3sm.org/model/running-e3sm/developing-e3sm/](https://e3sm.org/model/running-e3sm/developing-e3sm/). + +The MPAS developers guide is at [https://mpas-dev.github.io/files/documents/MPAS-DevelopersGuide.pdf](https://mpas-dev.github.io/files/documents/MPAS-DevelopersGuide.pdf). diff --git a/components/mpas-ocean/docs/gcase.template.v3LR.chrysalis.sh b/components/mpas-ocean/docs/gcase.template.v3LR.chrysalis.sh new file mode 100755 index 00000000000..b9fff6197f8 --- /dev/null +++ b/components/mpas-ocean/docs/gcase.template.v3LR.chrysalis.sh @@ -0,0 +1,498 @@ +#!/bin/bash -fe + +# E3SM Coupled Model Group run_e3sm script template. +# +# Bash coding style inspired by: +# http://kfirlavi.herokuapp.com/blog/2012/11/14/defensive-bash-programming + +main() { + +# For debugging, uncomment libe below +#set -x + +# --- Configuration flags ---- + +# Machine and project +readonly MACHINE=chrysalis +readonly PROJECT="e3sm" + +# Simulation +readonly COMPSET="GMPAS-JRA1p5" +readonly RESOLUTION="TL319_IcoswISC30E3r5" +readonly CASE_NAME="test4.GMPAS-JRA.TL319_IcoswISC30E3r5.chrysalis" # MODIFY +#readonly CASE_GROUP="" + +# Code and compilation +readonly CHECKOUT="20240304" +readonly BRANCH="399d430" # master as of 2024-03-04 E3Sm v3.0.0 tag +#readonly CHERRY=() +readonly DEBUG_COMPILE=false + +# Run options +readonly MODEL_START_TYPE="initial" # 'initial', 'continue', 'branch', 'hybrid' +readonly START_DATE="0001-01-01" + +# Additional options for 'branch' and 'hybrid' +# readonly GET_REFCASE=TRUE +# readonly RUN_REFDIR="" +# readonly RUN_REFCASE="" +# readonly RUN_REFDATE="0301-01-01" + +# Set paths +readonly CODE_ROOT="/lcrc/group/e3sm/${USER}/E3SM/code/${CHECKOUT}" +readonly CASE_ROOT="/lcrc/group/e3sm/${USER}/e3sm_scratch/${MACHINE}/${CASE_NAME}" + +# Sub-directories +readonly CASE_BUILD_DIR=${CASE_ROOT}/build +readonly CASE_ARCHIVE_DIR=${CASE_ROOT}/archive + +# Define type of run +# short tests: 'S_2x5_ndays', 'M_1x10_ndays', 'M80_1x10_ndays' +# or 'production' for full simulation + +#readonly run='S_1x1_nmonth' +readonly run='production' +if [ "${run}" != "production" ]; then + + # Short test simulations + tmp=($(echo $run | tr "_" " ")) + layout=${tmp[0]} + units=${tmp[2]} + resubmit=$(( ${tmp[1]%%x*} -1 )) + length=${tmp[1]##*x} + + readonly CASE_SCRIPTS_DIR=${CASE_ROOT}/tests/${run}/case_scripts + readonly CASE_RUN_DIR=${CASE_ROOT}/tests/${run}/run + readonly PELAYOUT=${layout} + readonly WALLTIME="2:00:00" + readonly STOP_OPTION=${units} + readonly STOP_N=${length} + readonly REST_OPTION=${STOP_OPTION} + readonly REST_N=${STOP_N} + readonly RESUBMIT=${resubmit} + readonly DO_SHORT_TERM_ARCHIVING=false + +else + + # Production simulation + readonly CASE_SCRIPTS_DIR=${CASE_ROOT}/case_scripts + readonly CASE_RUN_DIR=${CASE_ROOT}/run + readonly PELAYOUT="L" + readonly WALLTIME="02:00:00" + readonly STOP_OPTION="nmonths" + readonly STOP_N="1" + readonly REST_OPTION="nmonths" + readonly REST_N="1" + readonly RESUBMIT="0" + readonly DO_SHORT_TERM_ARCHIVING=false +fi + +# Coupler history +readonly HIST_OPTION="nmonths" +readonly HIST_N="1" + +# Leave empty (unless you understand what it does) +readonly OLD_EXECUTABLE="" + +# --- Toggle flags for what to do ---- +do_fetch_code=false +do_create_newcase=true +do_modify_pelayout=false +do_case_setup=true +do_case_build=true +do_case_submit=true + +# --- Now, do the work --- + +# Make directories created by this script world-readable +umask 022 + +# Fetch code from Github +fetch_code + +# Create case +create_newcase + +# Custom PE layout +modify_pelayout + +# Setup +case_setup + +# Build +case_build + +# Configure runtime options +runtime_options + +# Copy script into case_script directory for provenance +copy_script + +# Submit +case_submit + +# All done +echo $'\n----- All done -----\n' + +} + +# ======================= +# Custom user_nl settings +# ======================= + +user_nl() { + +cat << EOF >> user_nl_eam +EOF + +cat << EOF >> user_nl_elm +EOF + +cat << EOF >> user_nl_mpaso +EOF + +cat << EOF >> user_nl_mpassi +EOF + +} + +# ===================================== +# Customize MPAS stream files if needed +# ===================================== + +patch_mpas_streams() { + +echo + +} + +# ===================================================== +# Custom PE layout: +# ===================================================== + +modify_pelayout() { + + if [ "${do_modify_pelayout,,}" != "true" ]; then + echo $'\n----- Skipping changing PE-layout -----\n' + return + fi + + echo $'\n----- changing PE layout to custom -----\n' + pushd ${CASE_SCRIPTS_DIR} + + ./xmlchange MAX_MPITASKS_PER_NODE=32 + ./xmlchange MAX_TASKS_PER_NODE=256 + ./xmlchange NTASKS_ATM=1024 + ./xmlchange NTASKS_CPL=1024 + ./xmlchange NTASKS_OCN=1024 + ./xmlchange NTASKS_WAV=1024 + ./xmlchange NTASKS_GLC=1024 + ./xmlchange NTASKS_ICE=1024 + ./xmlchange NTASKS_ROF=1024 + ./xmlchange NTASKS_LND=1024 + ./xmlchange NTASKS_ESP=1 + ./xmlchange NTASKS_IAC=1 + + ./xmlchange NTHRDS_ATM=8 + ./xmlchange NTHRDS_CPL=8 + ./xmlchange NTHRDS_OCN=8 + ./xmlchange NTHRDS_WAV=8 + ./xmlchange NTHRDS_GLC=1 + ./xmlchange NTHRDS_ICE=8 + ./xmlchange NTHRDS_ROF=8 + ./xmlchange NTHRDS_LND=8 + ./xmlchange NTHRDS_ESP=1 + ./xmlchange NTHRDS_IAC=1 + + ./xmlchange ROOTPE_ATM=0 + ./xmlchange ROOTPE_CPL=0 + ./xmlchange ROOTPE_OCN=0 + ./xmlchange ROOTPE_WAV=0 + ./xmlchange ROOTPE_GLC=0 + ./xmlchange ROOTPE_ICE=0 + ./xmlchange ROOTPE_ROF=0 + ./xmlchange ROOTPE_LND=0 + ./xmlchange ROOTPE_ESP=0 + ./xmlchange ROOTPE_IAC=0 + + popd + + } +###################################################### +### Most users won't need to change anything below ### +###################################################### + +#----------------------------------------------------- +fetch_code() { + + if [ "${do_fetch_code,,}" != "true" ]; then + echo $'\n----- Skipping fetch_code -----\n' + return + fi + + echo $'\n----- Starting fetch_code -----\n' + local path=${CODE_ROOT} + local repo=E3SM + + echo "Cloning $repo repository branch $BRANCH under $path" + if [ -d "${path}" ]; then + echo "ERROR: Directory already exists. Not overwriting" + exit 20 + fi + mkdir -p ${path} + pushd ${path} + + # This will put repository, with all code + git clone git@github.com:E3SM-Project/${repo}.git . + + # Check out desired branch + git checkout ${BRANCH} + + # Custom addition + if [ "${CHERRY}" != "" ]; then + echo ----- WARNING: adding git cherry-pick ----- + for commit in "${CHERRY[@]}" + do + echo ${commit} + git cherry-pick ${commit} + done + echo ------------------------------------------- + fi + + # Bring in all submodule components + git submodule update --init --recursive + + popd +} + +#----------------------------------------------------- +create_newcase() { + + if [ "${do_create_newcase,,}" != "true" ]; then + echo $'\n----- Skipping create_newcase -----\n' + return + fi + + echo $'\n----- Starting create_newcase -----\n' + + if [[ ${PELAYOUT} == custom-* ]]; + then + layout="M" # temporary placeholder for create_newcase + else + layout=${PELAYOUT} + + fi + ${CODE_ROOT}/cime/scripts/create_newcase \ + --case ${CASE_NAME} \ + --output-root ${CASE_ROOT} \ + --script-root ${CASE_SCRIPTS_DIR} \ + --handle-preexisting-dirs u \ + --compset ${COMPSET} \ + --res ${RESOLUTION} \ + --machine ${MACHINE} ${COMPILER} \ + --project ${PROJECT} \ + --walltime ${WALLTIME} \ + --pecount ${layout} \ + + if [ $? != 0 ]; then + echo $'\nNote: if create_newcase failed because sub-directory already exists:' + echo $' * delete old case_script sub-directory' + echo $' * or set do_newcase=false\n' + exit 35 + fi + +} + +#----------------------------------------------------- +case_setup() { + + if [ "${do_case_setup,,}" != "true" ]; then + echo $'\n----- Skipping case_setup -----\n' + return + fi + + echo $'\n----- Starting case_setup -----\n' + pushd ${CASE_SCRIPTS_DIR} + + # Setup some CIME directories + ./xmlchange EXEROOT=${CASE_BUILD_DIR} + ./xmlchange RUNDIR=${CASE_RUN_DIR} + + # Short term archiving + ./xmlchange DOUT_S=${DO_SHORT_TERM_ARCHIVING^^} + ./xmlchange DOUT_S_ROOT=${CASE_ARCHIVE_DIR} + + # Build with COSP, except for a data atmosphere (datm) + if [ `./xmlquery --value COMP_ATM` == "datm" ]; then + echo $'\nThe specified configuration uses a data atmosphere, so cannot activate COSP simulator\n' + else + echo $'\nConfiguring E3SM to use the COSP simulator\n' + ./xmlchange --id CAM_CONFIG_OPTS --append --val='-cosp' + fi + + # Extracts input_data_dir in case it is needed for user edits to the namelist later + local input_data_dir=`./xmlquery DIN_LOC_ROOT --value` + + # Custom user_nl + user_nl + + # Finally, run CIME case.setup + ./case.setup --reset + + popd +} + +#----------------------------------------------------- +case_build() { + + pushd ${CASE_SCRIPTS_DIR} + + # do_case_build = false + if [ "${do_case_build,,}" != "true" ]; then + + echo $'\n----- case_build -----\n' + + if [ "${OLD_EXECUTABLE}" == "" ]; then + # Ues previously built executable, make sure it exists + if [ -x ${CASE_BUILD_DIR}/e3sm.exe ]; then + echo 'Skipping build because $do_case_build = '${do_case_build} + else + echo 'ERROR: $do_case_build = '${do_case_build}' but no executable exists for this case.' + exit 297 + fi + else + # If absolute pathname exists and is executable, reuse pre-exiting executable + if [ -x ${OLD_EXECUTABLE} ]; then + echo 'Using $OLD_EXECUTABLE = '${OLD_EXECUTABLE} + cp -fp ${OLD_EXECUTABLE} ${CASE_BUILD_DIR}/ + else + echo 'ERROR: $OLD_EXECUTABLE = '$OLD_EXECUTABLE' does not exist or is not an executable file.' + exit 297 + fi + fi + echo 'WARNING: Setting BUILD_COMPLETE = TRUE. This is a little risky, but trusting the user.' + ./xmlchange BUILD_COMPLETE=TRUE + + # do_case_build = true + else + + echo $'\n----- Starting case_build -----\n' + + # Turn on debug compilation option if requested + if [ "${DEBUG_COMPILE^^}" == "TRUE" ]; then + ./xmlchange DEBUG=${DEBUG_COMPILE^^} + fi + + # Run CIME case.build + ./case.build + + fi + + # Some user_nl settings won't be updated to *_in files under the run directory + # Call preview_namelists to make sure *_in and user_nl files are consistent. + echo $'\n----- Preview namelists -----\n' + ./preview_namelists + + popd +} + +#----------------------------------------------------- +runtime_options() { + + echo $'\n----- Starting runtime_options -----\n' + pushd ${CASE_SCRIPTS_DIR} + + # Set simulation start date + ./xmlchange RUN_STARTDATE=${START_DATE} + + # Segment length + ./xmlchange STOP_OPTION=${STOP_OPTION,,},STOP_N=${STOP_N} + + # Restart frequency + ./xmlchange REST_OPTION=${REST_OPTION,,},REST_N=${REST_N} + + # Coupler history + ./xmlchange HIST_OPTION=${HIST_OPTION,,},HIST_N=${HIST_N} + + # Coupler budgets (always on) + ./xmlchange BUDGETS=TRUE + + # Set resubmissions + if (( RESUBMIT > 0 )); then + ./xmlchange RESUBMIT=${RESUBMIT} + fi + + # Run type + # Start from default of user-specified initial conditions + if [ "${MODEL_START_TYPE,,}" == "initial" ]; then + ./xmlchange RUN_TYPE="startup" + ./xmlchange CONTINUE_RUN="FALSE" + + # Continue existing run + elif [ "${MODEL_START_TYPE,,}" == "continue" ]; then + ./xmlchange CONTINUE_RUN="TRUE" + + elif [ "${MODEL_START_TYPE,,}" == "branch" ] || [ "${MODEL_START_TYPE,,}" == "hybrid" ]; then + ./xmlchange RUN_TYPE=${MODEL_START_TYPE,,} + ./xmlchange GET_REFCASE=${GET_REFCASE} + ./xmlchange RUN_REFDIR=${RUN_REFDIR} + ./xmlchange RUN_REFCASE=${RUN_REFCASE} + ./xmlchange RUN_REFDATE=${RUN_REFDATE} + echo 'Warning: $MODEL_START_TYPE = '${MODEL_START_TYPE} + echo '$RUN_REFDIR = '${RUN_REFDIR} + echo '$RUN_REFCASE = '${RUN_REFCASE} + echo '$RUN_REFDATE = '${START_DATE} + else + echo 'ERROR: $MODEL_START_TYPE = '${MODEL_START_TYPE}' is unrecognized. Exiting.' + exit 380 + fi + + # Patch mpas streams files + patch_mpas_streams + + popd +} + +#----------------------------------------------------- +case_submit() { + + if [ "${do_case_submit,,}" != "true" ]; then + echo $'\n----- Skipping case_submit -----\n' + return + fi + + echo $'\n----- Starting case_submit -----\n' + pushd ${CASE_SCRIPTS_DIR} + + # Run CIME case.submit + ./case.submit + + popd +} + +#----------------------------------------------------- +copy_script() { + + echo $'\n----- Saving run script for provenance -----\n' + + local script_provenance_dir=${CASE_SCRIPTS_DIR}/run_script_provenance + mkdir -p ${script_provenance_dir} + local this_script_name=`basename $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} + +} + +#----------------------------------------------------- +# Silent versions of popd and pushd +pushd() { + command pushd "$@" > /dev/null +} +popd() { + command popd "$@" > /dev/null +} + +# Now, actually run the script +#----------------------------------------------------- +main + diff --git a/components/mpas-ocean/docs/index.md b/components/mpas-ocean/docs/index.md new file mode 100644 index 00000000000..4e75ec0f8e8 --- /dev/null +++ b/components/mpas-ocean/docs/index.md @@ -0,0 +1,7 @@ +# Model for Prediction Across Scales-Ocean + +The Model for Prediction Across Scales-Ocean (MPAS-Ocean) is the ocean component of the Energy Exascale Earth System Model (E3SM), developed by the U.S. Department of Energy. + +* The [MPAS-Ocean User Guide](user-guide/index.md) explains how to run and customize MPAS-Ocean within E3SM. +* The [MPAS-Ocean Developer Guide](dev-guide/index.md) explains MPAS-Ocean data structures and how to write new code. +* The [MPAS-Ocean Technical Guide](tech-guide/index.md) explains the science behind MPAS-Ocean. diff --git a/components/mpas-ocean/docs/tech-guide/index.md b/components/mpas-ocean/docs/tech-guide/index.md new file mode 100644 index 00000000000..beb4d1e9e7a --- /dev/null +++ b/components/mpas-ocean/docs/tech-guide/index.md @@ -0,0 +1,29 @@ +# MPAS-Ocean Technical Guide + +This Technical Guide describes the governing equations, physics, and numerical discretizations of MPAS-Ocean. + +## Guides, Design Documents, and documentation + +MPAS-Ocean may be run as either a stand-alone model, or within the E3SM coupled climate model. +The MPAS-Ocean code for both stand-alone and coupled is housed in the repository [https://github.com/E3SM-Project/E3SM](https://github.com/E3SM-Project/E3SM) within the directory `components/mpas-ocean`. The stand-alone executable may be built within that directory using the make command with the required libraries, as described in Chapter 1 of the [User's Guide](https://zenodo.org/records/11098080). + +The [MPAS-Ocean User's Guide](https://zenodo.org/records/11098080) provides a description of the MPAS Framework in Part I, the Governing equations for MPAS-Ocean in Chapter 8, and describes the physics behind each term and parameterization in chapter 11. + +All new features are created with design documents. The location of these documents have moved over the years, but can still be found in these locations: + +1. [MPAS Documents repository](https://github.com/MPAS-Dev/MPAS-Documents/tree/master/ocean) +2. [E3SM repository MPAS-Ocean docs](https://github.com/E3SM-Project/E3SM/tree/master/components/mpas-ocean/docs/design_docs) +3. Documents for the new Omega model are similar to MPAS-Ocean and may be found in the [Omega documentation](https://docs.e3sm.org/Omega/develop/index.html). + +All test cases are housed in the [Compass repository](https://github.com/MPAS-Dev/compass) and, more recently, the [Polaris repository](https://github.com/E3SM-Project/polaris). The corresponding documentation is housed in the [Compass docs](https://mpas-dev.github.io/compass/latest/) and [Polaris docs](http://docs.e3sm.org/polaris/main/) pages. + +## Publications + +Beyond the documentation, there are many publications that describe the inner workings of MPAS-Ocean: + +Ringler, T., Petersen, M., Higdon, R.L., Jacobsen, D., Jones, P.W., Maltrud, M., 2013. +[A multi-resolution approach to global ocean modeling](https://doi.org/10.1016/j.ocemod.2013.04.010). Ocean Modelling 69, 211-232. + +Petersen, M.R., D.W. Jacobsen, T.D. Ringler, M.W. Hecht, M.E. Maltrud, [Evaluation of the arbitrary Lagrangian–Eulerian vertical coordinate method in the MPAS-Ocean model](http://dx.doi.org/10.1016/j.ocemod.2014.12.004), Ocean Modelling, Volume 86, February 2015, Pages 93-113, ISSN 1463-5003. + +Petersen, M. R., Asay‐Davis, X. S., Berres, A. S., Chen, Q., Feige, N., Hoffman, M. J., et al. (2019). [An evaluation of the ocean and sea ice climate of E3SM using MPAS and interannual CORE‐II forcing](https://doi.org/10.1029/2018MS001373). Journal of Advances in Modeling Earth Systems, 11, 1438– 1458. diff --git a/components/mpas-ocean/docs/user-guide/index.md b/components/mpas-ocean/docs/user-guide/index.md new file mode 100644 index 00000000000..0bc14046db0 --- /dev/null +++ b/components/mpas-ocean/docs/user-guide/index.md @@ -0,0 +1,200 @@ + +# MPAS-Ocean Quick Start + +This MPAS-Ocean Quick Start Guide describes how to set up and run MPAS-Ocean within E3SM. More details can be found in the [MPAS-Ocean User's Guide](https://zenodo.org/records/11098080), as well as instructions on running the stand-alone ocean model. + +## Steps to build and run MPAS-Ocean + +Step-by-step instructions on how to run E3SM can be found at [https://docs.e3sm.org/running-e3sm-guide](https://docs.e3sm.org/running-e3sm-guide). + +This MPAS-Ocean Quick Start guide provides the additional information to run configurations that are not fully-coupled (e.g. C-case: active ocean only; G-case: active ocean and sea ice) within E3SM. This is done by changing the compset. Certain parameters, including the mesh, namelist parameters, input data files, and output file specifcations can also be modified. These are described below as ways to customize runs. + +Templates of 1-month example E3SM run-scripts for a [G-case](../gcase.template.v3LR.chrysalis.sh) and [C-case](../ccase.template.v3LR.anvil.sh) are provided. Key information for the user to modify includes: + +- `MACHINE` and `PROJECT` if applicable +- Paths for code repository in `CODE_ROOT` and case directory in `CASE_ROOT`, which includes the run directory for output. +- Simulation compsets, resolution and name (see below) +- Wallclock duration in `WALLTIME` and simulation duration with `STOP_OPTION` and `STOP_N`. + +Additional runscript examples can be found [here](https://github.com/E3SM-Project/SimulationScripts/tree/master/archive/CoupledGroup/v3.LR) for v3.LR. + +## Scientifically supported compsets and meshes + +### Compsets + +The compsets below are typical ocean and sea ice-focused compsets supported by E3SM: + +`GMPAS-JRA1p5` - Active ocean-sea ice configuration forced by data atmosphere based on JRA55 v1.5 (covers 63 years, 1958-2020) + +`GMPAS-IAF` - Active ocean-sea ice configuration forced by data atmosphere based on CORE-II (covers 62 years, 1948-2009) + +`GMPAS-JRA1p5-DIB-DISMF` - Active ocean-sea ice configuration forced by JRA55 v1.5 atmosphere (as above), with data iceberg and data ice-shelf melt + +`GMPAS-JRA1p5-DIB-PISMF` - Active ocean-sea ice configuration forced by JRA55 v1.5 atmosphere (as above), with data iceberg and prognostic ice-shelf melt + +`CMPASO-JRA1p4` - Active ocean configuration forced by data atmosphere based on JRA55 v1.4 (covers 61 years, 1958-2018) + +`CMPASO-IAF` - Active ocean configuration forced by data atmosphere based on CORE-II (covers 62 years, 1948-2009) + +Additional compsets can be found in the [mpas-ocean `config_compsets.xml`](https://github.com/E3SM-Project/E3SM/blob/master/components/mpas-ocean/cime_config/config_compsets.xml). Note that the fully coupled compsets and their aliases can be found in the [cime allactive `config_compsets.xml`](https://github.com/E3SM-Project/E3SM/blob/master/cime_config/allactive/config_compsets.xml). +For more information on the schemes used within MPAS-Ocean, refer to the [MPAS-Ocean User's Guide](https://zenodo.org/records/11098080). + +A full list of Compsets in the current repository can be listed using + +```text +cd cime/scripts +./query_config --compsets +``` + +### Meshes + +Some supported meshes for G- and C-cases include: + +`TL319_IcoswISC30E3r5` - Icosahedral 30 km mesh with ice shelves cavities (wISC), E3SMv3 (E3) revision r5, TL319 is the grid for JRA. + +`T62_IcoswISC30E3r5` - Icosahedral 30 km mesh with ice shelves cavities (wISC), E3SMv3 (E3) revision r5, T62 is the grid for CORE-II. + +`T62_oQU240` - Quasi uniform 2-degree ocean mesh, to be used with CORE-II only. Good for rapid testing, used in nightly testing **not** production runs. This grid is not scientifically validated . + +Note: the mesh should be consistent with the compset (e.g. JRA vs CORE). Additional mesh information can be found [here](https://github.com/E3SM-Project/E3SM/blob/master/cime_config/config_grids.xml). + +A full list of Meshes in the current repository can be listed using + +```text +cd cime/scripts +./query_config --grids +``` + +## Customizing runs + +### Namelist changes + +Without additional input, E3SM will generate the namelist file `mpaso_in` in the run directory using the default values for the compset and mesh requested. +Namelist parameters can be changed from default values by modifying the `user_nl_mpaso` file, found in the `case_scripts` directory. This is done by entering ``[namelist option] = [changed value]`` as separate lines in the ``user_nl_mpaso`` file. All other options will remain defaults. These changes can be added at run time and will take effect in the next submission. + +Refer to the [MPAS-Ocean User's Guide](https://zenodo.org/records/11098080) (Chapter 10) for a comprehensive description of the namelist parameters and the options that they correspond to. Namelist options may also be found in the code repository in the file `components/mpas-ocean/src/Registry.xml` for general flags, `components/mpas-ocean/src/tracer_groups/Registry_*.xml` for specific tracer group flags, and `components/mpas-ocean/src/analysis_members/Registry_*.xml` for analysis member flags. + +#### Example of a namelist change via `user_nl_mpaso` + +```text + config_GM_closure = 'constant' + config_gm_constant_kappa = 900 + config_time_integrator = 'split_explicit' + config_am_timeseriesstatsmonthly_compute_interval = '00-00-01_00:00:00' +``` + +In this example, the namelist changes include changing the eddy closure (first 2 options for the type of closure and a parameter value), switching the time integration scheme, and modifying an analysis member (in this case, the interval from which the monthly analysis member is computed). + +Reminder: `user_nl_mpaso` can be empty. All options not specified are defaults (given the compset and mesh). Some options (like interior restoring) require extra fields to be present in the input file. + +### Configuring input and output for MPAS-Ocean + +The reading and writing of model fields in MPAS is handled by user-configurable streams. A stream +represents a fixed set of model fields, together with dimensions and attributes, that are all written +or read together to or from the same file or set of files. They are used for reading initial conditions, for writing and reading restart fields, and for writing additional model history fields. +Streams are defined in XML configuration files that are created at build time for each model core. The name of this XML file for the ocean core is `streams.ocean` (the sea ice has a similar `streams.seaice`). Importantly, the stream file is generated in the run directory during the ``./case.setup`` step, but **changes made into the run directory will not take effect**. To make changes to the output fields, **copy the `streams.ocean` file from the run directory into the``case_scripts/SourceMods/src.mpaso/`` directory**. Changes to the stream file made into the ``SourceMods`` sub-directory will take effect on the next case submission (there is no need to re-compile after making modifications to the XML file). Alternatively, changes to the streams file can be made directly in the code in ``components/mpas-ocean/cime_config/buildnml``. + +#### Checking initial conditions + +Key information to check regarding the input data typically include: + +```text + + +``` + +The `mesh` filename points to the mesh file used. The `input` filename points to the file containing the ocean initial conditions (if the run type is `initial`). +The streams file can be large, it is often useful to rely on the search function to navigate it. For larger meshes (millions of horizontal cells) the flag `io_type="pnetcdf"` must be changed to `io_type="pnetcdf,cdf5"`. + +#### Checking and modifying the output data + +By default, MPAS-Ocean will output a set of monthly-averaged variables. The streams file can be modified to include additional variables in the existing output files, produce additional output files, or change the output frequency (e.g. high frequency files shifting between daily or 5-daily frequencies). + +The XML file is organized into blocks describing each stream. Typical streams for output include: + +`timeSeriesStatsMonthlyOutput` - monthly averaged output + +`highFrequencyOutput` - high frequency snapshots (not averaged) output with frequency `output_interval` + +Under each block header is the list of variables (individual variables, variable structure, or variable arrays) that will be output within the relevant stream. + +##### Example workflow for modifying the output fields + +- copy the `streams.ocean` file from the run directory to the `SourceMods` directory (see above) +- identify the variable name for the variable of interest. You can find the variable name by searching the ocean Registry.xml (in the `src` directory) or Registry_package.xml in the `tracer` and `analysis_member` sub-directories. Note whether the variable of interest is included within a `var_array` or a `var_struct`. +- identify the output stream of interest (e.g. monthly averages, high frequency, others). You can search for a stream name, known output filename, or output interval. +- check whether the variable of interest is included in the `streams.ocean` file. Search for the `var name`, or the `var_array` and `var_struct` if applicable. If it is, copy the variable line from other streams into the stream of interest. If it is not included, copy it from the Registry.xml. +- check whether the relevant stream is turned on. This includes checking that `output_interval` in the stream header is not `None`. +- make further modifications: e.g. you can modify the `output_interval` for the high-frequency stream. If you are turning on a new stream, remove unnecessary variables from the stream. + +##### Excerpts from a `streams.ocean` file + +```text + + + + + + + + + + +... + +``` + +```text + + + + + + + + + + + + + + + + + + + + + +``` + +A more comprehensive description of the streams options can be found in Chapter 6 of the [MPAS-Ocean User's Guide](https://zenodo.org/records/11098080). diff --git a/components/mpas-ocean/driver/mpaso_cpl_indices.F b/components/mpas-ocean/driver/mpaso_cpl_indices.F index 968a4090fe4..f099cf8ea46 100644 --- a/components/mpas-ocean/driver/mpaso_cpl_indices.F +++ b/components/mpas-ocean/driver/mpaso_cpl_indices.F @@ -17,12 +17,18 @@ module mpaso_cpl_indices integer :: index_o2x_So_dhdx integer :: index_o2x_So_dhdy integer :: index_o2x_Fioo_q + integer :: index_o2x_Foxo_q_li integer :: index_o2x_Fioo_frazil + integer :: index_o2x_Foxo_frazil_li integer :: index_o2x_Faoo_h2otemp integer :: index_o2x_Faoo_fco2_ocn integer :: index_o2x_Faoo_fdms_ocn integer :: index_o2x_So_ssh - + integer :: index_o2x_Foxo_ismw + integer :: index_o2x_Foxo_rrofl + integer :: index_o2x_Foxo_rrofi + integer :: index_o2x_Foxo_ismh + integer :: index_o2x_Foxo_rrofih ! ocn -> drv for calculation of ocean-ice sheet interactions @@ -182,12 +188,21 @@ subroutine mpaso_cpl_indices_set( ) index_o2x_So_dhdx = mct_avect_indexra(o2x,'So_dhdx') index_o2x_So_dhdy = mct_avect_indexra(o2x,'So_dhdy') index_o2x_Fioo_q = mct_avect_indexra(o2x,'Fioo_q',perrWith='quiet') + index_o2x_Foxo_q_li = mct_avect_indexra(o2x,'Foxo_q_li',perrWith='quiet') index_o2x_Fioo_frazil = mct_avect_indexra(o2x,'Fioo_frazil',perrWith='quiet') + index_o2x_Foxo_frazil_li= mct_avect_indexra(o2x,'Foxo_frazil_li',perrWith='quiet') index_o2x_Faoo_h2otemp = mct_avect_indexra(o2x,'Faoo_h2otemp',perrWith='quiet') index_o2x_Faoo_fco2_ocn = mct_avect_indexra(o2x,'Faoo_fco2_ocn',perrWith='quiet') index_o2x_Faoo_fdms_ocn = mct_avect_indexra(o2x,'Faoo_fdms_ocn',perrWith='quiet') index_o2x_So_ssh = mct_avect_indexra(o2x,'So_ssh') + index_o2x_Foxo_ismw = mct_avect_indexra(o2x,'Foxo_ismw',perrWith='quiet') + index_o2x_Foxo_rrofl = mct_avect_indexra(o2x,'Foxo_rrofl',perrWith='quiet') + index_o2x_Foxo_rrofi = mct_avect_indexra(o2x,'Foxo_rrofi',perrWith='quiet') + + index_o2x_Foxo_ismh = mct_avect_indexra(o2x,'Foxo_ismh',perrWith='quiet') + index_o2x_Foxo_rrofih = mct_avect_indexra(o2x,'Foxo_rrofih',perrWith='quiet') + index_o2x_So_blt = mct_avect_indexra(o2x,'So_blt') index_o2x_So_bls = mct_avect_indexra(o2x,'So_bls') index_o2x_So_htv = mct_avect_indexra(o2x,'So_htv') diff --git a/components/mpas-ocean/driver/ocn_comp_mct.F b/components/mpas-ocean/driver/ocn_comp_mct.F index ec02127f7ca..be40de0622a 100644 --- a/components/mpas-ocean/driver/ocn_comp_mct.F +++ b/components/mpas-ocean/driver/ocn_comp_mct.F @@ -753,13 +753,12 @@ end subroutine xml_stream_get_attributes call mpas_pool_get_subpool(block_ptr % structs, 'scratch', scratchPool) call ocn_forcing_build_fraction_absorbed_array(meshPool, statePool, forcingPool, ierr, 1) + call ocn_frazil_forcing_build_arrays(domain, meshPool, forcingPool, statePool, ierr) call mpas_timer_start("land_ice_build_arrays", .false.) call ocn_surface_land_ice_fluxes_build_arrays(meshPool, forcingPool, scratchPool, & statePool, err=ierr) call mpas_timer_stop("land_ice_build_arrays") - call ocn_frazil_forcing_build_arrays(domain, meshPool, forcingPool, statePool, ierr) - block_ptr => block_ptr % next end do @@ -1095,7 +1094,7 @@ subroutine ocn_run_mct( EClock, cdata_o, x2o_o, o2x_o)!{{{ call mpas_pool_get_subpool(block_ptr % structs, 'scratch', scratchPool) call ocn_forcing_build_fraction_absorbed_array(meshPool, statePool, forcingPool, ierr, 1) - + call ocn_frazil_forcing_build_arrays(domain, meshPool, forcingPool, statePool, ierr) call mpas_timer_start("land_ice_build_arrays", .false.) call ocn_surface_land_ice_fluxes_build_arrays(meshPool, & forcingPool, scratchPool, statePool, ierr) @@ -1103,8 +1102,6 @@ subroutine ocn_run_mct( EClock, cdata_o, x2o_o, o2x_o)!{{{ call ocn_surface_land_ice_fluxes_accumulate_fluxes(meshPool, forcingPool, & statePool, dt, ierr) - call ocn_frazil_forcing_build_arrays(domain, meshPool, forcingPool, statePool, ierr) - call ocn_eddy_compute_mixed_layer_depth(statePool, forcingPool) if (config_use_GM .or. config_submesoscale_enable) then call ocn_eddy_compute_buoyancy_gradient() @@ -2700,7 +2697,12 @@ subroutine ocn_export_mct(o2x_o, errorCode) !{{{ avgOceanSurfaceDOCSemiLabile, & avgOceanSurfaceFeParticulate, & avgOceanSurfaceFeDissolved, & - ssh + ssh, & + avgLandIceFreshwaterFlux, & + avgRemovedRiverRunoffFlux, & + avgRemovedIceRunoffFlux, & + avgLandIceHeatFlux, & + avgRemovedIceRunoffHeatFlux real (kind=RKIND), dimension(:,:), pointer :: avgTracersSurfaceValue, avgSurfaceVelocity, & avgSSHGradient, avgOceanSurfacePhytoC, & @@ -2709,6 +2711,7 @@ subroutine ocn_export_mct(o2x_o, errorCode) !{{{ real (kind=RKIND) :: surfaceFreezingTemp logical, pointer :: frazilIceActive, & + config_remove_AIS_coupler_runoff, & config_use_ecosysTracers, & config_use_DMSTracers, & config_use_MacroMoleculesTracers, & @@ -2725,6 +2728,7 @@ subroutine ocn_export_mct(o2x_o, errorCode) !{{{ call mpas_pool_get_package(domain % packages, 'frazilIceActive', frazilIceActive) call mpas_pool_get_config(domain % configs, 'config_use_ecosysTracers', config_use_ecosysTracers) call mpas_pool_get_config(domain % configs, 'config_land_ice_flux_mode', config_land_ice_flux_mode) + call mpas_pool_get_config(domain % configs, 'config_remove_AIS_coupler_runoff', config_remove_AIS_coupler_runoff) call mpas_pool_get_config(domain % configs, 'config_use_DMSTracers', config_use_DMSTracers) call mpas_pool_get_config(domain % configs, 'config_use_MacroMoleculesTracers', config_use_MacroMoleculesTracers) call mpas_pool_get_config(domain % configs, 'config_use_ecosysTracers_sea_ice_coupling', & @@ -2767,6 +2771,17 @@ subroutine ocn_export_mct(o2x_o, errorCode) !{{{ call mpas_pool_get_array(statePool, 'accumulatedFrazilIceMass', accumulatedFrazilIceMass, 1) end if + ! Cryo fields + if (trim(config_land_ice_flux_mode) == 'standalone' .or. trim(config_land_ice_flux_mode) == 'data') then + call mpas_pool_get_array(forcingPool, 'avgLandIceFreshwaterFlux', avgLandIceFreshwaterFlux) + call mpas_pool_get_array(forcingPool, 'avgLandIceHeatFlux', avgLandIceHeatFlux) + endif + if (config_remove_AIS_coupler_runoff) then + call mpas_pool_get_array(forcingPool, 'avgRemovedRiverRunoffFlux', avgRemovedRiverRunoffFlux) + call mpas_pool_get_array(forcingPool, 'avgRemovedIceRunoffFlux', avgRemovedIceRunoffFlux) + call mpas_pool_get_array(forcingPool, 'avgRemovedIceRunoffHeatFlux', avgRemovedIceRunoffHeatFlux) + endif + ! BGC fields if (config_use_ecosysTracers) then @@ -2818,6 +2833,17 @@ subroutine ocn_export_mct(o2x_o, errorCode) !{{{ o2x_o % rAttr(index_o2x_Faoo_h2otemp, n) = avgTotalFreshWaterTemperatureFlux(i) * rho_sw * cp_sw + ! Cryo fields + if (trim(config_land_ice_flux_mode) == 'standalone' .or. trim(config_land_ice_flux_mode) == 'data') then + o2x_o % rAttr(index_o2x_Foxo_ismw, n) = avgLandIceFreshwaterFlux(i) + o2x_o % rAttr(index_o2x_Foxo_ismh, n) = avgLandIceHeatFlux(i) + endif + if (config_remove_AIS_coupler_runoff) then + o2x_o % rAttr(index_o2x_Foxo_rrofl, n) = avgRemovedRiverRunoffFlux(i) + o2x_o % rAttr(index_o2x_Foxo_rrofi, n) = avgRemovedIceRunoffFlux(i) + o2x_o % rAttr(index_o2x_Foxo_rrofih, n) = avgRemovedIceRunoffHeatFlux(i) + endif + if ( frazilIceActive ) then ! negative when frazil ice can be melted keepFrazil = .true. @@ -2853,6 +2879,10 @@ subroutine ocn_export_mct(o2x_o, errorCode) !{{{ o2x_o % rAttr(index_o2x_Fioo_q, n) = 0.0_RKIND o2x_o % rAttr(index_o2x_Fioo_frazil, n) = 0.0_RKIND + if (trim(config_land_ice_flux_mode) == 'standalone' .or. trim(config_land_ice_flux_mode) == 'data') then + o2x_o % rAttr(index_o2x_Foxo_q_li, n) = accumulatedFrazilIceMass(i) * config_frazil_heat_of_fusion / ocn_cpl_dt + o2x_o % rAttr(index_o2x_Foxo_frazil_li, n) = accumulatedFrazilIceMass(i) / ocn_cpl_dt + endif end if @@ -3981,7 +4011,12 @@ subroutine ocn_export_moab(EClock) !{{{ avgOceanSurfaceDOCSemiLabile, & avgOceanSurfaceFeParticulate, & avgOceanSurfaceFeDissolved, & - ssh + ssh, & + avgLandIceFreshwaterFlux, & + avgRemovedRiverRunoffFlux, & + avgRemovedIceRunoffFlux, & + avgLandIceHeatFlux, & + avgRemovedIceRunoffHeatFlux real (kind=RKIND), dimension(:,:), pointer :: avgTracersSurfaceValue, avgSurfaceVelocity, & avgSSHGradient, avgOceanSurfacePhytoC, & @@ -3990,6 +4025,7 @@ subroutine ocn_export_moab(EClock) !{{{ real (kind=RKIND) :: surfaceFreezingTemp logical, pointer :: frazilIceActive, & + config_remove_AIS_coupler_runoff, & config_use_ecosysTracers, & config_use_DMSTracers, & config_use_MacroMoleculesTracers, & @@ -4006,6 +4042,7 @@ subroutine ocn_export_moab(EClock) !{{{ call mpas_pool_get_package(domain % packages, 'frazilIceActive', frazilIceActive) call mpas_pool_get_config(domain % configs, 'config_use_ecosysTracers', config_use_ecosysTracers) call mpas_pool_get_config(domain % configs, 'config_land_ice_flux_mode', config_land_ice_flux_mode) + call mpas_pool_get_config(domain % configs, 'config_remove_AIS_coupler_runoff', config_remove_AIS_coupler_runoff) call mpas_pool_get_config(domain % configs, 'config_use_DMSTracers', config_use_DMSTracers) call mpas_pool_get_config(domain % configs, 'config_use_MacroMoleculesTracers', config_use_MacroMoleculesTracers) call mpas_pool_get_config(domain % configs, 'config_use_ecosysTracers_sea_ice_coupling', & @@ -4047,6 +4084,16 @@ subroutine ocn_export_moab(EClock) !{{{ call mpas_pool_get_array(forcingPool, 'frazilSurfacePressure', frazilSurfacePressure) call mpas_pool_get_array(statePool, 'accumulatedFrazilIceMass', accumulatedFrazilIceMass, 1) end if + + if (trim(config_land_ice_flux_mode) == 'standalone' .or. trim(config_land_ice_flux_mode) == 'data') then + call mpas_pool_get_array(forcingPool, 'avgLandIceFreshwaterFlux', avgLandIceFreshwaterFlux) + call mpas_pool_get_array(forcingPool, 'avgLandIceHeatFlux', avgLandIceHeatFlux) + endif + if (config_remove_AIS_coupler_runoff) then + call mpas_pool_get_array(forcingPool, 'avgRemovedRiverRunoffFlux', avgRemovedRiverRunoffFlux) + call mpas_pool_get_array(forcingPool, 'avgRemovedIceRunoffFlux', avgRemovedIceRunoffFlux) + call mpas_pool_get_array(forcingPool, 'avgRemovedIceRunoffHeatFlux', avgRemovedIceRunoffHeatFlux) + endif ! BGC fields if (config_use_ecosysTracers) then @@ -4098,7 +4145,17 @@ subroutine ocn_export_moab(EClock) !{{{ o2x_om(n, index_o2x_So_dhdy) = avgSSHGradient(index_avgMeridionalSSHGradient, i) o2x_om(n, index_o2x_Faoo_h2otemp) = avgTotalFreshWaterTemperatureFlux(i) * rho_sw * cp_sw - + + if (trim(config_land_ice_flux_mode) == 'standalone' .or. trim(config_land_ice_flux_mode) == 'data') then + o2x_om(n, index_o2x_Foxo_ismw) = avgLandIceFreshwaterFlux(i) + o2x_om(n, index_o2x_Foxo_ismh) = avgLandIceHeatFlux(i) + endif + if (config_remove_AIS_coupler_runoff) then + o2x_om(n, index_o2x_Foxo_rrofl) = avgRemovedRiverRunoffFlux(i) + o2x_om(n, index_o2x_Foxo_rrofi) = avgRemovedIceRunoffFlux(i) + o2x_om(n, index_o2x_Foxo_rrofih) = avgRemovedIceRunoffHeatFlux(i) + endif + if ( frazilIceActive ) then ! negative when frazil ice can be melted keepFrazil = .true. @@ -4134,7 +4191,10 @@ subroutine ocn_export_moab(EClock) !{{{ o2x_om(n, index_o2x_Fioo_q) = 0.0_RKIND o2x_om(n, index_o2x_Fioo_frazil) = 0.0_RKIND - + if (trim(config_land_ice_flux_mode) == 'standalone' .or. trim(config_land_ice_flux_mode) == 'data') then + o2x_om(n, index_o2x_Foxo_q_li) = accumulatedFrazilIceMass(i) * config_frazil_heat_of_fusion / ocn_cpl_dt + o2x_om(n, index_o2x_Foxo_frazil_li) = accumulatedFrazilIceMass(i) / ocn_cpl_dt + endif end if ! Reset SeaIce Energy and Accumulated Frazil Ice diff --git a/components/mpas-ocean/mkdocs.yml b/components/mpas-ocean/mkdocs.yml new file mode 100644 index 00000000000..3e250057929 --- /dev/null +++ b/components/mpas-ocean/mkdocs.yml @@ -0,0 +1,7 @@ +site_name: MPAS-Ocean + +nav: + - Introduction: 'index.md' + - Users's Guide: user-guide/index.md + - Developers's Guide: dev-guide/index.md + - Technical Guide: tech-guide/index.md diff --git a/components/mpas-ocean/src/Registry.xml b/components/mpas-ocean/src/Registry.xml index 783eb4951ca..475a2751def 100644 --- a/components/mpas-ocean/src/Registry.xml +++ b/components/mpas-ocean/src/Registry.xml @@ -110,6 +110,9 @@ description="Number of wavenumbers used to reconstruct Stokes drift depth profile" definition="6" /> + @@ -477,6 +480,14 @@ description="Background vertical diffusion applied to tracer quantities" possible_values="Any positive real value." /> + + + + + + + @@ -1637,6 +1662,7 @@ + @@ -2612,6 +2638,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + - @@ -305,7 +302,6 @@ - @@ -362,7 +358,6 @@ - diff --git a/components/mpas-ocean/src/analysis_members/Registry_global_stats.xml b/components/mpas-ocean/src/analysis_members/Registry_global_stats.xml index 1f76e701fd2..480ad08ef3f 100644 --- a/components/mpas-ocean/src/analysis_members/Registry_global_stats.xml +++ b/components/mpas-ocean/src/analysis_members/Registry_global_stats.xml @@ -148,6 +148,9 @@ + @@ -157,6 +160,9 @@ + @@ -247,6 +253,9 @@ + @@ -256,6 +265,9 @@ + @@ -346,6 +358,9 @@ + @@ -355,6 +370,9 @@ + @@ -445,6 +463,9 @@ + @@ -454,6 +475,9 @@ + @@ -544,6 +568,9 @@ + @@ -553,6 +580,9 @@ + @@ -643,6 +673,9 @@ + @@ -652,6 +685,9 @@ + @@ -742,6 +778,9 @@ + @@ -751,6 +790,9 @@ + + + diff --git a/components/mpas-ocean/src/analysis_members/Registry_time_series_stats_monthly_mean.xml b/components/mpas-ocean/src/analysis_members/Registry_time_series_stats_monthly_mean.xml index 58ac7e95af4..2858e01961d 100644 --- a/components/mpas-ocean/src/analysis_members/Registry_time_series_stats_monthly_mean.xml +++ b/components/mpas-ocean/src/analysis_members/Registry_time_series_stats_monthly_mean.xml @@ -187,6 +187,8 @@ + + diff --git a/components/mpas-ocean/src/analysis_members/Registry_time_series_stats_monthly_min.xml b/components/mpas-ocean/src/analysis_members/Registry_time_series_stats_monthly_min.xml index 5ee051585d7..30121568ad4 100644 --- a/components/mpas-ocean/src/analysis_members/Registry_time_series_stats_monthly_min.xml +++ b/components/mpas-ocean/src/analysis_members/Registry_time_series_stats_monthly_min.xml @@ -126,6 +126,8 @@ + + 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 a4f2a0b7ab5..bdd07e799b5 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 @@ -598,16 +598,14 @@ subroutine energy_conservation(domain, err) enddo end if - if (landIceFreshwaterFluxesOn & - .and.config_use_frazil_ice_formation & - .and.config_frazil_under_land_ice) then + if (config_use_frazil_ice_formation .and. config_frazil_under_land_ice) then call mpas_pool_get_array(statePool, 'accumulatedLandIceFrazilMass', accumulatedLandIceFrazilMassOld, 1) call mpas_pool_get_array(statePool, 'accumulatedLandIceFrazilMass', accumulatedLandIceFrazilMassNew, 2) do iCell = 1, nCellsSolve ! Frazil ice mass is negative. Negative coefficient makes heat ! flux positive, because freezing ice releases heat. sumArray(18) = sumArray(18) - areaCell(iCell) * config_frazil_heat_of_fusion & - * (accumulatedLandIceFrazilMassNew(iCell) - accumulatedLandIceFrazilMassOld(iCell)) + * (accumulatedLandIceFrazilMassNew(iCell) - accumulatedLandIceFrazilMassOld(iCell))/dt enddo end if @@ -748,9 +746,7 @@ subroutine energy_conservation(domain, err) if (landIceFreshwaterFluxesOn) then v=accumulatedLandIceHeatFlux ; write(m,"('landIceHeatFlux ',es16.8,' ',f16.8)") v,v/A; call mpas_log_write(m); s=s+v end if - if (landIceFreshwaterFluxesOn & - .and.config_use_frazil_ice_formation & - .and.config_frazil_under_land_ice) then + if (config_use_frazil_ice_formation .and. config_frazil_under_land_ice) then v=accumulatedLandIceFrazilHeatFlux ; write(m,"(' landIceFrazilHeatFlux ',es16.8,' (already in hfreeze, do not sum )',f16.8)") v,v/A; call mpas_log_write(m); ! no sum: s=s+v end if write(m,"('SUM EXPLICIT HEAT FLUXES ',es16.8,' ',f16.8)") s, s/A; call mpas_log_write(m) @@ -976,9 +972,7 @@ subroutine mass_conservation(domain, err) enddo end if - if (landIceFreshwaterFluxesOn & - .and.config_use_frazil_ice_formation & - .and.config_frazil_under_land_ice) then + if (config_use_frazil_ice_formation .and. config_frazil_under_land_ice) then call mpas_pool_get_array(statePool, 'accumulatedLandIceFrazilMass', accumulatedLandIceFrazilMassOld, 1) call mpas_pool_get_array(statePool, 'accumulatedLandIceFrazilMass', accumulatedLandIceFrazilMassNew, 2) do iCell = 1, nCellsSolve @@ -1101,9 +1095,7 @@ subroutine mass_conservation(domain, err) write(m,"(' SUM: ice runoff ',es16.8,' x2o_Foxx_rofi wfrzrof SUM ',f16.8)") v,v*c; call mpas_log_write(m) v=accumulatedLandIceFlux ; write(m,"('landIceFreshwaterFlux ',es16.8,' ',f16.8)") v,v*c; call mpas_log_write(m); s=s+v endif - if (landIceFreshwaterFluxesOn & - .and.config_use_frazil_ice_formation & - .and.config_frazil_under_land_ice) then + if (config_use_frazil_ice_formation .and. config_frazil_under_land_ice) then v=accumulatedLandIceFrazilFlux ; write(m,"(' landIceFrazilFlux ',es16.8,' (already in wfreeze, do not sum )',f16.8)") v,v*c; call mpas_log_write(m); ! no sum: s=s+v endif write(m,"('SUM VOLUME FLUXES ',es16.8,' ',f16.8,es16.8)") s, s*c; call mpas_log_write(m) @@ -1170,8 +1162,8 @@ subroutine salt_conservation(domain, err) real(kind=RKIND), pointer :: & accumulatedSeaIceSalinityFlux, & - accumulatedFrazilSalinityFlux, & - accumulatedLandIceFrazilSalinityFlux + accumulatedFrazilSalinityFlux + ! accumulatedLandIceFrazilSalinityFlux is not present because it is always 0 real(kind=RKIND), dimension(:), allocatable :: & sumArray, & @@ -1217,7 +1209,6 @@ 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, "accumulatedLandIceFrazilSalinityFlux", accumulatedLandIceFrazilSalinityFlux) !------------------------------------------------------------- ! Net salt flux to ice @@ -1258,14 +1249,10 @@ subroutine salt_conservation(domain, err) enddo end if - if (landIceFreshwaterFluxesOn & - .and.config_use_frazil_ice_formation & - .and.config_frazil_under_land_ice) then - call mpas_pool_get_array(statePool, 'accumulatedLandIceFrazilMass', accumulatedLandIceFrazilMassOld, 1) - call mpas_pool_get_array(statePool, 'accumulatedLandIceFrazilMass', accumulatedLandIceFrazilMassNew, 2) + if (config_use_frazil_ice_formation .and. config_frazil_under_land_ice) then + ! Land ice frazil salinity is always 0 do iCell = 1, nCellsSolve - sumArray(3) = sumArray(3) + areaCell(iCell) & - * (accumulatedLandIceFrazilMassNew(iCell) - accumulatedLandIceFrazilMassOld(iCell))/dt + sumArray(3) = sumArray(3) + 0.0_RKIND enddo end if @@ -1278,7 +1265,6 @@ subroutine salt_conservation(domain, err) ! accumulate fluxes accumulatedSeaIceSalinityFlux = accumulatedSeaIceSalinityFlux + sumArrayOut(1) accumulatedFrazilSalinityFlux = accumulatedFrazilSalinityFlux + sumArrayOut(2) - accumulatedLandIceFrazilSalinityFlux = accumulatedLandIceFrazilSalinityFlux + sumArrayOut(3) ! cleanup deallocate(sumArray) @@ -1295,7 +1281,6 @@ subroutine salt_conservation(domain, err) ! Average the fluxes accumulatedSeaIceSalinityFlux = accumulatedSeaIceSalinityFlux /accumulatedFluxCounter accumulatedFrazilSalinityFlux = accumulatedFrazilSalinityFlux /accumulatedFluxCounter - accumulatedLandIceFrazilSalinityFlux = accumulatedLandIceFrazilSalinityFlux /accumulatedFluxCounter ! get initial salt content call MPAS_pool_get_array(conservationCheckSaltAMPool, "initialSalt", initialSalt) @@ -1312,8 +1297,7 @@ subroutine salt_conservation(domain, err) call MPAS_pool_get_array(conservationCheckSaltAMPool, "netSaltFlux", netSaltFlux) netSaltFlux = accumulatedSeaIceSalinityFlux & - + accumulatedFrazilSalinityFlux & - + accumulatedLandIceFrazilSalinityFlux + + accumulatedFrazilSalinityFlux ! compute the final salt error call MPAS_pool_get_array(conservationCheckSaltAMPool, "absoluteSaltError", absoluteSaltError) @@ -1341,7 +1325,7 @@ subroutine salt_conservation(domain, err) if (landIceFreshwaterFluxesOn & .and.config_use_frazil_ice_formation & .and.config_frazil_under_land_ice) then -v=accumulatedLandIceFrazilSalinityFlux; 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 +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 write(m,"('SUM VOLUME FLUXES ',es16.8,' ',f16.8,es16.8)") s, s*c; call mpas_log_write(m) @@ -2266,8 +2250,7 @@ subroutine reset_accumulated_variables(domain) real(kind=RKIND), pointer :: & accumulatedSeaIceSalinityFlux, & - accumulatedFrazilSalinityFlux, & - accumulatedLandIceFrazilSalinityFlux + accumulatedFrazilSalinityFlux real(kind=RKIND), pointer :: & accumulatedCarbonSourceSink, & @@ -2353,11 +2336,9 @@ 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, "accumulatedLandIceFrazilSalinityFlux", accumulatedLandIceFrazilSalinityFlux) accumulatedSeaIceSalinityFlux = 0.0_RKIND accumulatedFrazilSalinityFlux = 0.0_RKIND - accumulatedLandIceFrazilSalinityFlux = 0.0_RKIND call MPAS_pool_get_subpool(domain % blocklist % structs, "conservationCheckCarbonAM", conservationCheckCarbonAMPool) @@ -2432,7 +2413,8 @@ subroutine ocn_restart_conservation_check(domain, err)!{{{ err = 0 if ( trim(config_land_ice_flux_mode) == 'standalone' .or. & - trim(config_land_ice_flux_mode) == 'coupled' ) then + trim(config_land_ice_flux_mode) == 'coupled' .or. & + trim(config_land_ice_flux_mode) == 'data' ) then landIceFreshwaterFluxesOn = .true. end if diff --git a/components/mpas-ocean/src/analysis_members/mpas_ocn_global_stats.F b/components/mpas-ocean/src/analysis_members/mpas_ocn_global_stats.F index c21d1d4b5b5..203665999a8 100644 --- a/components/mpas-ocean/src/analysis_members/mpas_ocn_global_stats.F +++ b/components/mpas-ocean/src/analysis_members/mpas_ocn_global_stats.F @@ -254,9 +254,9 @@ subroutine ocn_compute_global_stats(domain, timeLevel, err)!{{{ real (kind=RKIND), dimension(:), pointer :: evaporationFlux, snowFlux real (kind=RKIND), dimension(:), pointer :: seaIceFreshWaterFlux, icebergFreshWaterFlux, riverRunoffFlux, iceRunoffFlux - real (kind=RKIND), dimension(:), pointer :: rainFlux, landIceFreshwaterFlux + real (kind=RKIND), dimension(:), pointer :: rainFlux, landIceFreshwaterFlux, landIceFreshwaterFluxTotal real (kind=RKIND), dimension(:), pointer :: accumulatedLandIceMass, accumulatedLandIceHeat, & - accumulatedLandIceFrazilMass + accumulatedLandIceFrazilMass, frazilIceFreshwaterFlux real (kind=RKIND), dimension(:,:), pointer :: frazilLayerThicknessTendency @@ -364,6 +364,8 @@ subroutine ocn_compute_global_stats(domain, timeLevel, err)!{{{ call mpas_pool_get_array(forcingPool, 'rainFlux', rainFlux) call mpas_pool_get_array(forcingPool, 'frazilLayerThicknessTendency', frazilLayerThicknessTendency) call mpas_pool_get_array(forcingPool, 'landIceFreshwaterFlux', landIceFreshwaterFlux) + call mpas_pool_get_array(forcingPool, 'landIceFreshwaterFluxTotal', landIceFreshwaterFluxTotal) + call mpas_pool_get_array(forcingPool, 'frazilIceFreshwaterFlux', frazilIceFreshwaterFlux) call mpas_pool_get_array(forcingPool, 'landIceFloatingMask', landIceFloatingMask) call mpas_pool_get_array(tracersSurfaceFluxPool, 'activeTracersSurfaceFlux', activeTracersSurfaceFlux) @@ -377,6 +379,7 @@ subroutine ocn_compute_global_stats(domain, timeLevel, err)!{{{ call mpas_pool_get_array(statePool, 'accumulatedLandIceHeat', accumulatedLandIceHeat, 1) call mpas_pool_get_array(statePool, 'accumulatedLandIceFrazilMass', accumulatedLandIceFrazilMass, 1) + allocate(areaEdge(1:nEdgesSolve)) areaEdge = dcEdge(1:nEdgesSolve)*dvEdge(1:nEdgesSolve) @@ -958,6 +961,21 @@ subroutine ocn_compute_global_stats(domain, timeLevel, err)!{{{ maxes_tmp(variableIndex) = 0.0_RKIND end if + ! landIceFreshwaterFluxTotal + variableIndex = variableIndex + 1 + if ( associated(landIceFreshwaterFluxTotal) ) then + call ocn_compute_field_area_weighted_local_stats_surface(dminfo, nCellsSolve, & + landIceFloatingArea, & + landIceFreshwaterFluxTotal(1:nCellsSolve), sums_tmp(variableIndex), & + sumSquares_tmp(variableIndex), mins_tmp(variableIndex), & + maxes_tmp(variableIndex)) + else + sums_tmp(variableIndex) = 0.0_RKIND + sumSquares_tmp(variableIndex) = 0.0_RKIND + mins_tmp(variableIndex) = 0.0_RKIND + maxes_tmp(variableIndex) = 0.0_RKIND + end if + sums(variableIndex) = sums(variableIndex) + sums_tmp(variableIndex) sumSquares(variableIndex) = sumSquares(variableIndex) + sumSquares_tmp(variableIndex) mins(variableIndex) = min(mins(variableIndex), mins_tmp(variableIndex)) @@ -1024,6 +1042,21 @@ subroutine ocn_compute_global_stats(domain, timeLevel, err)!{{{ maxes_tmp(variableIndex) = 0.0_RKIND end if + ! frazilIceFreshwaterFlux + variableIndex = variableIndex + 1 + if ( associated(frazilIceFreshwaterFlux) ) then + call ocn_compute_field_area_weighted_local_stats_surface(dminfo, nCellsSolve, & + areaCell(1:nCellsSolve), & + frazilIceFreshwaterFlux(1:nCellsSolve), sums_tmp(variableIndex), & + sumSquares_tmp(variableIndex), mins_tmp(variableIndex), & + maxes_tmp(variableIndex)) + else + sums_tmp(variableIndex) = 0.0_RKIND + sumSquares_tmp(variableIndex) = 0.0_RKIND + mins_tmp(variableIndex) = 0.0_RKIND + maxes_tmp(variableIndex) = 0.0_RKIND + end if + sums(variableIndex) = sums(variableIndex) + sums_tmp(variableIndex) sumSquares(variableIndex) = sumSquares(variableIndex) + sumSquares_tmp(variableIndex) mins(variableIndex) = min(mins(variableIndex), mins_tmp(variableIndex)) @@ -1299,6 +1332,16 @@ subroutine ocn_compute_global_stats(domain, timeLevel, err)!{{{ rms(variableIndex) = 0.0_RKIND end if + ! landIceFreshwaterFluxTotal + variableIndex = variableIndex + 1 + if (associated(landIceFreshwaterFluxTotal) .and. landIceFloatingAreaSum > 0.0_RKIND) then + averages(variableIndex) = sums(variableIndex)/(landIceFloatingAreaSum) + rms(variableIndex) = sqrt(sumSquares(variableIndex)/(landIceFloatingAreaSum)) + else + averages(variableIndex) = 0.0_RKIND + rms(variableIndex) = 0.0_RKIND + end if + ! continue accumulating fresh water inputs netFreshwaterInput = netFreshwaterInput + sums(variableIndex) * dt/rho_sw @@ -1332,6 +1375,16 @@ subroutine ocn_compute_global_stats(domain, timeLevel, err)!{{{ rms(variableIndex) = 0.0_RKIND end if + ! frazilIceFreshwaterFlux + variableIndex = variableIndex + 1 + if (frazilIcePkgActive) then + averages(variableIndex) = sums(variableIndex)/(areaCellGlobal) + rms(variableIndex) = sqrt(sumSquares(variableIndex)/(areaCellGlobal)) + else + averages(variableIndex) = 0.0_RKIND + rms(variableIndex) = 0.0_RKIND + end if + ! calculate fresh water conservation check quantities absoluteFreshWaterConservation = totalVolumeChange - netFreshwaterInput if (abs(totalVolumeChange) < 1e-12_RKIND) then 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 ec6a19c81d1..7d9eb083f90 100644 --- a/components/mpas-ocean/src/driver/mpas_ocn_core_interface.F +++ b/components/mpas-ocean/src/driver/mpas_ocn_core_interface.F @@ -138,6 +138,7 @@ function ocn_setup_packages(configPool, packagePool, iocontext) result(ierr)!{{{ logical, pointer :: gotmPKGActive logical, pointer :: verticalRemapPKGActive logical, pointer :: activeWavePKGActive + logical, pointer :: subgridWetDryPKGActive type (mpas_pool_iterator_type) :: pkgItr logical, pointer :: packageActive @@ -172,6 +173,7 @@ function ocn_setup_packages(configPool, packagePool, iocontext) result(ierr)!{{{ logical, pointer :: config_use_time_varying_land_ice_forcing logical, pointer :: config_use_gotm logical, pointer :: config_use_active_wave + logical, pointer :: config_use_subgrid_wetting_drying character (len=StrKIND), pointer :: config_time_integrator character (len=StrKIND), pointer :: config_ocean_run_mode @@ -427,6 +429,15 @@ function ocn_setup_packages(configPool, packagePool, iocontext) result(ierr)!{{{ activeWavePKGActive = .true. endif + ! + ! test for use of subgrid wetting and drying + ! + call mpas_pool_get_package(packagePool, 'subgridWetDryPKGActive', subgridWetDryPKGActive) + call mpas_pool_get_config(configPool, 'config_use_subgrid_wetting_drying', config_use_subgrid_wetting_drying) + if (config_use_subgrid_wetting_drying) then + subgridWetDryPKGActive = .true. + end if + ! ! call into analysis member driver to set analysis member packages ! diff --git a/components/mpas-ocean/src/mode_forward/mpas_ocn_forward_mode.F b/components/mpas-ocean/src/mode_forward/mpas_ocn_forward_mode.F index af69a63e46c..d5ba6b08eb6 100644 --- a/components/mpas-ocean/src/mode_forward/mpas_ocn_forward_mode.F +++ b/components/mpas-ocean/src/mode_forward/mpas_ocn_forward_mode.F @@ -80,6 +80,7 @@ module ocn_forward_mode use ocn_submesoscale_eddies use ocn_stokes_drift use ocn_manufactured_solution + use ocn_subgrid use ocn_high_freq_thickness_hmix_del2 @@ -300,6 +301,8 @@ function ocn_forward_mode_init(domain, startTimeStamp) result(ierr)!{{{ ierr = ior(ierr, err_tmp) call ocn_diagnostics_init(domain, err_tmp) ierr = ior(ierr,err_tmp) + call ocn_subgrid_init(domain, err_tmp) + ierr = ior(ierr,err_tmp) if(ierr.eq.1) then call mpas_log_write('An error was encountered while initializing the MPAS-Ocean forward mode', MPAS_LOG_CRIT) @@ -700,6 +703,7 @@ function ocn_forward_mode_run(domain) result(ierr)!{{{ call mpas_pool_get_subpool(block_ptr % structs, 'forcing', forcingPool) call mpas_pool_get_subpool(block_ptr % structs, 'scratch', scratchPool) call ocn_forcing_build_fraction_absorbed_array(meshPool, statePool, forcingPool, ierr, 1) + call ocn_frazil_forcing_build_arrays(domain, meshPool, forcingPool, statePool, err) call mpas_timer_start("land_ice_build_arrays") call ocn_surface_land_ice_fluxes_build_arrays(meshPool, & forcingPool, scratchPool, statePool, err) @@ -707,7 +711,6 @@ function ocn_forward_mode_run(domain) result(ierr)!{{{ call ocn_surface_land_ice_fluxes_accumulate_fluxes(meshPool, forcingPool, & statePool, dt, err) - call ocn_frazil_forcing_build_arrays(domain, meshPool, forcingPool, statePool, err) call ocn_tidal_forcing_build_array(domain, meshPool, forcingPool, statePool, err) ! Compute normalGMBolusVelocity, relativeSlope and RediDiffVertCoef if respective flags are turned on diff --git a/components/mpas-ocean/src/mode_forward/mpas_ocn_time_integration_fblts.F b/components/mpas-ocean/src/mode_forward/mpas_ocn_time_integration_fblts.F index 36b6dc05766..5b0db3848cb 100644 --- a/components/mpas-ocean/src/mode_forward/mpas_ocn_time_integration_fblts.F +++ b/components/mpas-ocean/src/mode_forward/mpas_ocn_time_integration_fblts.F @@ -224,13 +224,12 @@ subroutine ocn_time_integrator_fblts(domain, dt)!{{{ call mpas_pool_get_array(LTSPool, 'nEdgesInLTSRegion', nEdgesInLTSRegion) ! Create and retrieve additional pools for LTS - call mpas_pool_create_pool(tendSum3rdPool) - call mpas_pool_clone_pool(tendPool, tendSum3rdPool, 1) - call mpas_pool_create_pool(tendSlowPool) - call mpas_pool_clone_pool(tendPool, tendSlowPool, 1) + call mpas_pool_get_subpool(block % structs, 'tend_sum_3rd', tendSum3rdPool) + call mpas_pool_get_subpool(block % structs, 'tend_slow', tendSlowPool) + + call mpas_pool_copy_pool(tendPool, tendSum3rdPool, 1) + call mpas_pool_copy_pool(tendPool, tendSlowPool, 1) - call mpas_pool_add_subpool(block % structs, 'tend_sum_3rd', tendSum3rdPool) - call mpas_pool_add_subpool(block % structs, 'tend_slow', tendSlowPool) call mpas_pool_get_array(tendSlowPool, 'normalVelocity', & normalVelocityTendSlow) @@ -259,47 +258,6 @@ subroutine ocn_time_integrator_fblts(domain, dt)!{{{ normalVelocityTendSum3rd(:,:) = 0.0_RKIND layerThicknessTendSum3rd(:,:) = 0.0_RKIND - if (associated(block % prev)) then - call mpas_pool_get_subpool(block % prev % structs, 'tend_sum_3rd', tendSum3rdPool) - call mpas_pool_get_subpool(block % prev % structs, 'tend_slow', tendSlowPool) - else - nullify(prevTendSum3rdPool) - nullify(prevTendSlowPool) - end if - - if (associated(block % next)) then - call mpas_pool_get_subpool(block % next % structs, 'tend_sum_3rd', nextTendSum3rdPool) - call mpas_pool_get_subpool(block % next % structs, 'tend_slow', nextTendSlowPool) - else - nullify(nextTendSum3rdPool) - nullify(nextTendSlowPool) - end if - - call mpas_pool_get_subpool(block % structs, 'tend_sum_3rd', tendSum3rdPool) - call mpas_pool_get_subpool(block % structs, 'tend_slow', tendSlowPool) - - if (associated(prevTendSum3rdPool) .and. associated(nextTendSum3rdPool)) then - call mpas_pool_link_pools(tendSum3rdPool, prevTendSum3rdPool, nextTendSum3rdPool) - else if (associated(prevTendSum3rdPool)) then - call mpas_pool_link_pools(tendSum3rdPool, prevTendSum3rdPool) - else if (associated(nextTendSum3rdPool)) then - call mpas_pool_link_pools(tendSum3rdPool,nextPool=nextTendSum3rdPool) - else - call mpas_pool_link_pools(tendSum3rdPool) - end if - - if (associated(prevTendSlowPool) .and. associated(nextTendSlowPool)) then - call mpas_pool_link_pools(tendSlowPool, prevTendSlowPool, nextTendSlowPool) - else if (associated(prevTendSlowPool)) then - call mpas_pool_link_pools(tendSlowPool, prevTendSlowPool) - else if (associated(nextTendSlowPool)) then - call mpas_pool_link_pools(tendSlowPool,nextPool=nextTendSlowPool) - else - call mpas_pool_link_pools(tendSlowPool) - end if - - call mpas_pool_link_parinfo(block, tendSum3rdPool) - call mpas_pool_link_parinfo(block, tendSlowPool) call mpas_timer_stop("FB_LTS time-step prep") @@ -1367,12 +1325,6 @@ subroutine ocn_time_integrator_fblts(domain, dt)!{{{ call ocn_diagnostic_solve(dt, statePool, forcingPool, meshPool, & verticalMeshPool, scratchPool, tracersPool, 2) - call mpas_pool_destroy_pool(tendSum3rdPool) - call mpas_pool_destroy_pool(tendSlowPool) - - call mpas_pool_remove_subpool(block % structs, 'tend_sum_3rd') - call mpas_pool_remove_subpool(block % structs, 'tend_slow') - call mpas_timer_stop("FB_LTS cleanup") end subroutine ocn_time_integrator_fblts!}}} @@ -1415,6 +1367,15 @@ subroutine ocn_time_integration_fblts_init(domain)!{{{ type (mpas_pool_type), pointer :: & LTSPool + + type (mpas_pool_type), pointer :: & + tendSlowPool, & + tendSum3rdPool, & + prevTendSlowPool, nextTendSlowPool, & + prevTendSum3rdPool, nextTendSum3rdPool + + type (mpas_pool_type), pointer :: & + tendPool integer, dimension(:), allocatable :: & isLTSRegionEdgeAssigned @@ -1445,6 +1406,58 @@ subroutine ocn_time_integration_fblts_init(domain)!{{{ minMaxLTSRegion(2) = 2 block => domain % blocklist + call mpas_pool_get_subpool(block%structs, 'tend', tendPool) + + call mpas_pool_create_pool(tendSum3rdPool) + call mpas_pool_clone_pool(tendPool, tendSum3rdPool, 1) + call mpas_pool_create_pool(tendSlowPool) + call mpas_pool_clone_pool(tendPool, tendSlowPool, 1) + + call mpas_pool_add_subpool(block % structs, 'tend_sum_3rd', tendSum3rdPool) + call mpas_pool_add_subpool(block % structs, 'tend_slow', tendSlowPool) + + if (associated(block % prev)) then + call mpas_pool_get_subpool(block % prev % structs, 'tend_sum_3rd', tendSum3rdPool) + call mpas_pool_get_subpool(block % prev % structs, 'tend_slow', tendSlowPool) + else + nullify(prevTendSum3rdPool) + nullify(prevTendSlowPool) + end if + + if (associated(block % next)) then + call mpas_pool_get_subpool(block % next % structs, 'tend_sum_3rd', nextTendSum3rdPool) + call mpas_pool_get_subpool(block % next % structs, 'tend_slow', nextTendSlowPool) + else + nullify(nextTendSum3rdPool) + nullify(nextTendSlowPool) + end if + + call mpas_pool_get_subpool(block % structs, 'tend_sum_3rd', tendSum3rdPool) + call mpas_pool_get_subpool(block % structs, 'tend_slow', tendSlowPool) + + if (associated(prevTendSum3rdPool) .and. associated(nextTendSum3rdPool)) then + call mpas_pool_link_pools(tendSum3rdPool, prevTendSum3rdPool, nextTendSum3rdPool) + else if (associated(prevTendSum3rdPool)) then + call mpas_pool_link_pools(tendSum3rdPool, prevTendSum3rdPool) + else if (associated(nextTendSum3rdPool)) then + call mpas_pool_link_pools(tendSum3rdPool,nextPool=nextTendSum3rdPool) + else + call mpas_pool_link_pools(tendSum3rdPool) + end if + + if (associated(prevTendSlowPool) .and. associated(nextTendSlowPool)) then + call mpas_pool_link_pools(tendSlowPool, prevTendSlowPool, nextTendSlowPool) + else if (associated(prevTendSlowPool)) then + call mpas_pool_link_pools(tendSlowPool, prevTendSlowPool) + else if (associated(nextTendSlowPool)) then + call mpas_pool_link_pools(tendSlowPool,nextPool=nextTendSlowPool) + else + call mpas_pool_link_pools(tendSlowPool) + end if + + call mpas_pool_link_parinfo(block, tendSum3rdPool) + call mpas_pool_link_parinfo(block, tendSlowPool) + call mpas_pool_get_subpool(block % structs, 'LTS', LTSPool) call mpas_pool_get_array(LTSPool, 'LTSRegion', LTSRegion) diff --git a/components/mpas-ocean/src/mode_forward/mpas_ocn_time_integration_lts.F b/components/mpas-ocean/src/mode_forward/mpas_ocn_time_integration_lts.F index d123c69aecb..24f9f208ab3 100644 --- a/components/mpas-ocean/src/mode_forward/mpas_ocn_time_integration_lts.F +++ b/components/mpas-ocean/src/mode_forward/mpas_ocn_time_integration_lts.F @@ -254,20 +254,18 @@ subroutine ocn_time_integrator_lts(domain,dt)!{{{ call mpas_pool_get_array(LTSPool, 'nEdgesInLTSRegion', & nEdgesInLTSRegion) - !--- Create additional pools for LTS - call mpas_pool_create_pool(tendSum1stPool) - call mpas_pool_clone_pool(tendPool, tendSum1stPool, 1) - call mpas_pool_create_pool(tendSum2ndPool) - call mpas_pool_clone_pool(tendPool, tendSum2ndPool, 1) - call mpas_pool_create_pool(tendSum3rdPool) - call mpas_pool_clone_pool(tendPool, tendSum3rdPool, 1) - call mpas_pool_create_pool(tendSlowPool) - call mpas_pool_clone_pool(tendPool, tendSlowPool, 1) + !--- Update additional pools for LTS + call mpas_pool_get_subpool(block % structs, 'tend_sum_1st', tendSum1stPool) + call mpas_pool_get_subpool(block % structs, 'tend_sum_2nd', tendSum2ndPool) + call mpas_pool_get_subpool(block % structs, 'tend_sum_3rd', tendSum3rdPool) + call mpas_pool_get_subpool(block % structs, 'tend_slow', tendSlowPool) + + + call mpas_pool_copy_pool(tendPool, tendSum1stPool, 1) + call mpas_pool_copy_pool(tendPool, tendSum2ndPool, 1) + call mpas_pool_copy_pool(tendPool, tendSum3rdPool, 1) + call mpas_pool_copy_pool(tendPool, tendSlowPool, 1) - call mpas_pool_add_subpool(block % structs, 'tend_sum_1st', tendSum1stPool) - call mpas_pool_add_subpool(block % structs, 'tend_sum_2nd', tendSum2ndPool) - call mpas_pool_add_subpool(block % structs, 'tend_sum_3rd', tendSum3rdPool) - call mpas_pool_add_subpool(block % structs, 'tend_slow', tendSlowPool) call mpas_pool_get_array(tendSlowPool, 'normalVelocity', normalVelocityTendSlow) @@ -307,79 +305,6 @@ subroutine ocn_time_integrator_lts(domain,dt)!{{{ normalVelocityTendSum3rd(:,:) = 0.0_RKIND layerThicknessTendSum3rd(:,:) = 0.0_RKIND - if (associated(block % prev)) then - call mpas_pool_get_subpool(block % prev % structs, 'tend_sum_1st', tendSum1stPool) - call mpas_pool_get_subpool(block % prev % structs, 'tend_sum_2nd', tendSum2ndPool) - call mpas_pool_get_subpool(block % prev % structs, 'tend_sum_3rd', tendSum3rdPool) - call mpas_pool_get_subpool(block % prev % structs, 'tend_slow', tendSlowPool) - else - nullify(prevTendSum1stPool) - nullify(prevTendSum2ndPool) - nullify(prevTendSum3rdPool) - nullify(prevTendSlowPool) - end if - - if (associated(block % next)) then - call mpas_pool_get_subpool(block % next % structs, 'tend_sum_1st', nextTendSum1stPool) - call mpas_pool_get_subpool(block % next % structs, 'tend_sum_2nd', nextTendSum2ndPool) - call mpas_pool_get_subpool(block % next % structs, 'tend_sum_3rd', nextTendSum3rdPool) - call mpas_pool_get_subpool(block % next % structs, 'tend_slow', nextTendSlowPool) - else - nullify(nextTendSum1stPool) - nullify(nextTendSum2ndPool) - nullify(nextTendSum3rdPool) - nullify(nextTendSlowPool) - end if - - call mpas_pool_get_subpool(block % structs, 'tend_sum_1st', tendSum1stPool) - call mpas_pool_get_subpool(block % structs, 'tend_sum_2nd', tendSum2ndPool) - call mpas_pool_get_subpool(block % structs, 'tend_sum_3rd', tendSum3rdPool) - call mpas_pool_get_subpool(block % structs, 'tend_slow', tendSlowPool) - - if (associated(prevTendSum1stPool) .and. associated(nextTendSum1stPool)) then - call mpas_pool_link_pools(tendSum1stPool, prevTendSum1stPool, nextTendSum1stPool) - else if (associated(prevTendSum1stPool)) then - call mpas_pool_link_pools(tendSum1stPool, prevTendSum1stPool) - else if (associated(nextTendSum1stPool)) then - call mpas_pool_link_pools(tendSum1stPool,nextPool=nextTendSum1stPool) - else - call mpas_pool_link_pools(tendSum1stPool) - end if - - if (associated(prevTendSum2ndPool) .and. associated(nextTendSum2ndPool)) then - call mpas_pool_link_pools(tendSum2ndPool, prevTendSum2ndPool, nextTendSum2ndPool) - else if (associated(prevTendSum2ndPool)) then - call mpas_pool_link_pools(tendSum2ndPool, prevTendSum2ndPool) - else if (associated(nextTendSum2ndPool)) then - call mpas_pool_link_pools(tendSum2ndPool,nextPool=nextTendSum2ndPool) - else - call mpas_pool_link_pools(tendSum2ndPool) - end if - - if (associated(prevTendSum3rdPool) .and. associated(nextTendSum3rdPool)) then - call mpas_pool_link_pools(tendSum3rdPool, prevTendSum3rdPool, nextTendSum3rdPool) - else if (associated(prevTendSum3rdPool)) then - call mpas_pool_link_pools(tendSum3rdPool, prevTendSum3rdPool) - else if (associated(nextTendSum3rdPool)) then - call mpas_pool_link_pools(tendSum3rdPool,nextPool=nextTendSum3rdPool) - else - call mpas_pool_link_pools(tendSum3rdPool) - end if - - if (associated(prevTendSlowPool) .and. associated(nextTendSlowPool)) then - call mpas_pool_link_pools(tendSlowPool, prevTendSlowPool, nextTendSlowPool) - else if (associated(prevTendSlowPool)) then - call mpas_pool_link_pools(tendSlowPool, prevTendSlowPool) - else if (associated(nextTendSlowPool)) then - call mpas_pool_link_pools(tendSlowPool,nextPool=nextTendSlowPool) - else - call mpas_pool_link_pools(tendSlowPool) - end if - - call mpas_pool_link_parinfo(block, tendSum1stPool) - call mpas_pool_link_parinfo(block, tendSum2ndPool) - call mpas_pool_link_parinfo(block, tendSum3rdPool) - call mpas_pool_link_parinfo(block, tendSlowPool) call mpas_timer_stop("lts time-step prep") @@ -1084,16 +1009,6 @@ subroutine ocn_time_integrator_lts(domain,dt)!{{{ ! DIAGNOSTICS UPDATE --- call ocn_diagnostic_solve(dt, statePool, forcingPool, meshPool, verticalMeshPool, scratchPool, tracersPool, 2) - call mpas_pool_destroy_pool(tendSum1stPool) - call mpas_pool_destroy_pool(tendSum2ndPool) - call mpas_pool_destroy_pool(tendSum3rdPool) - call mpas_pool_destroy_pool(tendSlowPool) - - call mpas_pool_remove_subpool(block % structs, 'tend_sum_1st') - call mpas_pool_remove_subpool(block % structs, 'tend_sum_2nd') - call mpas_pool_remove_subpool(block % structs, 'tend_sum_3rd') - call mpas_pool_remove_subpool(block % structs, 'tend_slow') - call mpas_timer_stop("lts cleanup phase") @@ -1123,6 +1038,16 @@ subroutine ocn_time_integration_lts_init(domain)!{{{ type (block_type), pointer :: block type (mpas_pool_type), pointer :: LTSPool + type (mpas_pool_type), pointer :: tendPool + type (mpas_pool_type), pointer :: & + tendSlowPool, & + tendSum1stPool, & + tendSum2ndPool, & + tendSum3rdPool, & + prevTendSlowPool, nextTendSlowPool, & + prevTendSum1stPool, nextTendSum1stPool, & + prevTendSum2ndPool, nextTendSum2ndPool, & + prevTendSum3rdPool, nextTendSum3rdPool integer, dimension(:), allocatable :: isLTSRegionEdgeAssigned integer :: i, iCell, iEdge, iRegion, coarseRegions, fineRegions, fineRegionsM1 integer, dimension(:), pointer :: LTSRegion @@ -1134,6 +1059,93 @@ subroutine ocn_time_integration_lts_init(domain)!{{{ minMaxLTSRegion(2) = 2 block => domain % blocklist + + ! Create additional pools + call mpas_pool_get_subpool(block%structs, 'tend', tendPool) + + call mpas_pool_create_pool(tendSum1stPool) + call mpas_pool_clone_pool(tendPool, tendSum1stPool, 1) + call mpas_pool_create_pool(tendSum2ndPool) + call mpas_pool_clone_pool(tendPool, tendSum2ndPool, 1) + call mpas_pool_create_pool(tendSum3rdPool) + call mpas_pool_clone_pool(tendPool, tendSum3rdPool, 1) + call mpas_pool_create_pool(tendSlowPool) + call mpas_pool_clone_pool(tendPool, tendSlowPool, 1) + + call mpas_pool_add_subpool(block % structs, 'tend_sum_1st', tendSum1stPool) + call mpas_pool_add_subpool(block % structs, 'tend_sum_2nd', tendSum2ndPool) + call mpas_pool_add_subpool(block % structs, 'tend_sum_3rd', tendSum3rdPool) + call mpas_pool_add_subpool(block % structs, 'tend_slow', tendSlowPool) + + if (associated(block % prev)) then + call mpas_pool_get_subpool(block % prev % structs, 'tend_sum_1st', tendSum1stPool) + call mpas_pool_get_subpool(block % prev % structs, 'tend_sum_2nd', tendSum2ndPool) + call mpas_pool_get_subpool(block % prev % structs, 'tend_sum_3rd', tendSum3rdPool) + call mpas_pool_get_subpool(block % prev % structs, 'tend_slow', tendSlowPool) + else + nullify(prevTendSum1stPool) + nullify(prevTendSum2ndPool) + nullify(prevTendSum3rdPool) + nullify(prevTendSlowPool) + end if + + if (associated(block % next)) then + call mpas_pool_get_subpool(block % next % structs, 'tend_sum_1st', nextTendSum1stPool) + call mpas_pool_get_subpool(block % next % structs, 'tend_sum_2nd', nextTendSum2ndPool) + call mpas_pool_get_subpool(block % next % structs, 'tend_sum_3rd', nextTendSum3rdPool) + call mpas_pool_get_subpool(block % next % structs, 'tend_slow', nextTendSlowPool) + else + nullify(nextTendSum1stPool) + nullify(nextTendSum2ndPool) + nullify(nextTendSum3rdPool) + nullify(nextTendSlowPool) + end if + + if (associated(prevTendSum1stPool) .and. associated(nextTendSum1stPool)) then + call mpas_pool_link_pools(tendSum1stPool, prevTendSum1stPool, nextTendSum1stPool) + else if (associated(prevTendSum1stPool)) then + call mpas_pool_link_pools(tendSum1stPool, prevTendSum1stPool) + else if (associated(nextTendSum1stPool)) then + call mpas_pool_link_pools(tendSum1stPool,nextPool=nextTendSum1stPool) + else + call mpas_pool_link_pools(tendSum1stPool) + end if + + if (associated(prevTendSum2ndPool) .and. associated(nextTendSum2ndPool)) then + call mpas_pool_link_pools(tendSum2ndPool, prevTendSum2ndPool, nextTendSum2ndPool) + else if (associated(prevTendSum2ndPool)) then + call mpas_pool_link_pools(tendSum2ndPool, prevTendSum2ndPool) + else if (associated(nextTendSum2ndPool)) then + call mpas_pool_link_pools(tendSum2ndPool,nextPool=nextTendSum2ndPool) + else + call mpas_pool_link_pools(tendSum2ndPool) + end if + + if (associated(prevTendSum3rdPool) .and. associated(nextTendSum3rdPool)) then + call mpas_pool_link_pools(tendSum3rdPool, prevTendSum3rdPool, nextTendSum3rdPool) + else if (associated(prevTendSum3rdPool)) then + call mpas_pool_link_pools(tendSum3rdPool, prevTendSum3rdPool) + else if (associated(nextTendSum3rdPool)) then + call mpas_pool_link_pools(tendSum3rdPool,nextPool=nextTendSum3rdPool) + else + call mpas_pool_link_pools(tendSum3rdPool) + end if + + if (associated(prevTendSlowPool) .and. associated(nextTendSlowPool)) then + call mpas_pool_link_pools(tendSlowPool, prevTendSlowPool, nextTendSlowPool) + else if (associated(prevTendSlowPool)) then + call mpas_pool_link_pools(tendSlowPool, prevTendSlowPool) + else if (associated(nextTendSlowPool)) then + call mpas_pool_link_pools(tendSlowPool,nextPool=nextTendSlowPool) + else + call mpas_pool_link_pools(tendSlowPool) + end if + + call mpas_pool_link_parinfo(block, tendSum1stPool) + call mpas_pool_link_parinfo(block, tendSum2ndPool) + call mpas_pool_link_parinfo(block, tendSum3rdPool) + call mpas_pool_link_parinfo(block, tendSlowPool) + call mpas_pool_get_subpool(block % structs, 'LTS', LTSPool) call mpas_pool_get_array(LTSPool, 'LTSRegion', LTSRegion) diff --git a/components/mpas-ocean/src/mode_forward/mpas_ocn_time_integration_rk4.F b/components/mpas-ocean/src/mode_forward/mpas_ocn_time_integration_rk4.F index af583448157..5fbb56e6ec1 100644 --- a/components/mpas-ocean/src/mode_forward/mpas_ocn_time_integration_rk4.F +++ b/components/mpas-ocean/src/mode_forward/mpas_ocn_time_integration_rk4.F @@ -44,6 +44,9 @@ module ocn_time_integration_rk4 use ocn_surface_land_ice_fluxes use ocn_transport_tests + use ocn_subgrid + + implicit none private save @@ -195,6 +198,9 @@ subroutine ocn_time_integrator_rk4(domain, dt)!{{{ real (kind=RKIND), dimension(:,:,:), pointer :: activeTracersCur, activeTracersNew + real(kind=RKIND), dimension(:,:), pointer :: subgridSshCellTableRange, subgridWetVolumeCellTable + + ! Get config options call mpas_pool_get_config(domain % configs, 'config_mom_del4', config_mom_del4) call mpas_pool_get_config(domain % configs, 'config_filter_btr_mode', config_filter_btr_mode) @@ -228,10 +234,9 @@ subroutine ocn_time_integrator_rk4(domain, dt)!{{{ call mpas_pool_get_subpool(block % structs, 'mesh', meshPool) call mpas_pool_get_subpool(block % structs, 'diagnostics', diagnosticsPool) - call mpas_pool_create_pool(provisStatePool) + call mpas_pool_get_subpool(block % structs, 'provis_state', provisStatePool) - call mpas_pool_clone_pool(statePool, provisStatePool, 1) - call mpas_pool_add_subpool(block % structs, 'provis_state', provisStatePool) + call mpas_pool_copy_pool(statePool, provisStatePool, 1) call mpas_pool_get_dimension(block % dimensions, 'nCells', nCells) call mpas_pool_get_dimension(block % dimensions, 'nEdges', nEdges) @@ -249,6 +254,13 @@ subroutine ocn_time_integrator_rk4(domain, dt)!{{{ call mpas_pool_get_array(meshPool, 'maxLevelCell', maxLevelCell) call mpas_pool_get_array(meshPool, 'maxLevelEdgeTop', maxLevelEdgeTop) + call mpas_pool_get_array(meshPool, 'subgridWetVolumeCellTable', & + subgridWetVolumeCellTable) + + call mpas_pool_get_array(meshPool, 'subgridSshCellTableRange', & + subgridSshCellTableRange) + + ! Lower k-loop limit of 1 rather than minLevel* needed in *New = *Cur ! assignments below are needed to maintain bit-for-bit results @@ -315,37 +327,6 @@ subroutine ocn_time_integrator_rk4(domain, dt)!{{{ block => block % next end do - block => domain % blocklist - do while(associated(block)) - if (associated(block % prev)) then - call mpas_pool_get_subpool(block % prev % structs, 'provis_state', prevProvisPool) - else - nullify(prevProvisPool) - end if - - if (associated(block % next)) then - call mpas_pool_get_subpool(block % next % structs, 'provis_state', nextProvisPool) - else - nullify(nextProvisPool) - end if - - call mpas_pool_get_subpool(block % structs, 'provis_state', provisStatePool) - - if (associated(prevProvisPool) .and. associated(nextProvisPool)) then - call mpas_pool_link_pools(provisStatePool, prevProvisPool, nextProvisPool) - else if (associated(prevProvisPool)) then - call mpas_pool_link_pools(provisStatePool, prevProvisPool) - else if (associated(nextProvisPool)) then - call mpas_pool_link_pools(provisStatePool, nextPool=nextProvisPool) - else - call mpas_pool_link_pools(provisStatePool) - end if - - call mpas_pool_link_parinfo(block, provisStatePool) - - block => block % next - end do - ! Fourth-order Runge-Kutta, solving dy/dt = f(t,y) is typically written as follows ! where h = delta t is the large time step. Here f(t,y) is the right hand side, ! called the tendencies in the code below. @@ -481,7 +462,7 @@ subroutine ocn_time_integrator_rk4(domain, dt)!{{{ if (config_prevent_drying) then block => domain % blocklist do while (associated(block)) - call ocn_prevent_drying_rk4(block, dt, rk_substep_weights(rk_step), config_zero_drying_velocity, err) + call ocn_prevent_drying_rk4(domain, block, dt, rk_substep_weights(rk_step), config_zero_drying_velocity, err) block => block % next end do ! exchange fields for parallelization @@ -708,6 +689,15 @@ subroutine ocn_time_integrator_rk4(domain, dt)!{{{ layerThicknessNew(k, iCell) = tidalInputMask(iCell)*(tidalBCValue(iCell) + bottomDepth(iCell))*(restingThickness(k,iCell)/totalDepth) !(1.0_RKIND - tidalInputMask(iCell))*layerThicknessNew(k, iCell) ! generalized tappered assumption code end do + + if ( config_use_subgrid_wetting_drying ) then + call ocn_subgrid_layer_thickness_lookup( tidalBCValue(iCell), & + subgridWetVolumeCellTable(:,iCell), & + subgridSshCellTableRange(:,iCell),& + bottomDepth(iCell), & + layerThicknessNew(1,iCell) ) + end if + end if end do end if @@ -853,16 +843,6 @@ subroutine ocn_time_integrator_rk4(domain, dt)!{{{ call mpas_timer_stop("RK4-cleanup phase") - block => domain % blocklist - do while(associated(block)) - call mpas_pool_get_subpool(block % structs, 'provis_state', provisStatePool) - - call mpas_pool_destroy_pool(provisStatePool) - - call mpas_pool_remove_subpool(block % structs, 'provis_state') - block => block % next - end do - end subroutine ocn_time_integrator_rk4!}}} subroutine ocn_time_integrator_rk4_compute_vel_tends(domain, block, dt, & @@ -1731,7 +1711,8 @@ subroutine ocn_time_integration_rk4_init(domain)!{{{ ! local variables !----------------------------------------------------------------- type (block_type), pointer :: block - type (mpas_pool_type), pointer :: meshPool + type (mpas_pool_type), pointer :: meshPool, statePool, provisStatePool + type (mpas_pool_type), pointer :: nextProvisPool, prevProvisPool logical, pointer :: config_use_debugTracers integer, pointer :: nVertLevels ! End preamble @@ -1742,12 +1723,43 @@ subroutine ocn_time_integration_rk4_init(domain)!{{{ block => domain % blocklist do while (associated(block)) call mpas_pool_get_subpool(block % structs, 'mesh', meshPool) + call mpas_pool_get_subpool(block % structs, 'state', statePool) call mpas_pool_get_dimension(meshPool, 'nVertLevels', nVertLevels) if (config_use_debugTracers .and. nVertLevels == 1) then call mpas_log_write('Debug tracers may cause failures in a ' & // 'single layer case. Consider setting ' & // 'config_use_debugTracers to .false.', MPAS_LOG_WARN) endif + + call mpas_pool_create_pool(provisStatePool) + call mpas_pool_clone_pool(statePool, provisStatePool, 1) + call mpas_pool_add_subpool(block % structs, 'provis_state', provisStatePool) + + if (associated(block % prev)) then + call mpas_pool_get_subpool(block % prev % structs, 'provis_state', prevProvisPool) + else + nullify(prevProvisPool) + end if + + if (associated(block % next)) then + call mpas_pool_get_subpool(block % next % structs, 'provis_state', nextProvisPool) + else + nullify(nextProvisPool) + end if + + call mpas_pool_get_subpool(block % structs, 'provis_state', provisStatePool) + + if (associated(prevProvisPool) .and. associated(nextProvisPool)) then + call mpas_pool_link_pools(provisStatePool, prevProvisPool, nextProvisPool) + else if (associated(prevProvisPool)) then + call mpas_pool_link_pools(provisStatePool, prevProvisPool) + else if (associated(nextProvisPool)) then + call mpas_pool_link_pools(provisStatePool, nextPool=nextProvisPool) + else + call mpas_pool_link_pools(provisStatePool) + end if + + call mpas_pool_link_parinfo(block, provisStatePool) block => block % next end do diff --git a/components/mpas-ocean/src/mode_init/Makefile b/components/mpas-ocean/src/mode_init/Makefile index d1aba81e14f..2f16f197318 100644 --- a/components/mpas-ocean/src/mode_init/Makefile +++ b/components/mpas-ocean/src/mode_init/Makefile @@ -7,7 +7,8 @@ UTILS = mpas_ocn_init_spherical_utils.o \ mpas_ocn_init_cell_markers.o \ mpas_ocn_init_interpolation.o \ mpas_ocn_init_ssh_and_landIcePressure.o \ - mpas_ocn_init_smoothing.o + mpas_ocn_init_smoothing.o \ + mpas_ocn_init_subgrid.o TEST_CASES = mpas_ocn_init_baroclinic_channel.o \ mpas_ocn_init_lock_exchange.o \ @@ -31,7 +32,8 @@ TEST_CASES = mpas_ocn_init_baroclinic_channel.o \ mpas_ocn_init_mixed_layer_eddy.o \ mpas_ocn_init_transport_tests.o \ mpas_ocn_init_test_sht.o \ - mpas_ocn_init_parabolic_bowl.o + mpas_ocn_init_parabolic_bowl.o \ + mpas_ocn_init_buttermilk_bay.o #mpas_ocn_init_TEMPLATE.o all: init_mode @@ -54,6 +56,8 @@ mpas_ocn_init_vertical_grids.o: mpas_ocn_init_seaSurfaceHeightAndPressure.o: +mpas_ocn_init_subgrid.o: + mpas_ocn_init_baroclinic_channel.o: $(UTILS) mpas_ocn_init_iso.o: $(UTILS) @@ -100,6 +104,7 @@ mpas_ocn_init_test_sht.o: $(UTILS) mpas_ocn_init_parabolic_bowl.o: $(UTILS) +mpas_ocn_init_buttermilk_bay.o: $(UTILS) #mpas_ocn_init_TEMPLATE.o: $(UTILS) diff --git a/components/mpas-ocean/src/mode_init/Registry.xml b/components/mpas-ocean/src/mode_init/Registry.xml index 3c05635a9c1..1ef457fe532 100644 --- a/components/mpas-ocean/src/mode_init/Registry.xml +++ b/components/mpas-ocean/src/mode_init/Registry.xml @@ -20,6 +20,7 @@ #include "Registry_mixed_layer_eddy.xml" #include "Registry_test_sht.xml" #include "Registry_parabolic_bowl.xml" +#include "Registry_buttermilk_bay.xml" // #include "Registry_TEMPLATE.xml" diff --git a/components/mpas-ocean/src/mode_init/Registry_buttermilk_bay.xml b/components/mpas-ocean/src/mode_init/Registry_buttermilk_bay.xml new file mode 100644 index 00000000000..09754d2a7d4 --- /dev/null +++ b/components/mpas-ocean/src/mode_init/Registry_buttermilk_bay.xml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + diff --git a/components/mpas-ocean/src/mode_init/Registry_parabolic_bowl.xml b/components/mpas-ocean/src/mode_init/Registry_parabolic_bowl.xml index b2188231dc4..bd01e21e1be 100644 --- a/components/mpas-ocean/src/mode_init/Registry_parabolic_bowl.xml +++ b/components/mpas-ocean/src/mode_init/Registry_parabolic_bowl.xml @@ -2,16 +2,16 @@ - + - - @@ -23,13 +23,24 @@ description="Gravitational accerlation" possible_values="Any real number" /> - + + + + - - - - - diff --git a/components/mpas-ocean/src/mode_init/mpas_ocn_init_buttermilk_bay.F b/components/mpas-ocean/src/mode_init/mpas_ocn_init_buttermilk_bay.F new file mode 100644 index 00000000000..0b9f4cbf512 --- /dev/null +++ b/components/mpas-ocean/src/mode_init/mpas_ocn_init_buttermilk_bay.F @@ -0,0 +1,906 @@ +! Copyright (c) 2013, Los Alamos National Security, LLC (LANS) +! and the University Corporation for Atmospheric Research (UCAR). +! +! Unless noted otherwise source code is licensed under the BSD license. +! Additional copyright and license information can be found in the LICENSE file +! distributed with this code, or at http://mpas-dev.github.com/license.html +! +!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +! +! ocn_init_buttermilk_bay +! +!> \brief initialize the Buttermilk Bay case +!> \author D. Wirasaet, S. Brus +!> \date May-June 2022 +!> \details +!> This module contains the routines for initializing the Buttermilk +!> Bay test case with or without subgrid corrections +!> +!----------------------------------------------------------------------- + +module ocn_init_Buttermilk_bay + + use mpas_kind_types + use mpas_io_units + use mpas_derived_types + use mpas_pool_routines + use mpas_constants + use mpas_dmpar + + use ocn_constants + use ocn_config + use ocn_init_vertical_grids + use ocn_init_cell_markers + use ocn_subgrid + use ocn_init_subgrid + + use mpas_constants + use mpas_io + use mpas_io_streams + use mpas_stream_manager + + + implicit none + private + save + + !-------------------------------------------------------------------- + ! + ! Public parameters + ! + !-------------------------------------------------------------------- + + !-------------------------------------------------------------------- + ! + ! Public member functions + ! + !-------------------------------------------------------------------- + + public :: ocn_init_setup_Buttermilk_bay, & + ocn_init_validate_Buttermilk_bay + + !-------------------------------------------------------------------- + ! + ! Private module variables + ! + !-------------------------------------------------------------------- + + ! For netcdf topobathy input variables + integer :: nLatTopo, nLonTopo + + type (field1DReal) :: topoLat, topoLon + type (field2DReal) :: topoIC + + real(kind=RKIND), parameter:: eps = 1.0e-10_RKIND ; +!*********************************************************************** + +contains + +!*********************************************************************** +! +! routine ocn_init_setup_Buttermilk_bay +! +!> \brief Setup for this initial condition +!> \author D. Wirasaet and S. Brus +!> \date May-June 2022 +!> \details +!> This routine sets up the initial conditions for this case. +!> To be run in sigma vertical coordinates and single-layer +! +!----------------------------------------------------------------------- + + subroutine ocn_init_setup_Buttermilk_bay(domain, iErr)!{{{ + use mpas_vector_operations ! To calcutate edgeNormalVector + + implicit none + !-------------------------------------------------------------------- + + type (domain_type), intent(inout) :: domain + integer, intent(out) :: iErr + + type (block_type), pointer :: block_ptr + type (mpas_pool_type), pointer :: meshPool + type (mpas_pool_type), pointer :: statePool + type (mpas_pool_type), pointer :: tracersPool + type (mpas_pool_type), pointer :: verticalMeshPool + type (mpas_pool_type), pointer :: forcingPool + + ! local variables + integer :: iCell, iEdge, iVertex, k, idx + real (kind=RKIND) :: yMin, yMax, xMin, xMax, dcEdgeMin, dcEdgeMinGlobal + real (kind=RKIND) :: yMinGlobal, yMaxGlobal, yMidGlobal, xMinGlobal, xMaxGlobal + real (kind=RKIND) :: localVar1, localVar2 + real (kind=RKIND), dimension(:), pointer :: interfaceLocations + + ! Define dimension pointers + integer, pointer :: nCellsSolve, nEdgesSolve, nVerticesSolve, nVertLevels, nVertLevelsP1 + integer, pointer :: index_temperature, index_salinity + integer, pointer :: maxEdges + + ! Define variable pointers + logical, pointer :: on_a_sphere + integer, dimension(:), pointer :: minLevelCell, maxLevelCell + integer, dimension(:), pointer :: nEdgesOnCell + integer, dimension(:,:), pointer :: verticesOnCell, verticesOnEdge + integer, dimension(:,:), pointer :: cellsOnEdge, cellsOnVertex + real (kind=RKIND), dimension(:), pointer :: xCell, yCell, refBottomDepth, refZMid, & + vertCoordMovementWeights, bottomDepth, fCell, fEdge, fVertex, dcEdge + real (kind=RKIND), dimension(:,:), pointer:: zMid + + real (kind=RKIND), dimension(:), pointer:: xEdge, yEdge, xVertex, yVertex + real (kind=RKIND) :: minBottomDepth, maxBottomDepth, globalMaxBottomDepth, globalMinBottomDepth + real (kind=RKIND), dimension(:,:), pointer :: layerThickness, restingThickness + real (kind=RKIND), dimension(:,:,:), pointer :: activeTracers + + real (kind=RKIND), dimension(:), pointer :: ssh + real (kind=RKIND), dimension(:), pointer :: areaCell + real (kind=RKIND), dimension(:,:), pointer :: edgeNormalVectors + real (kind=RKIND), dimension(:,:), pointer :: normalVelocity + ! Elevation Bcs + real (kind=RKIND), dimension(:), pointer :: tidalInputMask + + + real (kind=RKIND):: HH, uu, vv + real (kind=RKIND):: RR, num, den + real (kind=RKIND):: xshift = 0.0, yshift = 0.0 + real (kind=RKIND) :: layerThicknessEdgeAverage + real (kind=RKIND), dimension(:,:), allocatable :: rSubgridPoints, sSubgridPoints + real (kind=RKIND), dimension(:), allocatable :: subgridBathymetryValues, subgridAreas + real (kind=RKIND), dimension(:), allocatable :: subgridSshValues + real (kind=RKIND), dimension(:), allocatable :: subgridUValues, subgridVValues + real (kind=RKIND), dimension(:), allocatable :: uVelocityAverage, vVelocityAverage + integer :: nSubgridCell, nSubgridEdge, nSubgridVertex + integer :: nSubgridTriPerSlice + integer :: v1, v2 + integer :: c1, c2 + real (kind=RKIND) :: x(3), y(3) + integer :: slice, nSlice + real (kind=RKIND) :: deltaZ + + + integer:: i, j, jj + integer:: nsubgridCellEdge, iEdgeSegment + real (kind=RKIND):: pi + real (kind=RKIND), dimension(:,:), allocatable :: cellEdgeBathymetryValues + real (kind=RKIND), dimension(:), allocatable:: dsEdge + real (kind=RKIND), dimension(:), allocatable:: xSubgridCell, ySubgridCell + real (kind=RKIND):: bathymetryMin, bathymetryMax + iErr = 0 + + if(config_init_configuration .ne. trim('buttermilk_bay')) return + + ! Determine vertical grid for configuration + call mpas_pool_get_subpool(domain % blocklist % structs, 'mesh', meshPool) + call mpas_pool_get_dimension(meshPool, 'nVertLevels', nVertLevels) + call mpas_pool_get_dimension(meshPool, 'nVertLevelsP1', nVertLevelsP1) + call mpas_pool_get_config(meshPool, 'on_a_sphere', on_a_sphere) + + nVertLevels = config_Buttermilk_bay_vert_levels ; + nVertLevelsP1 = nVertLevels + 1 + + allocate(interfaceLocations(nVertLevelsP1)) + call ocn_generate_vertical_grid( config_vertical_grid, interfaceLocations, ocnConfigs ) ; + !! Mental note: interfaceLocatons = (k-1)/N ; + + ! Initalize min/max values to large positive and negative values + yMin = 1.0E10_RKIND + yMax = -1.0E10_RKIND + xMin = 1.0E10_RKIND + xMax = -1.0E10_RKIND + dcEdgeMin = 1.0E10_RKIND + + ! Determine local min and max values. + block_ptr => domain % blocklist + do while(associated(block_ptr)) + call mpas_pool_get_subpool(block_ptr % structs, 'mesh', meshPool) + + call mpas_pool_get_dimension( meshPool, 'nCellsSolve', nCellsSolve ) + call mpas_pool_get_dimension( meshPool, 'nEdgesSolve', nEdgesSolve ) + + call mpas_pool_get_array(meshPool, 'xCell', xCell) + call mpas_pool_get_array(meshPool, 'yCell', yCell) + call mpas_pool_get_array(meshPool, 'dcEdge', dcEdge) + + yMin = min( yMin, minval(yCell(1:nCellsSolve))) + yMax = max( yMax, maxval(yCell(1:nCellsSolve))) + xMin = min( xMin, minval(xCell(1:nCellsSolve))) + xMax = max( xMax, maxval(xCell(1:nCellsSolve))) + dcEdgeMin = min( dcEdgeMin, minval(dcEdge(1:nEdgesSolve))) + + block_ptr => block_ptr % next + end do + + ! Determine global min and max values. + call mpas_dmpar_min_real(domain % dminfo, yMin, yMinGlobal) + call mpas_dmpar_max_real(domain % dminfo, yMax, yMaxGlobal) + call mpas_dmpar_min_real(domain % dminfo, xMin, xMinGlobal) + call mpas_dmpar_max_real(domain % dminfo, xMax, xMaxGlobal) + call mpas_dmpar_min_real(domain % dminfo, dcEdgeMin, dcEdgeMinGlobal) + + pi = acos(-1.0_RKIND) + + xshift = xMin + yshift = (3.0_RKIND*yMin + dcEdgeMin*sin(pi/3.0_RKIND))/3.0_RKIND + ! print*, "xMin, yMin = ", xMin, yMin, dcEdgeMin + ! print*, "xshift, yshift = ", xshift, yshift + + !*********************************************************************** + ! + ! Topography + ! + !*********************************************************************** + + call mpas_log_write( 'Reading bathymetry from a NetCDF file') + + if (config_Buttermilk_bay_topography_source == 'latlon_file' .or. & + config_Buttermilk_bay_topography_source == 'xy_file' ) then + call mpas_log_write( 'Reading topography data from file.') + call ocn_init_setup_Buttermilk_bay_read_topo(domain, iErr) + endif + + !-------------------------------------------------------------------- + ! Use this section to set initial values + !-------------------------------------------------------------------- + + block_ptr => domain % blocklist + call mpas_pool_get_subpool(block_ptr % structs, 'mesh', meshPool) + call mpas_pool_get_subpool(block_ptr % structs, 'state', statePool) + call mpas_pool_get_subpool(block_ptr % structs, 'verticalMesh', verticalMeshPool) + call mpas_pool_get_subpool(statePool, 'tracers', tracersPool) + + call mpas_pool_get_subpool(block_ptr % structs, 'forcing', forcingPool) + call mpas_pool_get_array(forcingPool, 'tidalInputMask', tidalInputMask) + + call mpas_pool_get_dimension(meshPool, 'nVertLevels', nVertLevels) ; + call mpas_pool_get_dimension(meshPool, 'nCellsSolve', nCellsSolve) ; + call mpas_pool_get_dimension(meshPool, 'nEdgesSolve', nEdgesSolve) ; + call mpas_pool_get_dimension(meshPool, 'nVerticesSolve', nVerticesSolve) ; + call mpas_pool_get_dimension(meshPool, 'maxEdges', maxEdges) + + call mpas_pool_get_dimension(tracersPool, 'index_temperature', index_temperature) + call mpas_pool_get_dimension(tracersPool, 'index_salinity', index_salinity) + + call mpas_pool_get_array(meshPool, 'xCell', xCell) + call mpas_pool_get_array(meshPool, 'yCell', yCell) + call mpas_pool_get_array(meshPool, 'refBottomDepth', refBottomDepth) + call mpas_pool_get_array(meshPool, 'vertCoordMovementWeights', vertCoordMovementWeights) + call mpas_pool_get_array(meshPool, 'bottomDepth', bottomDepth) + call mpas_pool_get_array(meshPool, 'minLevelCell', minLevelCell) + call mpas_pool_get_array(meshPool, 'maxLevelCell', maxLevelCell) + call mpas_pool_get_array(meshPool, 'nEdgesOnCell', nEdgesOnCell) + call mpas_pool_get_array(meshPool, 'areaCell', areaCell) + + call mpas_pool_get_array(meshPool, 'verticesOnCell', verticesOnCell) + call mpas_pool_get_array(meshPool, 'verticesOnEdge', verticesOnEdge) + call mpas_pool_get_array(meshPool, 'cellsOnEdge', cellsOnEdge) + call mpas_pool_get_array(meshPool, 'cellsOnVertex', cellsOnVertex) + + call mpas_pool_get_array(meshPool, 'fCell', fCell) + call mpas_pool_get_array(meshPool, 'fEdge', fEdge) + call mpas_pool_get_array(meshPool, 'fVertex', fVertex) + + call mpas_pool_get_array(meshPool, 'xEdge', xEdge ) + call mpas_pool_get_array(meshPool, 'yEdge', yEdge ) + call mpas_pool_get_array(meshPool, 'xVertex', xVertex ) + call mpas_pool_get_array(meshPool, 'yVertex', yVertex ) + + call mpas_pool_get_array(statePool, 'zMid', zMid, 1) ; + + call mpas_pool_get_array(statePool, 'ssh', ssh, 1) + call mpas_pool_get_array(meshPool, 'edgeNormalVectors', edgeNormalVectors ) ; + call mpas_pool_get_array(statePool, 'normalVelocity', normalVelocity ) ; + + call mpas_pool_get_array(tracersPool, 'activeTracers', activeTracers, 1) + call mpas_pool_get_array(statePool, 'layerThickness', layerThickness, 1) + + call mpas_pool_get_array(verticalMeshPool, 'refZMid', refZMid) + call mpas_pool_get_array(verticalMeshPool, 'restingThickness', restingThickness) + + call mpas_pool_get_array(meshPool, 'subgridWetVolumeCellTable', & + subgridWetVolumeCellTable) + call mpas_pool_get_array(meshPool, 'subgridWetVolumeEdgeTable', & + subgridWetVolumeEdgeTable) + call mpas_pool_get_array(meshPool, 'subgridWetVolumeVertexTable', & + subgridWetVolumeVertexTable) + call mpas_pool_get_array(meshPool, 'subgridWetFractionCellTable', & + subgridWetFractionCellTable) + call mpas_pool_get_array(meshPool, 'subgridWetFractionEdgeTable', & + subgridWetFractionEdgeTable) + call mpas_pool_get_array(meshPool,'subgridWetFractionVertexTable',& + subgridWetFractionVertexTable) + call mpas_pool_get_array(meshPool, 'subgridSshCellTableRange', & + subgridSshCellTableRange) + call mpas_pool_get_array(meshPool, 'subgridSshEdgeTableRange', & + subgridSshEdgeTableRange) + call mpas_pool_get_array(meshPool, 'subgridSshVertexTableRange', & + subgridSshVertexTableRange) + call mpas_pool_get_array(meshPool, 'subgridEdgeBathymetryMean', & + subgridEdgeBathymetryMean) + call mpas_pool_get_array(meshPool, 'subgridVertexBathymetryMean', & + subgridVertexBathymetryMean) + call mpas_pool_get_array(meshPool, 'subgridCellBathymetryMin', & + subgridCellBathymetryMin) + call mpas_pool_get_array(meshPool, 'subgridEdgeBathymetryMin', & + subgridEdgeBathymetryMin) + call mpas_pool_get_array(meshPool, 'subgridVertexBathymetryMin', & + subgridVertexBathymetryMin) + call mpas_pool_get_dimension(meshPool, 'nSubgridTableLevels', & + nSubgridTableLevels) + call mpas_pool_get_array(meshPool, 'subgridLayerThicknessDebug', & + subgridLayerThicknessDebug) + + ! if config_buttermilk_bay_adjust_domain_center == .true., + ! Adjust center of the mesh so that its center is located at (0,0) + if ( config_Buttermilk_bay_adjust_domain ) then + xCell = xCell - xshift ; + yCell = yCell - yshift ; + + xEdge = xEdge - xshift ; + yEdge = yEdge - yshift ; + + xVertex = xVertex - xshift ; + yVertex = yVertex - yshift ; + + ! get min, max coordinates of model domain ! + ! after adjusting the coordinates ! + yMin = min( yMin, minval(yCell(1:nCellsSolve))) + yMax = max( yMax, maxval(yCell(1:nCellsSolve))) + xMin = min( xMin, minval(xCell(1:nCellsSolve))) + xMax = max( xMax, maxval(xCell(1:nCellsSolve))) + + ! Determine global min and max values. + call mpas_dmpar_min_real(domain % dminfo, yMin, yMinGlobal) + call mpas_dmpar_max_real(domain % dminfo, yMax, yMaxGlobal) + call mpas_dmpar_min_real(domain % dminfo, xMin, xMinGlobal) + call mpas_dmpar_max_real(domain % dminfo, xMax, xMaxGlobal) + end if + + ! Initlialze vector + call mpas_initialize_vectors(meshPool) ; + + minLevelCell(:) = 1 + do iCell = 1, nCellsSolve + ! Set up vertical grid + maxLevelCell(iCell) = nVertLevels ; ! sigma coordinates + end do + + + do iCell = 1, nCellsSolve + ! Set temperature + activeTracers(index_temperature, :, iCell) = 10.0_RKIND + + ! Set salinity + activeTracers(index_salinity, :, iCell) = 30.0_RKIND + + ! Set Coriolis parameters, if other than zero + fCell(iCell) = 0.0_RKIND; + end do + + do iEdge = 1, nEdgesSolve + fEdge(iEdge) = 0.0_RKIND; + end do + + do iVertex = 1, nVerticesSolve + fVertex(iVertex) = 0.0_RKIND; + end do + + allocate(uVelocityAverage(nEdgesSolve)) + allocate(vVelocityAverage(nEdgesSolve)) + + if (config_use_subgrid_wetting_drying) then + + call ocn_subgrid_init(domain,iErr) + call ocn_init_subgrid_calculations(domain, & + ocn_init_Buttermilk_bay_bathymetry, & + ocn_init_Buttermilk_bay_velocity, & + ocn_init_Buttermilk_bay_ssh, & + config_Buttermilk_bay_subgrid_refinement_level, & + config_Buttermilk_bay_subgrid_edge_bathymetry_max_pixel, & + config_Buttermilk_bay_subgrid_use_thin_layer, & + uVelocityAverage, & + vVelocityAverage, & + iErr) + end if + + ! Find max bottom depth + maxBottomDepth = maxval( bottomDepth ) ; + minBottomDepth = minval( bottomDepth ) ; + call mpas_dmpar_max_real( domain % dminfo, maxBottomDepth, globalMaxBottomDepth ) ; + call mpas_dmpar_min_real( domain % dminfo, minBottomDepth, globalMinBottomDepth ) ; + + ! Set refBottomDepth and refZMid + do k = 1, nVertLevels + refBottomDepth(k) = globalMaxBottomDepth*interfaceLocations(k+1) ; + refZMid(k) = -0.5_RKIND*( interfaceLocations(k+1) + interfaceLocations(k))*globalMaxBottomDepth ; + end do + + ! Set vertCoordMovementWeights + vertCoordMovementWeights(:) = 1.0_RKIND + + ! Set velocity + do iEdge = 1, nEdgesSolve + + if (config_use_subgrid_wetting_drying) then + do k = 1, nVertLevels + normalVelocity(k,iEdge) = uVelocityAverage(iEdge)*edgeNormalVectors(1,iEdge) & + + vVelocityAverage(iEdge)*edgeNormalVectors(2,iEdge) ; + end do + else + call ocn_init_Buttermilk_bay_velocity(xEdge(iEdge), yEdge(iEdge), uu, vv) + do k = 1, nVertLevels + normalVelocity(k,iEdge) = uu*edgeNormalVectors(1,iEdge) + vv*edgeNormalVectors(2,iEdge) ; + end do + end if + end do + + ! Set layer thickness and ssh + if (config_use_wetting_drying) then + + do iCell = 1, nCellsSolve + ! Set up vertical grid + maxLevelCell(iCell) = nVertLevels ; ! sigma coordinates + end do + + do iCell = 1, nCellsSolve + ! + ! make sure depth is thick enough via ssh = TOTAL_DEPTH - bottomDepth + ! add a thin layer of nlayer*config_drying_min_cellhight + ! + + if (config_use_subgrid_wetting_drying) then + ! Initial contion for a subgrid run + call ocn_subgrid_ssh_lookup(layerThickness(1,iCell),& + subgridWetVolumeCellTable(:,iCell),& + subgridSshCellTableRange(:,iCell),& + bottomDepth(iCell),& + subgridCellBathymetryMin(iCell),& + ssh(iCell)) + !call ocn_subgrid_layer_thickness_lookup(ssh(iCell), & + ! subgridWetVolumeCellTable(:,iCell), & + ! subgridSshCellTableRange(:,iCell),& + ! bottomDepth(iCell),& + ! LayerThickness(1,iCell)) + + else + ! Initial condition for a standard run + call ocn_init_Buttermilk_bay_bathymetry(xCell(iCell), yCell(iCell), bottomDepth(iCell)) + + ssh(iCell) = -bottomDepth(iCell) ; + do k = 1, maxLevelCell(iCell) + ! + layerThickness(k,iCell) = max( config_drying_min_cell_height, & + bottomDepth(iCell)/real(maxLevelCell(iCell),RKIND) ) + + + if (layerThickness(k,iCell) < config_drying_min_cell_height) then + call mpas_log_write('layerThickness($i,$i)=$r', MPAS_LOG_CRIT, & + intArgs=(/k,iCell/), & + realArgs=(/layerThickness(k,iCell)/)) + end if + + ssh(iCell) = ssh(iCell) + layerThickness(k,iCell) ; + end do + ! + endif + + do k = 1, maxLevelCell(iCell) + restingThickness(k,iCell) = bottomDepth(iCell)/maxLevelCell(iCell) + end do + + end do + + end if + + + if (config_use_subgrid_wetting_drying) then + do iCell = 1,nCellsSolve + call ocn_subgrid_layer_thickness_lookup(ssh(iCell), & + subgridWetVolumeCellTable(:,iCell), & + subgridSshCellTableRange(:,iCell),& + bottomDepth(iCell),& + subgridLayerThicknessDebug(iCell)) + enddo + end if + + ! Set tidal boundary mask + do iCell = 1, nCellsSolve + tidalInputMask(iCell) = 0.0_RKIND + if ( yCell(iCell) < (yMin+(dcEdgeMin*sin(pi/3.0_RKIND)/2.0_RKIND)) & + .and. yCell(iCell) > (yMin-(dcEDgeMin*sin(pi/3.0_RKIND)/2.0_RKIND)) ) then + + if ( (xCell(iCell) - dcEdgeMin/2.0_RKIND) > 2048.0_RKIND & + .and. (xCell(iCell) + dcEdgeMin/2.0_RKIND) < 3072.0_RKIND ) then + tidalInputMask(iCell) = 1.0_RKIND + end if + ! spread it over multiple cells + ! if (yCell(iCell) > (25.0e3 - 3*dcEdgeMinGlobal)) then + ! tidalInputMask(iCell) = exp(-((yCell(iCell)-25.0e3)/dcEdgeMinGlobal)**2.0) + end if + end do + + deallocate(interfaceLocations) + if (config_global_ocean_topography_source == 'latlon_file') then + call mpas_log_write( 'Cleaning up topography IC fields') + call ocn_init_Buttermilk_bay_destroy_topo_fields() + endif + !-------------------------------------------------------------------- + + print*, "****** End Butter milk bay init *****" ; + + return ; + end subroutine ocn_init_setup_Buttermilk_bay!}}} + +!*********************************************************************** +! +! routine ocn_init_Buttermilk_bay_bathymetry +! +!> \brief Interpolate bathymetry +!> \author Steven Brus, D. Wirasaet +!> \date November 2022 +!> \details Return the value of the bathymetry at a given x,y point +!> +! +!----------------------------------------------------------------------- + + subroutine ocn_init_Buttermilk_bay_bathymetry(x, y, depth)!{{{ + + implicit none + + real (kind=RKIND), intent(in) :: x, y + real (kind=RKIND), intent(out) :: depth + + integer:: ix(2) + real (kind=RKIND) :: xc(2) + real (kind=RKIND) :: dx(2), x0(2), xN(2), bath(4), f(4), den + real (kind=RKIND) :: xv(2), yv(2) + + !-------------------------------------------------------------------- + ! + ! DEM must be on a uniform grid + x0 = (/ topoLon%array(1), topoLat%array(1) /) ; + xN = (/ topoLon%array(nLonTopo), topoLat%array(nLatTopo) /) ; + dx = (/ topoLon%array(2) - topoLon%array(1), & + topoLat%array(2) - topoLat%array(1) /) ; + + ! Bilienar interpolation + xc = (/ x, y /) ; + ix = floor( (xc - x0)/dx ) + 1 ; + + if ( ( ix(1) >= 1 .and. ix(1) < nLonTopo ) .and. & + ( ix(2) >= 1 .and. ix(2) < nLatTopo ) ) then + ! include the west and soutth bourdaries of + ! a given uniform raster DEM + bath(1) = TopoIC%array(ix(1),ix(2)) ; + bath(2) = TopoIC%array(ix(1)+1,ix(2)) ; + bath(3) = TopoIC%array(ix(1)+1,ix(2)+1) ; + bath(4) = TopoIC%array(ix(1),ix(2)) ; + + xv(1) = topoLon%array(ix(1)) ; + xv(2) = topoLon%array(ix(1)+1) ; + + yv(1) = topoLat%array(ix(2)) ; + yv(2) = topoLat%array(ix(2)+1) ; + + den = dx(1)*dx(2) ; + + f(1) = ( xc(1) - xv(2) )*( xc(2) - yv(2) )/den ; + f(2) = ( xc(1) - xv(1) )*( xc(2) - yv(2) )/(-den) ; + f(3) = ( xc(1) - xv(1) )*( xc(2) - yv(1) )/den ; + f(4) = ( xc(1) - xv(2) )*( xc(2) - yv(1) )/(-den) ; + + depth = sum( bath*f ) ; + else + ! nearest extrapolation ! + ix(1) = merge( 1, ix(1), ix(1) < 1 ) ; + ix(1) = merge( nLonTopo, ix(1), ix(1) >= nLonTopo ) ; + ix(2) = merge( 1, ix(2), ix(2) < 1 ) ; + ix(2) = merge( nLatTopo, ix(2), ix(2) >= nLatTopo ) ; + + depth = TopoIC%array(ix(1),ix(2)) ; + endif + + return ; + end subroutine ocn_init_Buttermilk_bay_bathymetry!}}} + +!*********************************************************************** +! +! routine ocn_init_Buttermilk_bay_ssh +! +!> \brief Compute initial ssh field +!> \author Steven Brus, D. Wirasaet +!> \date November 2022 +!> \details Use exact solution to compute ssh field for initial conditions +!> +! +!----------------------------------------------------------------------- + + subroutine ocn_init_Buttermilk_bay_ssh(x, y, bottomDepth, ssh)!{{{ + + implicit none + + real (kind=RKIND), intent(in) :: x, y + real (kind=RKIND), intent(in) :: bottomDepth + real (kind=RKIND), intent(out) :: ssh + real (kind=RKIND) :: RR + + !-------------------------------------------------------------------- + + ssh = 0.0_RKIND ; + ssh = - bottomDepth + max( ssh + bottomDepth, 0.0_RKIND ) ; + + return + !-------------------------------------------------------------------- + + end subroutine ocn_init_Buttermilk_bay_ssh!}}} + +!*********************************************************************** +! +! routine ocn_init_Buttermilk_bay_velocity +! +!> \brief Compute initial velocity field +!> \author Steven Brus, D. Wirasaet +!> \date November 2022 +!> \details Use exact solution to comupte velocity field for initial conditions +!> +! +!----------------------------------------------------------------------- + + subroutine ocn_init_Buttermilk_bay_velocity(x, y, u, v)!{{{ + + implicit none + + real (kind=RKIND), intent(in) :: x, y + real (kind=RKIND), intent(out) :: u, v + real (kind=RKIND) :: RR, HH + + !-------------------------------------------------------------------- + + u = 0.0_RKIND ; + v = 0.0_RKIND ; + !-------------------------------------------------------------------- + + end subroutine ocn_init_Buttermilk_bay_velocity!}}} + +!*********************************************************************** +! +! routine ocn_init_setup_global_ocean_read_topo +! +!> \brief Read the topography IC file +!> \author D. Wirasaet, S. Brus +!> \date Sep 2023 +!> \details +!> This routine reads the topography IC file, including latitude and longitude +!> information for topography data. +!> +!> Adapted from ocn_init_setup_global_ocean_read_topo +!----------------------------------------------------------------------- + subroutine ocn_init_setup_Buttermilk_bay_read_topo(domain, iErr)!{{{ + type (domain_type), intent(inout) :: domain + integer, intent(out) :: iErr + + type (MPAS_Stream_type) :: topographyStream + + iErr = 0 + + ! Define stream for depth levels + call MPAS_createStream(topographyStream, domain % iocontext, & + config_Buttermilk_bay_topography_file, MPAS_IO_NETCDF, & + MPAS_IO_READ, ierr=iErr) + + ! Setup topoLat, topoLon, and topoIC fields for stream to be read in + topoLat % fieldName = trim(config_Buttermilk_bay_topography_lat_varname) + topoLat % dimSizes(1) = nLatTopo + topoLat % dimNames(1) = trim(config_Buttermilk_bay_topography_nlat_dimname) + topoLat % isVarArray = .false. + topoLat % isPersistent = .true. + topoLat % isActive = .true. + topoLat % hasTimeDimension = .false. + topoLat % block => domain % blocklist + allocate(topoLat % attLists(1)) + allocate(topoLat % array(nLatTopo)) + + topoLon % fieldName = trim(config_Buttermilk_bay_topography_lon_varname) + topoLon % dimSizes(1) = nLonTopo + topoLon % dimNames(1) = trim(config_Buttermilk_bay_topography_nlon_dimname) + topoLon % isVarArray = .false. + topoLon % isPersistent = .true. + topoLon % isActive = .true. + topoLon % hasTimeDimension = .false. + topoLon % block => domain % blocklist + allocate(topoLon % attLists(1)) + allocate(topoLon % array(nLonTopo)) + + topoIC % fieldName = trim(config_Buttermilk_bay_topography_varname) + topoIC % dimSizes(1) = nLonTopo + topoIC % dimSizes(2) = nLatTopo + topoIC % dimNames(1) = trim(config_Buttermilk_bay_topography_nlon_dimname) + topoIC % dimNames(2) = trim(config_Buttermilk_bay_topography_nlat_dimname) + topoIC % isVarArray = .false. + topoIC % isPersistent = .true. + topoIC % isActive = .true. + topoIC % hasTimeDimension = .false. + topoIC % block => domain % blocklist + allocate(topoIC % attLists(1)) + allocate(topoIC % array(nLonTopo, nLatTopo)) + + + ! Add topoLat, topoLon, and topoIC fields to stream + call MPAS_streamAddField(topographyStream, topoLat, iErr) + call MPAS_streamAddField(topographyStream, topoLon, iErr) + call MPAS_streamAddField(topographyStream, topoIC, iErr) + + ! Read stream + call MPAS_readStream(topographyStream, 1, iErr) + topoIC%array = -topoIC%array ; + + + ! Close stream + call MPAS_closeStream(topographyStream) + + if ( config_Buttermilk_bay_topography_latlon_degrees .and. & + config_Buttermilk_bay_topography_source == 'latlon_file' ) then + topoLat % array(:) = topoLat % array(:) * pii / 180.0_RKIND + topoLon % array(:) = topoLon % array(:) * pii / 180.0_RKIND + end if + + end subroutine ocn_init_setup_Buttermilk_bay_read_topo!}}} + + +!*********************************************************************** +! +! routine ocn_init_Buttermilk_bay_destroy_topo_fields +! +!> \brief Topography field cleanup routine +!> \author D. Wirasaet and S. Brus +!> \date Sep 2023 +!> \details +!> This routine destroys the fields that were created to hold topography +!> initial condition information +!> +!> NOTE: adapteed from ocn_init_global_ocaen_destroy_topo_fileds +!----------------------------------------------------------------------- + + subroutine ocn_init_Buttermilk_bay_destroy_topo_fields()!{{{ + implicit none + + deallocate(topoIC % array) + deallocate(topoLat % array) + deallocate(topoLon % array) + end subroutine ocn_init_Buttermilk_bay_destroy_topo_fields!}}} + + +!*********************************************************************** +! +! routine ocn_init_Buttermilk_bay +! +!> \brief Validation for this initial condition +!> \author D. Wirasaet and Steven Brus +!> \date Sep 2022 +!> \details +!> This routine validates the configuration options for this case. +!> +!----------------------------------------------------------------------- + subroutine ocn_init_validate_Buttermilk_bay(configPool, packagePool, iocontext, iErr)!{{{ + implicit none + + !-------------------------------------------------------------------- + type (mpas_pool_type), intent(inout) :: configPool, packagePool + type (mpas_io_context_type), intent(inout), target :: iocontext + + integer, intent(out) :: iErr + + ! character (len=StrKIND), pointer :: config_init_configuration + integer, pointer :: config_vert_levels, config_Buttermilk_bay_vert_levels + integer, pointer :: config_subgrid_table_levels, config_Buttermilk_bay_subgrid_table_levels + + + type (mpas_io_context_type), pointer :: iocontext_ptr + type (MPAS_IO_Handle_type) :: inputFile + character (len=StrKIND), pointer :: config_init_configuration, & + config_Buttermilk_bay_topography_source, & + config_Buttermilk_bay_topography_file, & + config_Buttermilk_bay_topography_nlat_dimname, & + config_Buttermilk_bay_topography_nlon_dimname + + iErr = 0 + + call mpas_pool_get_config(configPool, 'config_init_configuration', config_init_configuration) + + if(config_init_configuration .ne. trim('buttermilk_bay')) return + + iocontext_ptr => iocontext + + call mpas_pool_get_config(configPool, 'config_vert_levels', config_vert_levels) + call mpas_pool_get_config(configPool, & + 'config_Buttermilk_bay_vert_levels', & + config_Buttermilk_bay_vert_levels) + + if(config_vert_levels <= 0 .and. config_Buttermilk_bay_vert_levels > 0) then + config_vert_levels = config_Buttermilk_bay_vert_levels + else if (config_vert_levels <= 0) then + call mpas_log_write( 'Validation failed for Buttermilk bay.'// & + 'Not given a usable value for vertical levels.', MPAS_LOG_CRIT) + iErr = 1 + end if + + call mpas_pool_get_config(configPool, 'config_subgrid_table_levels', config_subgrid_table_levels) + call mpas_pool_get_config(configPool, & + 'config_Buttermilk_bay_subgrid_table_levels', & + config_Buttermilk_bay_subgrid_table_levels) + if (config_subgrid_table_levels <=0 .and. config_Buttermilk_bay_subgrid_table_levels >0) then + config_subgrid_table_levels = config_Buttermilk_bay_subgrid_table_levels + else if (config_subgrid_table_levels <=0) then + call mpas_log_write( 'Validation failed for Buttermilk bay.'// & + 'Not given a usable value for subgrid table levels.', MPAS_LOG_CRIT) + iErr = 1 + end if + + + !---------- adapted from ocn_init_validate_global_ocean + call mpas_pool_get_config(configPool, 'config_Buttermilk_bay_topography_source', & + config_Buttermilk_bay_topography_source) + call mpas_pool_get_config(configPool, 'config_Buttermilk_bay_topography_file', & + config_Buttermilk_bay_topography_file) + call mpas_pool_get_config(configPool, 'config_Buttermilk_bay_topography_nlat_dimname', & + config_Buttermilk_bay_topography_nlat_dimname) + call mpas_pool_get_config(configPool, 'config_Buttermilk_bay_topography_nlon_dimname', & + config_Buttermilk_bay_topography_nlon_dimname) + + + call mpas_log_write( config_Buttermilk_bay_topography_source ) + call mpas_log_write( config_Buttermilk_bay_topography_file ) + call mpas_log_write( config_Buttermilk_bay_topography_nlat_dimname ) + call mpas_log_write( config_Buttermilk_bay_topography_nlon_dimname ) + + if (config_Buttermilk_bay_topography_source /= 'latlon_file' .and. & + config_Buttermilk_bay_topography_source /= 'xy_file') then + call mpas_log_write( 'Unexpected value for & + config_Buttermilk_bay_topography_source: ' & + // trim(config_Buttermilk_bay_topography_source), MPAS_LOG_CRIT) + iErr = 1 + return + end if + + if (config_Buttermilk_bay_topography_file == 'none' .and. & + (config_Buttermilk_bay_topography_source == 'latlon_file' .or. & + config_Buttermilk_bay_topography_source == 'xy_file') ) then + call mpas_log_write( 'Validation failed for Buttermilk bay test case. ' & + // 'Invalid filename for config_Buttermilk_bay_topography_file ' & + // config_Buttermilk_bay_topography_file // ' ' & + // config_Buttermilk_bay_topography_source , MPAS_LOG_CRIT) + iErr = 1 + return + end if + + call mpas_log_write( ' in ocn_init_validate_buttermilk_bay '//config_Buttermilk_bay_topography_source ) + + if (config_Buttermilk_bay_topography_source == 'latlon_file' .or. & + config_Buttermilk_bay_topography_source == 'xy_file' ) then + + inputFile = MPAS_io_open(trim(config_Buttermilk_bay_topography_file), & + MPAS_IO_READ, MPAS_IO_NETCDF, iocontext_ptr, ierr=iErr) + if (iErr /= 0) then + call mpas_log_write( 'could not open file '// & + trim(config_Buttermilk_bay_topography_file), MPAS_LOG_CRIT) + return + end if + + call MPAS_io_inq_dim(inputFile, config_Buttermilk_bay_topography_nlat_dimname, nLatTopo, iErr) + call MPAS_io_inq_dim(inputFile, config_Buttermilk_bay_topography_nlon_dimname, nLonTopo, iErr) + + call MPAS_io_close(inputFile, iErr) + + end if + !---------- + + call mpas_log_write( ' Done ocn_init_validate_buttermilk_bay ' ) + !-------------------------------------------------------------------- + + end subroutine ocn_init_validate_ButterMilk_bay!}}} + +!*********************************************************************** + +end module ocn_init_Buttermilk_bay + +!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +! vim: foldmethod=marker diff --git a/components/mpas-ocean/src/mode_init/mpas_ocn_init_mode.F b/components/mpas-ocean/src/mode_init/mpas_ocn_init_mode.F index 2ffa19a6646..0c73a0f8301 100644 --- a/components/mpas-ocean/src/mode_init/mpas_ocn_init_mode.F +++ b/components/mpas-ocean/src/mode_init/mpas_ocn_init_mode.F @@ -63,8 +63,8 @@ module ocn_init_mode use ocn_init_mixed_layer_eddy use ocn_init_transport_tests use ocn_init_test_sht - use ocn_init_parabolic_bowl + use ocn_init_Buttermilk_bay implicit none private @@ -310,6 +310,7 @@ function ocn_init_mode_run(domain) result(iErr)!{{{ call ocn_init_setup_transport_tests(domain, ierr) call ocn_init_setup_test_sht(domain, ierr) call ocn_init_setup_parabolic_bowl(domain, iErr) + call ocn_init_setup_Buttermilk_bay(domain, iErr) !call ocn_init_setup_TEMPLATE(domain, ierr) call mpas_log_write( ' Completed setup of: ' // trim(config_init_configuration)) @@ -429,6 +430,8 @@ subroutine ocn_init_mode_validate_configuration(configPool, packagePool, ioconte call ocn_init_validate_parabolic_bowl(configPool, packagePool, iocontext, iErr=err_tmp) iErr = ior(iErr, err_tmp) + call ocn_init_validate_Buttermilk_bay(configPool, packagePool, iocontext, iErr=err_tmp) + iErr = ior(iErr, err_tmp) ! call ocn_init_validate_TEMPLATE(configPool, packagePool, iocontext, iErr=err_tmp) ! iErr = ior(iErr, err_tmp) diff --git a/components/mpas-ocean/src/mode_init/mpas_ocn_init_parabolic_bowl.F b/components/mpas-ocean/src/mode_init/mpas_ocn_init_parabolic_bowl.F index 43fb215ed23..a67da7e52ac 100644 --- a/components/mpas-ocean/src/mode_init/mpas_ocn_init_parabolic_bowl.F +++ b/components/mpas-ocean/src/mode_init/mpas_ocn_init_parabolic_bowl.F @@ -33,6 +33,8 @@ module ocn_init_parabolic_bowl use ocn_config use ocn_init_vertical_grids use ocn_init_cell_markers + use ocn_subgrid + use ocn_init_subgrid implicit none private @@ -132,6 +134,9 @@ subroutine ocn_init_setup_parabolic_bowl(domain, iErr)!{{{ real (kind=RKIND):: xshift = 0.0, yshift = 0.0 real (kind=RKIND) :: layerThicknessEdgeAverage real (kind=RKIND), dimension(:,:), allocatable :: rSubgridPoints, sSubgridPoints + real (kind=RKIND), dimension(:), allocatable :: subgridBathymetryValues, subgridAreas + real (kind=RKIND), dimension(:), allocatable :: subgridSshValues + real (kind=RKIND), dimension(:), allocatable :: subgridUValues, subgridVValues real (kind=RKIND), dimension(:), allocatable :: uVelocityAverage, vVelocityAverage integer :: nSubgridCell, nSubgridEdge, nSubgridVertex integer :: nSubgridTriPerSlice @@ -142,6 +147,12 @@ subroutine ocn_init_setup_parabolic_bowl(domain, iErr)!{{{ integer :: i,j real (kind=RKIND) :: deltaZ + integer:: nsubgridCellEdge, iEdgeSegment + real (kind=RKIND), dimension(:,:), allocatable :: cellEdgeBathymetryValues + real (kind=RKIND), dimension(:), allocatable:: dsEdge + integer:: jj + real (kind=RKIND), dimension(:), allocatable:: xSubgridCell, ySubgridCell + iErr = 0 if(config_init_configuration .ne. trim('parabolic_bowl')) return @@ -212,137 +223,180 @@ subroutine ocn_init_setup_parabolic_bowl(domain, iErr)!{{{ block_ptr => domain % blocklist - do while(associated(block_ptr)) - call mpas_pool_get_subpool(block_ptr % structs, 'mesh', meshPool) - call mpas_pool_get_subpool(block_ptr % structs, 'state', statePool) - call mpas_pool_get_subpool(block_ptr % structs, 'verticalMesh', verticalMeshPool) - call mpas_pool_get_subpool(statePool, 'tracers', tracersPool) - - call mpas_pool_get_dimension(meshPool, 'nVertLevels', nVertLevels) ; - call mpas_pool_get_dimension(meshPool, 'nCellsSolve', nCellsSolve) ; - call mpas_pool_get_dimension(meshPool, 'nEdgesSolve', nEdgesSolve) ; - call mpas_pool_get_dimension(meshPool, 'nVerticesSolve', nVerticesSolve) ; - call mpas_pool_get_dimension(meshPool, 'maxEdges', maxEdges) - - call mpas_pool_get_dimension(tracersPool, 'index_temperature', index_temperature) - call mpas_pool_get_dimension(tracersPool, 'index_salinity', index_salinity) + call mpas_pool_get_subpool(block_ptr % structs, 'mesh', meshPool) + call mpas_pool_get_subpool(block_ptr % structs, 'state', statePool) + call mpas_pool_get_subpool(block_ptr % structs, 'verticalMesh', verticalMeshPool) + call mpas_pool_get_subpool(statePool, 'tracers', tracersPool) + + call mpas_pool_get_dimension(meshPool, 'nVertLevels', nVertLevels) ; + call mpas_pool_get_dimension(meshPool, 'nCellsSolve', nCellsSolve) ; + call mpas_pool_get_dimension(meshPool, 'nEdgesSolve', nEdgesSolve) ; + call mpas_pool_get_dimension(meshPool, 'nVerticesSolve', nVerticesSolve) ; + call mpas_pool_get_dimension(meshPool, 'maxEdges', maxEdges) + + call mpas_pool_get_dimension(tracersPool, 'index_temperature', index_temperature) + call mpas_pool_get_dimension(tracersPool, 'index_salinity', index_salinity) + + call mpas_pool_get_array(meshPool, 'xCell', xCell) + call mpas_pool_get_array(meshPool, 'yCell', yCell) + call mpas_pool_get_array(meshPool, 'refBottomDepth', refBottomDepth) + call mpas_pool_get_array(meshPool, 'vertCoordMovementWeights', vertCoordMovementWeights) + call mpas_pool_get_array(meshPool, 'bottomDepth', bottomDepth) + call mpas_pool_get_array(meshPool, 'minLevelCell', minLevelCell) + call mpas_pool_get_array(meshPool, 'maxLevelCell', maxLevelCell) + call mpas_pool_get_array(meshPool, 'nEdgesOnCell', nEdgesOnCell) + call mpas_pool_get_array(meshPool, 'areaCell', areaCell) + + call mpas_pool_get_array(meshPool, 'verticesOnCell', verticesOnCell) + call mpas_pool_get_array(meshPool, 'verticesOnEdge', verticesOnEdge) + call mpas_pool_get_array(meshPool, 'cellsOnEdge', cellsOnEdge) + call mpas_pool_get_array(meshPool, 'cellsOnVertex', cellsOnVertex) + + call mpas_pool_get_array(meshPool, 'fCell', fCell) + call mpas_pool_get_array(meshPool, 'fEdge', fEdge) + call mpas_pool_get_array(meshPool, 'fVertex', fVertex) + + call mpas_pool_get_array(meshPool, 'xEdge', xEdge ) + call mpas_pool_get_array(meshPool, 'yEdge', yEdge ) + call mpas_pool_get_array(meshPool, 'xVertex', xVertex ) + call mpas_pool_get_array(meshPool, 'yVertex', yVertex ) - call mpas_pool_get_array(meshPool, 'xCell', xCell) - call mpas_pool_get_array(meshPool, 'yCell', yCell) - call mpas_pool_get_array(meshPool, 'refBottomDepth', refBottomDepth) - call mpas_pool_get_array(meshPool, 'vertCoordMovementWeights', vertCoordMovementWeights) - call mpas_pool_get_array(meshPool, 'bottomDepth', bottomDepth) - call mpas_pool_get_array(meshPool, 'minLevelCell', minLevelCell) - call mpas_pool_get_array(meshPool, 'maxLevelCell', maxLevelCell) - call mpas_pool_get_array(meshPool, 'nEdgesOnCell', nEdgesOnCell) - call mpas_pool_get_array(meshPool, 'areaCell', areaCell) - - call mpas_pool_get_array(meshPool, 'verticesOnCell', verticesOnCell) - call mpas_pool_get_array(meshPool, 'verticesOnEdge', verticesOnEdge) - call mpas_pool_get_array(meshPool, 'cellsOnEdge', cellsOnEdge) - call mpas_pool_get_array(meshPool, 'cellsOnVertex', cellsOnVertex) - - call mpas_pool_get_array(meshPool, 'fCell', fCell) - call mpas_pool_get_array(meshPool, 'fEdge', fEdge) - call mpas_pool_get_array(meshPool, 'fVertex', fVertex) - - call mpas_pool_get_array(meshPool, 'xEdge', xEdge ) - call mpas_pool_get_array(meshPool, 'yEdge', yEdge ) - call mpas_pool_get_array(meshPool, 'xVertex', xVertex ) - call mpas_pool_get_array(meshPool, 'yVertex', yVertex ) + call mpas_pool_get_array(statePool, 'zMid', zMid, 1) ; - call mpas_pool_get_array(statePool, 'zMid', zMid, 1) ; + call mpas_pool_get_array(statePool, 'ssh', ssh, 1) + call mpas_pool_get_array(meshPool, 'edgeNormalVectors', edgeNormalVectors ) ; + call mpas_pool_get_array(statePool, 'normalVelocity', normalVelocity ) ; - call mpas_pool_get_array(statePool, 'ssh', ssh, 1) - call mpas_pool_get_array(meshPool, 'edgeNormalVectors', edgeNormalVectors ) ; - call mpas_pool_get_array(statePool, 'normalVelocity', normalVelocity ) ; + call mpas_pool_get_array(tracersPool, 'activeTracers', activeTracers, 1) + call mpas_pool_get_array(statePool, 'layerThickness', layerThickness, 1) - call mpas_pool_get_array(tracersPool, 'activeTracers', activeTracers, 1) - call mpas_pool_get_array(statePool, 'layerThickness', layerThickness, 1) + call mpas_pool_get_array(verticalMeshPool, 'refZMid', refZMid) + call mpas_pool_get_array(verticalMeshPool, 'restingThickness', restingThickness) - call mpas_pool_get_array(verticalMeshPool, 'refZMid', refZMid) - call mpas_pool_get_array(verticalMeshPool, 'restingThickness', restingThickness) + ! if config_parabolic_bowl_adjust_domain_center == .true., + ! Adjust center of the mesh so that its center is located at (0,0) + if ( config_parabolic_bowl_adjust_domain_center ) then + xCell = xCell - xshift ; + yCell = yCell - yshift ; - ! if config_parabolic_bowl_adjust_domain_center == .true., - ! Adjust center of the mesh so that its center is located at (0,0) - if ( config_parabolic_bowl_adjust_domain_center ) then - xCell = xCell - xshift ; - yCell = yCell - yshift ; + xEdge = xEdge - xshift ; + yEdge = yEdge - yshift ; - xEdge = xEdge - xshift ; - yEdge = yEdge - yshift ; + xVertex = xVertex - xshift ; + yVertex = yVertex - yshift ; + end if - xVertex = xVertex - xshift ; - yVertex = yVertex - yshift ; - end if + ! Initlialze vector + call mpas_initialize_vectors(meshPool) ; - ! Initlialze edge normal vectors - call mpas_initialize_vectors(meshPool) ; + minLevelCell(:) = 1 + do iCell = 1, nCellsSolve + ! Set up vertical grid + maxLevelCell(iCell) = nVertLevels ; ! sigma coordinates + end do - minLevelCell(:) = 1 - do iCell = 1, nCellsSolve - ! Set up vertical grid - maxLevelCell(iCell) = nVertLevels ; ! sigma coordinates - end do + do iCell = 1, nCellsSolve + + ! Set temperature + activeTracers(index_temperature, :, iCell) = 10.0_RKIND + + ! Set salinity + activeTracers(index_salinity, :, iCell) = 30.0_RKIND + + ! Set Coriolis parameters, if other than zero + fCell(iCell) = config_parabolic_bowl_coriolis_parameter ; + end do + + do iEdge = 1, nEdgesSolve + fEdge(iEdge) = config_parabolic_bowl_coriolis_parameter ; + end do + + do iVertex = 1, nVerticesSolve + fVertex(iVertex) = config_parabolic_bowl_coriolis_parameter ; + end do + + allocate(uVelocityAverage(nEdgesSolve)) + allocate(vVelocityAverage(nEdgesSolve)) + + if (config_use_subgrid_wetting_drying) then + + call ocn_subgrid_init(domain,iErr) + call ocn_init_subgrid_calculations(domain, & + ocn_init_parabolic_bowl_bathymetry, & + ocn_init_parabolic_bowl_velocity, & + ocn_init_parabolic_bowl_ssh, & + config_parabolic_bowl_subgrid_refinement_level, & + config_parabolic_bowl_subgrid_edge_bathymetry_max_pixel, & + config_parabolic_bowl_subgrid_use_thin_layer, & + uVelocityAverage, & + vVelocityAverage, & + iErr) + end if + + ! Find max bottom depth + maxBottomDepth = maxval( bottomDepth ) ; + minBottomDepth = minval( bottomDepth ) ; + call mpas_dmpar_max_real( domain % dminfo, maxBottomDepth, globalMaxBottomDepth ) ; + call mpas_dmpar_min_real( domain % dminfo, minBottomDepth, globalMinBottomDepth ) ; + + ! Set refBottomDepth and refZMid + do k = 1, nVertLevels + refBottomDepth(k) = globalMaxBottomDepth*interfaceLocations(k+1) ; + refZMid(k) = -0.5_RKIND*( interfaceLocations(k+1) + interfaceLocations(k))*globalMaxBottomDepth ; + end do + + ! Set vertCoordMovementWeights + vertCoordMovementWeights(:) = 1.0_RKIND + + ! Set velocity + do iEdge = 1, nEdgesSolve + + if (config_use_subgrid_wetting_drying) then + do k = 1, nVertLevels + normalVelocity(k,iEdge) = uVelocityAverage(iEdge)*edgeNormalVectors(1,iEdge) & + + vVelocityAverage(iEdge)*edgeNormalVectors(2,iEdge) ; + end do + else + call ocn_init_parabolic_bowl_velocity(xEdge(iEdge), yEdge(iEdge), uu, vv) + do k = 1, nVertLevels + normalVelocity(k,iEdge) = uu*edgeNormalVectors(1,iEdge) + vv*edgeNormalVectors(2,iEdge) ; + end do + end if + end do + + ! Set layer thickness and ssh + if (config_use_wetting_drying) then + + do iCell = 1, nCellsSolve + ! Set up vertical grid + maxLevelCell(iCell) = nVertLevels ; ! sigma coordinates + end do do iCell = 1, nCellsSolve - - ! Set temperature - activeTracers(index_temperature, :, iCell) = 10.0_RKIND - - ! Set salinity - activeTracers(index_salinity, :, iCell) = 30.0_RKIND - - ! Set Coriolis parameters - fCell(iCell) = config_parabolic_bowl_coriolis_parameter ; - end do - - do iEdge = 1, nEdgesSolve - fEdge(iEdge) = config_parabolic_bowl_coriolis_parameter ; - end do - - do iVertex = 1, nVerticesSolve - fVertex(iVertex) = config_parabolic_bowl_coriolis_parameter ; - end do - - - ! Find max bottom depth - maxBottomDepth = maxval( bottomDepth ) ; - minBottomDepth = minval( bottomDepth ) ; - call mpas_dmpar_max_real( domain % dminfo, maxBottomDepth, globalMaxBottomDepth ) ; - call mpas_dmpar_min_real( domain % dminfo, minBottomDepth, globalMinBottomDepth ) ; - - ! Set refBottomDepth and refZMid - do k = 1, nVertLevels - refBottomDepth(k) = globalMaxBottomDepth*interfaceLocations(k+1) ; - refZMid(k) = -0.5_RKIND*( interfaceLocations(k+1) + interfaceLocations(k))*globalMaxBottomDepth ; - end do - - ! Set vertCoordMovementWeights - vertCoordMovementWeights(:) = 1.0_RKIND - - ! Set velocity - do iEdge = 1, nEdgesSolve - - call ocn_init_parabolic_bowl_velocity(xEdge(iEdge), yEdge(iEdge), uu, vv) - do k = 1, nVertLevels - normalVelocity(k,iEdge) = uu*edgeNormalVectors(1,iEdge) + vv*edgeNormalVectors(2,iEdge) ; - end do - end do - - ! Set layer thickness and ssh - if (config_use_wetting_drying) then - - do iCell = 1, nCellsSolve - ! - ! make sure depth is thick enough via ssh = TOTAL_DEPTH - bottomDepth - ! add a thin layer of nlayer*config_drying_min_cellhight - ! + ! + ! make sure depth is thick enough via ssh = TOTAL_DEPTH - bottomDepth + ! add a thin layer of nlayer*config_drying_min_cellhight + ! + if (config_use_subgrid_wetting_drying) then + + call ocn_subgrid_ssh_lookup(layerThickness(1,iCell),& + subgridWetVolumeCellTable(:,iCell),& + subgridSshCellTableRange(:,iCell),& + bottomDepth(iCell),& + subgridCellBathymetryMin(iCell),& + ssh(iCell)) + !call ocn_subgrid_layer_thickness_lookup(ssh(iCell), & + ! subgridWetVolumeCellTable(:,iCell), & + ! subgridSshCellTableRange(:,iCell),& + ! bottomDepth(iCell),& + ! LayerThickness(1,iCell)) + + else call ocn_init_parabolic_bowl_bathymetry(xCell(iCell),yCell(iCell),bottomDepth(iCell)) call ocn_init_parabolic_bowl_ssh(xCell(iCell),yCell(iCell),bottomDepth(iCell),ssh(iCell)) ssh(iCell) = - bottomDepth(iCell) + & @@ -359,17 +413,25 @@ subroutine ocn_init_setup_parabolic_bowl(domain, iErr)!{{{ realArgs=(/layerThickness(k,iCell)/)) end if end do - - - do k = 1, maxLevelCell(iCell) - restingThickness(k,iCell) = bottomDepth(iCell)/maxLevelCell(iCell) - end do + endif + + + do k = 1, maxLevelCell(iCell) + restingThickness(k,iCell) = bottomDepth(iCell)/maxLevelCell(iCell) end do - - end if - - block_ptr => block_ptr % next - end do + end do + + end if + + if (config_use_subgrid_wetting_drying) then + do iCell = 1,nCellsSolve + call ocn_subgrid_layer_thickness_lookup(ssh(iCell), & + subgridWetVolumeCellTable(:,iCell), & + subgridSshCellTableRange(:,iCell),& + bottomDepth(iCell),& + subgridLayerThicknessDebug(iCell)) + enddo + endif deallocate(interfaceLocations) !-------------------------------------------------------------------- @@ -436,6 +498,7 @@ subroutine ocn_init_parabolic_bowl_ssh(x, y, bottomDepth, ssh)!{{{ ssh = (sqrtOneMC2/oneMC) - 1.0_RKIND - ((RR**2)/(LL**2))*( (oneMC2/(oneMC**2)) - 1.0_RKIND ) ; ssh = config_parabolic_bowl_b0*ssh ; + !ssh = - bottomDepth + max(ssh + bottomDepth, config_drying_min_cell_height + eps) !-------------------------------------------------------------------- @@ -506,6 +569,7 @@ subroutine ocn_init_validate_parabolic_bowl(configPool, packagePool, iocontext, character (len=StrKIND), pointer :: config_init_configuration integer, pointer :: config_vert_levels, config_parabolic_bowl_vert_levels + integer, pointer :: config_subgrid_table_levels, config_parabolic_bowl_subgrid_table_levels iErr = 0 @@ -519,7 +583,17 @@ subroutine ocn_init_validate_parabolic_bowl(configPool, packagePool, iocontext, if(config_vert_levels <= 0 .and. config_parabolic_bowl_vert_levels > 0) then config_vert_levels = config_parabolic_bowl_vert_levels else if (config_vert_levels <= 0) then - call mpas_log_write( 'Validation failed for para_bowl. Not given a usable value for vertical levels.', MPAS_LOG_CRIT) + call mpas_log_write( 'Validation failed for parabolic_bowl. Not given a usable value for vertical levels.', MPAS_LOG_CRIT) + iErr = 1 + end if + + call mpas_pool_get_config(configPool, 'config_subgrid_table_levels', config_subgrid_table_levels) + call mpas_pool_get_config(configPool, 'config_parabolic_bowl_subgrid_table_levels', config_parabolic_bowl_subgrid_table_levels) + + if (config_subgrid_table_levels <= 0 .and. config_parabolic_bowl_subgrid_table_levels > 0) then + config_subgrid_table_levels = config_parabolic_bowl_subgrid_table_levels + else if (config_subgrid_table_levels <= 0) then + call mpas_log_write( 'Validation failed for parabolic_bowl. Not given a usable value for subgrid table levels.', MPAS_LOG_CRIT) iErr = 1 end if diff --git a/components/mpas-ocean/src/mode_init/mpas_ocn_init_subgrid.F b/components/mpas-ocean/src/mode_init/mpas_ocn_init_subgrid.F new file mode 100644 index 00000000000..37c3e2a273d --- /dev/null +++ b/components/mpas-ocean/src/mode_init/mpas_ocn_init_subgrid.F @@ -0,0 +1,941 @@ +! Copyright (c) 2013, Los Alamos National Security, LLC (LANS) +! and the University Corporation for Atmospheric Research (UCAR). +! +! Unless noted otherwise source code is licensed under the BSD license. +! Additional copyright and license information can be found in the LICENSE file +! distributed with this code, or at http://mpas-dev.github.com/license.html +! +!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +! +! ocn_init_subgrid +! +!> \brief Calculate the subgrid information +!> \author D. Wirasaet, S. Brus +!> \date May-June 2022 +!> \details +!> This module contains the routines for calculating the information +!> needed to use subgrid corrctions within a forward model run. +!> +!----------------------------------------------------------------------- + +module ocn_init_subgrid + + use mpas_kind_types + use mpas_io_units + use mpas_derived_types + use mpas_pool_routines + use mpas_constants + use mpas_dmpar + + use ocn_constants + use ocn_config + use ocn_subgrid + + use mpas_constants + use mpas_io + use mpas_io_streams + use mpas_stream_manager + + + implicit none + private + save + + !-------------------------------------------------------------------- + ! + ! Public parameters + ! + !-------------------------------------------------------------------- + + !-------------------------------------------------------------------- + ! + ! Public member functions + ! + !-------------------------------------------------------------------- + + public :: ocn_init_subgrid_calculations + + !-------------------------------------------------------------------- + ! + ! Private module variables + ! + !-------------------------------------------------------------------- + + real(kind=RKIND), parameter:: eps = 1.0e-10_RKIND ; + real(kind=RKIND) :: subgrid_thin_layer + + abstract interface + subroutine bathymetry_function(x, y, b) + use mpas_kind_types, only: rkind + implicit none + real (kind=RKIND), intent(in) :: x + real (kind=RKIND), intent(in) :: y + real (kind=RKIND), intent(out) :: b + end subroutine + subroutine velocity_function(x, y, u, v) + use mpas_kind_types, only: rkind + implicit none + real (kind=RKIND), intent(in) :: x + real (kind=RKIND), intent(in) :: y + real (kind=RKIND), intent(out) :: u + real (kind=RKIND), intent(out) :: v + end subroutine + subroutine ssh_function(x, y, b, z) + use mpas_kind_types, only: rkind + implicit none + real (kind=RKIND), intent(in) :: x + real (kind=RKIND), intent(in) :: y + real (kind=RKIND), intent(in) :: b + real (kind=RKIND), intent(out) :: z + end subroutine + end interface + +!*********************************************************************** + +contains + +!*********************************************************************** +! +! routine ocn_init_subgrid_calculations +! +!> \brief Calculations for subgrid look-up tables +!> \author D. Wirasaet and S. Brus +!> \date May-June 2022 +!> \details +!> This routine performs the vertical integration of the wet fraction +!> over the cell, edge, and vertex control volumes to create +!> lookup tables for the relationship between ssh and wet volume per +!> unit area. +! +!----------------------------------------------------------------------- + + subroutine ocn_init_subgrid_calculations(domain, problem_bathymetry, problem_velocity, problem_ssh, & + subgrid_refinement_level, & + subgrid_edge_bathymetry_max_pixel, & + subgrid_use_thin_layer, & + uVelocityAverage, vVelocityAverage, iErr)!{{{ + + implicit none + !-------------------------------------------------------------------- + + type (domain_type), intent(inout) :: domain + integer, intent(out) :: iErr + procedure(bathymetry_function) :: problem_bathymetry + procedure(velocity_function) :: problem_velocity + procedure(ssh_function) :: problem_ssh + integer, intent(in) :: subgrid_refinement_level + logical, intent(in) :: subgrid_edge_bathymetry_max_pixel + logical, intent(in) :: subgrid_use_thin_layer + + real (kind=RKIND), dimension(:), intent(out) :: uVelocityAverage, vVelocityAverage + + type (block_type), pointer :: block_ptr + type (mpas_pool_type), pointer :: meshPool + type (mpas_pool_type), pointer :: statePool + + ! local variables + integer :: iCell, iEdge, iVertex, k, idx + + ! Define dimension pointers + integer, pointer :: nCellsSolve, nEdgesSolve, nVerticesSolve + integer, pointer :: maxEdges + + ! Define variable pointers + integer, dimension(:), pointer :: nEdgesOnCell + integer, dimension(:,:), pointer :: verticesOnCell, verticesOnEdge + integer, dimension(:,:), pointer :: cellsOnEdge, cellsOnVertex + real (kind=RKIND), dimension(:), pointer :: xCell, yCell, bottomDepth + real (kind=RKIND), dimension(:,:), pointer:: edgeNormalVectors + real (kind=RKIND), dimension(:), pointer:: xEdge, yEdge, xVertex, yVertex + + real (kind=RKIND), dimension(:), pointer :: ssh + real (kind=RKIND), dimension(:,:), pointer :: normalVelocity + real (kind=RKIND), dimension(:,:), pointer :: layerThickness + real (kind=RKIND), dimension(:), pointer :: areaCell + + real (kind=RKIND) :: layerThicknessEdgeAverage + real (kind=RKIND), dimension(:,:), allocatable :: rSubgridPoints, sSubgridPoints + real (kind=RKIND), dimension(:), allocatable :: subgridBathymetryValues, subgridAreas + real (kind=RKIND), dimension(:), allocatable :: subgridSshValues + real (kind=RKIND), dimension(:), allocatable :: subgridUValues, subgridVValues + integer :: nSubgridCell, nSubgridEdge, nSubgridVertex + integer :: nSubgridTriPerSlice + integer :: v1, v2 + integer :: c1, c2 + real (kind=RKIND) :: x(3), y(3) + integer :: slice, nSlice + real (kind=RKIND) :: deltaZ + + + + integer:: i, j, jj + integer:: nsubgridCellEdge, iEdgeSegment + real (kind=RKIND):: pi + real (kind=RKIND), dimension(:,:), allocatable :: cellEdgeBathymetryValues + real (kind=RKIND), dimension(:), allocatable:: dsEdge + real (kind=RKIND), dimension(:), allocatable:: xSubgridCell, ySubgridCell + real (kind=RKIND):: bathymetryMin, bathymetryMax + iErr = 0 + + + block_ptr => domain % blocklist + call mpas_pool_get_subpool(block_ptr % structs, 'mesh', meshPool) + call mpas_pool_get_subpool(block_ptr % structs, 'state', statePool) + + call mpas_pool_get_dimension(meshPool, 'nCellsSolve', nCellsSolve) ; + call mpas_pool_get_dimension(meshPool, 'nEdgesSolve', nEdgesSolve) ; + call mpas_pool_get_dimension(meshPool, 'nVerticesSolve', nVerticesSolve) ; + call mpas_pool_get_dimension(meshPool, 'maxEdges', maxEdges) + + call mpas_pool_get_array(meshPool, 'xCell', xCell) + call mpas_pool_get_array(meshPool, 'yCell', yCell) + call mpas_pool_get_array(meshPool, 'bottomDepth', bottomDepth) + call mpas_pool_get_array(meshPool, 'nEdgesOnCell', nEdgesOnCell) + call mpas_pool_get_array(meshPool, 'areaCell', areaCell) + + call mpas_pool_get_array(meshPool, 'verticesOnCell', verticesOnCell) + call mpas_pool_get_array(meshPool, 'verticesOnEdge', verticesOnEdge) + call mpas_pool_get_array(meshPool, 'cellsOnEdge', cellsOnEdge) + call mpas_pool_get_array(meshPool, 'cellsOnVertex', cellsOnVertex) + + call mpas_pool_get_array(meshPool, 'xEdge', xEdge ) + call mpas_pool_get_array(meshPool, 'yEdge', yEdge ) + call mpas_pool_get_array(meshPool, 'xVertex', xVertex ) + call mpas_pool_get_array(meshPool, 'yVertex', yVertex ) + + call mpas_pool_get_array(statePool, 'ssh', ssh, 1) + call mpas_pool_get_array(meshPool, 'edgeNormalVectors', edgeNormalVectors ) ; + call mpas_pool_get_array(statePool, 'normalVelocity', normalVelocity ) ; + call mpas_pool_get_array(statePool, 'layerThickness', layerThickness) ; + + if (subgrid_use_thin_layer) then + subgrid_thin_layer = config_drying_min_cell_height + eps + else + subgrid_thin_layer = 0.0_RKIND + end if + + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + ! Cells + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + print*, "Begin cells", nCellsSolve + + nSubgridTriPerSlice = subgrid_refinement_level**2 + allocate(rSubgridPoints(3,maxEdges*nSubgridTriPerSlice), sSubgridPoints(3,maxEdges*nSubgridTriPerSlice)) + call ocn_init_define_subgrid_points(subgrid_refinement_level, rSubgridPoints, sSubgridPoints) + allocate(subgridBathymetryValues(maxEdges*nSubgridTriPerSlice), subgridAreas(maxEdges*nSubgridTriPerSlice)) + allocate(subgridSshValues(maxEdges*nSubgridTriPerSlice)) + allocate(subgridUValues(maxEdges*nSubgridTriPerSlice)) + allocate(subgridVValues(maxEdges*nSubgridTriPerSlice)) + + allocate(xSubgridCell(maxEdges*nSubgridTriPerSlice)) + allocate(ySubgridCell(maxEdges*nSubgridTriPErSlice)) + xSubgridCell = 0.0_RKIND + ySubgridCell = 0.0_RKIND + + do iCell = 1,nCellsSolve + ! + ! Evaluate subgrid bathymetry at centers of sub-triangles for cell slices + ! (all subdivided triangles for each cell slice are gathered into + ! subgridBathymetryValues and subgridAreas) + !--------------------------------------------------------------- + + nSubgridCell = 0 ! Counter for all subgrid triangles over cell slices + do slice = 1,nEdgesOnCell(iCell) ! Loop over cell slices + + v1 = verticesOnCell(slice,iCell) + if (slice+1 <= nEdgesOnCell(iCell)) then + v2 = verticesOnCell(slice+1,iCell) + else + v2 = verticesOnCell(1,iCell) + endif + + ! Cell slice coordinates + x(1) = xCell(iCell) + y(1) = yCell(iCell) + + x(2) = xVertex(v1) + y(2) = yVertex(v1) + + x(3) = xVertex(v2) + y(3) = yVertex(v2) + + call ocn_init_evaluate_subgrid_data(x, y, nSubgridTriPerSlice, nSubgridCell, rSubgridPoints, sSubgridPoints, & + problem_bathymetry, problem_velocity, problem_ssh, & + subgridBathymetryValues, subgridAreas, subgridSshValues, & + subgridUValues, subgridVValues, xSubgridCell, ysubgridCell) !{{{ + enddo + + ! Evaluate bounds of look-up table range + !--------------------------------------------------------------- + bathymetryMin = maxval( subgridBathymetryValues(1:nSubgridCell) ) + bathymetryMax = minval( subgridBathymetryValues(1:nSubgridCell) ) + + if ( abs(bathymetryMin - bathymetryMax) > 100.0*eps ) then + subgridSshCellTableRange(1,iCell) = -maxval(subgridBathymetryValues(1:nSubgridCell)) + subgrid_thin_layer + subgridSshCellTableRange(2,iCell) = -minval(subgridBathymetryValues(1:nSubgridCell)) + else + ! flat bathy ! + subgridSshCellTableRange(1,iCell) = -bathymetryMin + subgrid_thin_layer + subgridSshCellTableRange(2,iCell) = -bathymetryMin + 2.0*config_drying_min_cell_height + endif + + ! Evaluate subgrid bathymetry + !--------------------------------------------------------------- + bottomDepth(iCell) = sum(subgridBathymetryValues(1:nSubgridCell)*subgridAreas(1:nSubgridCell))/sum(subgridAreas(1:nSubgridCell)) + subgridCellBathymetryMin(iCell) = maxval(subgridBathymetryValues(1:nSubgridCell)) + + ! Vertical integration of wet fraction + !--------------------------------------------------------------- + + call ocn_init_vertical_integration(iCell,subgridSshCellTableRange, nSubgridCell, subgridBathymetryValues, subgridAreas, & + subgridWetVolumeCellTable, subgridWetFractionCellTable) + + ! Evaluate wet layerThickness average + !--------------------------------------------------------------- + call ocn_init_grid_average(nSubgridCell, subgridBathymetryValues, subgridSshValues, subgridAreas, layerThickness(1,iCell)) +! call ocn_init_wet_average_ssh(nSubgridCell, subgridBathymetryValues, subgridSshValues, subgridAreas, ssh(iCell))!{{{ + enddo + + do iCell = 1, nCellsSolve + call ocn_subgrid_ssh_lookup( config_drying_min_cell_height, & + subgridWetVolumeCellTable(:,iCell), & + subgridSshCellTableRange(:,iCell),& + bottomDepth(iCell),& + subgridCellBathymetryMin(iCell),& + subgridSShCellTableRange(3,iCell) ) + + if ( ssh(iCell) < subgridSshCellTableRange(3,iCell) ) then + ssh(iCell) = subgridSshCellTableRange(3,iCell) ; + end if + end do + + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + ! Edges + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + print*, "Begin edges", nEdgesSolve + + nSubgridCellEdge=subgrid_refinement_level + allocate( cellEdgeBathymetryValues(3,nSubgridCellEdge) ) + allocate( dsEdge(nSubgridCellEdge) ) + cellEdgeBathymetryValues = -99999 ; + + + do iEdge = 1,nEdgesSolve + !-------------------------------------------------------------- + ! Evaluate subgrid bathymetry at centers of sub-triangles for edge slices + ! (all subdivided triangles for each edge slice are gathered into + ! subgridBathymetryValues and subgridAreas) + !--------------------------------------------------------------- + + nSlice = 0 + do slice = 1,2 + if (cellsOnEdge(slice,iEdge) <= nCellsSolve) then + nSlice = nSlice + 1 + endif + enddo + + nSubgridEdge = 0 ! Counter for all subgrid triangles over edge slices + do slice = 1,nSlice ! Loop over edge slices + + ! Edge slice coordinates + x(1) = xVertex(verticesOnEdge(1,iEdge)) + y(1) = yVertex(verticesOnEdge(1,iEdge)) + + x(2) = xVertex(verticesOnEdge(2,iEdge)) + y(2) = yVertex(verticesOnEdge(2,iEdge)) + + x(3) = xCell(cellsOnEdge(slice,iEdge)) + y(3) = yCell(cellsOnEdge(slice,iEdge)) + + + call ocn_init_evaluate_subgrid_data(x, y, nSubgridTriPerSlice, nSubgridEdge, rSubgridPoints, sSubgridPoints, & + problem_bathymetry, problem_velocity, problem_ssh, & + subgridBathymetryValues, subgridAreas, subgridSshValues, subgridUValues, subgridVValues, & + xSubgridCell, ySubgridCell) + + enddo + + ! Evaluate velocity average + !--------------------------------------------------------------- + call ocn_init_grid_average(nSubgridCell, subgridBathymetryValues, subgridSshValues, subgridAreas, layerThicknessEdgeAverage, & + subgridUValues, subgridVValues, uVelocityAverage(iEdge), vVelocityAverage(iEdge)) + + if ( .NOT. subgrid_edge_bathymetry_max_pixel) then + ! Evaluate bounds of look-up table range + !--------------------------------------------------------------- + subgridSshEdgeTableRange(1,iEdge) = -maxval(subgridBathymetryValues(1:nSubgridEdge)) + subgrid_thin_layer + subgridSshEdgeTableRange(2,iEdge) = -minval(subgridBathymetryValues(1:nSubgridEdge)) + + ! Evaluate subgrid bathymetry + !--------------------------------------------------------------- + subgridEdgeBathymetryMean(iEdge) = sum(subgridBathymetryValues(1:nSubgridEdge))/real(nSubgridEdge,RKIND) + subgridEdgeBathymetryMin(iEdge) = maxval(subgridBathymetryValues(1:nSubgridEdge)) + + ! Vertical integration of wet fraction + !--------------------------------------------------------------- + call ocn_init_vertical_integration(iEdge,subgridSshEdgeTableRange, nSubgridEdge, subgridBathymetryValues, subgridAreas, & + subgridWetVolumeEdgeTable, subgridWetFractionEdgeTable) + else + ! DW: Use the higher values of the pair of subcells along the + ! cell edge + cellEdgeBathymetryValues(1,:) = subgridBathymetryValues(1:2*nSubgridCellEdge - 1:2) + if ( nslice > 1 ) then + cellEdgeBathymetryValues(2,:) = & + subgridBathymetryValues(nSubgridTriPerSlice+2*nsubgridCellEdge - 1:nSubgridTriPerSlice+1:-2) + else + cellEdgeBathymetryValues(2,:) = cellEdgeBathymetryValues(1,:) + endif + + do iEdgeSegment = 1, nSubgridCellEdge + cellEdgeBathymetryValues(3,iEdgeSegment) = minval(cellEdgeBathymetryValues(1:2,iEdgeSegment) ) + end do + dsEdge(:) = sqrt( (x(2) - x(1))*(x(2) - x(1)) + (y(2) - y(1))*(y(2)- y(1)) )/nSubgridCellEdge + + + ! Evaluate bounds of look-up table range + !--------------------------------------------------------------- + subgridSshEdgeTableRange(1,iEdge) = -maxval(CellEdgeBathymetryValues(3,1:nSubgridCellEdge)) + subgrid_thin_layer + subgridSshEdgeTableRange(2,iEdge) = -minval(CellEdgeBathymetryValues(3,1:nSubgridCellEdge)) + + ! Evaluate bounds of look-up table range + !--------------------------------------------------------------- + subgridEdgeBathymetryMean(iEdge) = sum(cellEdgeBathymetryValues(3,1:nSubgridCellEdge))/real(nSubgridCellEdge,RKIND) + subgridEdgeBathymetryMin(iEdge) = maxval(cellEdgeBathymetryValues(3,1:nSubgridCellEdge)) + + ! Vertical integration of wet fraction + !--------------------------------------------------------------- + call ocn_init_vertical_integration( iEdge, subgridSshEdgeTableRange, & + nSubgridCellEdge, cellEdgeBathymetryValues(3,:), dsEdge, subgridWetVolumeEdgeTable, subgridWetFractionEdgeTable ) + endif + + end do + + ! find an ssh value corresponding to drying_min_cell-height + ! of each edge + do iEdge = 1,nEdgesSolve + call ocn_subgrid_ssh_lookup( config_drying_min_cell_height, & + subgridWetVolumeEdgeTable(:,iEdge),& + subgridSshEdgeTableRange(:,iEdge),& + subgridEdgeBathymetryMean(iEdge),& + subgridEdgeBathymetryMin(iEdge),& + subgridSshEdgeTableRange(3,iEdge) ) + end do + + + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + ! Vertex + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + print*, "Begin vertex", nVerticesSolve + +vertex: do iVertex = 1,nVerticesSolve + + ! Evaluate subgrid bathymetry at centers of sub-triangles for vertex triangle + !--------------------------------------------------------------- + + nSlice = 0 + do slice = 1,3 + if (cellsOnVertex(slice,iVertex) <= nCellsSolve) then + nSlice = nSlice + 1 + endif + enddo + + if (nSlice < 3) then + cycle vertex + endif + + nSubgridVertex = 0 ! Counter for all subgrid triangles over edge slices + do slice = 1,nSlice + + c1 = cellsOnVertex(slice,iVertex) + if (slice < 3) then + c2 = cellsOnVertex(slice+1,iVertex) + else + c2 = cellsOnVertex(1,iVertex) + endif + + ! Vertex slice coordinates + x(1) = xCell(c1) + y(1) = yCell(c1) + + x(2) = xCell(c2) + y(2) = yCell(c2) + + x(3) = xVertex(iVertex) + y(3) = yVertex(iVertex) + + call ocn_init_evaluate_subgrid_data(x, y, nSubgridTriPerSlice, nSubgridVertex, rSubgridPoints, sSubgridPoints, & + problem_bathymetry, problem_velocity, problem_ssh, & + subgridBathymetryValues, subgridAreas) + enddo + + ! Evaluate bounds of look-up table range + !--------------------------------------------------------------- + subgridSshVertexTableRange(1,iVertex) = -maxval(subgridBathymetryValues(1:nSubgridVertex)) + subgrid_thin_layer + subgridSshVertexTableRange(2,iVertex) = -minval(subgridBathymetryValues(1:nSubgridVertex)) + + ! Evaluate subgrid bathymetry + !--------------------------------------------------------------- + subgridVertexBathymetryMean(iVertex) = sum(subgridBathymetryValues(1:nSubgridVertex)*subgridAreas(1:nSubgridVertex))/sum(subgridAreas(1:nSubgridVertex)) + subgridVertexBathymetryMin(iVertex) = maxval(subgridBathymetryValues(1:nSubgridVertex)) + + ! Vertical integration of wet fraction + !--------------------------------------------------------------- + call ocn_init_vertical_integration(iVertex,subgridSshVertexTableRange, nSubgridVertex, subgridBathymetryValues, subgridAreas, & + subgridWetVolumeVertexTable, subgridWetFractionVertexTable) + + enddo vertex + + ! find an ssh value corresponding to drying_min_cell-height + ! of each edge + do iVertex = 1,nVerticesSolve + + call ocn_subgrid_ssh_lookup( config_drying_min_cell_height, & + subgridWetVolumeVertexTable(:,iVertex),& + subgridSshVertexTableRange(:,iVertex),& + subgridVertexBathymetryMean(iVertex),& + subgridVertexBathymetryMin(iVertex),& + subgridSshVertexTableRange(3,iVertex) ) + end do + + return ; + end subroutine ocn_init_subgrid_calculations!}}} + +!*********************************************************************** +! +! routine ocn_init_define_subgrid_points +! +!> \brief Define subgrid points on reference triangle +!> \author Steven Brus +!> \date November 2022 +!> \details Gives the r and s coordinates of the subgrid triangle vertices +!> +! +!----------------------------------------------------------------------- + + subroutine ocn_init_define_subgrid_points(nSubgridLevel, rSubgridPoints, sSubgridPoints)!{{{ + + implicit none + + integer, intent(in) :: nSubgridLevel + real (kind=RKIND), dimension(:,:), intent(inout) :: rSubgridPoints, sSubgridPoints + + integer :: i,j,k + integer :: nSubgridTri + real (kind=RKIND) :: dx + real (kind=RKIND), dimension(:), allocatable :: xPoints + + !-------------------------------------------------------------------- + + ! Equi-spaced nodes on -1,+1 + allocate(xPoints(nSubgridLevel+1)) + dx = 2.0_RKIND/real(nSubgridLevel,RKIND) + xPoints(1) = -1.0_RKIND + do i = 2,nSubgridLevel+1 + xPoints(i) = xPoints(i-1)+dx + enddo + + ! * + ! |\ + ! | \ + ! | \ + ! | \ + ! s *----* + ! |\ u |\ + ! | \ | \ + ! | \ | \ + ! | l \| l \ + ! *----*----* + ! r + + ! Trianglulate tensor product of equi-spaced nodes on reference triangle + ! r - horizontal coordinate (i index), s - vertical coordinate (j index) + nSubgridTri = 0 + do j = 1,nSubgridLevel + do i = 1,nSubgridLevel+1 - j + + nSubgridTri = nSubgridTri+1 + + ! lower triangle in pair (see l in triangle above) + rSubgridPoints(1,nSubgridTri) = xPoints(i) + sSubgridPoints(1,nSubgridTri) = xPoints(j) + + rSubgridPoints(2,nSubgridTri) = xPoints(i+1) + sSubgridPoints(2,nSubgridTri) = xPoints(j) + + rSubgridPoints(3,nSubgridTri) = xPoints(i) + sSubgridPoints(3,nSubgridTri) = xPoints(j+1) + + ! upper triangle in pair (see u in triangle above, doesn't occur next to hypotenuse) + if (i < nSubgridLevel+1 - j) then + + nSubgridTri = nSubgridTri + 1 + + rSubgridPoints(1,nSubgridTri) = xPoints(i+1) + sSubgridPoints(1,nSubgridTri) = xPoints(j) + + rSubgridPoints(2,nSubgridTri) = xPoints(i+1) + sSubgridPoints(2,nSubgridTri) = xPoints(j+1) + + rSubgridPoints(3,nSubgridTri) = xPoints(i) + sSubgridPoints(3,nSubgridTri) = xPoints(j+1) + + endif + + enddo + enddo + + print*, "exit ocn_init_define_subgrid_points" + + + !-------------------------------------------------------------------- + + end subroutine ocn_init_define_subgrid_points!}}} + +!*********************************************************************** +! +! routine ocn_init_evaluate_subgrid_data +! +!> \brief Evaluate subgrid infromation +!> \author Steven Brus +!> \date November 2022 +!> \details Evaluate data on subgrid triangles for a given triangluar grid cell region +!> +! +!----------------------------------------------------------------------- + + subroutine ocn_init_evaluate_subgrid_data(xTri, yTri, nSubgridTri, nSubgridCV, rSubgridPoints, sSubgridPoints, & + problem_bathymetry, problem_velocity, problem_ssh, & + subgridBathymetryValues, subgridAreas, & + subgridSshValues, subgridUValues, subgridVValues, & + xSubgridCell, ySubgridCell) !{{{ + + + implicit none + real (kind=RKIND), intent(inout) :: xTri(3), yTri(3) + integer, intent(in) :: nSubgridTri + integer, intent(inout) :: nSubgridCV + + procedure(bathymetry_function) :: problem_bathymetry + procedure(velocity_function) :: problem_velocity + procedure(ssh_function) :: problem_ssh + + real (kind=RKIND), dimension(:,:), intent(in) :: rSubgridPoints, sSubgridPoints + real (kind=RKIND), dimension(:), intent(inout) :: subgridBathymetryValues + real (kind=RKIND), dimension(:), intent(inout) :: subgridAreas + real (kind=RKIND), dimension(:), intent(inout),optional :: subgridSshValues + real (kind=RKIND), dimension(:), intent(inout),optional :: subgridUValues, subgridVValues + + real (kind=RKIND), dimension(:), intent(inout), optional :: xSubgridCell, ySubgridCell + + real (kind=RKIND) :: rCenter, sCenter + real (kind=RKIND) :: xCenter, yCenter + real (kind=RKIND) :: xSubgridPoints(3), ySubgridPoints(3) + real (kind=RKIND) :: x, y + real (kind=RKIND) :: area + + + integer :: iPt,i + + !-------------------------------------------------------------------- + + ! Coordinates of physical triangle + ! (ensure counter-clockwise numering) + call ocn_init_tri_area(xTri(:), yTri(:), area) + if (area < 0.0_RKIND) then + x = xTri(1) + y = yTri(1) + xTri(1) = xTri(2) + yTri(1) = yTri(2) + xTri(2) = x ; + yTri(2) = y ; + area = abs(area) ; + endif + + do iPt = 1,nSubgridTri + + ! Counter over all subcells within cell/edge/vertex control volume + nSubgridCV = nSubgridCV + 1 + + ! Center sub-triangle (on reference triangle) + rCenter = sum(rSubgridPoints(:,iPt))/3.0_RKIND + sCenter = sum(sSubgridPoints(:,iPt))/3.0_RKIND + + ! Transformation of sub-triangle center to physical coordinates + call ocn_init_tri_coordinate_transform(rCenter, sCenter, xTri, yTri, xCenter, yCenter) + + ! Evaluate bathymetry + call problem_bathymetry(xCenter, yCenter, subgridBathymetryValues(nSubgridCV)) + + ! Transformation of sub-triangle vertices to physical coordinates + do i = 1,3 + call ocn_init_tri_coordinate_transform(rSubgridPoints(i,iPt), sSubgridPoints(i,iPt), xTri, yTri, xSubgridPoints(i), ySubgridPoints(i)) + enddo + + ! Calculate area of sub-triangle + call ocn_init_tri_area(xSubgridPoints(:), ySubgridPoints(:), subgridAreas(nSubgridCV)) + + ! Optionally evalulate ssh ! + if (present(subgridsshValues)) then + call problem_ssh(xCenter, yCenter, subgridBathymetryValues(nSubgridCV), subgridSshValues(nSubgridCV)) + endif + + if (present(subgridUValues).and.present(subgridVValues)) then + call problem_velocity(xCenter, yCenter, subgridUValues(nSubgridCV), subgridVValues(nSubgridCV)) + endif + + if ( present(xSubgridCell) ) then + xSubgridCell(nSubgridCV) = xCenter ; + endif + + if ( present(ySubgridCell) ) then + ySubgridCell(nSubgridCV) = yCenter ; + end if + enddo + + !-------------------------------------------------------------------- + + end subroutine ocn_init_evaluate_subgrid_data!}}} + +!*********************************************************************** +! +! routine ocn_init_tri_area +! +!> \brief Compute triangle area +!> \author Steven Brus +!> \date November 2022 +!> \details Compute area of triangle given vertex coordinates +!> +! +!----------------------------------------------------------------------- + + subroutine ocn_init_tri_area(x, y, area)!{{{ + + implicit none + + real (kind=RKIND), intent(in) :: x(3), y(3) + real (kind=RKIND), intent(out) :: area + + !-------------------------------------------------------------------- + + area = 0.5_RKIND*(x(2)*y(3) - y(2)*x(3) - x(1)*y(3) + y(1)*x(3) + x(1)*y(2) - y(1)*x(2)) + + !-------------------------------------------------------------------- + + end subroutine ocn_init_tri_area!}}} + +!*********************************************************************** +! +! routine ocn_init_tri_coordinate_transform +! +!> \brief Transform reference triangle coordinates to mesh coordinates +!> \author Steven Brus +!> \date November 2022 +!> \details Evaluate r,s reference coordinates in x,y mesh +!> +! +!----------------------------------------------------------------------- + + subroutine ocn_init_tri_coordinate_transform(r, s, xTri, yTri, x, y)!{{{ + + implicit none + + real (kind=RKIND), intent(in) :: r, s + real (kind=RKIND), intent(in) :: xTri(3), yTri(3) + real (kind=RKIND), intent(out) :: x, y + + !-------------------------------------------------------------------- + + ! Transformation of sub-triangle center to physical coordinates + x = 0.5_RKIND*(-(r+s)*xTri(1) + (1.0_RKIND+r)*xTri(2) + (1.0_RKIND+s)*xTri(3)) + y = 0.5_RKIND*(-(r+s)*yTri(1) + (1.0_RKIND+r)*yTri(2) + (1.0_RKIND+s)*yTri(3)) + + !-------------------------------------------------------------------- + + end subroutine ocn_init_tri_coordinate_transform!}}} + +!*********************************************************************** +! +! routine ocn_init_vertical_integration +! +!> \brief Compute the wet volume per unit area lookup table +!> \author Steven Brus +!> \date November 2022 +!> \details Integrate the wet fraction over discrete ssh values +!> +! +!----------------------------------------------------------------------- + + subroutine ocn_init_vertical_integration(iCV, subgridSshTableRange, nSubgridCV, subgridBathymetryValues, subgridAreas, & + subgridWetVolumeTable, subgridWetFractionTable)!{{{ + + implicit none + + integer, intent(in) :: iCV + real (kind=RKIND), dimension(:,:), intent(in) :: subgridSshTableRange + integer, intent(in) :: nSubgridCV + real (kind=RKIND), dimension(:), intent(in) :: subgridBathymetryValues, subgridAreas + real (kind=RKIND), dimension(:,:), intent(inout) :: subgridWetVolumeTable + real (kind=RKIND), dimension(:,:), intent(inout) :: subgridWetFractionTable + + real (kind=RKIND) :: deltaZ, ssh, pVal + integer :: lev, tri + + + !-------------------------------------------------------------------- + + deltaZ = (subgridSshTableRange(2,iCV)-subgridSshTableRange(1,iCV))/real(nSubgridTableLevels-1,RKIND); + + subgridWetVolumeTable(1,iCV) = subgrid_thin_layer + ssh = subgridSshTableRange(1,iCV) + deltaZ + subgridWetVolumeTable(2,iCV) = subgridWetVolumeTable(1,iCV)*sum(subgridAreas(1:nSubgridCV)) + subgridWetFractionTable(1,iCV) = 0.0_RKIND + do lev = 2,nSubgridTableLevels + do tri = 1,nSubgridCV + + pVal = 0.0_RKIND + if (subgridBathymetryValues(tri) + ssh >= 0.0_RKIND) then + pVal = 1.0_RKIND + endif + + subgridWetVolumeTable(lev,iCV) = subgridWetVolumeTable(lev,iCV) + pVal*deltaZ*subgridAreas(tri) + subgridWetFractionTable(lev,iCV) = subgridWetFractionTable(lev,iCV) + pVal*subgridAreas(tri) + + enddo + + if (lev < nSubgridTableLevels) then + subgridWetVolumeTable(lev+1,iCV) = subgridWetVolumeTable(lev,iCV) + endif + + subgridWetVolumeTable(lev,iCV) = subgridWetVolumeTable(lev,iCV)/sum(subgridAreas(1:nSubgridCV)) + subgridWetFractionTable(lev,iCV) = subgridWetFractionTable(lev,iCV)/sum(subgridAreas(1:nSubgridCV)) + + ssh = ssh + deltaZ + enddo + + !-------------------------------------------------------------------- + + end subroutine ocn_init_vertical_integration!}}} + + +!*********************************************************************** +! +! routine ocn_init_grid_average +! +!> \brief Compute thickness and velocity averages over wet area +!> \author Steven Brus +!> \date November 2022 +!> \details Compute the thickness and velocity averages over an area +!> based on the subgrid wet area +! +!----------------------------------------------------------------------- + + subroutine ocn_init_grid_average(nSubgridCV, subgridBathymetryValues, subgridSshValues, subgridAreas, subgridThicknessAverage, & + subgridUValues, subgridVValues, subgridUAverage, subgridVAverage)!{{{ + + implicit none + + integer, intent(in) :: nSubgridCV + real (kind=RKIND), dimension(:), intent(in) :: subgridBathymetryValues, subgridAreas + real (kind=RKIND), dimension(:), intent(in) :: subgridSshValues + real (kind=RKIND), intent(inout) :: subgridThicknessAverage + real (kind=RKIND), dimension(:), intent(in), optional :: subgridUValues, subgridVValues + real (kind=RKIND), intent(inout), optional :: subgridUAverage, subgridVAverage + + real (kind=RKIND) :: deltaZ, ssh, pVal + real (kind=RKIND) :: averageDepth, cellArea, layerThicknessValue + real (kind=RKIND) :: H_int + real (kind=RKIND) :: HU_int, HV_int + logical :: computeVelAverage + integer :: lev, tri + + + !-------------------------------------------------------------------- + + averageDepth = sum(subgridBathymetryValues(1:nSubgridCV))/real(nSubgridCV,RKIND) + + computeVelAverage = .false. + if (present(subgridUValues) .and. present(subgridVValues) .and. & + present(subgridUAverage) .and. present(subgridVAverage)) then + computeVelAverage = .true. + endif + + H_int = 0.0_RKIND + cellArea = 0.0_RKIND + HU_int = 0.0_RKIND + HV_int = 0.0_RKIND + do tri = 1,nSubgridCV + + layerThicknessValue = subgridBathymetryValues(tri) + subgridSshValues(tri) + if (layerThicknessValue <= config_drying_min_cell_height + eps) then + layerThicknessValue = config_drying_min_cell_height + eps + endif + H_int = H_int + layerThicknessValue*subgridAreas(tri) + cellArea = cellArea + subgridAreas(tri) + + if (computeVelAverage) then + HU_int = HU_int + layerThicknessValue*subgridUValues(tri)*subgridAreas(tri) + HV_int = HV_int + layerThicknessValue*subgridVValues(tri)*subgridAreas(tri) + endif + enddo + + if (computeVelAverage) then + subgridUAverage = HU_int/H_int + subgridVAverage = HV_int/H_int + endif + subgridThicknessAverage = H_int/cellArea + + + !-------------------------------------------------------------------- + + end subroutine ocn_init_grid_average!}}} + +!*********************************************************************** +! +! routine ocn_init_wet_average_ssh +! +!> \brief +!> \author Steven Brus +!> \date November 2022 +!> \details +!> +! +!----------------------------------------------------------------------- + subroutine ocn_init_wet_average_ssh( nSubgridCV, subgridBathymetryValues, subgridSshValues, subgridAreas, sshWetAverage)!{{{ + implicit none + + integer, intent(in) :: nSubgridCV + real (kind=RKIND), dimension(:), intent(in) :: subgridBathymetryValues, subgridAreas + real (kind=RKIND), dimension(:), intent(in) :: subgridSshValues + real (kind=RKIND), intent(inout) :: sshWetAverage + + real (kind=RKIND) :: deltaZ, ssh, pVal + real (kind=RKIND) :: averageDepth, wetArea, layerThicknessValue + integer :: lev, tri + + + sshWetAverage = 0.0_RKIND + wetArea = 0.0_RKIND + + do tri = 1, nsubgridCV + layerThicknessValue = subgridBathymetryValues(tri) + subgridSshValues(tri) + + if ( layerThicknessValue > subgrid_thin_layer) then + sshWetAverage = sshWetAverage + subgridSshValues(tri)*subgridAreas(tri) + wetArea = wetArea + subgridAreas(tri) + endif + end do + + if ( WetArea > 0.0_RKIND ) then + sshWetAverage = sshWetAverage/WetArea ; + else + sshWetAverage = -maxval(subgridBathymetryValues(1:nsubgridCV)) + subgrid_thin_layer + endif + + return ; + end subroutine ocn_init_wet_average_ssh + + +end module ocn_init_subgrid + +!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +! vim: foldmethod=marker diff --git a/components/mpas-ocean/src/ocean.cmake b/components/mpas-ocean/src/ocean.cmake index b353c231df7..8866a8cea3d 100644 --- a/components/mpas-ocean/src/ocean.cmake +++ b/components/mpas-ocean/src/ocean.cmake @@ -113,6 +113,7 @@ list(APPEND RAW_SOURCES core_ocean/shared/mpas_ocn_vel_tidal_potential.F core_ocean/shared/mpas_ocn_stokes_drift.F core_ocean/shared/mpas_ocn_manufactured_solution.F + core_ocean/shared/mpas_ocn_subgrid.F ) set(OCEAN_DRIVER diff --git a/components/mpas-ocean/src/shared/Makefile b/components/mpas-ocean/src/shared/Makefile index 5c5bc21cff1..35017551c75 100644 --- a/components/mpas-ocean/src/shared/Makefile +++ b/components/mpas-ocean/src/shared/Makefile @@ -69,6 +69,7 @@ OBJS = mpas_ocn_init_routines.o \ mpas_ocn_time_average_coupled.o \ mpas_ocn_framework_forcing.o \ mpas_ocn_time_varying_forcing.o \ + mpas_ocn_subgrid.o \ mpas_ocn_wetting_drying.o \ mpas_ocn_vel_tidal_potential.o \ mpas_ocn_vel_forcing_topographic_wave_drag.o \ @@ -84,7 +85,7 @@ mpas_ocn_init_routines.o: mpas_ocn_constants.o mpas_ocn_config.o mpas_ocn_mesh.o mpas_ocn_tendency.o: mpas_ocn_high_freq_thickness_hmix_del2.o mpas_ocn_tracer_surface_restoring.o mpas_ocn_thick_surface_flux.o mpas_ocn_tracer_short_wave_absorption.o mpas_ocn_tracer_advection.o mpas_ocn_tracer_hmix.o mpas_ocn_tracer_nonlocalflux.o mpas_ocn_surface_bulk_forcing.o mpas_ocn_surface_land_ice_fluxes.o mpas_ocn_tracer_surface_flux_to_tend.o mpas_ocn_tracer_interior_restoring.o mpas_ocn_tracer_exponential_decay.o mpas_ocn_tracer_ideal_age.o mpas_ocn_tracer_TTD.o mpas_ocn_vmix.o mpas_ocn_constants.o mpas_ocn_config.o mpas_ocn_frazil_forcing.o mpas_ocn_tidal_forcing.o mpas_ocn_tracer_ecosys.o mpas_ocn_tracer_DMS.o mpas_ocn_tracer_MacroMolecules.o mpas_ocn_tracer_CFC.o mpas_ocn_diagnostics.o mpas_ocn_wetting_drying.o mpas_ocn_vel_self_attraction_loading.o mpas_ocn_vel_tidal_potential.o mpas_ocn_mesh.o mpas_ocn_diagnostics_variables.o mpas_ocn_thick_hadv.o mpas_ocn_thick_vadv.o mpas_ocn_vel_hadv_coriolis.o mpas_ocn_vel_pressure_grad.o mpas_ocn_vel_vadv.o mpas_ocn_vel_hmix.o mpas_ocn_vel_forcing.o mpas_ocn_manufactured_solution.o -mpas_ocn_diagnostics.o: mpas_ocn_thick_ale.o mpas_ocn_equation_of_state.o mpas_ocn_gm.o mpas_ocn_constants.o mpas_ocn_config.o mpas_ocn_mesh.o mpas_ocn_diagnostics_variables.o mpas_ocn_surface_land_ice_fluxes.o mpas_ocn_vertical_advection.o mpas_ocn_submesoscale_eddies.o +mpas_ocn_diagnostics.o: mpas_ocn_thick_ale.o mpas_ocn_equation_of_state.o mpas_ocn_gm.o mpas_ocn_constants.o mpas_ocn_config.o mpas_ocn_mesh.o mpas_ocn_diagnostics_variables.o mpas_ocn_surface_land_ice_fluxes.o mpas_ocn_vertical_advection.o mpas_ocn_submesoscale_eddies.o mpas_ocn_subgrid.o mpas_ocn_diagnostics_variables.o: mpas_ocn_config.o @@ -184,7 +185,7 @@ mpas_ocn_surface_land_ice_fluxes.o: mpas_ocn_constants.o mpas_ocn_config.o mpas_ mpas_ocn_frazil_forcing.o: mpas_ocn_constants.o mpas_ocn_config.o mpas_ocn_mesh.o mpas_ocn_diagnostics_variables.o mpas_ocn_equation_of_state.o -mpas_ocn_tidal_forcing.o: mpas_ocn_constants.o mpas_ocn_config.o mpas_ocn_equation_of_state.o mpas_ocn_diagnostics_variables.o mpas_ocn_mesh.o +mpas_ocn_tidal_forcing.o: mpas_ocn_constants.o mpas_ocn_config.o mpas_ocn_equation_of_state.o mpas_ocn_diagnostics_variables.o mpas_ocn_mesh.o mpas_ocn_subgrid.o mpas_ocn_transport_tests.o: mpas_ocn_config.o @@ -238,6 +239,8 @@ mpas_ocn_stokes_drift.o: mpas_ocn_constants.o mpas_ocn_config.o mpas_ocn_diagnos mpas_ocn_manufactured_solution.o: mpas_ocn_constants.o mpas_ocn_config.o mpas_ocn_mesh.o +mpas_ocn_subgrid.o: mpas_ocn_diagnostics_variables.o mpas_ocn_config.o mpas_ocn_constants.o + clean: $(RM) *.o *.i *.mod *.f90 diff --git a/components/mpas-ocean/src/shared/mpas_ocn_diagnostics.F b/components/mpas-ocean/src/shared/mpas_ocn_diagnostics.F index 77796959538..cdb398f43ff 100644 --- a/components/mpas-ocean/src/shared/mpas_ocn_diagnostics.F +++ b/components/mpas-ocean/src/shared/mpas_ocn_diagnostics.F @@ -38,6 +38,7 @@ module ocn_diagnostics use ocn_mesh use ocn_surface_land_ice_fluxes use ocn_vertical_advection + use ocn_subgrid implicit none private @@ -239,10 +240,19 @@ subroutine ocn_diagnostic_solve(dt, statePool, forcingPool, meshPool, verticalMe ! endif #endif + ! + ! Z-coordinates + ! This section must be placed in the code before computing the density. + ! + ! inputs : layerThickness + ! outputs : zMid, zTop, ssh) + call ocn_diagnostic_solve_z_coordinates(layerThickness, zMid, zTop, ssh) + ! inputs: layerThickness, normalVelocity ! output: layerThickEdgeMean, layerThickEdgeDrag, layerThickEdgeFlux call ocn_diagnostic_solve_layerThicknessEdge(normalVelocity, & - layerThickness, restingThickness) + layerThickness, restingThickness, & + ssh) ! inputs: normalVelocity ! outputs: relativeVorticity, circulation @@ -337,13 +347,6 @@ subroutine ocn_diagnostic_solve(dt, statePool, forcingPool, meshPool, verticalMe call ocn_diagnostic_solve_surface_pressure(forcingPool, atmosphericPressure, & seaIcePressure, surfacePressure) - ! - ! Z-coordinates - ! This section must be placed in the code before computing the density. - ! - ! inputs : layerThickness - ! outputs : zMid, zTop, ssh) - call ocn_diagnostic_solve_z_coordinates(layerThickness, zMid, zTop, ssh) ! ! equation of state @@ -807,7 +810,8 @@ end subroutine ocn_diagnostic_solve_wctEdge!}}} !----------------------------------------------------------------------- subroutine ocn_diagnostic_solve_layerThicknessEdge(normalVelocity, & - layerThickness, restingThickness)!{{{ + layerThickness, restingThickness, & + ssh)!{{{ !----------------------------------------------------------------- ! input variables @@ -817,6 +821,8 @@ subroutine ocn_diagnostic_solve_layerThicknessEdge(normalVelocity, & normalVelocity, &!< [in] transport layerThickness, &!< [in] layer thickness at cell center restingThickness !< [in] initial layer thickness at cell center + real (kind=RKIND), dimension(:), intent(in) :: & + ssh !< [in] sea surface height at cell center !----------------------------------------------------------------- ! output variables @@ -879,64 +885,79 @@ subroutine ocn_diagnostic_solve_layerThicknessEdge(normalVelocity, & case (thickEdgeFluxCenter) ! Use centered (mean) thickness as flux value + if ( config_use_subgrid_wetting_drying ) then + + call ocn_subgrid_layerThickEdgeFlux_center(ssh, layerThickEdgeFlux) + + else + #ifdef MPAS_OPENACC - !$acc parallel loop collapse(2) & - !$acc present(layerThickEdgeFlux, layerThickEdgeMean) + !$acc parallel loop collapse(2) & + !$acc present(layerThickEdgeFlux, layerThickEdgeMean) #else - !$omp parallel - !$omp do schedule(runtime) private(k) + !$omp parallel + !$omp do schedule(runtime) private(k) #endif - do iEdge = 1, nEdgesAll - do k = 1,nVertLevels - layerThickEdgeFlux(k,iEdge) = & - layerThickEdgeMean(k,iEdge) - end do - end do + do iEdge = 1, nEdgesAll + do k = 1,nVertLevels + layerThickEdgeFlux(k,iEdge) = & + layerThickEdgeMean(k,iEdge) + end do + end do #ifndef MPAS_OPENACC - !$omp end do - !$omp end parallel + !$omp end do + !$omp end parallel #endif + end if + case (thickEdgeFluxUpwind) ! Use upwind thickness as the edge flux value + if (config_use_subgrid_wetting_drying) then + + call ocn_subgrid_layerThickEdgeFlux_upwind(ssh, normalVelocity, layerThickness, layerThickEdgeFlux) + + else #ifdef MPAS_OPENACC - !$acc parallel loop & - !$acc present(normalVelocity, layerThickness, & - !$acc minLevelEdgeBot, maxLevelEdgeTop, & - !$acc layerThickEdgeFlux, cellsOnEdge) & - !$acc private(k, kmin, kmax, cell1, cell2) + !$acc parallel loop & + !$acc present(normalVelocity, layerThickness, & + !$acc minLevelEdgeBot, maxLevelEdgeTop, & + !$acc layerThickEdgeFlux, cellsOnEdge) & + !$acc private(k, kmin, kmax, cell1, cell2) #else - !$omp parallel - !$omp do schedule(runtime) private(k, kmin, kmax, cell1, cell2) + !$omp parallel + !$omp do schedule(runtime) private(k, kmin, kmax, cell1, cell2) #endif - do iEdge = 1, nEdgesAll - kmin = minLevelEdgeBot(iEdge) - kmax = maxLevelEdgeTop(iEdge) - cell1 = cellsOnEdge(1,iEdge) - cell2 = cellsOnEdge(2,iEdge) - do k=1,nVertLevels - ! initialize layerThicknessEdgeFlux to avoid divide by - ! zero and NaN problems. - layerThickEdgeFlux(k,iEdge) = -1.0e34_RKIND - end do - do k = kmin,kmax - if (normalVelocity(k,iEdge) > 0.0_RKIND) then - layerThickEdgeFlux(k,iEdge) = layerThickness(k,cell1) - elseif (normalVelocity(k,iEdge) < 0.0_RKIND) then - layerThickEdgeFlux(k,iEdge) = layerThickness(k,cell2) - else - layerThickEdgeFlux(k,iEdge) = & - max(layerThickness(k,cell1), & - layerThickness(k,cell2)) - end if + do iEdge = 1, nEdgesAll + kmin = minLevelEdgeBot(iEdge) + kmax = maxLevelEdgeTop(iEdge) + cell1 = cellsOnEdge(1,iEdge) + cell2 = cellsOnEdge(2,iEdge) + do k=1,nVertLevels + ! initialize layerThicknessEdgeFlux to avoid divide by + ! zero and NaN problems. + layerThickEdgeFlux(k,iEdge) = -1.0e34_RKIND + end do + do k = kmin,kmax + if (normalVelocity(k,iEdge) > 0.0_RKIND) then + layerThickEdgeFlux(k,iEdge) = layerThickness(k,cell1) + elseif (normalVelocity(k,iEdge) < 0.0_RKIND) then + layerThickEdgeFlux(k,iEdge) = layerThickness(k,cell2) + else + layerThickEdgeFlux(k,iEdge) = & + max(layerThickness(k,cell1), & + layerThickness(k,cell2)) + end if + end do end do - end do #ifndef MPAS_OPENACC - !$omp end do - !$omp end parallel + !$omp end do + !$omp end parallel #endif + end if + case (thickEdgeFluxConstant) ! Use linearized version H*u where H is constant in time @@ -2600,8 +2621,21 @@ subroutine ocn_diagnostic_solve_z_coordinates(layerThickness, zMid, zTop, ssh)!{ + layerThickness(k ,iCell) end do - ! copy zTop(1,iCell) into sea-surface height array - ssh(iCell) = zTop(minLevelCell(iCell),iCell) + if (config_use_subgrid_wetting_drying) then + call ocn_subgrid_ssh_lookup(layerThickness(1,iCell), & + subgridWetVolumeCellTable(:,iCell), & + subgridSshCellTableRange(:,iCell), & + bottomDepth(iCell), & + subgridCellBathymetryMin(iCell), & + ssh(iCell)) + + + zTop(1,iCell) = ssh(iCell) + zMid(1,iCell) = -bottomDepth(iCell) + 0.5_RKIND*layerThickness(1,iCell) + else + ! copy zTop(1,iCell) into sea-surface height array + ssh(iCell) = zTop(minLevelCell(iCell),iCell) + end if end do #ifndef MPAS_OPENACC 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 567c3efc183..04511291953 100644 --- a/components/mpas-ocean/src/shared/mpas_ocn_diagnostics_variables.F +++ b/components/mpas-ocean/src/shared/mpas_ocn_diagnostics_variables.F @@ -140,7 +140,11 @@ module ocn_diagnostics_variables real (kind=RKIND), dimension(:,:), pointer :: wettingVelocityFactor type (field2DReal), pointer :: wettingVelocityField + real (kind=RKIND), dimension(:,:), pointer :: layerThicknessCellWetDry + real (kind=RKIND), dimension(:), pointer :: sshCellWetDry + real (kind=RKIND), dimension(:,:), pointer :: vertDiffTopOfCell + real (kind=RKIND), dimension(:,:), pointer :: vertDiffPassiveTopOfCell real (kind=RKIND), dimension(:,:,:), pointer :: vertNonLocalFlux integer, dimension(:,:), pointer :: rediLimiterCount real (kind=RKIND), dimension(:,:,:), pointer :: activeTracerSurfaceFluxTendency @@ -262,6 +266,10 @@ subroutine ocn_diagnostics_variables_init(domain, jenkinsOn, hollandJenkinsOn, e wettingVelocityFactor) call mpas_pool_get_field(diagnosticsPool, 'wettingVelocityFactor', & wettingVelocityField) + call mpas_pool_get_array(diagnosticsPool, 'layerThicknessCellWetDry', & + layerThicknessCellWetDry) + call mpas_pool_get_array(diagnosticsPool, 'sshCellWetDry', & + sshCellWetDry) end if if (config_use_GM.or.config_use_Redi) then @@ -494,6 +502,8 @@ subroutine ocn_diagnostics_variables_init(domain, jenkinsOn, hollandJenkinsOn, e vertViscTopOfCell) call mpas_pool_get_array(diagnosticsPool, 'vertDiffTopOfCell', & vertDiffTopOfCell) + call mpas_pool_get_array(diagnosticsPool, 'vertDiffPassiveTopOfCell', & + vertDiffPassiveTopOfCell) call mpas_pool_get_array(diagnosticsPool, 'vertAleTransportTop', & vertAleTransportTop) call mpas_pool_get_array(diagnosticsPool, 'vertTransportVelocityTop', & @@ -752,6 +762,7 @@ subroutine ocn_diagnostics_variables_init(domain, jenkinsOn, hollandJenkinsOn, e !$acc barotropicForcing, & !$acc vertViscTopOfCell, & !$acc vertDiffTopOfCell, & + !$acc vertDiffPassiveTopOfCell, & !$acc GMStreamFuncZonal, & !$acc relativeVorticity, & !$acc kineticEnergyCell, & @@ -999,6 +1010,7 @@ subroutine ocn_diagnostics_variables_destroy(err) !{{{ !$acc barotropicForcing, & !$acc vertViscTopOfCell, & !$acc vertDiffTopOfCell, & + !$acc vertDiffPassiveTopOfCell, & !$acc GMStreamFuncZonal, & !$acc relativeVorticity, & !$acc kineticEnergyCell, & @@ -1204,6 +1216,7 @@ subroutine ocn_diagnostics_variables_destroy(err) !{{{ barotropicForcing, & vertViscTopOfCell, & vertDiffTopOfCell, & + vertDiffPassiveTopOfCell, & GMStreamFuncZonal, & relativeVorticity, & kineticEnergyCell, & @@ -1246,6 +1259,8 @@ subroutine ocn_diagnostics_variables_destroy(err) !{{{ end if if ( trim(config_ocean_run_mode) == 'forward' ) then nullify(wettingVelocityFactor) + nullify(layerThicknessCellWetDry) + nullify(sshCellWetDry) end if if (config_use_GM.or.config_use_Redi) then nullify(RediKappa, & diff --git a/components/mpas-ocean/src/shared/mpas_ocn_frazil_forcing.F b/components/mpas-ocean/src/shared/mpas_ocn_frazil_forcing.F index 16c22398684..0f06a8d39c1 100644 --- a/components/mpas-ocean/src/shared/mpas_ocn_frazil_forcing.F +++ b/components/mpas-ocean/src/shared/mpas_ocn_frazil_forcing.F @@ -380,6 +380,7 @@ subroutine ocn_frazil_forcing_build_arrays(domain, meshPool, forcingPool, stateP real (kind=RKIND), pointer, dimension(:) :: accumulatedFrazilIceSalinityOld real (kind=RKIND), pointer, dimension(:) :: accumulatedLandIceFrazilMassNew real (kind=RKIND), pointer, dimension(:) :: accumulatedLandIceFrazilMassOld + real (kind=RKIND), pointer, dimension(:) :: frazilIceFreshwaterFlux real (kind=RKIND), pointer, dimension(:) :: ssh real (kind=RKIND), pointer, dimension(:,:) :: layerThickness real (kind=RKIND), pointer, dimension(:,:,:) :: activeTracers @@ -436,6 +437,7 @@ subroutine ocn_frazil_forcing_build_arrays(domain, meshPool, forcingPool, stateP call mpas_pool_get_array(forcingPool, 'frazilSurfacePressure', frazilSurfacePressure) call mpas_pool_get_array(forcingPool, 'landIceMask', landIceMask) call mpas_pool_get_array(forcingPool, 'landIceFloatingMask', landIceFloatingMask) + call mpas_pool_get_array(forcingPool, 'frazilIceFreshwaterFlux', frazilIceFreshwaterFlux) ! get time step in units of seconds timeStep = mpas_get_clock_timestep(domain % clock, ierr=err) @@ -607,6 +609,8 @@ subroutine ocn_frazil_forcing_build_arrays(domain, meshPool, forcingPool, stateP enddo ! do k=kBottom,minLevelCell,-1 + ! frazilIceFreshwaterFlux forms part of the landIceFreshwaterFluxTotal computed in surface land ice fluxes + frazilIceFreshwaterFlux(iCell) = - (sumNewFrazilIceThickness * config_frazil_ice_density) / dt ! accumulate frazil mass to column total ! note: the accumulatedFrazilIceMass (at both time levels) is reset to zero after being sent to the coupler accumulatedFrazilIceMassNew(iCell) = accumulatedFrazilIceMassOld(iCell) + sumNewFrazilIceThickness & diff --git a/components/mpas-ocean/src/shared/mpas_ocn_subgrid.F b/components/mpas-ocean/src/shared/mpas_ocn_subgrid.F new file mode 100644 index 00000000000..82208a97168 --- /dev/null +++ b/components/mpas-ocean/src/shared/mpas_ocn_subgrid.F @@ -0,0 +1,589 @@ +! Copyright (c) 2013, Los Alamos National Security, LLC (LANS) +! and the University Corporation for Atmospheric Research (UCAR). +! +! Unless noted otherwise source code is licensed under the BSD license. +! Additional copyright and license information can be found in the LICENSE file +! distributed with this code, or at http://mpas-dev.github.com/license.html +! +!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +! +! ocn_subgrid +! +!> \brief MPAS ocean subgrid wetting and drying +!> \authors Steven Brus, Damrongsak Wirasaet +!> \date September 2022 +!> \details +!> This module contains routines for subgrid wetting and drying +!> These routines primarily determine the relationship between the +!> wet volume per unit area (which can be thought of a as a layer thickness +!> for a completely wet cell) of a control volume and a the ssh +!> defined over the wet fraction of that control volume. When a +!> control volume is wet, this relationship is linear, i.e. H = \eta + b. +!> However, for partially wet cells, the nonlinear relationship between +!> these values can be pre-computed based on subgrid scale high-resolution data. +!> The routines in this module are responsible for providing interpolated +!> values for the forward and inverse relationship to be used in +!> computing the tendency terms from pre-computed look-up tables. +!> +!> See other details in Kennedy et al. (2019): +!> https://doi.org/10.1016/j.ocemod.2019.101491 +! +!----------------------------------------------------------------------- + +module ocn_subgrid + + use mpas_kind_types + use mpas_constants + use mpas_derived_types + use mpas_pool_routines + use mpas_timekeeping + use mpas_timer + use ocn_constants + use ocn_config + use ocn_mesh + use ocn_diagnostics_variables + + implicit none + private + save + + !-------------------------------------------------------------------- + ! + ! Public parameters + ! + !-------------------------------------------------------------------- + + real(kind=RKIND), public, dimension(:,:), pointer :: & + subgridWetVolumeCellTable, & + subgridWetVolumeEdgeTable, & + subgridWetVolumeVertexTable, & + subgridWetFractionCellTable, & + subgridWetFractionEdgeTable, & + subgridWetFractionVertexTable, & + subgridSshCellTableRange, & + subgridSshEdgeTableRange, & + subgridSshVertexTableRange + real(kind=RKIND), public, dimension(:), pointer :: & + subgridEdgeBathymetryMean, & + subgridVertexBathymetryMean, & + subgridCellBathymetryMin, & + subgridEdgeBathymetryMin, & + subgridVertexBathymetryMin, & + subgridLayerThicknessDebug + + integer, public, pointer :: nSubgridTableLevels + + !-------------------------------------------------------------------- + ! + ! Public member functions + ! + !-------------------------------------------------------------------- + + public :: ocn_subgrid_layerThickEdgeFlux_center, & + ocn_subgrid_layerThickEdgeFlux_upwind, & + ocn_subgrid_vorticity + + public :: ocn_subgrid_layer_thickness_lookup, & + ocn_subgrid_wet_fraction_lookup, & + ocn_subgrid_ssh_lookup, & + ocn_subgrid_init + + !-------------------------------------------------------------------- + ! + ! Private module variables + ! + !-------------------------------------------------------------------- + + + +contains + +!*********************************************************************** +! +! routine ocn_subgrid_layerThickEdgeFlux_center +! +!> \brief Copmutes centered layer thickness edge flux using subgrid info +!> \author Steven Brus, Damrongsak Wirasaet +!> \date September 2022 +!> \details +!> +!> +! +!----------------------------------------------------------------------- + + subroutine ocn_subgrid_layerThickEdgeFlux_center(ssh, layerThickEdgeFlux)!{{{ + + !----------------------------------------------------------------- + ! input variables + !----------------------------------------------------------------- + + real (kind=RKIND), dimension(:), intent(in) :: ssh + + !----------------------------------------------------------------- + ! output variables + !----------------------------------------------------------------- + + real (kind=RKIND), dimension(:,:), intent(out) :: layerThickEdgeFlux + + !----------------------------------------------------------------- + ! local variables + !----------------------------------------------------------------- + + integer :: iEdge + integer :: cell1, cell2 + real (kind=RKIND) :: sshMean + real(kind=RKIND):: eps = 1.0e-10_RKIND + + + do iEdge = 1, nEdgesAll + cell1 = cellsOnEdge(1,iEdge) + cell2 = cellsOnEdge(2,iEdge) + sshMean = 0.5_RKIND * (ssh(cell1) + ssh(cell2)) + call ocn_subgrid_layer_thickness_lookup(sshMean, & + subgridWetVolumeEdgeTable(:,iEdge), & + subgridSshEdgeTableRange(:,iEdge), & + subgridEdgeBathymetryMean(iEdge), & + layerThickEdgeFlux(1,iEdge) ) + + if ( layerThickEdgeFlux(1,iEdge) < eps ) then + layerThickEdgeFlux(1,iEdge) = layerThickEdgeMean(1,iEdge) ; + end if + end do + + end subroutine ocn_subgrid_layerThickEdgeFlux_center!}}} + +!*********************************************************************** +! +! routine ocn_subgrid_layerThickEdgeFlux_upwind +! +!> \brief Copmutes upwind layer thickness edge flux using subgrid info +!> \author Steven Brus, Damrongsak Wirasaet +!> \date September 2022 +!> \details +!> +!> +! +!----------------------------------------------------------------------- + + subroutine ocn_subgrid_layerThickEdgeFlux_upwind(ssh, normalVelocity, layerThickness, layerThickEdgeFlux)!{{{ + + !----------------------------------------------------------------- + ! input variables + !----------------------------------------------------------------- + + real (kind=RKIND), dimension(:), intent(in) :: ssh + real (kind=RKIND), dimension(:,:), intent(in) :: normalVelocity + real (kind=RKIND), dimension(:,:), intent(in) :: layerThickness + + !----------------------------------------------------------------- + ! output variables + !----------------------------------------------------------------- + + real (kind=RKIND), dimension(:,:), intent(out) :: layerThickEdgeFlux + + !----------------------------------------------------------------- + ! local variables + !----------------------------------------------------------------- + + integer :: iEdge + integer :: cell1, cell2 + real (kind=RKIND) :: sshMean + real(kind=RKIND):: eps = 1.0e-10_RKIND + + do iEdge = 1, nEdgesAll + cell1 = cellsOnEdge(1,iEdge) + cell2 = cellsOnEdge(2,iEdge) + if (normalVelocity(1,iEdge) > 0.0_RKIND) then + call ocn_subgrid_layer_thickness_lookup(ssh(cell1), & + subgridWetVolumeEdgeTable(:,iEdge), & + subgridSshEdgeTableRange(:,iEdge), & + subgridEdgeBathymetryMean(iEdge), & + layerThickEdgeFlux(1,iEdge)) + elseif (normalVelocity(1,iEdge) < 0.0_RKIND) then + call ocn_subgrid_layer_thickness_lookup(ssh(cell2), & + subgridWetVolumeEdgeTable(:,iEdge), & + subgridSshEdgeTableRange(:,iEdge), & + subgridEdgeBathymetryMean(iEdge), & + layerThickEdgeFlux(1,iEdge)) + else + sshMean = 0.5_RKIND*(ssh(cell1) + ssh(cell2)) + call ocn_subgrid_layer_thickness_lookup(sshMean, & + subgridWetVolumeEdgeTable(:,iEdge), & + subgridSshEdgeTableRange(:,iEdge), & + subgridEdgeBathymetryMean(iEdge), & + layerThickEdgeFlux(1,iEdge)) + end if + + if ( layerThickEdgeFlux(1,iEdge) < eps ) then + cell1 = cellsOnEdge(1,iEdge) + cell2 = cellsOnEdge(2,iEdge) + + layerThickEdgeFlux(1,iEdge) = 0.5_RKIND * & + ( layerThickness(1,cell1) + & + layerThickness(1,cell2) ) + end if + end do + + end subroutine ocn_subgrid_layerThickEdgeFlux_upwind!}}} + +!*********************************************************************** +! +! routine ocn_subgrid_vorticity +! +!> \brief Copmutes vorticity using subgrid info +!> \author Steven Brus, Damrongsak Wirasaet +!> \date September 2022 +!> \details +!> +!> +! +!----------------------------------------------------------------------- + + subroutine ocn_subgrid_vorticity(ssh, normalizedRelativeVorticityVertex, normalizedPlanetaryVorticityVertex)!{{{ + + !----------------------------------------------------------------- + ! input variables + !----------------------------------------------------------------- + + real (kind=RKIND), dimension(:), intent(in) :: ssh + + !----------------------------------------------------------------- + ! output variables + !----------------------------------------------------------------- + + real (kind=RKIND), dimension(:,:), intent(out) :: normalizedRelativeVorticityVertex + real (kind=RKIND), dimension(:,:), intent(out) :: normalizedPlanetaryVorticityVertex + + !----------------------------------------------------------------- + ! local variables + !----------------------------------------------------------------- + + integer :: iVertex, vertex + integer :: i, k + real (kind=RKIND) :: sshVertex + real (kind=RKIND) :: invAreaTri1 + real (kind=RKIND) :: layerThicknessVertex + + do iVertex = 1, nVerticesHalo(2) + invAreaTri1 = 1.0_RKIND / areaTriangle(iVertex) + do k = 1, maxLevelVertexBot(iVertex) + sshVertex = 0.0_RKIND + do i = 1, vertexDegree + sshVertex = sshVertex + ssh(cellsOnVertex(i,iVertex)) & + * kiteAreasOnVertex(i,iVertex) + end do + sshVertex = sshVertex * invAreaTri1 + + call ocn_subgrid_layer_thickness_lookup(sshVertex, & + subgridWetVolumeVertexTable(:,iVertex), & + subgridSshVertexTableRange(:,iVertex), & + subgridVertexBathymetryMean(iVertex), & + layerThicknessVertex) + if (layerThicknessVertex == 0) cycle + + normalizedRelativeVorticityVertex(k,iVertex) = relativeVorticity(k,iVertex) / layerThicknessVertex + normalizedPlanetaryVorticityVertex(k,iVertex) = fVertex(iVertex) / layerThicknessVertex + end do + end do + + end subroutine ocn_subgrid_vorticity!}}} + +!*********************************************************************** +! +! routine ocn_subgrid_layer_thickness_lookup +! +!> \brief Forward subgrid lookup (ssh -> layerThicknes) +!> \author Steven Brus, Damrongsak Wirasaet +!> \date September 2022 +!> \details Returns the wet volume per unit area (layerThick) for a +!> given ssh (defined over the wet-fraction based on subgrid +!> lookup table information +! +!----------------------------------------------------------------------- + + subroutine ocn_subgrid_layer_thickness_lookup(zeta, & + subgridTable, & + subgridTableRange, & + bathymetry, & + layerThick)!{{{ + + !----------------------------------------------------------------- + ! input variables + !----------------------------------------------------------------- + + real (kind=RKIND), intent(in) :: zeta + real (kind=RKIND), dimension(:), intent(in) :: subgridTable + real (kind=RKIND), dimension(:), intent(in) :: subgridTableRange + real (kind=RKIND), intent(in) :: bathymetry + + !----------------------------------------------------------------- + ! output variables + !----------------------------------------------------------------- + + real (kind=RKIND), intent(out) :: layerThick + + !----------------------------------------------------------------- + ! local variables + !----------------------------------------------------------------- + + integer :: lev + + real (kind=RKIND) :: tableMin + real (kind=RKIND) :: tableMax + real (kind=RKIND) :: deltaZ + real (kind=RKIND) :: zeta0, zeta1 + + tableMin = subgridTableRange(1) + tableMax = subgridTableRange(2) + deltaZ = (tableMax - tableMin)/real(nSubgridTableLevels-1,RKIND) + + if (zeta >= tableMax) then + layerThick = zeta + bathymetry + else if (zeta <= tableMin) then + layerThick = 0.0_RKIND + else + do lev = 1, nSubgridTableLevels-1 + zeta0 = (real(lev,RKIND)-1.0_RKIND)*deltaZ + tableMin + zeta1 = zeta0 + deltaZ + + if ((zeta <= zeta1) .and. (zeta >= zeta0)) then + layerThick = ((zeta-zeta0)*subgridTable(lev+1) - (zeta-zeta1)*subgridTable(lev))/deltaZ + return + end if + + end do + end if + + end subroutine ocn_subgrid_layer_thickness_lookup!}}} + +!*********************************************************************** +! +! routine ocn_subgrid_wet_fraction_lookup +! +!> \brief Wet fraction lookup +!> \author Steven Brus, Damrongsak Wirasaet +!> \date September 2022 +!> \details Returns the wet fraction for a given ssh (defined over the +!> wet fraction) value based on subgrid lookup table information +! +!----------------------------------------------------------------------- + + subroutine ocn_subgrid_wet_fraction_lookup(zeta, & + subgridTable, & + subgridTableRange, & + wetFraction)!{{{ + + !----------------------------------------------------------------- + ! input variables + !----------------------------------------------------------------- + + real (kind=RKIND), intent(in) :: zeta + real (kind=RKIND), dimension(:), intent(in) :: subgridTable + real (kind=RKIND), dimension(:), intent(in) :: subgridTableRange + + !----------------------------------------------------------------- + ! output variables + !----------------------------------------------------------------- + + real (kind=RKIND), intent(out) :: wetFraction + + !----------------------------------------------------------------- + ! local variables + !----------------------------------------------------------------- + + integer :: lev + + real (kind=RKIND) :: tableMin + real (kind=RKIND) :: tableMax + real (kind=RKIND) :: deltaZ + real (kind=RKIND) :: zeta0, zeta1 + + tableMin = subgridTableRange(1) + tableMax = subgridTableRange(2) + deltaZ = (tableMax - tableMin)/real(nSubgridTableLevels-1,RKIND) + + if (zeta >= tableMax) then + wetFraction = 1.0_RKIND + else if (zeta <= tableMin) then + wetFraction = 0.0_RKIND + else + do lev = 1, nSubgridTableLevels-1 + zeta0 = (real(lev,RKIND)-1.0_RKIND)*deltaZ + tableMin + zeta1 = zeta0 + deltaZ + + if ((zeta <= zeta1) .and. (zeta >= zeta0)) then + wetFraction = ((zeta-zeta0)*subgridTable(lev+1) - (zeta-zeta1)*subgridTable(lev))/deltaZ + return + end if + + end do + end if + + end subroutine ocn_subgrid_wet_fraction_lookup!}}} + +!*********************************************************************** +! +! routine ocn_subgrid_ssh_lookup +!> \brief Inverse subgrid lookup (layerThickness -> ssh) +!> \author Steven Brus, Damrongsak Wirasaet +!> \date September 2022 +!> \details Returns the ssh (defined over the wet fraction) for a given +!> wet volume per unit area value (layerThick) based on subgrid +!> lookup table information +! +!----------------------------------------------------------------------- + + subroutine ocn_subgrid_ssh_lookup(layerThick, & + subgridTable, & + subgridTableRange, & + bathymetryMean, & + bathymetryMin, & + zeta)!{{{ + + !----------------------------------------------------------------- + ! input variables + !----------------------------------------------------------------- + + real (kind=RKIND), intent(in) :: layerThick + real (kind=RKIND), dimension(:), intent(in) :: subgridTable + real (kind=RKIND), dimension(:), intent(in) :: subgridTableRange + real (kind=RKIND), intent(in) :: bathymetryMean + real (kind=RKIND), intent(in) :: bathymetryMin + + !----------------------------------------------------------------- + ! output variables + !----------------------------------------------------------------- + + real (kind=RKIND), intent(inout) :: zeta + + !----------------------------------------------------------------- + ! local variables + !----------------------------------------------------------------- + + integer :: lev + + real (kind=RKIND) :: deltaZ + real (kind=RKIND) :: tableMin, tableMax + real (kind=RKIND) :: layerThickMin, layerThickMax + real (kind=RKIND) :: layerThick0, layerThick1 + real (kind=RKIND) :: zeta0, zeta1 + real (kind=RKIND) :: phi0, phi1 + + tableMin = subgridTableRange(1) + tableMax = subgridTableRange(2) + deltaZ = (tableMax - tableMin)/real(nSubgridTableLevels-1,RKIND) + + layerThickMin = subgridTable(1) + layerThickMax = subgridTable(nSubgridTableLevels) + + if (layerThick >= layerThickMax) then + zeta = layerThick - bathymetryMean + + else if (layerThick <= layerThickMin) then + zeta = - bathymetryMin ! prevent_drying likely fails to ensure positive water columbn + else + + do lev = 1, nSubgridTableLevels-1 + zeta0 = (real(lev,RKIND)-1.0_RKIND)*deltaZ + tableMin + zeta1 = zeta0 + deltaZ + + layerThick0 = subgridTable(lev) + layerThick1 = subgridTable(lev+1) + + if ((layerThick <= layerThick1) .and. (layerThick >= layerThick0)) then + phi0 = (layerThick-layerThick1)/(layerThick0-layerThick1) + phi1 = (layerThick-layerThick0)/(layerThick1-layerThick0) + zeta = phi0*zeta0 + phi1*zeta1 + return + end if + + end do + end if + + end subroutine ocn_subgrid_ssh_lookup!}}} + +!*********************************************************************** +! +! routine ocn_subgrid_init +! +!> \brief Initializes subgrid wetting and drying module. +!> \author Steven Brus, Damrongsak Wirasaet +!> \date September 2022 +!> \details +!> This routine initializes the subgrid wetting and drying module +! +!----------------------------------------------------------------------- + + subroutine ocn_subgrid_init(domain,err)!{{{ + + !----------------------------------------------------------------- + ! input/output variables + !----------------------------------------------------------------- + + type (domain_type), intent(inout) :: domain + + !----------------------------------------------------------------- + ! output variables + !----------------------------------------------------------------- + + integer, intent(out) :: err + + !----------------------------------------------------------------- + ! local variables + !----------------------------------------------------------------- + + type(block_type), pointer :: block + type(mpas_pool_type), pointer :: meshPool + + err = 0 + if (.not. config_use_subgrid_wetting_drying) then + return + end if + + if ((config_ocean_run_mode == 'forward') .and. (nVertLevels .ne. 1)) then + call mpas_log_write('config_config_use_subgrid_wetting_drying = .true. requires single layer' , MPAS_LOG_CRIT) + end if + + block => domain%blocklist + call mpas_pool_get_subpool(block%structs, 'mesh', meshPool) + + call mpas_pool_get_array(meshPool, 'subgridWetVolumeCellTable', & + subgridWetVolumeCellTable) + call mpas_pool_get_array(meshPool, 'subgridWetVolumeEdgeTable', & + subgridWetVolumeEdgeTable) + call mpas_pool_get_array(meshPool, 'subgridWetVolumeVertexTable', & + subgridWetVolumeVertexTable) + call mpas_pool_get_array(meshPool, 'subgridWetFractionCellTable', & + subgridWetFractionCellTable) + call mpas_pool_get_array(meshPool, 'subgridWetFractionEdgeTable', & + subgridWetFractionEdgeTable) + call mpas_pool_get_array(meshPool, 'subgridWetFractionVertexTable', & + subgridWetFractionVertexTable) + call mpas_pool_get_array(meshPool, 'subgridSshCellTableRange', & + subgridSshCellTableRange) + call mpas_pool_get_array(meshPool, 'subgridSshEdgeTableRange', & + subgridSshEdgeTableRange) + call mpas_pool_get_array(meshPool, 'subgridSshVertexTableRange', & + subgridSshVertexTableRange) + call mpas_pool_get_array(meshPool, 'subgridEdgeBathymetryMean', & + subgridEdgeBathymetryMean) + call mpas_pool_get_array(meshPool, 'subgridVertexBathymetryMean', & + subgridVertexBathymetryMean) + call mpas_pool_get_array(meshPool, 'subgridCellBathymetryMin', & + subgridCellBathymetryMin) + call mpas_pool_get_array(meshPool, 'subgridEdgeBathymetryMin', & + subgridEdgeBathymetryMin) + call mpas_pool_get_array(meshPool, 'subgridVertexBathymetryMin', & + subgridVertexBathymetryMin) + call mpas_pool_get_array(meshPool, 'subgridLayerThicknessDebug', & + subgridLayerThicknessDebug) + + call mpas_pool_get_dimension(meshPool, 'nSubgridTableLevels', & + nSubgridTableLevels) + + end subroutine ocn_subgrid_init!}}} + +end module ocn_subgrid + +!||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| +! vim: foldmethod=marker diff --git a/components/mpas-ocean/src/shared/mpas_ocn_surface_land_ice_fluxes.F b/components/mpas-ocean/src/shared/mpas_ocn_surface_land_ice_fluxes.F index 69c60c79ca5..c249f202757 100644 --- a/components/mpas-ocean/src/shared/mpas_ocn_surface_land_ice_fluxes.F +++ b/components/mpas-ocean/src/shared/mpas_ocn_surface_land_ice_fluxes.F @@ -468,6 +468,8 @@ subroutine ocn_surface_land_ice_fluxes_build_arrays(meshPool, & landIceFreshwaterFlux, & landIceHeatFlux, heatFluxToLandIce + real (kind=RKIND), dimension(:), pointer :: frazilIceFreshwaterFlux, landIceFreshwaterFluxTotal + integer, dimension(:), pointer :: landIceFloatingMask real (kind=RKIND), dimension(:,:), pointer :: & @@ -505,6 +507,9 @@ subroutine ocn_surface_land_ice_fluxes_build_arrays(meshPool, & call mpas_pool_get_array(forcingPool, 'landIceHeatFlux', landIceHeatFlux) call mpas_pool_get_array(forcingPool, 'heatFluxToLandIce', heatFluxToLandIce) + call mpas_pool_get_array(forcingPool, 'frazilIceFreshwaterFlux', frazilIceFreshwaterFlux) + call mpas_pool_get_array(forcingPool, 'landIceFreshwaterFluxTotal', landIceFreshwaterFluxTotal) + call mpas_pool_get_array(forcingPool, 'landIceInterfaceTracers', landIceInterfaceTracers) call mpas_pool_get_dimension(forcingPool, & 'index_landIceInterfaceTemperature', & @@ -650,6 +655,17 @@ subroutine ocn_surface_land_ice_fluxes_build_arrays(meshPool, & endif ! jenkinsOn or hollandJenkinsOn + ! Add frazil and interface melt/freeze to get total fresh water flux + if ( associated(frazilIceFreshwaterFlux) ) then + do iCell = 1, nCells + landIceFreshwaterFluxTotal(iCell) = landIceFreshwaterFlux(iCell) + landIceFloatingMask(iCell)*frazilIceFreshwaterFlux(iCell) + end do + else + do iCell = 1, nCells + landIceFreshwaterFluxTotal(iCell) = landIceFreshwaterFlux(iCell) + end do + end if + if(useHollandJenkinsAdvDiff) then deallocate(freezeInterfaceSalinity, & freezeInterfaceTemperature, & diff --git a/components/mpas-ocean/src/shared/mpas_ocn_tidal_forcing.F b/components/mpas-ocean/src/shared/mpas_ocn_tidal_forcing.F index e2c1705c39b..2a9b400dd90 100644 --- a/components/mpas-ocean/src/shared/mpas_ocn_tidal_forcing.F +++ b/components/mpas-ocean/src/shared/mpas_ocn_tidal_forcing.F @@ -29,6 +29,7 @@ module ocn_tidal_forcing use ocn_config use ocn_mesh use ocn_diagnostics_variables + use ocn_subgrid implicit none private @@ -260,7 +261,11 @@ subroutine ocn_tidal_forcing_build_array(domain, meshPool, forcingPool, statePoo if (config_use_wetting_drying .and. tidalInputMask(iCell) == 1.0_RKIND) then ! ensure that tidal height can't force below total minimum thickness ! condition wrong to ensure that there isn't any drying according to criteria - tidalHeight = max(-bottomDepth(iCell) + (float(maxLevelCell(iCell))+1.0_RKIND)*config_drying_min_cell_height, tidalHeight) + if ( config_use_subgrid_wetting_drying ) then + tidalHeight = max(tidalHeight, subgridSShCellTableRange(3,iCell) ) ; + else + tidalHeight = max(-bottomDepth(iCell) + (float(maxLevelCell(iCell))+1.0_RKIND)*config_drying_min_cell_height, tidalHeight) + end if end if ! compute total depth for relative thickness contribution diff --git a/components/mpas-ocean/src/shared/mpas_ocn_time_average_coupled.F b/components/mpas-ocean/src/shared/mpas_ocn_time_average_coupled.F index b796c56fa1a..751c547d95b 100644 --- a/components/mpas-ocean/src/shared/mpas_ocn_time_average_coupled.F +++ b/components/mpas-ocean/src/shared/mpas_ocn_time_average_coupled.F @@ -53,7 +53,10 @@ subroutine ocn_time_average_coupled_init(forcingPool)!{{{ real (kind=RKIND), dimension(:,:), pointer :: avgTracersSurfaceValue, avgSurfaceVelocity, avgSSHGradient, & avgLandIceBoundaryLayerTracers, avgLandIceTracerTransferVelocities - real (kind=RKIND), dimension(:), pointer :: avgEffectiveDensityInLandIce, avgTotalFreshWaterTemperatureFlux + real (kind=RKIND), dimension(:), pointer :: avgEffectiveDensityInLandIce, avgTotalFreshWaterTemperatureFlux, & + avgLandIceFreshwaterFlux, & + avgRemovedRiverRunoffFlux, avgRemovedIceRunoffFlux, & + avgLandIceHeatFlux, avgRemovedIceRunoffHeatFlux integer :: iCell integer, pointer :: nAccumulatedCoupled, nCells @@ -116,6 +119,37 @@ subroutine ocn_time_average_coupled_init(forcingPool)!{{{ !$omp end parallel end if + ! Set up polar fields if necessary + if(trim(config_land_ice_flux_mode)=='standalone' .or. trim(config_land_ice_flux_mode) == 'data') then + call mpas_pool_get_array(forcingPool, 'avgLandIceFreshwaterFlux', avgLandIceFreshwaterFlux) + call mpas_pool_get_array(forcingPool, 'avgLandIceHeatFlux', avgLandIceHeatFlux) + + !$omp parallel + !$omp do schedule(runtime) + do iCell = 1, nCells + avgLandIceFreshwaterFlux(iCell) = 0.0_RKIND + avgLandIceHeatFlux(iCell) = 0.0_RKIND + end do + !$omp end do + !$omp end parallel + end if + + if(config_remove_AIS_coupler_runoff) then + call mpas_pool_get_array(forcingPool, 'avgRemovedRiverRunoffFlux', avgRemovedRiverRunoffFlux) + call mpas_pool_get_array(forcingPool, 'avgRemovedIceRunoffFlux', avgRemovedIceRunoffFlux) + call mpas_pool_get_array(forcingPool, 'avgRemovedIceRunoffHeatFlux', avgRemovedIceRunoffHeatFlux) + + !$omp parallel + !$omp do schedule(runtime) + do iCell = 1, nCells + avgRemovedRiverRunoffFlux(iCell) = 0.0_RKIND + avgRemovedIceRunoffFlux(iCell) = 0.0_RKIND + avgRemovedIceRunoffHeatFlux(iCell) = 0.0_RKIND + end do + !$omp end do + !$omp end parallel + end if + ! set up BGC coupling fields if necessary if (config_use_ecosysTracers) then @@ -201,6 +235,9 @@ end subroutine ocn_time_average_coupled_init!}}} ! !----------------------------------------------------------------------- subroutine ocn_time_average_coupled_accumulate(statePool, forcingPool, timeLevel)!{{{ + use ocn_constants, only: & + latent_heat_fusion_mks + type (mpas_pool_type), intent(in) :: statePool type (mpas_pool_type), intent(inout) :: forcingPool integer, intent(in) :: timeLevel @@ -215,7 +252,12 @@ subroutine ocn_time_average_coupled_accumulate(statePool, forcingPool, timeLevel real (kind=RKIND), dimension(:,:), pointer :: & avgLandIceBoundaryLayerTracers, avgLandIceTracerTransferVelocities real (kind=RKIND), dimension(:), pointer :: effectiveDensityInLandIce, avgEffectiveDensityInLandIce, & - totalFreshWaterTemperatureFlux, avgTotalFreshWaterTemperatureFlux + totalFreshWaterTemperatureFlux, avgTotalFreshWaterTemperatureFlux, & + landIceFreshwaterFlux, avgLandIceFreshwaterFlux, & + landIceHeatFlux, avgLandIceHeatFlux, & + removedRiverRunoffFlux, avgRemovedRiverRunoffFlux, & + removedIceRunoffFlux, avgRemovedIceRunoffFlux, & + avgRemovedIceRunoffHeatFlux type (mpas_pool_type), pointer :: tracersPool @@ -311,6 +353,48 @@ subroutine ocn_time_average_coupled_accumulate(statePool, forcingPool, timeLevel !$omp end parallel end if + ! Accumulate polar fields if necessary + if(trim(config_land_ice_flux_mode) == 'standalone' .or. trim(config_land_ice_flux_mode) == 'data') then + call mpas_pool_get_array(forcingPool, 'avgLandIceFreshwaterFlux', avgLandIceFreshwaterFlux) + call mpas_pool_get_array(forcingPool, 'landIceFreshwaterFlux', landIceFreshwaterFlux) + call mpas_pool_get_array(forcingPool, 'avgLandIceHeatFlux', avgLandIceHeatFlux) + call mpas_pool_get_array(forcingPool, 'landIceHeatFlux', landIceHeatFlux) + + !$omp parallel + !$omp do schedule(runtime) + do iCell = 1, nCells + avgLandIceFreshwaterFlux(iCell) = ( avgLandIceFreshwaterFlux(iCell) * nAccumulatedCoupled & + + landIceFreshwaterFlux(iCell) ) / ( nAccumulatedCoupled + 1) + avgLandIceHeatFlux(iCell) = ( avgLandIceHeatFlux(iCell) * nAccumulatedCoupled & + + landIceHeatFlux(iCell) ) / ( nAccumulatedCoupled + 1) + end do + !$omp end do + !$omp end parallel + + end if + + if (config_remove_AIS_coupler_runoff) then + call mpas_pool_get_array(forcingPool, 'avgRemovedRiverRunoffFlux', avgRemovedRiverRunoffFlux) + call mpas_pool_get_array(forcingPool, 'avgRemovedIceRunoffFlux', avgRemovedIceRunoffFlux) + call mpas_pool_get_array(forcingPool, 'avgRemovedIceRunoffHeatFlux', avgRemovedIceRunoffHeatFlux) + call mpas_pool_get_array(forcingPool, 'removedRiverRunoffFlux', removedRiverRunoffFlux) + call mpas_pool_get_array(forcingPool, 'removedIceRunoffFlux', removedIceRunoffFlux) + + !$omp parallel + !$omp do schedule(runtime) + do iCell = 1, nCells + avgRemovedRiverRunoffFlux(iCell) = ( avgRemovedRiverRunoffFlux(iCell) * nAccumulatedCoupled & + + removedRiverRunoffFlux(iCell) ) / ( nAccumulatedCoupled + 1) + avgRemovedIceRunoffFlux(iCell) = ( avgRemovedIceRunoffFlux(iCell) * nAccumulatedCoupled & + + removedIceRunoffFlux(iCell) ) / ( nAccumulatedCoupled + 1) + avgRemovedIceRunoffHeatFlux(iCell) = ( avgRemovedIceRunoffHeatFlux(iCell) * nAccumulatedCoupled & + + removedIceRunoffFlux(iCell)*latent_heat_fusion_mks ) / ( nAccumulatedCoupled + 1) + end do + !$omp end do + !$omp end parallel + + end if + ! accumulate BGC coupling fields if necessary if (config_use_ecosysTracers) then diff --git a/components/mpas-ocean/src/shared/mpas_ocn_vel_pressure_grad.F b/components/mpas-ocean/src/shared/mpas_ocn_vel_pressure_grad.F index 8e23913960f..b8f83cd01dc 100644 --- a/components/mpas-ocean/src/shared/mpas_ocn_vel_pressure_grad.F +++ b/components/mpas-ocean/src/shared/mpas_ocn_vel_pressure_grad.F @@ -39,6 +39,19 @@ module ocn_vel_pressure_grad ! !-------------------------------------------------------------------- + integer, public :: & + pGradType ! id for pressure gradient method selected + + integer, parameter, public :: &! ids for supported methods + pGradTypeNone = 0, &! none selected + pGradTypeSSHgrad = 1, &! ssh gradient + pGradTypePZmid = 2, &! pressure and zMid + pGradTypeMontPot = 3, &! Montgomery potential + pGradTypeMontPotDens = 4, &! Montgomery potential and density + pGradTypeJacobDens = 5, &! Jacobian from density + pGradTypeJacobTS = 6, &! Jacobian from T,S + pGradTypeConstForced = 7 ! constant forced + !-------------------------------------------------------------------- ! ! Public member functions @@ -58,19 +71,6 @@ module ocn_vel_pressure_grad pGradOff, &! flag for turning pressure gradient on/off timeIntegratorLTS ! flag for Local Time Stepping - integer :: & - pGradType ! id for pressure gradient method selected - - integer, parameter :: &! ids for supported methods - pGradTypeNone = 0, &! none selected - pGradTypeSSHgrad = 1, &! ssh gradient - pGradTypePZmid = 2, &! pressure and zMid - pGradTypeMontPot = 3, &! Montgomery potential - pGradTypeMontPotDens = 4, &! Montgomery potential and density - pGradTypeJacobDens = 5, &! Jacobian from density - pGradTypeJacobTS = 6, &! Jacobian from T,S - pGradTypeConstForced = 7 ! constant forced - real (kind=RKIND) :: &! precomputed constants for efficiency density0Inv, &! 1/density0 gdensity0Inv, &! g/density0 diff --git a/components/mpas-ocean/src/shared/mpas_ocn_vmix.F b/components/mpas-ocean/src/shared/mpas_ocn_vmix.F index 87f23d65aa1..5eefa945a68 100644 --- a/components/mpas-ocean/src/shared/mpas_ocn_vmix.F +++ b/components/mpas-ocean/src/shared/mpas_ocn_vmix.F @@ -1583,9 +1583,44 @@ subroutine ocn_vmix_implicit(dt, meshPool, statePool, forcingPool, scratchPool, !$acc enter data copyin(tracerGroupSurfaceFlux) #endif - call ocn_tracer_vmix_tend_implicit(dt, vertDiffTopOfCell, layerThickness, tracersGroup, & + if (trim(groupItr % memberName) /= 'activeTracers' .and. & + config_cvmix_background_diffusion_passive_enable) then + + +#ifdef MPAS_OPENACC + !$acc parallel loop gang vector collapse(3) present(vertDiffPassiveTopOfCell, vertDiffTopOfCell) +#else + !$omp parallel + !$omp do schedule(runtime) private(k, iTracer) +#endif + do iCell = 1, nCellsOwned + do k = 2, maxLevelCell(iCell) + vertDiffPassiveTopOfCell(k,iCell) = vertDiffTopOfCell(k,iCell) - & + config_cvmix_background_diffusion + config_cvmix_background_diffusion_passive + end do + end do +#ifndef MPAS_OPENACC + !$omp end do + !$omp end parallel +#endif + + + + + + +#ifdef MPAS_OPENACC + !$acc update host (vertDiffPassiveTopOfCell) +#endif + + call ocn_tracer_vmix_tend_implicit(dt, vertDiffPassiveTopOfCell, layerThickness, tracersGroup, & + vertNonLocalFlux, tracerGroupSurfaceFlux, & + config_cvmix_kpp_nonlocal_with_implicit_mix, err) + else + call ocn_tracer_vmix_tend_implicit(dt, vertDiffTopOfCell, layerThickness, tracersGroup, & vertNonLocalFlux, tracerGroupSurfaceFlux, & config_cvmix_kpp_nonlocal_with_implicit_mix, err) + end if #ifdef MPAS_OPENACC !$acc exit data delete(tracerGroupSurfaceFlux) #endif diff --git a/components/mpas-ocean/src/shared/mpas_ocn_wetting_drying.F b/components/mpas-ocean/src/shared/mpas_ocn_wetting_drying.F index 92cb65b2bba..16d052df028 100644 --- a/components/mpas-ocean/src/shared/mpas_ocn_wetting_drying.F +++ b/components/mpas-ocean/src/shared/mpas_ocn_wetting_drying.F @@ -33,6 +33,8 @@ module ocn_wetting_drying use ocn_diagnostics_variables use ocn_gm use ocn_mesh + use ocn_subgrid + use ocn_vel_pressure_grad implicit none private @@ -200,7 +202,7 @@ end subroutine ocn_wetting_drying_verify !}}} ! !----------------------------------------------------------------------- - subroutine ocn_prevent_drying_rk4(block, dt, rkSubstepWeight, config_zero_drying_velocity, err) !{{{ + subroutine ocn_prevent_drying_rk4(domain, block, dt, rkSubstepWeight, config_zero_drying_velocity, err) !{{{ !----------------------------------------------------------------- ! @@ -208,6 +210,7 @@ subroutine ocn_prevent_drying_rk4(block, dt, rkSubstepWeight, config_zero_drying ! !----------------------------------------------------------------- + type (domain_type), intent(inout) :: domain type (block_type), intent(in) :: block real (kind=RKIND), intent(in) :: dt real (kind=RKIND), intent(in) :: rkSubstepWeight @@ -263,10 +266,10 @@ subroutine ocn_prevent_drying_rk4(block, dt, rkSubstepWeight, config_zero_drying !$omp end do !$omp end parallel - ! ensure cells stay wet by selectively damping cells with a damping tendency to make + ! ensure cells stay wet by selectively damping cells with a damping tendency to make ! sure tendency doesn't dry cells - call ocn_wetting_drying_wettingVelocity(layerThickEdgeFlux, layerThicknessCur, layerThicknessProvis, & + call ocn_wetting_drying_wettingVelocity(domain, layerThickEdgeFlux, layerThicknessCur, layerThicknessProvis, & normalTransportVelocity, rkSubstepWeight, wettingVelocityFactor, err) ! prevent drying from happening with selective wettingVelocityFactor @@ -304,9 +307,9 @@ end subroutine ocn_prevent_drying_rk4 !}}} !> to prevent cells from drying. ! !----------------------------------------------------------------------- - subroutine ocn_wetting_drying_wettingVelocity(layerThickEdgeFlux, layerThicknessCur, layerThicknessProvis, & - normalVelocity, dt, wettingVelocityFactor, err)!{{{ + subroutine ocn_wetting_drying_wettingVelocity(domain, layerThickEdgeFlux, layerThicknessCur, layerThicknessProvis, & + normalVelocity, dt, wettingVelocityFactor, err)!{{{ !----------------------------------------------------------------- ! @@ -335,6 +338,10 @@ subroutine ocn_wetting_drying_wettingVelocity(layerThickEdgeFlux, layerThickness ! !----------------------------------------------------------------- + type (domain_type), optional, intent(inout) :: & + domain !< Input/Output: domain information, needed for halo exchange + + real (kind=RKIND), dimension(:,:), intent(inout) :: & wettingVelocityFactor !< Input/Output: velocity wettingVelocityFactor @@ -355,21 +362,39 @@ subroutine ocn_wetting_drying_wettingVelocity(layerThickEdgeFlux, layerThickness integer :: cell1, cell2, iEdge, iCell, k, i real (kind=RKIND) :: divOutFlux - real (kind=RKIND) :: layerThickness + real (kind=RKIND) :: columnThickness + real (kind=RKIND) :: hCrit, hRampMin, hRampMax, hEdgeTotal character (len=100) :: log_string + integer:: cellDummy(2), cellCur, CellNei + real (kind=RKIND) :: sshCur, sshNei + real (kind=RKIND), dimension(:), pointer :: sshCell + real (kind=RKIND), dimension(:, :), pointer :: layerThicknessCell + + err = 0 if (.not. config_zero_drying_velocity) return + if (config_use_ssh_gradient_wetting_drying .and. & + pGradType /= pGradTypeSSHgrad) then + + call mpas_log_write("config_use_ssh_gradient_wetting_drying requires " // & + "config_pressure_gradient_type = 'ssh_gradient'", MPAS_LOG_CRIT) + endif + + hRampMin = config_zero_drying_velocity_ramp_hmin + hRampMax = config_zero_drying_velocity_ramp_hmax + hCrit = config_drying_min_cell_height + config_drying_safety_height + + layerThicknessCell => layerThicknessCellWetDry ! need predicted transport velocity to limit drying flux !$omp parallel - !$omp do schedule(runtime) private(i, iEdge, k, divOutFlux, layerThickness) + !$omp do schedule(runtime) private(i, iEdge, k, divOutFlux) do iCell = 1, nCellsAll do k = minLevelCell(iCell), maxLevelCell(iCell) divOutFlux = 0.0_RKIND - layerThickness = min(layerThicknessProvis(k, iCell), layerThicknessCur(k, iCell)) do i = 1, nEdgesOnCell(iCell) iEdge = edgesOnCell(i, iCell) if (k <= maxLevelEdgeTop(iEdge) .and. k >= minLevelEdgeBot(iEdge)) then @@ -382,15 +407,148 @@ subroutine ocn_wetting_drying_wettingVelocity(layerThickEdgeFlux, layerThickness end if end if end do - layerThickness = layerThickness + dt * divOutFlux - - call ocn_wetting_velocity_factor_on_cell_edges(wettingVelocityFactor, layerThickness, normalVelocity, iCell, k) + layerThicknessCell(k, iCell) = min(layerThicknessProvis(k, iCell), layerThicknessCur(k, iCell)) + dt * divOutFlux + if ( .not. config_use_ssh_gradient_wetting_drying ) then + call ocn_wetting_velocity_factor_on_cell_edges( & + wettingVelocityFactor, layerThicknessCell(k, iCell), normalVelocity, iCell, k) + end if end do end do !$omp end do !$omp end parallel + call mpas_dmpar_field_halo_exch(domain, 'layerThicknessCellWetDry') + + + ! This wetting and drying implementation is based on the one above. + ! However, it has special considerations for edges with normal velocities + ! that have been previously zeroed to limit drying (or are zero initially), + ! but have ssh gradients that would cause flow into the current cell, + ! i.e., the neighboring cell's ssh is higher. + ! There are two cases that require special treatment: + ! 1) In the case that the neighbor cell is predicted to be wet, flow should + ! be allowed into the current cell. + ! 2) In the case that the neighor cell is predicted to be dry, flow should + ! be prevented completely (and not ramped). + ! Currently, this only works for single layer configurations with the 'ssh_gradient' + ! pressure gradient option + if (config_use_ssh_gradient_wetting_drying ) then + ! Compute predicted ssh + sshCell => sshCellWetDry + sshCell = 0.0_RKIND + + wettingVelocityFactor = 0.0_RKIND + + if ( config_use_subgrid_wetting_drying ) then + do iCell = 1, nCellsAll + k = 1 + call ocn_subgrid_ssh_lookup(layerThicknessCell(k, iCell), & + subgridWetVolumeCellTable(:,iCell), & + subgridSshCellTableRange(:,iCell), & + bottomDepth(iCell), & + subgridCellBathymetryMin(iCell), & + sshCell(iCell)) + enddo + else + !$omp parallel + !$omp do schedule(runtime) private(k, columnThickness) + do iCell = 1, nCellsAll + columnThickness = 0.0_RKIND + do k = minLevelCell(iCell), maxLevelCell(iCell) + columnThickness = columnThickness + layerThicknessCell(k, iCell) + enddo + sshCell(iCell) = columnThickness - bottomDepth(iCell) + enddo + !$omp end do + !$omp end parallel + end if + + !$omp parallel + !$omp do schedule(runtime) private(k, i, iEdge, cellDummy, cellNei, cellCur, sshCur, sshNei) + do iCell = 1, nCellsAll + do i = 1, nEdgesOnCell(iCell) + iEdge = edgesOnCell(i, iCell) + do k = minLevelCell(iCell), maxLevelCell(iCell) + if (k <= maxLevelEdgeTop(iEdge) .and. k >= minLevelEdgeBot(iEdge) .and. & + layerThicknessCell(k, iCell) <= hCrit ) then + ! If edge velocity has been zeroed, check neighbor and currnt cell ssh. + ! Allow flow into current cell if neighbor cell is wet and the ssh gradient + ! would cause flow from neighbor cell into current cell. + if ( normalVelocity(k,iEdge)*edgeSignOnCell(i, iCell) < 0.0_RKIND ) then + + wettingVelocityFactor(k,iEdge) = 1.0_RKIND + + elseif ( normalVelocity(k,iEdge)*edgeSignOnCell(i, iCell) == 0.0_RKIND ) then + + cellDummy(1:2) = cellsOnEdge(1:2,iEdge) + cellNei = merge( cellDummy(2), cellDummy(1), iCell == cellDummy(1) ) + cellCur = iCell + if ( cellNei > nCellsAll ) cellNei = cellCur + sshCur = sshCell(cellCur) + sshNei = sshCell(cellNei) + + wettingVelocityFactor(k,iEdge) = 1.0_RKIND + + ! if the neigbor cell is anticipated wet + if ( layerThicknessCell(k, cellNei) > hCrit ) then + if ( sshCur < sshNei ) then + wettingVelocityFactor(k,iEdge) = 0.0_RKIND + end if + end if + + end if ! velocity check + endif ! k check and thickness check + enddo ! k + enddo ! i + end do ! iCell + !$omp end do + !$omp end parallel + + !$omp parallel + !$omp do schedule(runtime) private(k, i, iEdge, cellDummy, cellNei, cellCur, sshCur, sshNei) + do iCell = 1, nCellsAll + do i = 1, nEdgesOnCell(iCell) + iEdge = edgesOnCell(i, iCell) + do k = minLevelCell(iCell), maxLevelCell(iCell) + if (k <= maxLevelEdgeTop(iEdge) .and. k >= minLevelEdgeBot(iEdge) .and. & + config_zero_drying_velocity_ramp .and. & + (layerThicknessCell(k, iCell) > hCrit) .and. & + (layerThicknessCell(k, iCell) <= hRampMax) ) then + + if ( normalVelocity(k, iEdge) * edgeSignOnCell(i, iCell) <= 0.0_RKIND ) then + wettingVelocityFactor(k, iEdge) = 1.0_RKIND - & + tanh(50.0_RKIND * (layerThicknessCell(k, iCell) - hRampMin)/hRampMin) + endif + + ! If edge velocity has been zeroed, check neighbor and current cell ssh. + ! Prevent flow out of cell if neighbor cell is dry and the ssh gradient + ! would cause flow from neighbor cell into current cell. + if ( normalVelocity(k, iEdge) * edgeSignOnCell(i,iCell) == 0.0_RKIND ) then + + cellDummy(1:2) = cellsOnEdge(1:2,iEdge) + cellNei = merge( cellDummy(2), cellDummy(1), iCell == cellDummy(1) ) + cellCur = iCell + if ( cellNei > nCellsAll ) cellNei = cellCur + sshCur = sshCell(cellCur) + sshNei = sshCell(cellNei) + + ! if the neigbor cell is anticipated dry + if ( layerThicknessCell(k, cellNei) <= hCrit ) then + if ( sshCur < sshNei ) then + wettingVelocityFactor(k,iEdge) = 1.0_RKIND + end if + end if + end if ! velocity check + end if ! thickness check + enddo ! k + enddo ! iEdge + end do ! iCell + !$omp end do + !$omp end parallel + + end if + end subroutine ocn_wetting_drying_wettingVelocity !}}} !*********************************************************************** 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 a47e5798159..23f258f2a30 100644 --- a/components/mpas-seaice/bld/namelist_files/namelist_defaults_mpassi.xml +++ b/components/mpas-seaice/bld/namelist_files/namelist_defaults_mpassi.xml @@ -25,6 +25,7 @@ 1800.0 1800.0 1800.0 +1800.0 480.0 240.0 120.0 @@ -81,6 +82,7 @@ 75.0 70.0 +70.0 85.0 85.0 85.0 @@ -95,6 +97,7 @@ -75.0 -60.0 +-60.0 -85.0 -85.0 -85.0 @@ -160,6 +163,7 @@ 1 1 1 +1 1 1 1 diff --git a/components/mpas-seaice/cime_config/buildnml b/components/mpas-seaice/cime_config/buildnml index 0aa12105bf9..2e602311033 100755 --- a/components/mpas-seaice/cime_config/buildnml +++ b/components/mpas-seaice/cime_config/buildnml @@ -129,6 +129,7 @@ def buildnml(case, caseroot, compname): decomp_prefix = 'partitions/mpas-seaice.graph.info.' grid_date = '160929' grid_prefix = 'cice.QU240wLI' + data_iceberg_file = 'Iceberg_Climatology_Merino.oQU240wLI.20240404.nc' if ice_ic_mode == 'spunup': logger.warning("WARNING: The specified compset is requesting seaice ICs spunup from a G-case") logger.warning(" But no file available for this grid.") @@ -307,6 +308,16 @@ def buildnml(case, caseroot, compname): grid_date = '20231121' grid_prefix = 'mpassi.IcoswISC30E3r5.rstFromG-chrysalis' + elif ice_grid == 'IcosXISC30E3r7': + grid_date = '20240314' + grid_prefix = 'mpassi.IcosXISC30E3r7' + decomp_date = '20240314' + decomp_prefix = 'partitions/mpas-seaice.graph.info.' + data_iceberg_file = 'Iceberg_Climatology_Merino.IcosXISC30E3r7.20240314.nc' + if ice_ic_mode == 'spunup': + grid_date = '20240314' + grid_prefix = 'mpassi.IcosXISC30E3r7.rstFromPiControlSpinup-chrysalis' + elif ice_grid == 'ICOS10': grid_date = '211015' grid_prefix = 'seaice.ICOS10' diff --git a/components/mpas-seaice/docs/dev-guide/MPAS-Analysis_scripts.zip b/components/mpas-seaice/docs/dev-guide/MPAS-Analysis_scripts.zip new file mode 100644 index 00000000000..7db9d8ca7cc Binary files /dev/null and b/components/mpas-seaice/docs/dev-guide/MPAS-Analysis_scripts.zip differ diff --git a/components/mpas-seaice/docs/dev-guide/index.md b/components/mpas-seaice/docs/dev-guide/index.md new file mode 100644 index 00000000000..be53365c8a0 --- /dev/null +++ b/components/mpas-seaice/docs/dev-guide/index.md @@ -0,0 +1,330 @@ +# Developer's Guide + +Development of the MPAS-seaice component should follow the general procedures outlined by the E3SM project. + +[Development Guide for E3SM Code](https://acme-climate.atlassian.net/wiki/spaces/DOC/pages/1868455/Development+Getting+Started+Guide) +[Development Guide for E3SM Documentation](https://acme-climate.atlassian.net/wiki/spaces/DOC/pages/3924787306/Developing+Documentation) + +## Configuration Controls + +MPAS-seaice is controlled using namelist options. Namelist files for E3SM runs are found in ``E3SM/components/mpas-seaice/bld/namelist_files/``. However, the values in these files are drawn from the Registry, following the convention of all MPAS components. Registry files are used directly for stand-alone MPAS-seaice runs, and E3SM scripts pass information from them into E3SM's namelist files when a PR is merged. E3SM's namelist files need to be changed for development purposes. It's easiest to change all of them when needed, to keep them consistent, taking care not to unintentionally change standalone MPAS-seaice configurations. + +## MPAS Framework + +MPAS-seaice is built on the MPAS Framework. + +The MPAS Framework provides the foundation for a generalized geophysical fluid dynamics model on unstructured spherical and planar meshes. On top of the framework, implementations specific to the modeling of a particular physical system (e.g., sea ice, ocean) are created as MPAS cores. The MPAS design philosophy is to leverage the efforts of developers from the various MPAS cores to provide common framework functionality with minimal effort, allowing MPAS core developers to focus on development of the physics and features relevant to their application. + +The framework code includes shared modules for fundamental model operation. Significant capabilities include: + +- **Description of model data types.** MPAS uses a handful of fundamental Fortran derived types for basic model functionality. Core-specific model variables are handled through custom groupings of model fields called pools, for which custom access routines exist. Core-specific variables are defined in XML syntax in a Registry, and the framework parses the Registry, defines variables, and allocates memory as needed. +- **Mesh specification.** MPAS requires 36 fields to fully describe the mesh used in a simulation. These include the position, area, orientation, and connectivity of all cells, edges, and vertices in the mesh. The mesh specification can flexibly describe both spherical and planar meshes. For more information about the meshes, see the [Users Guide](../user-guide/index.md). +- **Distributed memory parallelization and domain decomposition.** The MPAS Framework provides needed routines for exchanging information between processors in a parallel environment using Message Passing Interface (MPI). This includes halo updates, global reductions, and global broadcasts. MPAS also supports decomposing multiple domain blocks on each processor to optimize model performance by minimizing transfer of data from disk to memory. Shared memory parallelization through OpenMP is also supported, but the implementation is left up to each core. +- **Parallel input and output capabilities.** MPAS performs parallel input and output of data from and to disk through the commonly used libraries of NetCDF, Parallel NetCDF (pnetcdf), and Parallel Input/Output (PIO). The Registry definitions control which fields can be input and/or output, and a framework "streams" functionality provides run-time configuration of what fields are to be written to what file name and at what frequency through an XML streams file. The MPAS framework includes additional functionality specific to providing a flexible model restart capability. +- **Advanced timekeeping.** MPAS uses a customized version of the timekeeping functionality of the Earth System Modeling Framework (ESMF), which includes a robust set of time and calendar tools used by many Earth System Models (ESMs). This allows explicit definition of model epochs in terms of years, months, days, hours, minutes, seconds, and fractional seconds and can be set to three different calendar types: Gregorian, Gregorian no leap, and 360 day. This flexibility helps enable multi-scale physics and simplifies coupling to ESMs. To manage the complex date/time types that ensue, MPAS framework provides routines for arithmetic of time intervals and the definition of alarm objects for handling events (e.g., when to write output, when the simulation should end). +- **Run-time configurable control of model options.** Model options are configured through namelist files that use standard Fortran namelist file format, and input/output are configured through streams files that use XML format. Both are completely adjustable at run time. +- **Online, run-time analysis framework.** A system for defining analysis of model states during run time, reducing the need for post-processing and model output. + +Additionally, a number of shared operators exist to perform common operations on model data. These include geometric operations (e.g., length, area, and angle operations on the sphere or the plane), interpolation (linear, barycentric, Wachspress, radial basis functions, spline), vector and tensor operations (e.g., cross products, divergence), and vector reconstruction (e.g., interpolating from cell edges to cell centers). Most operators work on both spherical and planar meshes. + +## Coupling of MPAS-seaice within E3SM + +Several files within MPAS-SI control the coupling of fields between MPAS-SI and other E3SM components via the coupler. A list of all variables being passed to and from MPAS-SI can be found in ``components/mpas-seaice/driver/mpassi_cpl_indices.F``. +Variables named with the prefix ``x2i`` are passed from the coupler to MPAS-SI, variables with the prefix ``i2x`` are passed from MPAS-SI to the coupler. +For example, all coupled variables are named with the following convention: +``index_i2x_Si_ithick`` refers to a state variable of ice (``Si``) that gets passed from MPAS-SI to the coupler (``i2x``) for the ice thickness (``ithick``). ``index_x2i_So_t`` refers to an ocean state variable (``So``) passed from the the coupler to MPAS-SI (``x2i``) for ocean temperature (``t``). + +## Icepack + +For changes to Icepack, please consult the [CICE Consortium's recommendations for code contributions](https://github.com/CICE-Consortium/About-Us/wiki/Contributing). + +To access the column physics in Icepack, MPAS-seaice uses methods defined in ``icepack_intfc.F90``. The 'init' and 'query' methods are used to set and retrieve Icepack values. A 'write' method is also available for documenting these values. MPAS-seaice follows the 'icepack_warnings' methodology where ``icepack_warnings_aborted`` is checked and ``icepack_warnings_flush`` is called after every call to an Icepack method. It does not directly “use” Icepack data, accessing Icepack data only through these interfaces. + +Basic Icepack development can be done in standalone mode using Icepack's testing scripts, directly in the submodule branch in MPAS-seaice. **We recommend that Icepack developments be thoroughly tested within E3SM's coupled framework throughout the development process, including fully coupled simulations.** + +## E3SM-Polar-Developer Script + +To accelerate early development stages, a script is available for configuring and testing MPAS-seaice (including the Icepack submodule) in D compsets, which have the sea ice component active and data models for the other components. + +### View helpful information, including default values for duration, configuration, etc + +```text +git clone git@github.com:E3SM-Project/SimulationScripts.git +cd SimulationScripts/archive/PolarGroup +./E3SM-Polar-Developer.sh -h +``` + +For debugging E3SM, search the script for 'debug' and follow the instructions. + +The following examples describe how to use the script for development in Icepack. Similar procedures could be used for any MPAS-SI physics development. + +### Set up and run baselines + +Create a file containing modified namelist options. The file ``nset01.nlk`` in this example creates baselines for two types of column physics and turns off the ``snicar_ad`` radiation scheme. + +```text +$ less nset01.nlk +[mpassi] +config_column_physics_type = {'column_package','icepack'} +config_use_snicar_ad = {.false.} +``` + +Notes: + +- A .nlk file without any config settings will create a baseline using default settings. +- The ``column_package`` option is still available but is no longer being supported in MPAS-seaice. + +Fetch E3SM (choose any name for the directory baselines01): + +```text +./E3SM-Polar-Developer.sh -s baselines01 -f git@github.com:E3SM-Project/E3SM +``` + +Set up a new case and build it: + +```text +./E3SM-Polar-Developer.sh -s baselines01 -k nset01.nlk -e -n -b +``` + +Submit: + +```text +./E3SM-Polar-Developer.sh -s baselines01 -k nset01.nlk -e -q +``` + +Examine the diagnostic output (compares the icepack run with the column_package run in this example): + +```text +./E3SM-Polar-Developer.sh -s baselines01 -k nset01.nlk -e -a -v +``` + +### Set up a sandbox for model development, to be compared with the baselines + +Fetch E3SM (choose any name for the directory newdev01): + +```text +./E3SM-Polar-Developer.sh -s newdev01 -f git@github.com:E3SM-Project/E3SM +``` + +Create a new development branch: + +```text +cd ~/E3SM-Polar/code/newdev01 +git branch newbranch +git checkout newbranch +``` + +Set up a new case and build it: + +```text +./E3SM-Polar-Developer.sh -s newdev01 -k nset01.nlk -e -n -b +``` + +Develop and test... +Build/compile: + +```text +./E3SM-Polar-Developer.sh -s newdev01 -k nset01.nlk -e -b +``` + +Submit: + +```text +./E3SM-Polar-Developer.sh -s newdev01 -k nset01.nlk -e -q +``` + +Examine the diagnostic output: + +```text +./E3SM-Polar-Developer.sh -s newdev01 -k nset01.nlk -e -a -v +``` + +Compare with the baselines case directory (use your D3 baselines directory): + +```text +./E3SM-Polar-Developer.sh -s newdev01 -k nset01.nlk -a D3.nset01.baselines01.master.E3SM-Project.anvil -v +``` + +### Make changes in Icepack and PR to the Consortium + +We recommend PR’ing Icepack changes first to the Consortium then to E3SM’s icepack fork, in order to keep the repositories in sync and to ensure the changes are robust outside of E3SM. Some changes to Icepack require extensive changes to the driver code (e.g. MPAS-seaice or CICE), making this process challenging. Contact the [CICE Consortium](https://github.com/CICE-Consortium/About-Us/wiki/Contributing) to discuss and identify a collaborative path forward. + +First, create a baseline (standalone) Icepack test suite using the E3SM icepack fork or, if the Consortium code is different, using Consortium icepack main (see [Consortium documentation](https://cice-consortium-icepack.readthedocs.io/en/main/user_guide/ug_testing.html).) + +Similarly test your branch of Icepack within E3SM and compare with the baseline. +When satisfied with E3SM testing, PR to Consortium icepack main: + +```text +git remote add consortium git@github.com:cice-consortium/icepack.git +git pull consortium main +``` + +Fix conflicts if needed, then + +```text +git add ... +git commit -m "update from cice-consortium main" +``` + +Continue testing. When satisfied, + +```text +git push origin branch +``` + +Create a PR from branch to cice-consortium/icepack -b main. + +Once the PR has been tested and merged into the main Icepack codebase, a new PR is submitted to E3SM. + +More extensive documentation of this workflow tool used for the Icepack merge project is available [here](https://acme-climate.atlassian.net/wiki/spaces/ICE/pages/3450339435/Project+Workflow). + +## CICE-QC Quality Control Testing + +Example to run a CICE-QC comparison between two E3SM simulations with changes to the sea ice component. + +### Set up and run simulations to be compared + +```text +cd ~/SimulationScripts/archive/PolarGroup/ +``` + +Create a `.nlk` file with namelist changes to include the thickness analysis member. Include changes to namelist values needed in both the baseline and the test here, if desired (append the last 3 lines here to the end of your standard D-case test .nlk). + +```text +$ less qcbase.nlk +[mpassi] +config_AM_thicknesses_enable = {.true.} +config_AM_thicknesses_compute_on_startup = {.true.} +config_AM_thicknesses_write_on_startup = {.true.} +``` + +Use test script to clone E3SM, and create a sandbox + +```text +./E3SM-Polar-Developer.sh -s qcbaseline -f git@github.com:E3SM-Project/E3SM +``` + +Edit ``~/E3SM-Polar/code/qcbaseline/components/mpas-seaice/cime_config/buildnml`` to change: + +```text +lines.append(' output_interval="none">') +``` + +to + +```text +lines.append(' output_interval="00-00-01_00:00:00">') +``` + +for ``stream name=“output”`` and add + +```text +lines.append(' ') +``` + +a few lines below that: + +```text + lines.append('') ++ lines.append(' output_interval="00-00-01_00:00:00">') + lines.append('') + lines.append(' ') + lines.append(' ') + lines.append(' ') + lines.append(' ') + lines.append(' ') + lines.append(' ') ++ lines.append(' ') + lines.append(' ') + lines.append(' ') + lines.append('') + lines.append('') +``` + +Build and run baseline case for 5 years (60 months): + +```text +./E3SM-Polar-Developer.sh -s qcbaseline -k qcbase.nlk -e -d60 -nb +./E3SM-Polar-Developer.sh -s qcbaseline -k qcbase.nlk -e -d60 -q +``` + +Copy the thickness analysis member changes into your development directory: + +```text +cd ~/E3SM-Polar/code/newdev01/components/mpas-seaice/cime_config/ +cp ~/E3SM-Polar/code/qcbaseline/components/mpas-seaice/cime_config/buildnml . +``` + +If your development case adds namelist parameters, add the thickness analysis member to your .nlk file as above. This example uses the default configuration. + +Build and run the development case: + +```text +cd ~/SimulationScripts/archive/PolarGroup/ +./E3SM-Polar-Developer.sh -s newdev01 -k qcbase.nlk -e -d60 -nb +./E3SM-Polar-Developer.sh -s newdev01 -k qcbase.nlk -e -d60 -q +``` + +### Run QC comparison + +```text +cd ~/E3SM-Polar/code/newdev01/components/mpas-seaice/testing/cice-qc +``` + +See README.md. This example is for anvil. + +Edit ``job_script.cice-qc.anvil`` to export (insert your username) + +```text +BASE = /lcrc/group/e3sm/[username]/E3SM-Polar/D12.qcbase.emc.qcbaseline.master.E3SM-Project.anvil/run.k000/ +TEST = /lcrc/group/e3sm/[username]/E3SM-Polar/D12.qcbase.emc.newdev01.branch.E3SM-Project.anvil/run.k000 +``` + +Submit QC test. Test results will be in the file ``qc_log.txt``. + +```text +sbatch job_script.qc-testing-mpassi.anvil +less qc_log.txt +``` + +Example of desired result: + +```text +Running QC test on the following directories: + /lcrc/group/e3sm/ac.eclare/E3SM-Polar/D12.qcbase.emc.qcbaseline.master.E3SM-Project.anvil/run.k000/ + /lcrc/group/e3sm/ac.eclare/E3SM-Polar/D12.qcbase.emc.newdev01.branch.E3SM-Project.anvil/run.k000 +Number of files: 61 +2 Stage Test Passed +Quadratic Skill Test Passed for Northern Hemisphere +Quadratic Skill Test Passed for Southern Hemisphere +``` + +### Generate statistics from the CICE-QC runs + +This only works if the .nlk filename is the same for both cases. If comparing only namelist changes within MPAS-seaice, use the ``./E3SM-Polar-Developer.sh`` script with a single .nlk file that includes each option. + +```text +cd ~/SimulationScripts/archive/PolarGroup/ +$ ./E3SM-Polar-Developer.sh -s qcbaseline -k qcbase.nlk -e -d60 -a D12.qcbase.emc.newdev01.branch.E3SM-Project.anvil -v +``` + +### Create comparison plots + +To generate MPAS-Analysis plots from the CICE-QC runs and compare: + +Copy the scripts in the file [MPAS-Analysis_scripts.zip](./MPAS-Analysis_scripts.zip) to anvil or chrysalis. + +Edit each script for your run names, directories, etc (search for 'echmod' to find settings used for a QC comparison) + +Edit and submit (on chrysalis) the job script 3 times, once for icepack, once for column, and finally for the comparison. + +Browse the html output by navigating to the location indicated by ``htmlSubdirectory`` in the comparison script, e.g. +``https://web.lcrc.anl.gov/public/e3sm/diagnostic_output/ac.eclare/icepack-testing/D12.qcPR19.emc.qcPR19.snicar_active.eclare108213.anvil/mpas_analysis_output/`` diff --git a/components/mpas-seaice/docs/figures/mesh.png b/components/mpas-seaice/docs/figures/mesh.png new file mode 100644 index 00000000000..f4ddc361238 Binary files /dev/null and b/components/mpas-seaice/docs/figures/mesh.png differ diff --git a/components/mpas-seaice/docs/index.md b/components/mpas-seaice/docs/index.md new file mode 100644 index 00000000000..e4239d697fd --- /dev/null +++ b/components/mpas-seaice/docs/index.md @@ -0,0 +1,44 @@ +The E3SM Sea Ice Model (MPAS-seaice) +==================================== + +MPAS-seaice is an unstructured-mesh sea-ice model that uses the Modeling for Prediction Across Scales (MPAS) framework, allowing enhanced horizontal resolution in regions of interest. MPAS-seaice incorporates many of the methods used in the Los Alamos CICE sea-ice model, but adapted to the Spherical Centroidal Vornoi Tesselation (SCVT) meshes used by the MPAS framework. + +* The [MPAS-seaice User's Guide](user-guide/index.md) outlines the MPAS Framework, on which MPAS-seaice is built, and Icepack, the column physics submodule in MPAS-seaice, and it provides guidance for controlling MPAS-seaice within E3SM. +* The [MPAS-seaice Technical Guide](tech-guide/index.md) describes the mesh and major physics components underlying MPAS-seaice code and its coupling to E3SM. +* The [MPAS-seaice Developer's Guide](dev-guide/index.md) provides additional information relevant for model development, including the Icepack interface and development/testing scripts. + +**Icepack** +----------- + +MPAS-seaice incorporates the Icepack software package for sea ice column physics, developed by the [CICE Consortium](https://github.com/cice-consortium), as a submodule. [Icepack documentation](https://e3sm-icepack.readthedocs.io/en/latest/). provides a complete description of the column physics and instructions for using Icepack as a standalone model. The source code for this documentation is maintained in [E3SM's Icepack fork](https://github.com/E3SM-Project/Icepack/) (navigate to the desired branch, then to doc/source/, etc). This is the documentation associated with the latest Icepack version that has been merged into E3SM, plus any documentation changes made within E3SM itself. This documentation is fully rendered in [E3SM's Icepack readthedocs](https://e3sm-icepack.readthedocs.io/en/latest/). + + + +[Guidance for developing Icepack documentation](https://github.com/CICE-Consortium/About-Us/wiki/Documentation-Workflow-Guide) includes instructions for building the readthedocs documentation yourself. + +**MPAS-seaice code structure** +------------------------------ + +Some MPAS-seaice functionality is sourced from the MPAS Framework: +``E3SM/components/mpas-framework``. In particular, see ``E3SM/components/mpas-framework/core_seaice``. + +Code structure within the ``mpas-seaice/``component-level directory: + +| Directories | Function | +| ----------- | -------- | +| ``bld`` | namelist configuration files | +| ``cime_config`` | build and configuration scripts | +| ``docs`` | this documentation | +| ``driver`` | coupling modules | +| ``src`` | source code for the model physics and output | +| ``src/analysis_members`` | source code for model output | +| ``src/column`` | source code for the (original) ``column_package`` | +| ``src/icepack`` | link to the icepack submodule | +| ``src/model_forward`` | top-level mpas-seaice modules | +| ``src/shared`` | dynamics and general-purpose modules (e.g. mesh, constants) | +| ``testing`` | testing scripts | diff --git a/components/mpas-seaice/docs/references.md b/components/mpas-seaice/docs/references.md new file mode 100644 index 00000000000..95dbe8f36ee --- /dev/null +++ b/components/mpas-seaice/docs/references.md @@ -0,0 +1,47 @@ +References +========== + +Bitz, C. M., and W. H. Lipscomb (1999). An energy-conserving thermodynamic model of sea ice, Journal of Geophysical Research: Oceans, 104(C7), 15,669–15,677, doi: 10.1029/1999JC900100. + +Briegleb, B. P., and B. Light (2007). A Delta-Eddington multiple scattering parameterization for solar radiation in the sea ice component of the Community Climate Sys- tem Model, Tech. Rep. NCAR/TN-472+STR, National Center for Atmospheric Research, Boulder, Colorado USA. + +Dang, C., C. S. Zender, and M. G. Flanner (2019). Intercomparison and improvement of two-stream shortwave radiative transfer schemes in earth system models for a unified treatment of cryospheric surfaces. The Cryosphere, 13:2325–2343. doi:10.5194/tc-13-2325-2019. + +Dasgupta, G. (2003). Interpolants within convex polygons: Wachpress' shape functions. Journal of Aerospace Engineering, 16, 1–8. + +Dukowicz, J. K., & Baumgardner, J. R. (2000). Incremental remapping as a transport/advection algorithm. Journal of Computational Physics, 160(1), 318–335. + +Dunavant, D. A. (1985). High degree efficient symmetrical Gaussian quadrature rules for the triangle. International Journal for Numerical Methods in Engineering, 21(6), 1129–1148. + +Flocco, D., D. L. Feltham, and A. K. Turner (2010). Incorporation of a physically based melt pond scheme into the sea ice component of a climate model, Journal of Geophysi- cal Research: Oceans, 115(C8), doi:10.1029/2009JC005568, C08012. + +Golaz, J.-C., Caldwell, P. M.,
Van Roekel, L. P., Petersen, M. R., Tang, Q., Wolfe, J. D., et al. (2019). The DOE E3SM coupled model version 1: Overview and evaluation at
standard resolution. Journal of Advances in Modeling Earth
Systems, 11, 2089–2129. + +Golaz, J.-C., Van Roekel, L. P., Zheng, X., Roberts, A. F., Wolfe, J. D., Lin, W., et al. (2022). The DOE E3SM Model version 2: Overview of the physical model and initial model evaluation. Journal of Advances in Modeling Earth Systems, 14, e2022MS003156. + +Hibler, W. D. III (1979). A dynamic thermodynamic sea ice model. Journal of Physical Oceanography, 9(4), 815–846. + +Holland, M. M., D. A. Bailey, B. P. Briegleb, B. Light, and E. Hunke (2012). Improved sea ice shortwave radiation physics in CCSM4: The impact of melt ponds and aerosols on arctic sea ice, Journal of Climate, 25(5), 1413–1430, doi:10.1175/JCLI-D-11-00078.1. + + +Hunke, E., et al. (2018). CICE-Consortium/Icepack. Zenodo. + +Hunke, E. C., & Dukowicz, J. K. (1997). An elastic-viscous-plastic model for sea ice dynamics. Journal of Physical Oceanography, 27(9), 1849–1867. + +Hunke, E. C., & Dukowicz, J. K. (2002). The elastic-viscous-plastic sea ice dynamics model in general orthogonal curvilinear coordinates on a sphere—Incorporation of metric terms. Monthly Weather Review, 130(7), 1848–1865. + +Hunke, E. C., Hebert, D. A., & Lecomte, O. (2013). Level-ice melt ponds in the Los Alamos sea ice model, CICE. Ocean Modelling, 71, 26–42. + +Lipscomb, W. H. (2001). Remapping the thickness distribution in sea ice models, Journal of Geophysical Research: Oceans, 106(C7), 13,989–14,000, doi:10.1029/2000JC000518. + +Lipscomb, W. H., & Hunke, E. C. (2004). Modeling sea ice transport using incremental remapping. Monthly Weather Review, 132(6), 1341–1354. + +Lipscomb, W. H., Hunke, E. C., Maslowski, W., & Jakacki, J. (2007). Ridging, strength, and stability in high-resolution sea ice models. Journal of Geophysical Research, 112. C03S91. + +Lipscomb, W. H., & Ringler, T. D. (2005). An incremental remapping transport scheme on a spherical geodesic grid. Monthly Weather Review, 133(8), 2335–2350. + +Turner, A. K., and E. C. Hunke (2015). Impacts of a mushy-layer thermodynamic ap- proach in global sea-ice simulations using the CICE sea-ice model, Journal of Geophys- ical Research: Oceans, 120(2), 1253–1275, doi:10.1002/2014JC010358. + +Turner, A. K., E. C. Hunke, and C. M. Bitz (2013). Two modes of sea-ice gravity drainage: A parameterization for large-scale modeling, Journal of Geophysical Research: Oceans, 118(5), 2279–2294, doi:10.1002/jgrc.20171. + +Turner, A. K., Lipscomb, W. H., Hunke, E. C., Jacobsen, D. W., Jeffery, N., Engwirda, D., Ringer, T. D., Wolfe, J. D. (2021). MPAS-seaice (v1.0.0): Sea-ice dynamics on unstructured Voronoi meshes. Geoscientific Model Development Discussions, 1–46. diff --git a/components/mpas-seaice/docs/tech-guide/index.md b/components/mpas-seaice/docs/tech-guide/index.md new file mode 100644 index 00000000000..3d6d4a1786d --- /dev/null +++ b/components/mpas-seaice/docs/tech-guide/index.md @@ -0,0 +1,97 @@ +# Technical Guide + +## Primary documentation for MPAS-seaice + +See complete citations in [References](../references.md). + +**E3SM v1 Overview**: Golaz et al., JAMES 2019 + +**MPAS-seaice v1**: Turner et al., GMD Discussions, 2021. + +**E3SM v2 Overview**: Golaz et al., JAMES 2022 + +**Icepack**: Full documentation for E3SM's version of Icepack can be found in [E3SM's Icepack readthedocs](https://e3sm-icepack.readthedocs.io/en/latest). The most up-to-date documentation from the CICE Consortium's main Icepack repository is [here](https://cice-consortium-icepack.readthedocs.io/en/main). + +A comprehensive paper describing MPAS-seaice is in preparation. + +## Meshes + +MPAS-Seaice is the sea ice component of E3SMv1. MPAS-Seaice and MPAS-Ocean share identical meshes, but MPAS-Seaice uses B-grid discretizations (Arakawa & Lamb, 1977) with sea ice concentration, volume, and tracers defined at cell centers and velocity defined at cell vertices. + +The MPAS mesh system requires the definition of seven elements. These seven elements are composed of two types of _cells_, two types of _lines_, and three types of _points_. These elements can be defined on either the plane or the surface of the sphere. The two types of cells form two meshes, a primal mesh composed of Voronoi regions and a dual mesh composed of Delaunay triangles. Each corner of a primal mesh cell is uniquely associated with the "center" of a dual mesh cell and vice versa. The boundary of a given primal mesh cell is composed of the set of lines that connect the centers of the dual mesh cells. Similarly, the boundary of a given dual mesh cell is composed of the set of lines that connect the center points of the associated primal mesh cells. A line segment that connects two primal mesh cell centers is uniquely associated with a line seqment that connects two dual mesh cell centers. We assume that these two line seqments cross and are orthogonal. Since the two line seqments crossing are othogonal, they form a convenient local coordinate system for each edge. +![mesh](../figures/mesh.png) +Figure: Sample from an MPAS mesh showing the primal mesh (solid lines), the dual mesh (dashed), and velocity components aligned with a locally Cartesian coordinate system (east/north). + +## Velocity and Stresses + +Velocity components at cell vertices are not aligned with the mesh, as in sea ice models with structured meshes and quadrilateral cells. Instead, the velocity components are aligned with a spherical coordinate system that is locally Cartesian, eastwards (u) and northwards (v), irrespective of the orientation of edges joining that vertex. Such a definition, however, would result in a convergence of v components at the geographic North Pole and strong metric terms in the velocity solution. Consequently, in addition, these definitions of u and v are rotated so that their pole lies on the geographical equator at 0 deg longitude. + +Velocities are determined by solving the sea ice momentum equation (Hibler, 1979; Hunke & Dukowicz, 1997). During coupled simulations the ocean model provides the ocean surface tilt term; the only other term that depends on the properties of the horizontal grid is the divergence of internal stress. Therefore only this stress term must be adapted for use on MPAS meshes. Otherwise the velocity solver is identical to that in CICE’s standard EVP approach. Determination of the divergence of the internal stress can be broken down into three stages: + +1. The strain rate tensor is determined from the velocity field. + +2. The stress tensor at a point is determined, through a constitutive relation, from the strain rate tensor at that point. + +3. The divergence of this stress tensor is calculated. + +Two schemes to calculate the strain rate tensor and the divergence of internal stress on MPAS meshes are implemented in MPAS-Seaice, a variational scheme based on that used in CICE (Hunke and Dukowicz, 2002), and a weak scheme that uses the line integral forms of the symmetric gradient and divergence operators. The variational scheme is based on the fact that over the entire domain, Ω, and ignoring boundary effects, the total work done by the internal stress is equal to the dissipation of mechanical energy. Instead of the bilinear basis functions used by CICE, MPAS-Seaice uses Wachspress basis functions (Dasgupta, 2003), which are integrated with the quadrature rules of Dunavant (1985). + +## Horizontal Transport of Ice Area Fraction and Tracers + +Horizontal transport of ice concentration, volume, and tracers is achieved with an incremental remapping (IR) scheme similar to that described in Dukowicz and Baumgardner (2000), Lipscomb and Hunke (2004), and Lipscomb and Ringler (2005). For MPAS-Seaice the IR scheme was generalized to work on either the standard MPAS mesh (hexagons and other n-gons of varying sizes, with a vertex degree of 3, or a quadrilateral mesh with a vertex degree of 4 as in CICE. Since MPAS meshes are unstructured, the IR scheme had to be rewritten from scratch. Most of the code is mesh-agnostic, but a small amount of code is specific to quad meshes. +The transport equations describe conservation of quantities such as volume and energy. Fractional ice area (also known as sea ice concentration) is a mass-like quantity whose transport equation forms the basis for all other transported quantities in the model. In particular, ice volume is the product of ice area and thickness; therefore thickness is treated as a tracer on ice area, transported with the continuity equation for conservation of volume. Likewise, snow depth is carried as a tracer on ice area via a conservation of snow volume equation. Ice thickness and snow depth are referred to as “type 1” tracers (carried directly on ice area). Ice and snow enthalpy in each vertical layer are type 2 tracers, carried on ice and snow volume. When run with advanced options (e.g., active melt ponds and biogeochemistry), MPAS-Seaice advects tracers up to type 3. Thus, the mass-like field (area) is the “parent field” for type 1 tracers; type 1 tracers are parents of type 2; and type 2 tracers are parents of type 3. Sources and sinks of mass and tracers (e.g., ice growth and melting) are treated separately from transport. + +The transport time step is limited by the requirement that trajectories projected backward from vertices are confined to the cells sharing the vertex (i.e., 3 cells for the standard MPAS mesh and 4 for the quad mesh). This is what is meant by incremental as opposed to general remapping. For highly divergent velocity fields, the maximum time step may have to be reduced by a factor of 2 to ensure that trajectories do not cross. The incremental remapping algorithm consists of the following steps: + +1. Given mean values of the ice area and tracer fields in each grid cell and thickness category, construct linear approximations of these fields. Limit the field gradients to preserve mono- tonicity. +2. Given ice velocities at grid cell vertices, identify departure regions for the transport across each cell edge. Divide these departure regions into triangles and compute the coordinates of the triangle vertices. +3. Integrate the area and tracer fields over the departure triangles to obtain the area, volume, and other conserved quantities transported across each cell edge. +4. Given these transports, update the area and tracers. + +Since all fields are transported by the same velocity field, the second step is done only once per time step. The other steps are repeated for each field. + +With advanced physics and biogeochemistry (BGC) options, MPAS-Seaice can be configured to include numerous tracer fields, each of which is advected in every thickness category, and many of which are defined in each vertical ice or snow layer. In order to accommodate different tracer combinations and make it easy to add new tracers, the tracer fields are organized in a linked list that depends on which physics and BGC packages are active. The list is arranged with fractional ice area first, followed by the type 1 tracers, type 2 tracers, and finally type 3 tracers. In this way, values computed for parent tracers are always available when needed for computations involving child tracers. + +## Column Physics + +The Icepack software has replaced the original ``colpkg`` column physics code in MPAS-seaice. The ``config_column_physics_type = 'column_package'`` option is still available but is no longer being supported in MPAS-seaice. + +Because of the strong thermal gradients between the (cold) atmosphere and (relatively warm) oceans in polar regions, a large portion of the physics in sea ice models can be described in a vertical column, without reference to neighboring grid cells. MPAS-Seaice shares the same column physics code as CICE through the Icepack library (Hunke et al., 2018), which is maintained by the CICE Consortium. This code includes several options for simulating sea ice thermodynamics, mechanical redistribution (ridging) and associated area and thickness changes. In addition, the model supports a number of tracers, including thickness, enthalpy, ice age, first-year ice area, deformed ice area and volume, melt ponds, snow properties and biogeochemistry. + +Icepack is implemented in MPAS-seaice as a git submodule. Icepack consists of three independent parts, the column physics code, the Icepack driver that supports stand-alone testing of the column physics code, and the Icepack scripts that build and test the Icepack model. E3SM uses only the column physics code, which is called for each ocean grid cell. Icepack’s own driver and testing scripts are used when preparing new developments to be merged back to the CICE Consortium’s Icepack repository. + +Icepack includes sophisticated vertical physics and biogeochemical schemes, which include vertical thermodynamics schemes (Bitz and Lipscomb, 1999; Turner et al., 2013; Turner and Hunke, 2015), melt-pond parameterizations (Flocco et al., 2010; Hunke et al., 2013), a delta-Eddington radiation scheme (Briegleb and Light, 2007; Holland et al., 2012a), schemes for transport in thickness space (Lipscomb, 2001), and representations of mechanical redistribution (Lipscomb et al., 2007). + +Full documentation for E3SM's version of Icepack can be found in [E3SM's Icepack readthedocs](https://e3sm-icepack.readthedocs.io/en/latest). The most up-to-date documentation from the CICE Consortium's main Icepack repository is [here](https://cice-consortium-icepack.readthedocs.io/en/main). + +### Thermodynamics + +In its default configuration, MPAS-Seaice uses the “mushy layer” vertical thermodynamics scheme of Turner et al. (2013) and Turner and Hunke (2015). The mushy layer formulation describes the sea ice as a two-phase system of crystalline, fresh ice and liquid brine. Enthalpy depends on temperature and salinity, all of which are prognostic variables. The mushy layer equations are derived from conservation of energy, conservation of salt, an ice-brine liquidus relation that determines the temperature- and salinity-dependent phase, and Darcy flow through a porous medium to describe the vertical movement of brine within the ice. When or where the ice is cold, brine pockets are isolated from each other, but warmer temperatures cause the brine pockets to expand and connect into vertical channels in which meltwater, seawater, biology and nutrients may move through the ice. + +### Melt Ponds + +MPAS-seaice uses the level-ice melt pond scheme of Hunke et al. (2013). The ponds are carried as tracers on the level (undeformed) ice area of each thickness category, thus limiting their spatial extent based on the simulated sea ice topography. This limiting is meant to approximate the horizontal drainage of melt water into depressions in ice floes. The ponds evolve according to physically based process descriptions, assuming a thickness-area ratio for changes in pond volume. Melt pond processes include addition of liquid water from rain, melting snow and melting surface ice, drainage of pond water when its weight pushes the ice surface below sea level or when the ice interior becomes permeable, and refreezing of the pond water. If snow falls after a layer of ice has formed on the ponds, the snow may block sunlight from reaching the ponds below. When melt water forms with snow still on the ice, the water is assumed to infiltrate the snow. If there is enough water to fill the air spaces within the snowpack, then the pond becomes visible above the snow, thus decreasing the albedo and ultimately causing the snow to melt faster. The albedo also decreases as snow depth decreases, and thus a thin layer of snow remaining above a pond-saturated layer of snow will have a lower albedo than if the melt water were not present. Level-ice melt ponds are “virtual” in the sense that rain and meltwater is sent to the ocean immediately, and the tracers are only used thereafter to adjust the radiative calculations as if the ponds were present. The delta-Eddington radiative transfer scheme must be active for this purpose. + +### Radiation + +The Delta-Eddington radiation scheme of Briegleb & Light (2007) has been updated to the Dang et al. (2019) SNICAR-AD model, to ensure radiative consistency across all snow surfaces in E3SM, including on land, ice sheets and sea ice. The SNICAR-AD radiative transfer code includes five-band snow single-scattering properties, two-stream Delta-Eddington approximation with the adding–doubling technique, and parameterization for correcting the near-infrared (NIR) snow albedo biases when solar zenith angle exceeds 75 degrees (Dang et al., 2019). + +### Snow + +A new snow-on-sea-ice morphology has been added to E3SMv2 that includes the effects of wind redistribution: losses to leads and meltponds, and the piling of snow against ridges. Snow grain radius, now a prognosed tracer field on sea ice, evolves according to temperature gradient and wet snow metamorphism and feeds back to the SNICAR-AD radiative model up to a dry maximum of 2800 μm. Fresh snow falls at a grain radius of 54.5 μm, and five vertical snow layers replace the previous single snow layer atop each of the five sea ice thickness categories retained from E3SMv1. + +A paper describing the advanced snow physics is in preparation. + +### Biogeochemistry + +This section is under construction, pending the full merge of BGC codes in Icepack and the older column physics package. + +## Coupling of MPAS-seaice within E3SM + +This description is taken from the v1 overview paper (Golaz et al. 2019). Refer to that paper for further information. Coupling of the sea ice component to the ocean takes advantage of z star ocean coordinates and is a departure from the coupling of CICE and POP (Parallel Ocean Program) in CESM1. The weight of sea ice contributes to the ocean's barotropic mode, notably affecting the free surface over continental shelves. In shallow water depths at or less than the floating ice draft, the weight passed to the ocean model is limited to prevent evacuation of the underlying liquid column. When frazil ice forms in the ocean model, the volume of newly formed crystals is passed to the sea ice model with a fixed salinity of 4 PSU, rather than exchanging a freezing potential as in other models. Future versions of E3SM will permit progressive brine drainage to the ocean from the mushy layer physics used in MPAS-Seaice. For E3SMv1, brine drainage occurs internally in MPAS-Seaice for thermodynamic calculations, but for the sake of freshwater coupling, the ocean model only receives mass fluxes back from melted sea ice at the fixed salinity that it originally passed to its cryospheric counterpart (4 PSU). The ocean temperature immediately under the ice is the same as the liquid phase in the lowest layer of the sea ice model and is not fixed at −1.8 ◦C as is typical of previous generation coupled models. For the current version, we have addressed these long-standing ocean-ice coupling issues identified by the modeling community: explicit sea ice mass and salt exchange, a pressure force of the ice on the ocean, a basal sea ice temperature consistent with the ocean model's equation of state, and resolved inertial oscillations. + +This paragraph, taken from the v2 overview paper (Golaz et al. 2022), describes changes since v1. The most significant improvement to the sea ice climate since E3SMv1 was achieved with coupling changes associated with mushy-layer thermodynamics. Whereas the basal temperature of the ice was held fixed at -1.8◦C in E3SMv1, the new version of the model assumes the mushy liquidus basal temperature from the sea ice as described by Turner & Hunke (2015). Conversion of frazil ice from MPAS-Ocean with a fixed reference salinity of 4 PSU to the mushy layer now conserves to computational accuracy over a 500-year control integration. This was achieved by exchanging additional mass between the upper ocean and sea ice model to accommodate an assumed 25% mushy liquid content, assumed from heat and mass transferred adiabatically from the MPAS-Ocean frazil scheme active from a depth of 100 m. In addition to achieving perfect heat and mass conservation between sea ice and ocean models, this improvement greatly reduces a negative sea ice thickness bias in the summer Arctic reported by Golaz et al. (2019) for E3SMv1; it only minimally impacts Southern Ocean sea ice mass that was better simulated as compared to northern hemisphere sea ice in E3SMv1. Note that E3SM does not use virtual ice-ocean fluxes, but instead full mass and heat flux exchange consistent with a Boussinesq ocean model. Radiative coupling with the atmosphere still integrates across just two bands (visible and NIR) separated at 700nm, which does not fully exploit the five-band capability available in the delta-Eddington scheme. + +### Prescribed Ice Mode + +E3SM also includes a prescribed-extent ice mode for MPAS-SeaIce based the CESM implementation. This mode is needed for Atmospheric Model Intercomparison Project (AMIP) style simulations where a full prognostic sea ice model is not desired but sea ice surface fluxes, albedos, snow depth, and surface temperature are needed by the atmosphere model. These fields are calculated by the vertical thermodynamics module of the sea ice component. The prescribed-ice mode is intended for atmosphere sensitivity experiments and does not conserve energy or mass. In this mode, sea ice thermodynamics is active but sea ice dynamics are disabled, and at each time step ice area and thickness are reset to specified values. Ice area is interpolated in time and space from an input data set, while ice thickness in grid cells containing sea ice is set to 2 m in the Northern hemisphere and 1 m in the Southern hemisphere. During each area and thickness adjustment, snow volume preserves the snow thickness prognosed in the previous time step. Snow temperatures are reset to the surface temperature, as prognosed in the previous time step, while ice temperatures are set so that the ice temperature gradient is linear, with the ice temperature at the top equal to the prognosed surface temperature, and equal to the sea freezing temperature at the base of the ice. The vertical ice salinity profile is reset to the profile from Bitz & Lipscomb (1999). The prescribed-ice mode implemented in MPAS-SeaIce can now replace that in CICE in such configurations, but CICE continues to be used for those requiring exceptional computational efficiency. diff --git a/components/mpas-seaice/docs/user-guide/index.md b/components/mpas-seaice/docs/user-guide/index.md new file mode 100644 index 00000000000..21fbca2c32d --- /dev/null +++ b/components/mpas-seaice/docs/user-guide/index.md @@ -0,0 +1,65 @@ +# User's Guide + +Guidance for using E3SM is available from [E3SM's public web site](). + +## Configuring MPAS-seaice + +MPAS-seaice is controlled using namelist options. + +- Default namelist values are found in +``E3SM/components/mpas-seaice/bld/namelist_files/namelist_defaults_mpassi.xml``. +- Namelist options are defined in +``E3SM/components/mpas-seaice/bld/namelist_files/namelist_definitions_mpassi.xml``, +including type, category (``seaice_model``), group, valid values and a brief description. Each namelist variable is defined in an ``entry`` element. The content of the element is the documentation of how the variable is used. Other aspects of the variable's definition are expressed as attributes of the ``entry`` element. +- Users can change namelist options from defaults by entering ``[namelist option] = [changed value]`` as separate lines in the ``user_nl_mpassi`` file in the case directory. +- Some namelist values or combinations are not allowed and will generate warnings and often abort the code. The consistency checks for using MPAS-seaice within E3SM are in ``mpas_seaice_initialize`` (subroutines ``seaice_check_configs_coupled``, ``seaice_check_constants_coupled``), and those specific to Icepack can be found in subroutine ``check_column_package_configs`` in ``mpas_seaice_icepack.F``. + +Related namelist variables are grouped according to their application. + +| Namelist Groups | Relevant application | +| ------------------- | -------------------- | +| ``seaice_model`` | general options | +| ``io`` | input/output | +| ``decomposition`` | mesh parallelization | +| ``restart`` | restarting the code | +| ``dimensions`` | column physics dimensions (layers, categories) | +| ``initialize`` | initialization | +| ``use_sections`` | turn entire parameterizations on and off | +| ``forcing`` | forcing for standalone configurations | +| ``velocity_solver`` | algorithms for solving the dynamics (velocity and stress) equations | +| ``advection`` | advection | +| ``column_package`` | general column package software configurations | +| ``biogeochemistry`` | biogeochemistry | +| ``shortwave`` | radiation | +| ``snow`` | advanced snow physics | +| ``meltponds`` | melt pond parameterization flags and parameters | +| ``thermodynamics`` | basic thermodynamics | +| ``itd`` | ice thickness distribution | +| ``floesize`` | floe size distribution | +| ``ridging`` | mechanical redistribution | +| ``atmosphere`` | atmospheric boundary layer and coupling | +| ``ocean`` | oceanic boundary layer and coupling | +| ``diagnostics`` | diagnostic output | +| ``prescribed_ice`` | for testing atmosphere simulations | + +## Icepack + +The Icepack software has replaced the original ``colpkg`` column physics code in MPAS-seaice. The ``column_package`` option is still available but is no longer being supported in MPAS-seaice. + +Full documentation for E3SM's version of Icepack can be found in [E3SM's Icepack readthedocs](). The most up-to-date documentation from the CICE Consortium's main Icepack repository is [here](). + +The MPAS-seaice driver for Icepack is + +``E3SM/components/mpas-seaice/src/shared/mpas_seaice_icepack.f`` + +and the mapping between the names of Icepack's namelist options and those in MPAS-seaice can be found in subroutine ``init_icepack_package_configs`` (see the argument list for calls to subroutine ``icepack_init_parameters`` and comments at the end of ``init_icepack_package_configs``. + +## Configuring Model Input and Output + +The reading and writing of model fields in MPAS is handled by user-configurable streams. A stream represents a fixed set of model fields, together with dimensions and attributes, that are all written or read together to or from the same file or set of files. Besides these default streams, users may define new streams to, e.g., write certain diagnostic fields at a higher temporal frequency than the usual model history fields. + +Streams are defined in XML configuration files that are created at build time for each model core. The name of this XML file is simply ‘streams.’ suffixed with the name of the core. For example, the streams for the sea-ice core are defined in a file named ‘streams.seaice’. An XML stream file may further reference other text files that contain lists of the model fields that are read or written in each of the streams defined in the XML stream file. + +The stream file can be modified by copying the ``streams.seaice`` file (generated during ``./case.setup``) from the run directory to the case directory under ``SourceMods/src.mpassi/``, and making changes to the stream file there. Changes to the stream file will take effect on the next case submission. Alternatively, changes to the streams file can be made directly in the code in ``components/mpas-seaice/cime_config/buildnml``. + +Two classes of streams exist in MPAS: immutable streams and mutable streams. Immutable streams are those for which the set of fields that belong to the stream may not be modified at model run-time; however, it is possible to modify the interval at which the stream is read or written, the filename template describing the files containing the stream on disk, and several other parameters of the stream. In contrast, all aspects of mutable streams, including the set of fields that belong to the stream, may be modified at run-time. The motivation for the creation of two stream classes is the idea that an MPAS core may not function correctly if certain fields are not read in upon model start-up or written to restart files, and it is therefore not reasonable for users to modify this set of required fields at run-time. An MPAS core developer may choose to implement such streams as immutable streams. Since fields may not be added to an immutable stream at run-time, new immutable streams may not be defined at run-time, and the only type of new stream that may be defined at run-time is the mutable stream type. diff --git a/components/mpas-seaice/mkdocs.yml b/components/mpas-seaice/mkdocs.yml new file mode 100644 index 00000000000..c89222d5e58 --- /dev/null +++ b/components/mpas-seaice/mkdocs.yml @@ -0,0 +1,9 @@ +site_name: MPAS-seaice + +nav: + - Introduction: 'index.md' + - User's Guide: 'user-guide/index.md' + - Technical Guide: 'tech-guide/index.md' + - Developer's Guide: 'dev-guide/index.md' + - References: 'references.md' + diff --git a/docs/.markdownlint.json b/docs/.markdownlint.json new file mode 100644 index 00000000000..23e8b392689 --- /dev/null +++ b/docs/.markdownlint.json @@ -0,0 +1,4 @@ +{ + "line-length": false, + "no-reversed-links": false +} diff --git a/docs/development.md b/docs/development.md new file mode 100644 index 00000000000..9b1e171a972 --- /dev/null +++ b/docs/development.md @@ -0,0 +1,13 @@ +# Development Guide + +Development of E3SM is carefully planned and tied to goals in the proposals that fund +work on E3SM. + +Most development occurs within one component and developers should consult the +relevant component's development guide. + +More information + ++ [Development Big Picture](https://acme-climate.atlassian.net/wiki/spaces/DOC/pages/7997024/Development+Big+Picture) ++ [Getting Started](https://acme-climate.atlassian.net/wiki/spaces/DOC/pages/1868455/Development+Getting+Started+Guide) ++ [Development Reference](https://acme-climate.atlassian.net/wiki/spaces/DOC/pages/2523163/Development+Reference) diff --git a/docs/index.md b/docs/index.md index 07a58797469..4bc48af94a5 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,12 +1,31 @@ # The Energy Exascale Earth System Model (E3SM) -The documentation for the components of E3SM is found here. +E3SM is a state-of-the-art fully coupled model of the Earth's climate including important biogeochemical +and cryospheric processes. It is intended to address the most challenging and demanding climate-change +research problems and Department of Energy mission needs while efficiently using DOE Leadership Computing Facilities. -## Components +!!! note + This is the future home for all documentation specific to E3SM and its components. Until complete, + some documentation will be found at the project's + [Confluence wiki](https://acme-climate.atlassian.net/wiki/spaces/DOC/overview) + +## E3SM Basics + +- [Installation](installation.md) +- [User Guide](user-guide/index.md) +- [Development](development.md) + +## Component Models - [EAM](./EAM/index.md) -- [EAMxx](./EAMxx/index.md) +- EAMxx — not yet supported. - [ELM](./ELM/index.md) - [MOSART](./MOSART/index.md) +- [MPAS-Ocean](./MPAS-Ocean/index.md) +- [MPAS-seaice](./MPAS-seaice/index.md) + +## Tools + +- [generate_domain_files](./generate_domain_files/index.md) -Please see [Developing Docs](https://acme-climate.atlassian.net/wiki/spaces/DOC/pages/3924787306/Developing+Documentation) to learn about developing documentation for E3SM. +Please see [Developing Docs](https://acme-climate.atlassian.net/wiki/spaces/DOC/pages/3924787306/Developing+Documentation) to learn about how to contribute to the documentation. diff --git a/docs/installation.md b/docs/installation.md new file mode 100644 index 00000000000..38b725e9f95 --- /dev/null +++ b/docs/installation.md @@ -0,0 +1,23 @@ +# Installation Guide + +E3SM is not available as a pre-compiled binary. You install +E3SM by cloning the source code using [git](https://git-scm.com/) +and building the executable on your local platform after making some +choices on model configuration (addressed in the [User Guide](user-guide/index.md)). + +It is recommended that you install E3SM on a supported platform. +(See [Hardware/Software Configuration](https://acme-climate.atlassian.net/wiki/spaces/DOC/pages/4116447351/Hardware+Software+Configuration)) + +The E3SM Project can not assist with installation on an un-supported platform but can point you in the right direction. +If you wish to port E3SM to your machine, first check that the target machine has +the software prerequisites detailed in +[Hardware/Software Configuration](https://acme-climate.atlassian.net/wiki/spaces/DOC/pages/4116447351/Hardware+Software+Configuration#Software-prerequisites). + +E3SM uses the CIME Case Control System (CCS) and a machine must be described to the CCS +in order to build and run E3SM. See the +[CIME Porting Guide](https://esmci.github.io/cime/versions/master/html/users_guide/porting-cime.html). + +Once you are on a supported machine, clone the source code by following the first steps (2-4 and 6) +in the [Development Getting Started Guide](https://acme-climate.atlassian.net/wiki/spaces/DOC/pages/1868455/Development+Getting+Started+Guide). + +To start configuration cases and building the model, see the User Guide diff --git a/docs/refs/eam.bib b/docs/refs/eam.bib new file mode 100644 index 00000000000..ff4415a519b --- /dev/null +++ b/docs/refs/eam.bib @@ -0,0 +1,1037 @@ + +@article{moncrieff_simulation_2017, + title = {Simulation, {Modeling}, and {Dynamically} {Based} {Parameterization} of {Organized} {Tropical} {Convection} for {Global} {Climate} {Models}}, + volume = {74}, + issn = {0022-4928, 1520-0469}, + url = {https://journals.ametsoc.org/view/journals/atsc/74/5/jas-d-16-0166.1.xml}, + doi = {10.1175/JAS-D-16-0166.1}, + language = {EN}, + number = {5}, + urldate = {2024-03-29}, + journal = {Journal of the Atmospheric Sciences}, + author = {Moncrieff, Mitchell W. and Liu, Changhai and Bogenschutz, Peter}, + month = may, + year = {2017}, + pages = {1363--1380}, +} + +@article{chen_effects_2021, + title = {Effects of {Organized} {Convection} {Parameterization} on the {MJO} and {Precipitation} in {E3SMv1}. {Part} {I}: {Mesoscale} {Heating}}, + volume = {13}, + issn = {1942-2466, 1942-2466}, + shorttitle = {Effects of {Organized} {Convection} {Parameterization} on the {MJO} and {Precipitation} in {E3SMv1}. {Part} {I}}, + url = {https://agupubs.onlinelibrary.wiley.com/doi/10.1029/2020MS002401}, + doi = {10.1029/2020MS002401}, + language = {en}, + number = {6}, + urldate = {2024-03-29}, + journal = {Journal of Advances in Modeling Earth Systems}, + author = {Chen, C.‐C. and Richter, J. H. and Liu, C. and Moncrieff, M. W. and Tang, Q. and Lin, W. and Xie, S. and Rasch, P. J.}, + month = jun, + year = {2021}, + pages = {e2020MS002401}, +} + +@article{morrison_parameterization_2015, + title = {Parameterization of {Cloud} {Microphysics} {Based} on the {Prediction} of {Bulk} {Ice} {Particle} {Properties}. {Part} {I}: {Scheme} {Description} and {Idealized} {Tests}}, + volume = {72}, + issn = {0022-4928, 1520-0469}, + shorttitle = {Parameterization of {Cloud} {Microphysics} {Based} on the {Prediction} of {Bulk} {Ice} {Particle} {Properties}. {Part} {I}}, + url = {https://journals.ametsoc.org/view/journals/atsc/72/1/jas-d-14-0065.1.xml}, + doi = {10.1175/JAS-D-14-0065.1}, + language = {EN}, + number = {1}, + urldate = {2024-03-29}, + journal = {Journal of the Atmospheric Sciences}, + author = {Morrison, Hugh and Milbrandt, Jason A.}, + month = jan, + year = {2015}, + pages = {287--311}, +} + +@article{milbrandt_parameterization_2016, + title = {Parameterization of {Cloud} {Microphysics} {Based} on the {Prediction} of {Bulk} {Ice} {Particle} {Properties}. {Part} {III}: {Introduction} of {Multiple} {Free} {Categories}}, + volume = {73}, + issn = {0022-4928, 1520-0469}, + shorttitle = {Parameterization of {Cloud} {Microphysics} {Based} on the {Prediction} of {Bulk} {Ice} {Particle} {Properties}. {Part} {III}}, + url = {https://journals.ametsoc.org/view/journals/atsc/73/3/jas-d-15-0204.1.xml}, + doi = {10.1175/JAS-D-15-0204.1}, + language = {EN}, + number = {3}, + urldate = {2024-03-29}, + journal = {Journal of the Atmospheric Sciences}, + author = {Milbrandt, J. A. and Morrison, H.}, + month = mar, + year = {2016}, + pages = {975--995}, +} + +@article{liu_ice_2005, + title = {Ice nucleation parameterization for global models}, + issn = {,}, + url = {https://www.schweizerbart.de/papers/metz/detail/14/54281/Ice_nucleation_parameterization_for_global_models}, + doi = {10.1127/0941-2948/2005/0059}, + language = {pt}, + urldate = {2024-03-29}, + journal = {Meteorologische Zeitschrift}, + author = {Liu, Xiaohong and Penner, Joyce E.}, + month = sep, + year = {2005}, + pages = {499--514}, +} + +@article{wang_impact_2021, + title = {Impact of a {New} {Cloud} {Microphysics} {Parameterization} on the {Simulations} of {Mesoscale} {Convective} {Systems} in {E3SM}}, + volume = {13}, + issn = {1942-2466, 1942-2466}, + url = {https://agupubs.onlinelibrary.wiley.com/doi/10.1029/2021MS002628}, + doi = {10.1029/2021MS002628}, + language = {en}, + number = {11}, + urldate = {2024-03-29}, + journal = {Journal of Advances in Modeling Earth Systems}, + author = {Wang, Jingyu and Fan, Jiwen and Feng, Zhe and Zhang, Kai and Roesler, Erika and Hillman, Benjamin and Shpund, Jacob and Lin, Wuyin and Xie, Shaocheng}, + month = nov, + year = {2021}, + pages = {e2021MS002628}, +} + +@misc{larson_clubb-silhs_2022, + title = {{CLUBB}-{SILHS}: {A} parameterization of subgrid variability in the atmosphere}, + shorttitle = {{CLUBB}-{SILHS}}, + url = {http://arxiv.org/abs/1711.03675}, + doi = {10.48550/arXiv.1711.03675}, + urldate = {2024-03-29}, + publisher = {arXiv}, + author = {Larson, Vincent E.}, + month = mar, + year = {2022}, + note = {arXiv:1711.03675 [physics]}, + keywords = {Physics - Atmospheric and Oceanic Physics}, +} + +@article{bogenschutz_path_2018, + title = {The path to {CAM6}: coupled simulations with {CAM5}.4 and {CAM5}.5}, + volume = {11}, + issn = {1991-959X}, + shorttitle = {The path to {CAM6}}, + url = {https://gmd.copernicus.org/articles/11/235/2018/}, + doi = {10.5194/gmd-11-235-2018}, + language = {English}, + number = {1}, + urldate = {2024-03-29}, + journal = {Geoscientific Model Development}, + author = {Bogenschutz, Peter A. and Gettelman, Andrew and Hannay, Cecile and Larson, Vincent E. and Neale, Richard B. and Craig, Cheryl and Chen, Chih-Chieh}, + month = jan, + year = {2018}, + pages = {235--255}, +} + +@article{golaz_pdf-based_2002, + title = {A {PDF}-{Based} {Model} for {Boundary} {Layer} {Clouds}. {Part} {I}: {Method} and {Model} {Description}}, + volume = {59}, + issn = {0022-4928, 1520-0469}, + shorttitle = {A {PDF}-{Based} {Model} for {Boundary} {Layer} {Clouds}. {Part} {I}}, + url = {https://journals.ametsoc.org/view/journals/atsc/59/24/1520-0469_2002_059_3540_apbmfb_2.0.co_2.xml}, + doi = {10.1175/1520-0469(2002)059<3540:APBMFB>2.0.CO;2}, + language = {EN}, + number = {24}, + urldate = {2024-03-29}, + journal = {Journal of the Atmospheric Sciences}, + author = {Golaz, Jean-Christophe and Larson, Vincent E. and Cotton, William R.}, + month = dec, + year = {2002}, + pages = {3540--3551}, +} + +@article{larson_using_2005, + title = {Using {Probability} {Density} {Functions} to {Derive} {Consistent} {Closure} {Relationships} among {Higher}-{Order} {Moments}}, + volume = {133}, + issn = {1520-0493, 0027-0644}, + url = {https://journals.ametsoc.org/view/journals/mwre/133/4/mwr2902.1.xml}, + doi = {10.1175/MWR2902.1}, + language = {EN}, + number = {4}, + urldate = {2024-03-29}, + journal = {Monthly Weather Review}, + author = {Larson, Vincent E. and Golaz, Jean-Christophe}, + month = apr, + year = {2005}, + pages = {1023--1042}, +} + +@article{neale_impact_2008, + title = {The {Impact} of {Convection} on {ENSO}: {From} a {Delayed} {Oscillator} to a {Series} of {Events}}, + volume = {21}, + issn = {0894-8755, 1520-0442}, + shorttitle = {The {Impact} of {Convection} on {ENSO}}, + url = {https://journals.ametsoc.org/view/journals/clim/21/22/2008jcli2244.1.xml}, + doi = {10.1175/2008JCLI2244.1}, + language = {EN}, + number = {22}, + urldate = {2024-03-29}, + journal = {Journal of Climate}, + author = {Neale, Richard B. and Richter, Jadwiga H. and Jochum, Markus}, + month = nov, + year = {2008}, + pages = {5904--5924}, +} + +@article{zhang_sensitivity_1995, + title = {Sensitivity of climate simulations to the parameterization of cumulus convection in the {Canadian} climate centre general circulation model}, + volume = {33}, + issn = {0705-5900, 1480-9214}, + url = {http://www.tandfonline.com/doi/abs/10.1080/07055900.1995.9649539}, + doi = {10.1080/07055900.1995.9649539}, + language = {en}, + number = {3}, + urldate = {2024-03-29}, + journal = {Atmosphere-Ocean}, + author = {Zhang, G.J. and McFarlane, Norman A.}, + month = sep, + year = {1995}, + pages = {407--446}, +} + +@article{xie_improved_2019, + title = {Improved {Diurnal} {Cycle} of {Precipitation} in {E3SM} {With} a {Revised} {Convective} {Triggering} {Function}}, + volume = {11}, + issn = {1942-2466, 1942-2466}, + url = {https://agupubs.onlinelibrary.wiley.com/doi/10.1029/2019MS001702}, + doi = {10.1029/2019MS001702}, + language = {en}, + number = {7}, + urldate = {2024-03-29}, + journal = {Journal of Advances in Modeling Earth Systems}, + author = {Xie, Shaocheng and Wang, Yi‐Chi and Lin, Wuyin and Ma, Hsi‐Yen and Tang, Qi and Tang, Shuaiqi and Zheng, Xue and Golaz, Jean‐Christophe and Zhang, Guang J. and Zhang, Minghua}, + month = jul, + year = {2019}, + pages = {2290--2310}, +} + +@article{xie_impact_2000, + title = {Impact of the convection triggering function on single‐column model simulations}, + volume = {105}, + issn = {0148-0227}, + url = {https://agupubs.onlinelibrary.wiley.com/doi/10.1029/2000JD900170}, + doi = {10.1029/2000JD900170}, + language = {en}, + number = {D11}, + urldate = {2024-03-29}, + journal = {Journal of Geophysical Research: Atmospheres}, + author = {Xie, Shaocheng and Zhang, Minghua}, + month = jun, + year = {2000}, + pages = {14983--14996}, +} + +@article{wang_impacts_2015, + title = {Impacts of the triggering function of cumulus parameterization on warm-season diurnal rainfall cycles at the {Atmospheric} {Radiation} {Measurement} {Southern} {Great} {Plains} site: {CONVECTIVE} {TRIGGER} {ON} {SGP} {NOCTURNAL} {RAIN}}, + volume = {120}, + issn = {2169897X}, + shorttitle = {Impacts of the triggering function of cumulus parameterization on warm-season diurnal rainfall cycles at the {Atmospheric} {Radiation} {Measurement} {Southern} {Great} {Plains} site}, + url = {http://doi.wiley.com/10.1002/2015JD023337}, + doi = {10.1002/2015JD023337}, + language = {en}, + number = {20}, + urldate = {2024-03-29}, + journal = {Journal of Geophysical Research: Atmospheres}, + author = {Wang, Yi-Chi and Pan, Hua-Lu and Hsu, Huang-Hsiung}, + month = oct, + year = {2015}, + pages = {10,681--10,702}, +} + +@article{song_microphysics_2011, + title = {Microphysics parameterization for convective clouds in a global climate model: {Description} and single-column model tests}, + volume = {116}, + issn = {0148-0227}, + shorttitle = {Microphysics parameterization for convective clouds in a global climate model}, + url = {http://doi.wiley.com/10.1029/2010JD014833}, + doi = {10.1029/2010JD014833}, + language = {en}, + number = {D2}, + urldate = {2024-03-29}, + journal = {Journal of Geophysical Research}, + author = {Song, Xiaoliang and Zhang, Guang J.}, + month = jan, + year = {2011}, + pages = {D02201}, +} + +@article{song_evaluation_2012, + title = {Evaluation of {Microphysics} {Parameterization} for {Convective} {Clouds} in the {NCAR} {Community} {Atmosphere} {Model} {CAM5}}, + volume = {25}, + issn = {0894-8755, 1520-0442}, + url = {http://journals.ametsoc.org/doi/10.1175/JCLI-D-11-00563.1}, + doi = {10.1175/JCLI-D-11-00563.1}, + language = {en}, + number = {24}, + urldate = {2024-03-29}, + journal = {Journal of Climate}, + author = {Song, Xiaoliang and Zhang, Guang J. and Li, J.-L. F.}, + month = dec, + year = {2012}, + pages = {8568--8590}, +} + +@article{storer_effects_2015, + title = {Effects of {Convective} {Microphysics} {Parameterization} on {Large}-{Scale} {Cloud} {Hydrological} {Cycle} and {Radiative} {Budget} in {Tropical} and {Midlatitude} {Convective} {Regions}}, + volume = {28}, + issn = {0894-8755, 1520-0442}, + url = {https://journals.ametsoc.org/view/journals/clim/28/23/jcli-d-15-0064.1.xml}, + doi = {10.1175/JCLI-D-15-0064.1}, + language = {EN}, + number = {23}, + urldate = {2024-03-29}, + journal = {Journal of Climate}, + author = {Storer, Rachel L. and Zhang, Guang J. and Song, Xiaoliang}, + month = dec, + year = {2015}, + pages = {9277--9297}, +} + +@article{song_incorporating_2023, + title = {Incorporating the {Effect} of {Large}‐{Scale} {Vertical} {Motion} on {Convection} {Through} {Convective} {Mass} {Flux} {Adjustment} in {E3SMv2}}, + volume = {15}, + issn = {1942-2466, 1942-2466}, + url = {https://agupubs.onlinelibrary.wiley.com/doi/10.1029/2022MS003553}, + doi = {10.1029/2022MS003553}, + language = {en}, + number = {10}, + urldate = {2024-03-29}, + journal = {Journal of Advances in Modeling Earth Systems}, + author = {Song, Xiaoliang and Zhang, Guang and Wan, Hui and Xie, Shaocheng}, + month = oct, + year = {2023}, + pages = {e2022MS003553}, +} + +@article{mlawer_radiative_1997, + title = {Radiative transfer for inhomogeneous atmospheres: {RRTM}, a validated correlated‐k model for the longwave}, + volume = {102}, + issn = {0148-0227}, + shorttitle = {Radiative transfer for inhomogeneous atmospheres}, + url = {https://agupubs.onlinelibrary.wiley.com/doi/10.1029/97JD00237}, + doi = {10.1029/97JD00237}, + language = {en}, + number = {D14}, + urldate = {2024-03-29}, + journal = {Journal of Geophysical Research: Atmospheres}, + author = {Mlawer, Eli J. and Taubman, Steven J. and Brown, Patrick D. and Iacono, Michael J. and Clough, Shepard A.}, + month = jul, + year = {1997}, + pages = {16663--16682}, +} + +@article{iacono_radiative_2008, + title = {Radiative forcing by long‐lived greenhouse gases: {Calculations} with the {AER} radiative transfer models}, + volume = {113}, + issn = {0148-0227}, + shorttitle = {Radiative forcing by long‐lived greenhouse gases}, + url = {https://agupubs.onlinelibrary.wiley.com/doi/10.1029/2008JD009944}, + doi = {10.1029/2008JD009944}, + language = {en}, + number = {D13}, + urldate = {2024-03-29}, + journal = {Journal of Geophysical Research: Atmospheres}, + author = {Iacono, Michael J. and Delamere, Jennifer S. and Mlawer, Eli J. and Shephard, Mark W. and Clough, Shepard A. and Collins, William D.}, + month = jul, + year = {2008}, + pages = {2008JD009944}, +} + +@article{pincus_fast_2003, + title = {A fast, flexible, approximate technique for computing radiative transfer in inhomogeneous cloud fields}, + volume = {108}, + issn = {0148-0227}, + url = {https://agupubs.onlinelibrary.wiley.com/doi/10.1029/2002JD003322}, + doi = {10.1029/2002JD003322}, + language = {en}, + number = {D13}, + urldate = {2024-03-29}, + journal = {Journal of Geophysical Research: Atmospheres}, + author = {Pincus, Robert and Barker, Howard W. and Morcrette, Jean‐Jacques}, + month = jul, + year = {2003}, + pages = {2002JD003322}, +} + +@article{liu_description_2016, + title = {Description and evaluation of a new four-mode version of the {Modal} {Aerosol} {Module} ({MAM4}) within version 5.3 of the {Community} {Atmosphere} {Model}}, + volume = {9}, + issn = {1991-9603}, + url = {https://gmd.copernicus.org/articles/9/505/2016/}, + doi = {10.5194/gmd-9-505-2016}, + language = {en}, + number = {2}, + urldate = {2024-03-29}, + journal = {Geoscientific Model Development}, + author = {Liu, X. and Ma, P.-L. and Wang, H. and Tilmes, S. and Singh, B. and Easter, R. C. and Ghan, S. J. and Rasch, P. J.}, + month = feb, + year = {2016}, + pages = {505--522}, +} + +@article{wu_development_2022, + title = {Development and {Evaluation} of {E3SM}‐{MOSAIC}: {Spatial} {Distributions} and {Radiative} {Effects} of {Nitrate} {Aerosol}}, + volume = {14}, + issn = {1942-2466, 1942-2466}, + shorttitle = {Development and {Evaluation} of {E3SM}‐{MOSAIC}}, + url = {https://agupubs.onlinelibrary.wiley.com/doi/10.1029/2022MS003157}, + doi = {10.1029/2022MS003157}, + language = {en}, + number = {11}, + urldate = {2024-03-29}, + journal = {Journal of Advances in Modeling Earth Systems}, + author = {Wu, Mingxuan and Wang, Hailong and Easter, Richard C. and Lu, Zheng and Liu, Xiaohong and Singh, Balwinder and Ma, Po‐Lun and Tang, Qi and Zaveri, Rahul A. and Ke, Ziming and Zhang, Rudong and Emmons, Louisa K. and Tilmes, Simone and Dibb, Jack E. and Zheng, Xue and Xie, Shaocheng and Leung, L. Ruby}, + month = nov, + year = {2022}, + pages = {e2022MS003157}, +} + +@article{lou_new_2020, + title = {New {SOA} {Treatments} {Within} the {Energy} {Exascale} {Earth} {System} {Model} ({E3SM}): {Strong} {Production} and {Sinks} {Govern} {Atmospheric} {SOA} {Distributions} and {Radiative} {Forcing}}, + volume = {12}, + issn = {1942-2466, 1942-2466}, + shorttitle = {New {SOA} {Treatments} {Within} the {Energy} {Exascale} {Earth} {System} {Model} ({E3SM})}, + url = {https://agupubs.onlinelibrary.wiley.com/doi/10.1029/2020MS002266}, + doi = {10.1029/2020MS002266}, + language = {en}, + number = {12}, + urldate = {2024-03-29}, + journal = {Journal of Advances in Modeling Earth Systems}, + author = {Lou, Sijia and Shrivastava, Manish and Easter, Richard C. and Yang, Yang and Ma, Po‐Lun and Wang, Hailong and Cubison, Michael J. and Campuzano‐Jost, Pedro and Jimenez, Jose L. and Zhang, Qi and Rasch, Philip J. and Shilling, John E. and Zelenyuk, Alla and Dubey, Manvendra and Cameron‐Smith, Philip and Martin, Scot T. and Schneider, Johannes and Schulz, Christiane}, + month = dec, + year = {2020}, + pages = {e2020MS002266}, +} + +@article{shrivastava_global_2015, + title = {Global transformation and fate of {SOA}: {Implications} of low‐volatility {SOA} and gas‐phase fragmentation reactions}, + volume = {120}, + issn = {2169-897X, 2169-8996}, + shorttitle = {Global transformation and fate of {SOA}}, + url = {https://agupubs.onlinelibrary.wiley.com/doi/10.1002/2014JD022563}, + doi = {10.1002/2014JD022563}, + language = {en}, + number = {9}, + urldate = {2024-03-29}, + journal = {Journal of Geophysical Research: Atmospheres}, + author = {Shrivastava, Manish and Easter, Richard C. and Liu, Xiaohong and Zelenyuk, Alla and Singh, Balwinder and Zhang, Kai and Ma, Po‐Lun and Chand, Duli and Ghan, Steven and Jimenez, Jose L. and Zhang, Qi and Fast, Jerome and Rasch, Philip J. and Tiitta, Petri}, + month = may, + year = {2015}, + pages = {4169--4195}, +} + + +@article{hodzic_rethinking_2016, + title = {Rethinking the global secondary organic aerosol ({SOA}) budget: stronger production, faster removal, shorter lifetime}, + volume = {16}, + issn = {1680-7316}, + shorttitle = {Rethinking the global secondary organic aerosol ({SOA}) budget}, + url = {https://acp.copernicus.org/articles/16/7917/2016/}, + doi = {10.5194/acp-16-7917-2016}, + language = {English}, + number = {12}, + urldate = {2024-03-29}, + journal = {Atmospheric Chemistry and Physics}, + author = {Hodzic, Alma and Kasibhatla, Prasad S. and Jo, Duseong S. and Cappa, Christopher D. and Jimenez, Jose L. and Madronich, Sasha and Park, Rokjin J.}, + month = jun, + year = {2016}, + pages = {7917--7941}, +} + +@article{kok_improved_2014, + title = {An improved dust emission model – {Part} 1: {Model} description and comparison against measurements}, + volume = {14}, + issn = {1680-7316}, + shorttitle = {An improved dust emission model – {Part} 1}, + url = {https://acp.copernicus.org/articles/14/13023/2014/}, + doi = {10.5194/acp-14-13023-2014}, + language = {English}, + number = {23}, + urldate = {2024-03-29}, + journal = {Atmospheric Chemistry and Physics}, + author = {Kok, J. F. and Mahowald, N. M. and Fratini, G. and Gillies, J. A. and Ishizuka, M. and Leys, J. F. and Mikami, M. and Park, M.-S. and Park, S.-U. and Van Pelt, R. S. and Zobeck, T. M.}, + month = dec, + year = {2014}, + pages = {13023--13041}, +} + +@article{zender_mineral_2003, + title = {Mineral {Dust} {Entrainment} and {Deposition} ({DEAD}) model: {Description} and 1990s dust climatology}, + volume = {108}, + issn = {0148-0227}, + shorttitle = {Mineral {Dust} {Entrainment} and {Deposition} ({DEAD}) model}, + url = {https://agupubs.onlinelibrary.wiley.com/doi/10.1029/2002JD002775}, + doi = {10.1029/2002JD002775}, + language = {en}, + number = {D14}, + urldate = {2024-03-29}, + journal = {Journal of Geophysical Research: Atmospheres}, + author = {Zender, Charles S. and Bian, Huisheng and Newman, David}, + month = jul, + year = {2003}, + pages = {2002JD002775}, +} + +@article{martensson_laboratory_2003, + title = {Laboratory simulations and parameterization of the primary marine aerosol production}, + volume = {108}, + issn = {0148-0227}, + url = {https://agupubs.onlinelibrary.wiley.com/doi/10.1029/2002JD002263}, + doi = {10.1029/2002JD002263}, + language = {en}, + number = {D9}, + urldate = {2024-03-29}, + journal = {Journal of Geophysical Research: Atmospheres}, + author = {Mårtensson, E. M. and Nilsson, E. D. and De Leeuw, G. and Cohen, L. H. and Hansson, H.‐C.}, + month = may, + year = {2003}, + pages = {2002JD002263}, +} + +@incollection{monahan_model_1986, + address = {Dordrecht}, + title = {A {Model} of {Marine} {Aerosol} {Generation} {Via} {Whitecaps} and {Wave} {Disruption}}, + isbn = {9789400946682}, + url = {https://doi.org/10.1007/978-94-009-4668-2_16}, + language = {en}, + urldate = {2024-03-29}, + booktitle = {Oceanic {Whitecaps}: {And} {Their} {Role} in {Air}-{Sea} {Exchange} {Processes}}, + publisher = {Springer Netherlands}, + author = {Monahan, E. C. and Spiel, D. E. and Davidson, K. L.}, + editor = {Monahan, Edward C. and Niocaill, Gearóid Mac}, + year = {1986}, + doi = {10.1007/978-94-009-4668-2_16}, + keywords = {Wind Speed, Droplet Radius, Marine Aerosol, Aerosol Generation, Aerosol Droplet}, + pages = {167--174}, +} + +@article{lee_e3sm_2024, + title = {{E3SM} {Chemistry} {Diagnostics} {Package} ({ChemDyg}) {Version} 0.1.4}, + url = {https://gmd.copernicus.org/preprints/gmd-2023-203/}, + doi = {10.5194/gmd-2023-203}, + language = {English}, + urldate = {2024-03-29}, + journal = {Geoscientific Model Development Discussions}, + author = {Lee, Hsiang-He and Tang, Qi and Prather, Michael}, + month = jan, + year = {2024}, + pages = {1--46}, +} + +@article{hsu_global_2010, + title = {Global long‐lived chemical modes excited in a 3‐{D} chemistry transport model: {Stratospheric} {N} $_{\textrm{2}}$ {O}, {NO} $_{\textrm{ \textit{y} }}$ , {O} $_{\textrm{3}}$ and {CH} $_{\textrm{4}}$ chemistry}, + volume = {37}, + issn = {0094-8276, 1944-8007}, + shorttitle = {Global long‐lived chemical modes excited in a 3‐{D} chemistry transport model}, + url = {https://agupubs.onlinelibrary.wiley.com/doi/10.1029/2009GL042243}, + doi = {10.1029/2009GL042243}, + language = {en}, + number = {7}, + urldate = {2024-03-29}, + journal = {Geophysical Research Letters}, + author = {Hsu, Juno and Prather, Michael J.}, + month = apr, + year = {2010}, + pages = {2009GL042243}, +} + +@article{tang_evaluation_2021, + title = {Evaluation of the interactive stratospheric ozone ({O3v2}) module in the {E3SM} version 1 {Earth} system model}, + volume = {14}, + issn = {1991-9603}, + url = {https://gmd.copernicus.org/articles/14/1219/2021/}, + doi = {10.5194/gmd-14-1219-2021}, + language = {en}, + number = {3}, + urldate = {2024-03-29}, + journal = {Geoscientific Model Development}, + author = {Tang, Qi and Prather, Michael J. and Hsu, Juno and Ruiz, Daniel J. and Cameron-Smith, Philip J. and Xie, Shaocheng and Golaz, Jean-Christophe}, + month = mar, + year = {2021}, + pages = {1219--1236}, +} + +@article{zhang_understanding_2024, + title = {Understanding changes in cloud simulations from {E3SM} version 1 to version 2}, + volume = {17}, + issn = {1991-9603}, + url = {https://gmd.copernicus.org/articles/17/169/2024/}, + doi = {10.5194/gmd-17-169-2024}, + language = {en}, + number = {1}, + urldate = {2024-03-29}, + journal = {Geoscientific Model Development}, + author = {Zhang, Yuying and Xie, Shaocheng and Qin, Yi and Lin, Wuyin and Golaz, Jean-Christophe and Zheng, Xue and Ma, Po-Lun and Qian, Yun and Tang, Qi and Terai, Christopher R. and Zhang, Meng}, + month = jan, + year = {2024}, + pages = {169--189}, +} + +@article{zhang_evaluation_2019, + title = {Evaluation of {Clouds} in {Version} 1 of the {E3SM} {Atmosphere} {Model} {With} {Satellite} {Simulators}}, + volume = {11}, + issn = {1942-2466, 1942-2466}, + url = {https://agupubs.onlinelibrary.wiley.com/doi/10.1029/2018MS001562}, + doi = {10.1029/2018MS001562}, + language = {en}, + number = {5}, + urldate = {2024-03-29}, + journal = {Journal of Advances in Modeling Earth Systems}, + author = {Zhang, Yuying and Xie, Shaocheng and Lin, Wuyin and Klein, Stephen A. and Zelinka, Mark and Ma, Po‐Lun and Rasch, Philip J. and Qian, Yun and Tang, Qi and Ma, Hsi‐Yen}, + month = may, + year = {2019}, + pages = {1253--1268}, +} + +@article{swales_cloud_2018, + title = {The {Cloud} {Feedback} {Model} {Intercomparison} {Project} {Observational} {Simulator} {Package}: {Version} 2}, + volume = {11}, + issn = {1991-9603}, + shorttitle = {The {Cloud} {Feedback} {Model} {Intercomparison} {Project} {Observational} {Simulator} {Package}}, + url = {https://gmd.copernicus.org/articles/11/77/2018/}, + doi = {10.5194/gmd-11-77-2018}, + language = {en}, + number = {1}, + urldate = {2024-03-29}, + journal = {Geoscientific Model Development}, + author = {Swales, Dustin J. and Pincus, Robert and Bodas-Salcedo, Alejandro}, + month = jan, + year = {2018}, + pages = {77--81}, +} + +@article{bodas-salcedo_cosp_2011, + title = {{COSP}: {Satellite} simulation software for model assessment}, + volume = {92}, + issn = {0003-0007, 1520-0477}, + shorttitle = {{COSP}}, + url = {https://journals.ametsoc.org/doi/10.1175/2011BAMS2856.1}, + doi = {10.1175/2011BAMS2856.1}, + language = {en}, + number = {8}, + urldate = {2024-03-29}, + journal = {Bulletin of the American Meteorological Society}, + author = {Bodas-Salcedo, A. and Webb, M. J. and Bony, S. and Chepfer, H. and Dufresne, J.-L. and Klein, S. A. and Zhang, Y. and Marchand, R. and Haynes, J. M. and Pincus, R. and John, V. O.}, + month = aug, + year = {2011}, + pages = {1023--1043}, +} + +@article{zhang_arm_2020, + title = {The {ARM} {Data}-{Oriented} {Metrics} and {Diagnostics} {Package} for {Climate} {Models}: {A} {New} {Tool} for {Evaluating} {Climate} {Models} with {Field} {Data}}, + volume = {101}, + issn = {0003-0007, 1520-0477}, + shorttitle = {The {ARM} {Data}-{Oriented} {Metrics} and {Diagnostics} {Package} for {Climate} {Models}}, + url = {https://journals.ametsoc.org/view/journals/bams/101/10/bamsD190282.xml}, + doi = {10.1175/BAMS-D-19-0282.1}, + language = {EN}, + number = {10}, + urldate = {2024-03-29}, + journal = {Bulletin of the American Meteorological Society}, + author = {Zhang, C. and Xie, S. and Tao, C. and Tang, S. and Emmenegger, T. and Neelin, J. D. and Schiro, K. A. and Lin, W. and Shaheen, Z.}, + month = oct, + year = {2020}, + pages = {E1619--E1627}, +} + +@article{zheng_assessment_2023, + title = {Assessment of {CMIP5} and {CMIP6} {AMIP} {Simulated} {Clouds} and {Surface} {Shortwave} {Radiation} {Using} {ARM} {Observations} over {Different} {Climate} {Regions}}, + volume = {36}, + issn = {0894-8755, 1520-0442}, + url = {https://journals.ametsoc.org/view/journals/clim/36/24/JCLI-D-23-0247.1.xml}, + doi = {10.1175/JCLI-D-23-0247.1}, + language = {EN}, + number = {24}, + urldate = {2024-03-29}, + journal = {Journal of Climate}, + author = {Zheng, Xiaojian and Tao, Cheng and Zhang, Chengzhu and Xie, Shaocheng and Zhang, Yuying and Xi, Baike and Dong, Xiquan}, + month = nov, + year = {2023}, + pages = {8475--8495}, +} + +@article{zhang_causes_2018, + title = {{CAUSES}: {Diagnosis} of the {Summertime} {Warm} {Bias} in {CMIP5} {Climate} {Models} at the {ARM} {Southern} {Great} {Plains} {Site}}, + volume = {123}, + issn = {2169-897X, 2169-8996}, + shorttitle = {{CAUSES}}, + url = {https://agupubs.onlinelibrary.wiley.com/doi/10.1002/2017JD027200}, + doi = {10.1002/2017JD027200}, + language = {en}, + number = {6}, + urldate = {2024-03-29}, + journal = {Journal of Geophysical Research: Atmospheres}, + author = {Zhang, Chengzhu and Xie, Shaocheng and Klein, Stephen A. and Ma, Hsi‐yen and Tang, Shuaiqi and Van Weverberg, Kwinten and Morcrette, Cyril J. and Petch, Jon}, + month = mar, + year = {2018}, + pages = {2968--2992}, +} + +@article{emmenegger_evaluating_2022, + title = {Evaluating {Tropical} {Precipitation} {Relations} in {CMIP6} {Models} with {ARM} {Data}}, + volume = {35}, + issn = {0894-8755, 1520-0442}, + url = {https://journals.ametsoc.org/view/journals/clim/35/19/JCLI-D-21-0386.1.xml}, + doi = {10.1175/JCLI-D-21-0386.1}, + number = {19}, + urldate = {2024-03-29}, + journal = {Journal of Climate}, + author = {Emmenegger, Todd and Kuo, Yi-Hung and Xie, Shaocheng and Zhang, Chengzhu and Tao, Cheng and Neelin, J. David}, + month = oct, + year = {2022}, + pages = {6343--6360}, +} + +@article{zhang_e3sm_2022, + title = {The {E3SM} {Diagnostics} {Package} ({E3SM} {Diags} v2.7): a {Python}-based diagnostics package for {Earth} system model evaluation}, + volume = {15}, + issn = {1991-9603}, + shorttitle = {The {E3SM} {Diagnostics} {Package} ({E3SM} {Diags} v2.7)}, + url = {https://gmd.copernicus.org/articles/15/9031/2022/}, + doi = {10.5194/gmd-15-9031-2022}, + language = {en}, + number = {24}, + urldate = {2024-03-29}, + journal = {Geoscientific Model Development}, + author = {Zhang, Chengzhu and Golaz, Jean-Christophe and Forsyth, Ryan and Vo, Tom and Xie, Shaocheng and Shaheen, Zeshawn and Potter, Gerald L. and Asay-Davis, Xylar S. and Zender, Charles S. and Lin, Wuyin and Chen, Chih-Chieh and Terai, Chris R. and Mahajan, Salil and Zhou, Tian and Balaguru, Karthik and Tang, Qi and Tao, Cheng and Zhang, Yuying and Emmenegger, Todd and Burrows, Susannah and Ullrich, Paul A.}, + month = dec, + year = {2022}, + pages = {9031--9056}, +} + + +@article{taylor_energy_2020, + title = {An {Energy} {Consistent} {Discretization} of the {Nonhydrostatic} {Equations} in {Primitive} {Variables}}, + volume = {12}, + issn = {1942-2466, 1942-2466}, + url = {https://agupubs.onlinelibrary.wiley.com/doi/10.1029/2019MS001783}, + doi = {10.1029/2019MS001783}, + language = {en}, + number = {1}, + urldate = {2024-03-29}, + journal = {Journal of Advances in Modeling Earth Systems}, + author = {Taylor, Mark A. and Guba, Oksana and Steyer, Andrew and Ullrich, Paul A. and Hall, David M. and Eldred, Christopher}, + month = jan, + year = {2020}, + pages = {e2019MS001783}, +} + +@article{bradley_islet_2022, + title = {Islet: interpolation semi-{Lagrangian} element-based transport}, + volume = {15}, + issn = {1991-9603}, + shorttitle = {Islet}, + url = {https://gmd.copernicus.org/articles/15/6285/2022/}, + doi = {10.5194/gmd-15-6285-2022}, + language = {en}, + number = {16}, + urldate = {2024-03-29}, + journal = {Geoscientific Model Development}, + author = {Bradley, Andrew M. and Bosler, Peter A. and Guba, Oksana}, + month = aug, + year = {2022}, + pages = {6285--6310}, +} + +@techreport{guba_spectral_2014, + type = {preprint}, + title = {The spectral element method on variable resolution grids: evaluating grid sensitivity and resolution-aware numerical viscosity}, + shorttitle = {The spectral element method on variable resolution grids}, + url = {https://gmd.copernicus.org/preprints/7/4081/2014/gmdd-7-4081-2014.pdf}, + urldate = {2024-03-29}, + institution = {Numerical Methods}, + author = {Guba, O. and Taylor, M. A. and Ullrich, P. A. and Overfelt, J. R. and Levy, M. N.}, + month = jun, + year = {2014}, + doi = {10.5194/gmdd-7-4081-2014}, +} + +@article{taylor_compatible_2010, + title = {A compatible and conservative spectral element method on unstructured grids}, + volume = {229}, + issn = {00219991}, + url = {https://linkinghub.elsevier.com/retrieve/pii/S0021999110001841}, + doi = {10.1016/j.jcp.2010.04.008}, + language = {en}, + number = {17}, + urldate = {2024-03-29}, + journal = {Journal of Computational Physics}, + author = {Taylor, Mark A. and Fournier, Aimé}, + month = aug, + year = {2010}, + pages = {5879--5895}, +} + +@misc{elliott_macromolecule_2015, + title = {Macromolecule distributions input file for the {OCEANFILMS} parameterization}, + copyright = {Creative Commons Attribution 4.0 International, Open Access}, + url = {https://zenodo.org/record/6320812}, + doi = {10.5281/ZENODO.6320812}, + urldate = {2024-03-29}, + publisher = {[object Object]}, + author = {Elliott, Scott M. and Maltrud, Mathew and Burrows, Susannah M.}, + month = nov, + year = {2015}, + keywords = {Sea spray organic matter, Emissions parameterization}, +} + +@article{wang_influence_2015, + title = {Influence of explicit \textit{{Phaeocystis}} parameterizations on the global distribution of marine dimethyl sulfide}, + volume = {120}, + issn = {2169-8953, 2169-8961}, + url = {https://agupubs.onlinelibrary.wiley.com/doi/10.1002/2015JG003017}, + doi = {10.1002/2015JG003017}, + language = {en}, + number = {11}, + urldate = {2024-03-29}, + journal = {Journal of Geophysical Research: Biogeosciences}, + author = {Wang, Shanlin and Elliott, Scott and Maltrud, Mathew and Cameron‐Smith, Philip}, + month = nov, + year = {2015}, + pages = {2158--2177}, +} + +@article{burrows_physically_2014, + title = {A physically based framework for modeling the organic fractionation of sea spray aerosol from bubble film {Langmuir} equilibria}, + volume = {14}, + issn = {1680-7316}, + url = {https://acp.copernicus.org/articles/14/13601/2014/}, + doi = {10.5194/acp-14-13601-2014}, + language = {English}, + number = {24}, + urldate = {2024-03-29}, + journal = {Atmospheric Chemistry and Physics}, + author = {Burrows, S. M. and Ogunro, O. and Frossard, A. A. and Russell, L. M. and Rasch, P. J. and Elliott, S. M.}, + month = dec, + year = {2014}, + pages = {13601--13629}, +} + +@article{burrows_oceanfilms_2022, + title = {{OCEANFILMS} ({Organic} {Compounds} from {Ecosystems} to {Aerosols}: {Natural} {Films} and {Interfaces} via {Langmuir} {Molecular} {Surfactants}) sea spray organic aerosol emissions – implementation in a global climate model and impacts on clouds}, + volume = {22}, + issn = {1680-7316}, + shorttitle = {{OCEANFILMS} ({Organic} {Compounds} from {Ecosystems} to {Aerosols}}, + url = {https://acp.copernicus.org/articles/22/5223/2022/}, + doi = {10.5194/acp-22-5223-2022}, + language = {English}, + number = {8}, + urldate = {2024-03-29}, + journal = {Atmospheric Chemistry and Physics}, + author = {Burrows, Susannah M. and Easter, Richard C. and Liu, Xiaohong and Ma, Po-Lun and Wang, Hailong and Elliott, Scott M. and Singh, Balwinder and Zhang, Kai and Rasch, Philip J.}, + month = apr, + year = {2022}, + pages = {5223--5251}, +} + +@article{maltrud_global_1998, + title = {Global eddy‐resolving ocean simulations driven by 1985–1995 atmospheric winds}, + volume = {103}, + issn = {0148-0227}, + url = {https://agupubs.onlinelibrary.wiley.com/doi/10.1029/1998JC900013}, + doi = {10.1029/1998JC900013}, + language = {en}, + number = {C13}, + urldate = {2024-03-29}, + journal = {Journal of Geophysical Research: Oceans}, + author = {Maltrud, Mathew E. and Smith, Richard D. and Semtner, Albert J. and Malone, Robert C.}, + month = dec, + year = {1998}, + pages = {30825--30853}, +} + +@article{moore_upper_2004, + title = {Upper ocean ecosystem dynamics and iron cycling in a global three‐dimensional model}, + volume = {18}, + issn = {0886-6236, 1944-9224}, + url = {https://agupubs.onlinelibrary.wiley.com/doi/10.1029/2004GB002220}, + doi = {10.1029/2004GB002220}, + language = {en}, + number = {4}, + urldate = {2024-03-29}, + journal = {Global Biogeochemical Cycles}, + author = {Moore, J. Keith and Doney, Scott C. and Lindsay, Keith}, + month = dec, + year = {2004}, + pages = {2004GB002220}, +} + +@article{liu_toward_2012, + title = {Toward a minimal representation of aerosols in climate models: description and evaluation in the {Community} {Atmosphere} {Model} {CAM5}}, + volume = {5}, + issn = {1991-9603}, + shorttitle = {Toward a minimal representation of aerosols in climate models}, + url = {https://gmd.copernicus.org/articles/5/709/2012/}, + doi = {10.5194/gmd-5-709-2012}, + language = {en}, + number = {3}, + urldate = {2024-03-29}, + journal = {Geoscientific Model Development}, + author = {Liu, X. and Easter, R. C. and Ghan, S. J. and Zaveri, R. and Rasch, P. and Shi, X. and Lamarque, J.-F. and Gettelman, A. and Morrison, H. and Vitt, F. and Conley, A. and Park, S. and Neale, R. and Hannay, C. and Ekman, A. M. L. and Hess, P. and Mahowald, N. and Collins, W. and Iacono, M. J. and Bretherton, C. S. and Flanner, M. G. and Mitchell, D.}, + month = may, + year = {2012}, + pages = {709--739}, +} + +@article{wang_aerosols_2020, + title = {Aerosols in the {E3SM} {Version} 1: {New} {Developments} and {Their} {Impacts} on {Radiative} {Forcing}}, + volume = {12}, + issn = {1942-2466, 1942-2466}, + shorttitle = {Aerosols in the {E3SM} {Version} 1}, + url = {https://agupubs.onlinelibrary.wiley.com/doi/10.1029/2019MS001851}, + doi = {10.1029/2019MS001851}, + language = {en}, + number = {1}, + urldate = {2024-03-29}, + journal = {Journal of Advances in Modeling Earth Systems}, + author = {Wang, Hailong and Easter, Richard C. and Zhang, Rudong and Ma, Po‐Lun and Singh, Balwinder and Zhang, Kai and Ganguly, Dilip and Rasch, Philip J. and Burrows, Susannah M. and Ghan, Steven J. and Lou, Sijia and Qian, Yun and Yang, Yang and Feng, Yan and Flanner, Mark and Leung, L. Ruby and Liu, Xiaohong and Shrivastava, Manish and Sun, Jian and Tang, Qi and Xie, Shaocheng and Yoon, Jin‐Ho}, + month = jan, + year = {2020}, + pages = {e2019MS001851}, +} + +@article{feng_global_2022, + title = {Global {Dust} {Cycle} and {Direct} {Radiative} {Effect} in {E3SM} {Version} 1: {Impact} of {Increasing} {Model} {Resolution}}, + volume = {14}, + issn = {1942-2466, 1942-2466}, + shorttitle = {Global {Dust} {Cycle} and {Direct} {Radiative} {Effect} in {E3SM} {Version} 1}, + url = {https://agupubs.onlinelibrary.wiley.com/doi/10.1029/2021MS002909}, + doi = {10.1029/2021MS002909}, + language = {en}, + number = {7}, + urldate = {2024-03-29}, + journal = {Journal of Advances in Modeling Earth Systems}, + author = {Feng, Y. and Wang, H. and Rasch, P. J. and Zhang, K. and Lin, W. and Tang, Q. and Xie, S. and Hamilton, D. S. and Mahowald, N. and Yu, H.}, + month = jul, + year = {2022}, + pages = {e2021MS002909}, +} + +@article{dentener_emissions_2006, + title = {Emissions of primary aerosol and precursor gases in the years 2000 and 1750 prescribed data-sets for {AeroCom}}, + volume = {6}, + issn = {1680-7316}, + url = {https://acp.copernicus.org/articles/6/4321/2006/acp-6-4321-2006.html}, + doi = {10.5194/acp-6-4321-2006}, + language = {English}, + number = {12}, + urldate = {2024-04-24}, + journal = {Atmospheric Chemistry and Physics}, + author = {Dentener, F. and Kinne, S. and Bond, T. and Boucher, O. and Cofala, J. and Generoso, S. and Ginoux, P. and Gong, S. and Hoelzemann, J. J. and Ito, A. and Marelli, L. and Penner, J. E. and Putaud, J.-P. and Textor, C. and Schulz, M. and van der Werf, G. R. and Wilson, J.}, + year = {2006}, + pages = {4321--4344}, +} + +@article{visioni_limitations_2022, + title = {Limitations of assuming internal mixing between different aerosol species: a case study with sulfate geoengineering simulations}, + volume = {22}, + issn = {1680-7316}, + shorttitle = {Limitations of assuming internal mixing between different aerosol species}, + url = {https://acp.copernicus.org/articles/22/1739/2022/}, + doi = {10.5194/acp-22-1739-2022}, + language = {English}, + number = {3}, + urldate = {2024-04-25}, + journal = {Atmospheric Chemistry and Physics}, + author = {Visioni, Daniele and Tilmes, Simone and Bardeen, Charles and Mills, Michael and MacMartin, Douglas G. and Kravitz, Ben and Richter, Jadwiga H.}, + month = feb, + year = {2022}, + pages = {1739--1756}, +} + +@misc{neely_iii_volcaneesm_2016, + title = {{VolcanEESM}: {Global} volcanic sulphur dioxide ({SO2}) emissions database from 1850 to present - {Version} 1.0}, + shorttitle = {{VolcanEESM}}, + url = {https://catalogue.ceda.ac.uk/uuid/a8a7e52b299a46c9b09d8e56b283d385}, + doi = {10.5285/76EBDC0B-0EED-4F70-B89E-55E606BCD568}, + language = {en}, + urldate = {2024-04-25}, + publisher = {[object Object]}, + author = {Neely III, R. R. and Schmidt, A.}, + year = {2016}, + keywords = {Atmospheric Sciences, FOS: Earth and related environmental sciences}, +} + +@article{mills_global_2016, + title = {Global volcanic aerosol properties derived from emissions, 1990–2014, using {CESM1}({WACCM})}, + volume = {121}, + copyright = {http://onlinelibrary.wiley.com/termsAndConditions\#am}, + issn = {2169-897X, 2169-8996}, + url = {https://agupubs.onlinelibrary.wiley.com/doi/10.1002/2015JD024290}, + doi = {10.1002/2015JD024290}, + language = {en}, + number = {5}, + urldate = {2024-04-25}, + journal = {Journal of Geophysical Research: Atmospheres}, + author = {Mills, Michael J. and Schmidt, Anja and Easter, Richard and Solomon, Susan and Kinnison, Douglas E. and Ghan, Steven J. and Neely, Ryan R. and Marsh, Daniel R. and Conley, Andrew and Bardeen, Charles G. and Gettelman, Andrew}, + month = mar, + year = {2016}, + pages = {2332--2348}, +} + + +@article{rinaldi_is_2013, + title = {Is chlorophyll‐ \textit{a} the best surrogate for organic matter enrichment in submicron primary marine aerosol?}, + volume = {118}, + copyright = {http://onlinelibrary.wiley.com/termsAndConditions\#vor}, + issn = {2169-897X, 2169-8996}, + url = {https://agupubs.onlinelibrary.wiley.com/doi/10.1002/jgrd.50417}, + doi = {10.1002/jgrd.50417}, + language = {en}, + number = {10}, + urldate = {2024-04-25}, + journal = {Journal of Geophysical Research: Atmospheres}, + author = {Rinaldi, Matteo and Fuzzi, Sandro and Decesari, Stefano and Marullo, Salvatore and Santoleri, Rosalia and Provenzale, Antonello and Von Hardenberg, Jost and Ceburnis, Darius and Vaishya, Aditya and O'Dowd, Colin D. and Facchini, Maria Cristina}, + month = may, + year = {2013}, + pages = {4964--4973}, +} + +@article{gantt_wind_2011, + title = {Wind speed dependent size-resolved parameterization for the organic mass fraction of sea spray aerosol}, + volume = {11}, + issn = {1680-7316}, + url = {https://acp.copernicus.org/articles/11/8777/2011/acp-11-8777-2011.html}, + doi = {10.5194/acp-11-8777-2011}, + language = {English}, + number = {16}, + urldate = {2024-04-25}, + journal = {Atmospheric Chemistry and Physics}, + author = {Gantt, B. and Meskhidze, N. and Facchini, M. C. and Rinaldi, M. and Ceburnis, D. and O'Dowd, C. D.}, + month = aug, + year = {2011}, + pages = {8777--8790}, +} + +@article{quinn_contribution_2014, + title = {Contribution of sea surface carbon pool to organic matter enrichment in sea spray aerosol}, + volume = {7}, + copyright = {2014 Springer Nature Limited}, + issn = {1752-0908}, + url = {https://www.nature.com/articles/ngeo2092}, + doi = {10.1038/ngeo2092}, + language = {en}, + number = {3}, + urldate = {2024-04-25}, + journal = {Nature Geoscience}, + author = {Quinn, Patricia K. and Bates, Timothy S. and Schulz, Kristen S. and Coffman, D. J. and Frossard, A. A. and Russell, L. M. and Keene, W. C. and Kieber, D. J.}, + month = mar, + year = {2014}, + keywords = {Atmospheric chemistry, Marine biology, Marine chemistry}, + pages = {228--232}, +} + +@article{neale_description_2012, + title = {Description of the {NCAR} {Community} {Atmosphere} {Model} ({CAM} 5.0)}, + url = {https://opensky.ucar.edu/islandora/object/technotes%3A594/}, + doi = {10.5065/wgtk-4g06}, + language = {en}, + urldate = {2024-04-25}, + author = {Neale, Richard B. and Gettelman, Andrew and Park, Sungsu and Chen, Chih-Chieh and Lauritzen, Peter H. and Williamson, David L. and Conley, Andrew J. and Kinnison, Doug and Marsh, Dan and Smith, Anne K. and Vitt, Francis M. and Garcia, Rolando and Lamarque, Jean-Francois and Mills, Michael J. and Tilmes, Simone and Morrison, Hugh and Cameron-Smith, Philip and Collins, William D. and Iacono, Michael J. and Easter, Richard C. and Liu, Xiaohong and Ghan, Steven J. and Rasch, Philip J. and Taylor, Mark A.}, + journal = {UNKNOWN}, + year = {2012}, +} diff --git a/components/elm/docs/refs.bib b/docs/refs/elm.bib similarity index 100% rename from components/elm/docs/refs.bib rename to docs/refs/elm.bib diff --git a/docs/user-guide/index.md b/docs/user-guide/index.md new file mode 100644 index 00000000000..c2daf519a42 --- /dev/null +++ b/docs/user-guide/index.md @@ -0,0 +1,69 @@ +# User Guide + +E3SM is not just one climate model but a modeling system that allows +many different configurations of atmosphere, ocean, land and other +components with both full model and data model options. Also, the configurations of model +components can run at different resolutions. Some configurations +can run easily on a laptop. Other's require the most powerful +supercomputers. + +Using the model requires first deciding what configuration to use and creating +a case with that configuration. +The configuration options are managed by the Case Control System (CCS) +within the +[Community Infrastructure for Modeling the Earth](https://esmci.github.io/cime/versions/master/html/what_cime/index.html) (CIME). + +Before reading the rest of this guide, you should become familiar with +cases, compsets and grids by reading the +[Case Control System Basic Usage](https://esmci.github.io/cime/versions/master/html/users_guide/index.html#case-control-system-part-1-basic-usage) + +A [step-by-step guide](https://docs.e3sm.org/running-e3sm-guide/) for running E3SM with a run script +is available. + +## Supported Coupled Compsets + +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. +Below list the standard configuration compsets supported in the current version of E3SM: + +|Compset alias | Description | +|:----------- |:----------- | +|`WCYCL1850` | Standard configuration with pre-industrial climatological forcings | +|`WCYCL1850-4xCO2` | Same as `WCYCL1850` except with abrupt (then persistent) 4xCO2 forcing. | +|`WCYCL1850-1pctCO2` | Same as `WCYCL1850` except with 1 percent per year increase of CO2 concentration | +|`WCYCL1950` | Standard configuration with perpetual 1950 forcings | +|`WCYCL20TR` | Standard configuration with prescribed transient forcings over the historical period (1850-2014) | +|`WCYCLSSP245` | Standard configuration with prescribed SSP-245 forcings | +|`WCYCLSSP370` | Standard configuration with prescribed SSP-370 forcings | +|`WCYCLSSP585` | Standard configuration with prescribed SSP-585 forcings | + +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. + +Compsets are also available for standalone component model configurations, See the User Guides for the components for more information. + +## Supported resolution + +Currently two grid sets are supported for the above compsets, including a nominal low-resosluton confiuguration and one regionally refined mesh. Additional regionally refined meshes and a high-resolution grid will become available in the near future. + +| Grid Alias | Description | +| ----------- | ------------ | +|ne30pg2_r05_IcoswISC30E3r5 | For this grid set, the atmosphere is on the ne30pg2 cubed-sphere mesh with approximately 100km resolution, the land and river are on a 0.5deg x 0.5deg structured grid, and the ocean and sea ice are on a hexagonal mesh dervied from the dual of a 30km resolution icosahedral mesh with ice shelf cavities (wISC) around Antarctica.| +|northamericax4v1pg2_r025_IcoswISC30E3r5 | The atmosphere for this grid set uses North America regionally refined mesh from about 110 km down to 25 km over the refined region. The land and river are on 0.25deg x 0.25deg structured grid. The ocean and sea ice are on the same icosahedral mesh as for `ne30pg2_r05_IcoswISC30E3r5`.| + +## Input data + +Inputdata for coupled compsets at component model levels are the same as for the standalone component configurations +for a given forcing scenario (e.g., `1850` for the pre-industrial period, `20TR` for the historical period, `2010` +for present-day condition, and `SSPs` for Shared Socioeconomic Pathways of climate change scenarios). +Between the coupled compsets, the differences are in the prescribed solar forcing, volcanic emissions, +atmospheric forcing data, and land use and land cover. The required inputdata for the pre-industrial and the historical periods +as well as the present-day condition are described in [the EAM User's Guide](https://e3sm-project.github.io/E3SM/EAM) and +[the ELM's User's Guide](https://e3sm-project.github.io/E3SM/ELM). Below are the prescribed forcing data for the SSP scenarios. + +### [SSP245 forcing data](ssp245-forcings.md) + +### [SSP370 forcing data](ssp370-forcings.md) + +### [SSP585 forcing data](ssp585-forcings.md) diff --git a/docs/user-guide/ssp245-forcings.md b/docs/user-guide/ssp245-forcings.md new file mode 100644 index 00000000000..d4cbded160e --- /dev/null +++ b/docs/user-guide/ssp245-forcings.md @@ -0,0 +1,68 @@ +# SSP245 Forcing data + +These are the prescribed inputdata specifically for the SSP245 scenario, in place of the files for the historical period. + +## Solar constant + +`\$DIN_LOC_ROOT/atm/cam/solar/Solar_1850-2299_input4MIPS_c20181106.nc` + +## Greenhouse gas concentrations + +`\$DIN_LOC_ROOT/atm/cam/ggas/GHG_CMIP_SSP245-1-2-1_Annual_Global_2015-2500_c20200807.nc` + +## Elevated external forcings + +```fortran +NO2 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/emissions-cmip6_ssp245_e3sm_NO2_aircraft_vertical_2015-2100_1.9x2.5_c20240219.nc +SO2 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_so2_volc_elev_2015-2100_c240331.nc +SOAG0 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/emissions-cmip6_ssp245_e3sm_SOAG0_elev_2015-2100_1.9x2.5_c20240219.nc +bc_a4 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_bc_a4_elev_2015-2100_c200716.nc +num_a1 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_num_a1_elev_2015-2100_c200716.nc +num_a2 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_num_a2_elev_2015-2100_c200716.nc +num_a4 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_num_a4_elev_2015-2100_c200716.nc +pom_a4 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_pom_a4_elev_2015-2100_c200716.nc +so4_a1 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_so4_a1_elev_2015-2100_c200716.nc +so4_a2 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_so4_a2_elev_2015-2100_c200716.nc +``` + +## Surface emissions + +```fortran +C2H4 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/emissions-cmip6_ssp245_e3sm_C2H4_surface_2015-2100_1.9x2.5_c20240219.nc +C2H6 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/emissions-cmip6_ssp245_e3sm_C2H6_surface_2015-2100_1.9x2.5_c20240219.nc +C3H8 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/emissions-cmip6_ssp245_e3sm_C3H8_surface_2015-2100_1.9x2.5_c20240219.nc +CH2O \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/emissions-cmip6_ssp245_e3sm_CH2O_surface_2015-2100_1.9x2.5_c20240219.nc +CH3CHO \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/emissions-cmip6_ssp245_e3sm_CH3CHO_surface_2015-2100_1.9x2.5_c20240219.nc +CH3COCH3 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/emissions-cmip6_ssp245_e3sm_CH3COCH3_surface_2015-2100_1.9x2.5_c20240219.nc +CO \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/emissions-cmip6_ssp245_e3sm_CO_surface_2015-2100_1.9x2.5_c20240219.nc +ISOP \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/emissions-cmip6_ssp245_e3sm_ISOP_surface_2015-2100_1.9x2.5_c20240219.nc +ISOP_VBS \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/emissions-cmip6_ssp245_e3sm_ISOP_surface_2015-2100_1.9x2.5_c20240219.nc +C10H16 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/emissions-cmip6_ssp245_e3sm_MTERP_surface_2015-2100_1.9x2.5_c20240219.nc +NOX \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/emissions-cmip6_ssp245_e3sm_NO_surface_2015-2100_1.9x2.5_c20240219.nc +DMS \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DMSflux.1850-2100.1deg_latlon_conserv.POPmonthlyClimFromACES4BGC_c20160727.nc +SO2 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_so2_surf_2015-2100_c200716.nc +SOAG0 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/emissions-cmip6_ssp245_e3sm_SOAG0_surf_2015-2100_1.9x2.5_c20240219.nc +bc_a4 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_bc_a4_surf_2015-2100_c200716.nc +num_a1 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_num_a1_surf_2015-2100_c200716.nc +num_a2 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_num_a2_surf_2015-2100_c200716.nc +num_a4 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_num_a4_surf_2015-2100_c200716.nc +pom_a4 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_pom_a4_surf_2015-2100_c200716.nc +so4_a1 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_so4_a1_surf_2015-2100_c200716.nc +so4_a2 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP245_ne30/cmip6_ssp245_mam4_so4_a2_surf_2015-2100_c200716.nc +E90 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart/ub/emissions_E90_surface_1750-2101_1.9x2.5_c20231222.nc +``` + +## Prescribed oxidant for aerosol chemistry + +`$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/oxid/oxid_SSP245_1.9x2.5_L70_1849-2101_c20240228.nc` + +## Stratospheric ozone (linoz) and chlorine loading data + +```fortran +\$DIN_LOC_ROOT/atm/cam/chem/trop_mozart/ub/Linoz_Chlorine_Loading_CMIP6_Hist_SSP245_0003-2503_c20200808.nc +\$DIN_LOC_ROOT/atm/cam/chem/trop_mozart/ub/linv3_1849-2101_CMIP6_Hist_SSP245_10deg_58km_c20230705.nc +``` + +## Land use and land cover + +`\$DIN_LOC_ROOT/lnd/clm2/surfdata_map/landuse.timeseries_0.5x0.5_ssp2_rcp45_simyr2015-2100_c240408.nc` diff --git a/docs/user-guide/ssp370-forcings.md b/docs/user-guide/ssp370-forcings.md new file mode 100644 index 00000000000..29477a5d179 --- /dev/null +++ b/docs/user-guide/ssp370-forcings.md @@ -0,0 +1,68 @@ +# SSP370 Forcing data + +These are the prescribed inputdata specifically for the SSP370 scenario, in place of the files for the historical period. + +## Solar constant + +`\$DIN_LOC_ROOT/atm/cam/solar/Solar_1850-2299_input4MIPS_c20181106.nc` + +## Greenhouse gas concentrations + +`\$DIN_LOC_ROOT/atm/cam/ggas/GHG_CMIP_SSP370-1-2-1_Annual_Global_2015-2500_c20210509.nc` + +## Elevated external forcings + +```fortran +NO2 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_NO2_aircraft_vertical_2015-2100_1.9x2.5_c20240208.nc +SO2 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_so2_volc_elev_2015-2100_c240331.nc +SOAG0 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_SOAG0_elev_2015-2100_1.9x2.5_c20240208.nc +bc_a4 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_bc_a4_elev_2015-2100_c210216.nc +num_a1 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_num_a1_elev_2015-2100_c210216.nc +num_a2 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_num_a2_elev_2015-2100_c210216.nc +num_a4 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_num_a4_elev_2015-2100_c210216.nc +pom_a4 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_pom_a4_elev_2015-2100_c210216.nc +so4_a1 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_so4_a1_elev_2015-2100_c210216.nc +so4_a2 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_so4_a2_elev_2015-2100_c210216.nc +``` + +## Surface emissions + +```fortran +C2H4 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_C2H4_surface_2015-2100_1.9x2.5_c20240208.nc +C2H6 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_C2H6_surface_2015-2100_1.9x2.5_c20240208.nc +C3H8 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_C3H8_surface_2015-2100_1.9x2.5_c20240208.nc +CH2O \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_CH2O_surface_2015-2100_1.9x2.5_c20240208.nc +CH3CHO \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_CH3CHO_surface_2015-2100_1.9x2.5_c20240208.nc +CH3COCH3 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_CH3COCH3_surface_2015-2100_1.9x2.5_c20240208.nc +CO \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_CO_surface_2015-2100_1.9x2.5_c20240208.nc +ISOP \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_ISOP_surface_2015-2100_1.9x2.5_c20240208.nc +ISOP_VBS \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_ISOP_surface_2015-2100_1.9x2.5_c20240208.nc +C10H16 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_MTERP_surface_2015-2100_1.9x2.5_c20240208.nc +NOX \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_NO_surface_2015-2100_1.9x2.5_c20240208.nc +DMS \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DMSflux.1850-2100.1deg_latlon_conserv.POPmonthlyClimFromACES4BGC_c20160727.nc +SO2 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_so2_surf_2015-2100_c210216.nc +SOAG0 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/emissions-cmip6_ssp370_e3sm_SOAG0_surf_2015-2100_1.9x2.5_c20240208.nc +bc_a4 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_bc_a4_surf_2015-2100_c210216.nc +num_a1 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_num_a1_surf_2015-2100_c210216.nc +num_a2 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_num_a2_surf_2015-2100_c210216.nc +num_a4 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_num_a4_surf_2015-2100_c210216.nc +pom_a4 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_pom_a4_surf_2015-2100_c210216.nc +so4_a1 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_so4_a1_surf_2015-2100_c210216.nc +so4_a2 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP370_ne30/cmip6_ssp370_mam4_so4_a2_surf_2015-2100_c210216.nc +E90 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart/ub/emissions_E90_surface_1750-2101_1.9x2.5_c20231222.nc +``` + +## Prescribed oxidant for aerosol chemistry + +`\$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/oxid/oxid_SSP370_1.9x2.5_L70_1849-2101_c20240228.nc` + +## Stratospheric ozone (linoz) and chlorine loading data + +```fortran +\$DIN_LOC_ROOT/atm/cam/chem/trop_mozart/ub/Linoz_Chlorine_Loading_CMIP6_Hist_SSP370_0003-2503_c20210202.nc +\$DIN_LOC_ROOT/atm/cam/chem/trop_mozart/ub/linv3_1849-2101_CMIP6_Hist_SSP370_10deg_58km_c20230705.nc +``` + +## Land use and land cover + +`\$DIN_LOC_ROOT/lnd/clm2/surfdata_map/landuse.timeseries_0.5x0.5_ssp3_rcp70_simyr2015-2100_c240308.nc` diff --git a/docs/user-guide/ssp585-forcings.md b/docs/user-guide/ssp585-forcings.md new file mode 100644 index 00000000000..2c5b6ec2649 --- /dev/null +++ b/docs/user-guide/ssp585-forcings.md @@ -0,0 +1,68 @@ +# SSP585 Forcing data + +These are the prescribed inputdata specifically for the SSP585 scenario, in place of the files for the historical period. + +## Solar constant + +`\$DIN_LOC_ROOT/atm/cam/solar/Solar_1850-2299_input4MIPS_c20181106.nc` + +## Greenhouse gas concentrations + +`\$DIN_LOC_ROOT/atm/cam/ggas/GHG_CMIP_SSP585-1-2-1_Annual_Global_2015-2500_c20190310.nc` + +## Elevated external forcings + +```fortran +NO2 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/emissions-cmip6_ssp585_e3sm_NO2_aircraft_vertical_2015-2100_1.9x2.5_c20240304.nc +SO2 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/cmip6_ssp585_mam4_so2_volc_elev_2015-2100_c240331.nc +SOAG0 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/emissions-cmip6_ssp585_e3sm_SOAG0_elev_2015-2100_1.9x2.5_c20240304.nc +bc_a4 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/cmip6_ssp585_mam4_bc_a4_elev_2015-2100_c190828.nc +num_a1 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/cmip6_ssp585_mam4_num_a1_elev_2015-2100_c190828.nc +num_a2 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/cmip6_ssp585_mam4_num_a2_elev_2015-2100_c190828.nc +num_a4 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/cmip6_ssp585_mam4_num_a4_elev_2015-2100_c190828.nc +pom_a4 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/cmip6_ssp585_mam4_pom_a4_elev_2015-2100_c190828.nc +so4_a1 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/cmip6_ssp585_mam4_so4_a1_elev_2015-2100_c190828.nc +so4_a2 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/cmip6_ssp585_mam4_so4_a2_elev_2015-2100_c190828.nc +``` + +## Surface emissions + +```fortran +C2H4 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/emissions-cmip6_ssp585_e3sm_C2H4_surface_2015-2100_1.9x2.5_c20240304.nc +C2H6 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/emissions-cmip6_ssp585_e3sm_C2H6_surface_2015-2100_1.9x2.5_c20240304.nc +C3H8 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/emissions-cmip6_ssp585_e3sm_C3H8_surface_2015-2100_1.9x2.5_c20240304.nc +CH2O \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/emissions-cmip6_ssp585_e3sm_CH2O_surface_2015-2100_1.9x2.5_c20240304.nc +CH3CHO \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/emissions-cmip6_ssp585_e3sm_CH3CHO_surface_2015-2100_1.9x2.5_c20240304.nc +CH3COCH3 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/emissions-cmip6_ssp585_e3sm_CH3COCH3_surface_2015-2100_1.9x2.5_c20240304.nc +CO \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/emissions-cmip6_ssp585_e3sm_CO_surface_2015-2100_1.9x2.5_c20240304.nc +ISOP \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/emissions-cmip6_ssp585_e3sm_ISOP_surface_2015-2100_1.9x2.5_c20240304.nc +ISOP_VBS \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/emissions-cmip6_ssp585_e3sm_ISOP_surface_2015-2100_1.9x2.5_c20240304.nc +C10H16 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/emissions-cmip6_ssp585_e3sm_MTERP_surface_2015-2100_1.9x2.5_c20240304.nc +NOX \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/emissions-cmip6_ssp585_e3sm_NO_surface_2015-2100_1.9x2.5_c20240304.nc +DMS \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/DMSflux.1850-2100.1deg_latlon_conserv.POPmonthlyClimFromACES4BGC_c20160727.nc +SO2 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/cmip6_ssp585_mam4_so2_surf_2015-2100_c190828.nc +SOAG0 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/emissions-cmip6_ssp585_e3sm_SOAG0_surf_2015-2100_1.9x2.5_c20240304.nc +bc_a4 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/cmip6_ssp585_mam4_bc_a4_surf_2015-2100_c190828.nc +num_a1 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/cmip6_ssp585_mam4_num_a1_surf_2015-2100_c190828.nc +num_a2 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/cmip6_ssp585_mam4_num_a2_surf_2015-2100_c190828.nc +num_a3 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/cmip6_ssp585_mam4_num_a4_surf_2015-2100_c190828.nc +pom_a4 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/cmip6_ssp585_mam4_pom_a4_surf_2015-2100_c190828.nc +so4_a1 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/cmip6_ssp585_mam4_so4_a1_surf_2015-2100_c190828.nc +so4_a2 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/emis/CMIP6_SSP585_ne30/cmip6_ssp585_mam4_so4_a2_surf_2015-2100_c190828.nc +E90 \$DIN_LOC_ROOT/atm/cam/chem/trop_mozart/ub/emissions_E90_surface_1750-2101_1.9x2.5_c20231222.nc +``` + +## Prescribed oxidant for aerosol chemistry + +`\$DIN_LOC_ROOT/atm/cam/chem/trop_mozart_aero/oxid/oxid_SSP585_1.9x2.5_L70_2014-2101_c20240228.nc` + +## Stratospheric ozone (linoz) and chlorine loading data + +```fortran +\$DIN_LOC_ROOT/atm/cam/chem/trop_mozart/ub/Linoz_Chlorine_Loading_CMIP6_Hist_SSP585_0003-2503_c20190414.nc +\$DIN_LOC_ROOT/atm/cam/chem/trop_mozart/ub/linv3_1849-2101_CMIP6_Hist_SSP585_10deg_58km_c20230705.nc +``` + +## Land use and land cover + +`\$DIN_LOC_ROOT/lnd/clm2/surfdata_map/landuse.timeseries_0.5x0.5_ssp5_rcp85_simyr2015-2100_c240408.nc` diff --git a/driver-mct/cime_config/buildnml b/driver-mct/cime_config/buildnml index 426995b8ffb..4938e9da0b1 100755 --- a/driver-mct/cime_config/buildnml +++ b/driver-mct/cime_config/buildnml @@ -40,6 +40,7 @@ def _create_drv_namelists(case, infile, confdir, nmlgen, files): config['CPL_ALBAV'] = case.get_value('CPL_ALBAV') config['CPL_EPBAL'] = case.get_value('CPL_EPBAL') config['FLDS_WISO'] = case.get_value('FLDS_WISO') + config['FLDS_POLAR'] = case.get_value('FLDS_POLAR') config['BUDGETS'] = case.get_value('BUDGETS') config['MACH'] = case.get_value('MACH') config['MPILIB'] = case.get_value('MPILIB') diff --git a/driver-mct/cime_config/config_component.xml b/driver-mct/cime_config/config_component.xml index d037770ed5c..5b5126af893 100644 --- a/driver-mct/cime_config/config_component.xml +++ b/driver-mct/cime_config/config_component.xml @@ -1085,8 +1085,8 @@ char - gland20,gland10,gland5,gland5UM,gland4,mpas.aisgis20km,mpas.gis20km,mpas.ais20km,mpas.gis1to10km,null - gland5UM + mpas.aisgis20km,mpas.gis20km,mpas.ais20km,mpas.gis1to10km,mpas.gis1to10kmR2,null + mpas.gis20km build_grid env_build.xml glacier (glc) grid - DO NOT EDIT (for experts only) diff --git a/driver-mct/cime_config/config_component_e3sm.xml b/driver-mct/cime_config/config_component_e3sm.xml index 1690c26b94e..2895650d242 100755 --- a/driver-mct/cime_config/config_component_e3sm.xml +++ b/driver-mct/cime_config/config_component_e3sm.xml @@ -172,6 +172,19 @@ Turn on the passing of water isotope fields through the coupler + + logical + TRUE,FALSE + FALSE + + TRUE + TRUE + + run_flags + env_run.xml + Turn on the passing of polar fields through the coupler + + char minus1p8,linear_salt,mushy @@ -265,6 +278,7 @@ CO2A CO2A CO2A + CO2A CO2A_OI CO2A_OI CO2C diff --git a/driver-mct/cime_config/namelist_definition_drv.xml b/driver-mct/cime_config/namelist_definition_drv.xml index 038444efa94..7fbf83688c8 100644 --- a/driver-mct/cime_config/namelist_definition_drv.xml +++ b/driver-mct/cime_config/namelist_definition_drv.xml @@ -137,6 +137,18 @@ + + logical + seq_flds + seq_cplflds_inparm + + If set to .true. Polar fields will be passed from the ocean to the coupler. + + + $FLDS_POLAR + + + logical seq_flds diff --git a/driver-mct/main/seq_diag_mct.F90 b/driver-mct/main/seq_diag_mct.F90 index 2a7d999ccc5..8534008f9be 100644 --- a/driver-mct/main/seq_diag_mct.F90 +++ b/driver-mct/main/seq_diag_mct.F90 @@ -138,13 +138,13 @@ module seq_diag_mct integer(in),parameter :: f_hlatf = 8 ! heat : latent, fusion, snow integer(in),parameter :: f_hioff = 9 ! heat : latent, fusion, frozen runoff integer(in),parameter :: f_hsen =10 ! heat : sensible - integer(in),parameter :: f_hberg =11 ! heat : data icebergs + integer(in),parameter :: f_hpolar =11 ! heat : AIS imbalance integer(in),parameter :: f_hh2ot =12 ! heat : water temperature integer(in),parameter :: f_wfrz =13 ! water: freezing integer(in),parameter :: f_wmelt =14 ! water: melting integer(in),parameter :: f_wrain =15 ! water: precip, liquid integer(in),parameter :: f_wsnow =16 ! water: precip, frozen - integer(in),parameter :: f_wberg =17 ! water: data icebergs + integer(in),parameter :: f_wpolar =17 ! water: AIS imbalance integer(in),parameter :: f_wevap =18 ! water: evaporation integer(in),parameter :: f_wroff =19 ! water: runoff/flood integer(in),parameter :: f_wioff =20 ! water: frozen runoff @@ -189,8 +189,8 @@ module seq_diag_mct (/' area',' hfreeze',' hmelt',' hnetsw',' hlwdn', & ' hlwup',' hlatvap',' hlatfus',' hiroff',' hsen', & - ' hberg',' hh2otemp',' wfreeze',' wmelt',' wrain', & - ' wsnow',' wberg',' wevap',' wrunoff',' wfrzrof', & + ' hpolar',' hh2otemp',' wfreeze',' wmelt',' wrain', & + ' wsnow',' wpolar',' wevap',' wrunoff',' wfrzrof', & ' wirrig', & ' wfreeze_16O',' wmelt_16O',' wrain_16O',' wsnow_16O', & ' wevap_16O',' wrunoff_16O',' wfrzrof_16O', & @@ -286,7 +286,15 @@ module seq_diag_mct integer :: index_o2x_Faoo_h2otemp integer :: index_o2x_Fioo_frazil + integer :: index_o2x_Foxo_frazil_li integer :: index_o2x_Fioo_q + integer :: index_o2x_Foxo_q_li + + integer :: index_o2x_Foxo_ismw + integer :: index_o2x_Foxo_rrofl + integer :: index_o2x_Foxo_rrofi + integer :: index_o2x_Foxo_ismh + integer :: index_o2x_Foxo_rrofih integer :: index_xao_Faox_lwup integer :: index_xao_Faox_lat @@ -311,8 +319,6 @@ module seq_diag_mct integer :: index_i2x_Fioi_melth integer :: index_i2x_Fioi_meltw - integer :: index_i2x_Fioi_bergh - integer :: index_i2x_Fioi_bergw integer :: index_i2x_Fioi_salt integer :: index_i2x_Faii_swnet integer :: index_i2x_Fioi_swpen @@ -1337,9 +1343,10 @@ subroutine seq_diag_ocn_mct( ocn, xao_o, frac_o, infodata, do_o2x, do_x2o, do_xa integer(in) :: kArea ! index of area field in aVect integer(in) :: ko,ki ! fraction indices integer(in) :: lSize ! size of aVect - real(r8) :: ca_i,ca_o ! area of a grid cell + real(r8) :: ca_i,ca_o,ca_c ! area of a grid cell logical,save :: first_time = .true. logical,save :: flds_wiso_ocn = .false. + logical,save :: flds_polar = .false. !----- formats ----- character(*),parameter :: subName = '(seq_diag_ocn_mct) ' @@ -1371,8 +1378,18 @@ subroutine seq_diag_ocn_mct( ocn, xao_o, frac_o, infodata, do_o2x, do_x2o, do_xa if (present(do_o2x)) then if (first_time) then index_o2x_Fioo_frazil = mct_aVect_indexRA(o2x_o,'Fioo_frazil') + index_o2x_Foxo_frazil_li= mct_aVect_indexRA(o2x_o,'Foxo_frazil_li',perrWith='quiet') index_o2x_Fioo_q = mct_aVect_indexRA(o2x_o,'Fioo_q') + index_o2x_Foxo_q_li = mct_aVect_indexRA(o2x_o,'Foxo_q_li',perrWith='quiet') index_o2x_Faoo_h2otemp = mct_aVect_indexRA(o2x_o,'Faoo_h2otemp') + index_o2x_Foxo_ismw = mct_aVect_indexRA(o2x_o,'Foxo_ismw',perrWith='quiet') + if ( index_o2x_Foxo_ismw /= 0 ) flds_polar = .true. + if ( flds_polar ) then + index_o2x_Foxo_rrofl = mct_aVect_indexRA(o2x_o,'Foxo_rrofl',perrWith='quiet') + index_o2x_Foxo_rrofi = mct_aVect_indexRA(o2x_o,'Foxo_rrofi',perrWith='quiet') + index_o2x_Foxo_ismh = mct_aVect_indexRA(o2x_o,'Foxo_ismh',perrWith='quiet') + index_o2x_Foxo_rrofih = mct_aVect_indexRA(o2x_o,'Foxo_rrofih',perrWith='quiet') + end if end if lSize = mct_avect_lSize(o2x_o) @@ -1380,10 +1397,20 @@ subroutine seq_diag_ocn_mct( ocn, xao_o, frac_o, infodata, do_o2x, do_x2o, do_xa do n=1,lSize ca_o = dom_o%data%rAttr(kArea,n) * frac_o%rAttr(ko,n) ca_i = dom_o%data%rAttr(kArea,n) * frac_o%rAttr(ki,n) + ca_c = dom_o%data%rAttr(kArea,n) nf = f_area; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + ca_o nf = f_wfrz; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) - (ca_o+ca_i)*max(0.0_r8,o2x_o%rAttr(index_o2x_Fioo_frazil,n)) nf = f_hfrz; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + (ca_o+ca_i)*max(0.0_r8,o2x_o%rAttr(index_o2x_Fioo_q,n)) nf = f_hh2ot; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + (ca_o+ca_i)*o2x_o%rAttr(index_o2x_Faoo_h2otemp,n) + if (flds_polar) then + nf = f_wpolar;budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) - ca_c*o2x_o%rAttr(index_o2x_Foxo_frazil_li,n) + nf = f_wpolar;budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + ca_c*o2x_o%rAttr(index_o2x_Foxo_ismw,n) + nf = f_wpolar;budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) - (ca_o+ca_i)*o2x_o%rAttr(index_o2x_Foxo_rrofl,n) + nf = f_wpolar;budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) - (ca_o+ca_i)*o2x_o%rAttr(index_o2x_Foxo_rrofi,n) + nf = f_hpolar;budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + ca_c*o2x_o%rAttr(index_o2x_Foxo_q_li,n) + nf = f_hpolar;budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + ca_c*o2x_o%rAttr(index_o2x_Foxo_ismh,n) + nf = f_hpolar;budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + ca_c*o2x_o%rAttr(index_o2x_Foxo_rrofih,n) + end if end do end if @@ -1490,11 +1517,11 @@ subroutine seq_diag_ocn_mct( ocn, xao_o, frac_o, infodata, do_o2x, do_x2o, do_xa nf = f_hmelt ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + (ca_o+ca_i)*x2o_o%rAttr(index_x2o_Fioi_melth,n) nf = f_hswnet; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + (ca_o+ca_i)*x2o_o%rAttr(index_x2o_Foxx_swnet,n) nf = f_hlwdn ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + (ca_o+ca_i)*x2o_o%rAttr(index_x2o_Faxa_lwdn,n) - nf = f_hberg ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + (ca_o+ca_i)*x2o_o%rAttr(index_x2o_Fioi_bergh,n) + nf = f_hpolar; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + (ca_o+ca_i)*x2o_o%rAttr(index_x2o_Fioi_bergh,n) nf = f_wmelt ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + (ca_o+ca_i)*x2o_o%rAttr(index_x2o_Fioi_meltw,n) nf = f_wrain ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + (ca_o+ca_i)*x2o_o%rAttr(index_x2o_Faxa_rain,n) nf = f_wsnow ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + (ca_o+ca_i)*x2o_o%rAttr(index_x2o_Faxa_snow,n) - nf = f_wberg ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + (ca_o+ca_i)*x2o_o%rAttr(index_x2o_Fioi_bergw,n) + nf = f_wpolar; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + (ca_o+ca_i)*x2o_o%rAttr(index_x2o_Fioi_bergw,n) nf = f_wroff ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + (ca_o+ca_i)*x2o_o%rAttr(index_x2o_Foxx_rofl,n) nf = f_wioff ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + (ca_o+ca_i)*x2o_o%rAttr(index_x2o_Foxx_rofi,n) @@ -1613,8 +1640,6 @@ subroutine seq_diag_ice_mct( ice, frac_i, infodata, do_i2x, do_x2i) if (present(do_i2x)) then index_i2x_Fioi_melth = mct_aVect_indexRA(i2x_i,'Fioi_melth') index_i2x_Fioi_meltw = mct_aVect_indexRA(i2x_i,'Fioi_meltw') - index_i2x_Fioi_bergh = mct_aVect_indexRA(i2x_i,'PFioi_bergh') - index_i2x_Fioi_bergw = mct_aVect_indexRA(i2x_i,'PFioi_bergw') index_i2x_Fioi_swpen = mct_aVect_indexRA(i2x_i,'Fioi_swpen') index_i2x_Faii_swnet = mct_aVect_indexRA(i2x_i,'Faii_swnet') index_i2x_Faii_lwup = mct_aVect_indexRA(i2x_i,'Faii_lwup') @@ -1650,9 +1675,7 @@ subroutine seq_diag_ice_mct( ice, frac_i, infodata, do_i2x, do_x2i) nf = f_hlwup ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + ca_i*i2x_i%rAttr(index_i2x_Faii_lwup,n) nf = f_hlatv ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + ca_i*i2x_i%rAttr(index_i2x_Faii_lat,n) nf = f_hsen ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + ca_i*i2x_i%rAttr(index_i2x_Faii_sen,n) - nf = f_hberg ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) - (ca_o+ca_i)*i2x_i%rAttr(index_i2x_Fioi_bergh,n) nf = f_wmelt ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) - ca_i*i2x_i%rAttr(index_i2x_Fioi_meltw,n) - nf = f_wberg ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) - (ca_o+ca_i)*i2x_i%rAttr(index_i2x_Fioi_bergw,n) nf = f_wevap ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + ca_i*i2x_i%rAttr(index_i2x_Faii_evap,n) if ( flds_wiso_ice )then diff --git a/driver-mct/main/seq_map_mod.F90 b/driver-mct/main/seq_map_mod.F90 index 13623d0b920..0eaa45296d9 100644 --- a/driver-mct/main/seq_map_mod.F90 +++ b/driver-mct/main/seq_map_mod.F90 @@ -910,9 +910,11 @@ subroutine seq_map_avNormArr(mapper, av_i, av_o, norm_i, rList, norm, omit_nonli call mct_aVect_init(avp_i, rList=trim( rList)//trim(appnd), lsize=lsize_i) call mct_aVect_init(avp_o, rList=trim( rList)//trim(appnd), lsize=lsize_o) else - lrList = mct_aVect_exportRList2c(av_i) + lrList = '' + if(mct_aVect_nRAttr(av_i) /= 0) lrList = mct_aVect_exportRList2c(av_i) call mct_aVect_init(avp_i, rList=trim(lrList)//trim(appnd), lsize=lsize_i) - lrList = mct_aVect_exportRList2c(av_o) + lrList = '' + if(mct_aVect_nRAttr(av_o) /= 0) lrList = mct_aVect_exportRList2c(av_o) call mct_aVect_init(avp_o, rList=trim(lrList)//trim(appnd), lsize=lsize_o) endif diff --git a/driver-mct/shr/seq_flds_mod.F90 b/driver-mct/shr/seq_flds_mod.F90 index 4b37e40b7b3..dbfba0889d0 100644 --- a/driver-mct/shr/seq_flds_mod.F90 +++ b/driver-mct/shr/seq_flds_mod.F90 @@ -379,10 +379,11 @@ subroutine seq_flds_set(nmlfile, ID, infodata) logical :: flds_co2_dmsa logical :: flds_bgc_oi logical :: flds_wiso + logical :: flds_polar integer :: glc_nec namelist /seq_cplflds_inparm/ & - flds_co2a, flds_co2b, flds_co2c, flds_co2_dmsa, flds_wiso, glc_nec, & + flds_co2a, flds_co2b, flds_co2c, flds_co2_dmsa, flds_wiso, flds_polar, glc_nec, & ice_ncat, seq_flds_i2o_per_cat, flds_bgc_oi, & nan_check_component_fields, rof_heat, atm_flux_method, atm_gustiness, & rof2ocn_nutrients, lnd_rof_two_way, ocn_rof_two_way, rof_sed @@ -416,6 +417,7 @@ subroutine seq_flds_set(nmlfile, ID, infodata) flds_co2_dmsa = .false. flds_bgc_oi = .false. flds_wiso = .false. + flds_polar = .false. glc_nec = 0 ice_ncat = 1 seq_flds_i2o_per_cat = .false. @@ -449,6 +451,7 @@ subroutine seq_flds_set(nmlfile, ID, infodata) call shr_mpi_bcast(flds_co2_dmsa, mpicom) call shr_mpi_bcast(flds_bgc_oi , mpicom) call shr_mpi_bcast(flds_wiso , mpicom) + call shr_mpi_bcast(flds_polar , mpicom) call shr_mpi_bcast(glc_nec , mpicom) call shr_mpi_bcast(ice_ncat , mpicom) call shr_mpi_bcast(seq_flds_i2o_per_cat, mpicom) @@ -1583,6 +1586,70 @@ subroutine seq_flds_set(nmlfile, ID, infodata) attname = 'PFioi_bergw' call metadata_set(attname, longname, stdname, units) + !-------------------------------- + ! ocn<->cpl only exchange - Polar + !-------------------------------- + + if (flds_polar) then + + ! Ocean Land ice freeze potential + call seq_flds_add(o2x_fluxes,"Foxo_q_li") + longname = 'Ocean land ice freeze potential' + stdname = 'ice_shelf_cavity_ice_heat_flux' + units = 'W m-2' + attname = 'Foxo_q_li' + call metadata_set(attname, longname, stdname, units) + + ! Ocean land ice frazil production + call seq_flds_add(o2x_fluxes,"Foxo_frazil_li") + longname = 'Ocean land ice frazil production' + stdname = 'ocean_land_ice_frazil_ice_production' + units = 'kg m-2 s-1' + attname = 'Foxo_frazil_li' + call metadata_set(attname, longname, stdname, units) + + ! Water flux from ice shelf melt + call seq_flds_add(o2x_fluxes,"Foxo_ismw") + longname = 'Water flux due to basal melting of ice shelves' + stdname = 'basal_iceshelf_melt_flux' + units = 'kg m-2 s-1' + attname = 'Foxo_ismw' + call metadata_set(attname, longname, stdname, units) + + ! Heat flux from ice shelf melt + call seq_flds_add(o2x_fluxes,"Foxo_ismh") + longname = 'Heat flux due to basal melting of ice shelves' + stdname = 'basal_iceshelf_heat_flux' + units = 'W m-2' + attname = 'Foxo_ismh' + call metadata_set(attname, longname, stdname, units) + + ! Water flux from removed liquid runoff + call seq_flds_add(o2x_fluxes,"Foxo_rrofl") + longname = 'Water flux due to removed liqiud runoff' + stdname = 'removed_liquid_runoff_flux' + units = 'kg m-2 s-1' + attname = 'Foxo_rrofl' + call metadata_set(attname, longname, stdname, units) + + ! Water flux from removed solid runoff + call seq_flds_add(o2x_fluxes,"Foxo_rrofi") + longname = 'Water flux due to removed solid runoff' + stdname = 'removed_solid_runoff_flux' + units = 'kg m-2 s-1' + attname = 'Foxo_rrofi' + call metadata_set(attname, longname, stdname, units) + + ! Heat flux from removed solid runoff + call seq_flds_add(o2x_fluxes,"Foxo_rrofih") + longname = 'Heat flux due to removed solid runoff' + stdname = 'removed_solid_runoff_heat_flux' + units = 'W m-2' + attname = 'Foxo_rrofih' + call metadata_set(attname, longname, stdname, units) + + end if + ! Salt flux call seq_flds_add(i2x_fluxes,"Fioi_salt") call seq_flds_add(x2o_fluxes,"Fioi_salt") diff --git a/driver-moab/cime_config/buildnml b/driver-moab/cime_config/buildnml index 0d282d40215..cfaa3c63f8b 100755 --- a/driver-moab/cime_config/buildnml +++ b/driver-moab/cime_config/buildnml @@ -40,6 +40,7 @@ def _create_drv_namelists(case, infile, confdir, nmlgen, files): config['CPL_ALBAV'] = case.get_value('CPL_ALBAV') config['CPL_EPBAL'] = case.get_value('CPL_EPBAL') config['FLDS_WISO'] = case.get_value('FLDS_WISO') + config['FLDS_POLAR'] = case.get_value('FLDS_POLAR') config['BUDGETS'] = case.get_value('BUDGETS') config['MACH'] = case.get_value('MACH') config['MPILIB'] = case.get_value('MPILIB') diff --git a/driver-moab/cime_config/config_component.xml b/driver-moab/cime_config/config_component.xml index 8e4e686aa1c..be0ee0fbd77 100644 --- a/driver-moab/cime_config/config_component.xml +++ b/driver-moab/cime_config/config_component.xml @@ -1085,8 +1085,8 @@ char - gland20,gland10,gland5,gland5UM,gland4,mpas.aisgis20km,mpas.gis20km,mpas.ais20km,mpas.gis1to10km,null - gland5UM + mpas.aisgis20km,mpas.gis20km,mpas.ais20km,mpas.gis1to10km,gis1to10kmR2,null + mpas.gis20km build_grid env_build.xml glacier (glc) grid - DO NOT EDIT (for experts only) @@ -2684,10 +2684,10 @@ integer - 1,2 + 1,2,3 run_pio env_run.xml - pio rearranger choice box=1, subset=2 + pio rearranger choice box=1, subset=2, any=3 $PIO_VERSION $PIO_VERSION diff --git a/driver-moab/cime_config/config_component_e3sm.xml b/driver-moab/cime_config/config_component_e3sm.xml index dd7a5ddb6c1..044cc1e9f9d 100644 --- a/driver-moab/cime_config/config_component_e3sm.xml +++ b/driver-moab/cime_config/config_component_e3sm.xml @@ -172,6 +172,19 @@ Turn on the passing of water isotope fields through the coupler + + logical + TRUE,FALSE + FALSE + + TRUE + TRUE + + run_flags + env_run.xml + Turn on the passing of polar fields through the coupler + + char minus1p8,linear_salt,mushy @@ -265,6 +278,7 @@ CO2A CO2A CO2A + CO2A CO2A_OI CO2A_OI CO2C diff --git a/driver-moab/cime_config/namelist_definition_drv.xml b/driver-moab/cime_config/namelist_definition_drv.xml index 203c6cf5f07..5510783582f 100644 --- a/driver-moab/cime_config/namelist_definition_drv.xml +++ b/driver-moab/cime_config/namelist_definition_drv.xml @@ -149,6 +149,18 @@ + + logical + seq_flds + seq_cplflds_inparm + + If set to .true. Polar fields will be passed from the ocean to the coupler. + + + $FLDS_POLAR + + + char seq_flds diff --git a/driver-moab/cime_config/namelist_definition_modelio.xml b/driver-moab/cime_config/namelist_definition_modelio.xml index ce0275e59bf..2860ffd7106 100644 --- a/driver-moab/cime_config/namelist_definition_modelio.xml +++ b/driver-moab/cime_config/namelist_definition_modelio.xml @@ -90,9 +90,9 @@ integer pio pio_inparm - -99,1,2 + -99,1,2,3 - Rearranger method for pio 1=box, 2=subset. + Rearranger method for pio 1=box, 2=subset, 3=any. $CPL_PIO_REARRANGER diff --git a/driver-moab/main/cime_comp_mod.F90 b/driver-moab/main/cime_comp_mod.F90 index e09483a3bc0..265f8e11338 100644 --- a/driver-moab/main/cime_comp_mod.F90 +++ b/driver-moab/main/cime_comp_mod.F90 @@ -129,6 +129,8 @@ module cime_comp_mod use seq_rest_mod, only : seq_rest_read, seq_rest_mb_read, seq_rest_write, seq_rest_mb_write #ifdef MOABDEBUG use seq_rest_mod, only : write_moab_state + use iMOAB, only: iMOAB_GetDoubleTagStorage, iMOAB_GetMeshInfo + use component_type_mod, only: component_get_name, component_get_c2x_cc #endif ! flux calc routines @@ -209,9 +211,7 @@ module cime_comp_mod use component_type_mod , only: expose_mct_grid_moab #endif -#ifdef MOABCOMP - use iso_c_binding -#endif + use iso_c_binding implicit none @@ -681,7 +681,7 @@ module cime_comp_mod !---------------------------------------------------------------------------- ! formats !---------------------------------------------------------------------------- - character(*), parameter :: subname = '(seq_mct_drv)' + character(*), parameter :: subname = '(moab_driver)' character(*), parameter :: F00 = "('"//subname//" : ', 4A )" character(*), parameter :: F0L = "('"//subname//" : ', A, L6 )" character(*), parameter :: F01 = "('"//subname//" : ', A, 2i8, 3x, A )" @@ -690,6 +690,14 @@ module cime_comp_mod character(*), parameter :: FormatD = '(A,": =============== ", A20,I10.8,I8,6x, " ===============")' character(*), parameter :: FormatR = '(A,": =============== ", A31,F12.3,1x, " ===============")' character(*), parameter :: FormatQ = '(A,": =============== ", A20,2F10.2,4x," ===============")' + +#ifdef MOABDEBUG +! allocate to get data frpm moab + real(r8) , private, pointer :: moab_tag_vals(:,:) ! various tags for debug purposes + integer nvert(3), nvise(3), nbl(3), nsurf(3), nvisBC(3), arrsize, ent_type + character(100) :: tagname + type(mct_aVect) , pointer :: a2x_aa => null() +#endif !=============================================================================== contains !=============================================================================== @@ -1541,6 +1549,7 @@ subroutine cime_init() call t_adj_detailf(-2) call t_stopf('CPL:comp_init_cc_iac') + !--------------------------------------------------------------------------------------- ! Initialize coupler-component data ! if processor has cpl or model diff --git a/driver-moab/main/component_type_mod.F90 b/driver-moab/main/component_type_mod.F90 index 7f6ab3765b3..85a300356c9 100644 --- a/driver-moab/main/component_type_mod.F90 +++ b/driver-moab/main/component_type_mod.F90 @@ -482,7 +482,7 @@ subroutine compare_mct_av_moab_tag(comp, attrVect, mct_field, appId, tagname, en deallocate(values) ! now start comparing tags after set - ierr = iMOAB_GetMeshInfo ( appId, nvert, nvise, nbl, nsurf, nvisBC ); + ierr = iMOAB_GetMeshInfo ( appId, nvert, nvise, nbl, nsurf, nvisBC ) if (ierr > 0 ) & call shr_sys_abort(subname//'Error: fail to get mesh info') if (ent_type .eq. 0) then diff --git a/driver-moab/main/cplcomp_exchange_mod.F90 b/driver-moab/main/cplcomp_exchange_mod.F90 index 4a317bc621e..2fd8bb1f5f6 100644 --- a/driver-moab/main/cplcomp_exchange_mod.F90 +++ b/driver-moab/main/cplcomp_exchange_mod.F90 @@ -29,7 +29,7 @@ module cplcomp_exchange_mod use seq_comm_mct, only : MPSIID, mbixid ! sea-ice on comp pes and on coupler pes use seq_comm_mct, only : mrofid, mbrxid ! iMOAB id of moab rof app on comp pes and on coupler too use shr_mpi_mod, only: shr_mpi_max - use dimensions_mod, only : np ! for atmosphere + ! use dimensions_mod, only : np ! for atmosphere use iso_c_binding implicit none @@ -994,7 +994,7 @@ subroutine cplcomp_moab_Init(infodata,comp) ! use iMOAB, only: iMOAB_RegisterApplication, iMOAB_ReceiveMesh, iMOAB_SendMesh, & iMOAB_WriteMesh, iMOAB_DefineTagStorage, iMOAB_GetMeshInfo, & - iMOAB_SetIntTagStorage, iMOAB_FreeSenderBuffers, iMOAB_ComputeCommGraph, iMOAB_LoadMesh + iMOAB_FreeSenderBuffers, iMOAB_ComputeCommGraph, iMOAB_LoadMesh ! use seq_infodata_mod ! @@ -1020,13 +1020,17 @@ subroutine cplcomp_moab_Init(infodata,comp) character(CL) :: rtm_mesh character(CL) :: lnd_domain character(CL) :: ocn_domain + character(CL) :: atm_mesh integer :: maxMH, maxMPO, maxMLID, maxMSID, maxMRID ! max pids for moab apps atm, ocn, lnd, sea-ice, rof integer :: tagtype, numco, tagindex, partMethod, nghlay integer :: rank, ent_type integer :: typeA, typeB, ATM_PHYS_CID ! used to compute par graph between atm phys ! and atm spectral on coupler - character(CXX) :: tagname - integer nvert(3), nvise(3), nbl(3), nsurf(3), nvisBC(3) + character(CXX) :: tagname + integer nvert(3), nvise(3), nbl(3), nsurf(3), nvisBC(3) + ! type(mct_list) :: temp_list + ! integer :: nfields, arrsize + ! real(R8), allocatable, target :: values(:) !----------------------------------------------------- @@ -1052,7 +1056,7 @@ subroutine cplcomp_moab_Init(infodata,comp) call seq_comm_getinfo(ID_new ,mpicom=mpicom_new) call seq_comm_getinfo(ID_join,mpicom=mpicom_join) - call shr_mpi_max(mhid, maxMH, mpicom_join, all=.true.) ! if on atm / cpl joint, maxMH /= -1 + call shr_mpi_max(mphaid, maxMH, mpicom_join, all=.true.) ! if on atm / cpl joint, maxMH /= -1 call shr_mpi_max(mpoid, maxMPO, mpicom_join, all=.true.) call shr_mpi_max(mlnid, maxMLID, mpicom_join, all=.true.) call shr_mpi_max(MPSIID, maxMSID, mpicom_join, all=.true.) @@ -1064,18 +1068,31 @@ subroutine cplcomp_moab_Init(infodata,comp) if ( comp%oneletterid == 'a' .and. maxMH /= -1) then call seq_comm_getinfo(cplid ,mpigrp=mpigrp_cplid) ! receiver group call seq_comm_getinfo(id_old,mpigrp=mpigrp_old) ! component group pes + + ! find atm mesh/domain file if it exists; it would be for data atm model (atm_prognostic false) + call seq_infodata_GetData(infodata,atm_mesh = atm_mesh) ! now, if on coupler pes, receive mesh; if on comp pes, send mesh + + if (mphaid >= 0) then + ierr = iMOAB_GetMeshInfo ( mphaid, nvert, nvise, nbl, nsurf, nvisBC ) + comp%mbApCCid = mphaid ! phys atm + comp%mbGridType = 0 ! point cloud + comp%mblsize = nvert(1) ! point cloud + endif + if (MPI_COMM_NULL /= mpicom_old ) then ! it means we are on the component pes (atmosphere) ! send mesh to coupler - if (atm_pg_active) then ! change : send the pg2 mesh, not coarse mesh, when atm pg active - ierr = iMOAB_SendMesh(mhpgid, mpicom_join, mpigrp_cplid, id_join, partMethod) - else - ! still use the mhid, original coarse mesh - ierr = iMOAB_SendMesh(mhid, mpicom_join, mpigrp_cplid, id_join, partMethod) - endif - if (ierr .ne. 0) then - write(logunit,*) subname,' error in sending mesh from atm comp ' - call shr_sys_abort(subname//' ERROR in sending mesh from atm comp') + if ( trim(atm_mesh) == 'none' ) then + if (atm_pg_active) then ! change : send the pg2 mesh, not coarse mesh, when atm pg active + ierr = iMOAB_SendMesh(mhpgid, mpicom_join, mpigrp_cplid, id_join, partMethod) + else + ! still use the mhid, original coarse mesh + ierr = iMOAB_SendMesh(mhid, mpicom_join, mpigrp_cplid, id_join, partMethod) + endif + if (ierr .ne. 0) then + write(logunit,*) subname,' error in sending mesh from atm comp ' + call shr_sys_abort(subname//' ERROR in sending mesh from atm comp') + endif endif endif if (MPI_COMM_NULL /= mpicom_new ) then ! we are on the coupler pes @@ -1086,25 +1103,50 @@ subroutine cplcomp_moab_Init(infodata,comp) write(logunit,*) subname,' error in registering ', appname call shr_sys_abort(subname//' ERROR registering '// appname) endif - ierr = iMOAB_ReceiveMesh(mbaxid, mpicom_join, mpigrp_old, id_old) - if (ierr .ne. 0) then - write(logunit,*) subname,' error in receiving mesh on atm coupler ' - call shr_sys_abort(subname//' ERROR in receiving mesh on atm coupler ') + if ( trim(atm_mesh) == 'none' ) then + ierr = iMOAB_ReceiveMesh(mbaxid, mpicom_join, mpigrp_old, id_old) + if (ierr .ne. 0) then + write(logunit,*) subname,' error in receiving mesh on atm coupler ' + call shr_sys_abort(subname//' ERROR in receiving mesh on atm coupler ') + endif + else + ! we need to read the atm mesh on coupler, from domain file + ierr = iMOAB_LoadMesh(mbaxid, trim(atm_mesh)//C_NULL_CHAR, & + "PARALLEL=READ_PART;PARTITION_METHOD=SQIJ;NO_CULLING", 0) + if ( ierr /= 0 ) then + write(logunit,*) 'Failed to load atm domain mesh on coupler' + call shr_sys_abort(subname//' ERROR Failed to load atm domain mesh on coupler ') + endif + ! right now, turn atm_pg_active to true + atm_pg_active = .true. ! FIXME TODO + ! need to add global id tag to the app, it will be used in restart + tagtype = 0 ! dense, integer + numco = 1 + tagname='GLOBAL_ID'//C_NULL_CHAR + ierr = iMOAB_DefineTagStorage(mbaxid, tagname, tagtype, numco, tagindex ) + if (ierr .ne. 0) then + write(logunit,*) subname,' error in adding global id tag to atmx' + call shr_sys_abort(subname//' ERROR in adding global id tag to atmx ') + endif endif + + endif ! iMOAB_FreeSenderBuffers needs to be called after receiving the mesh if (mhid .ge. 0) then ! we are on component atm pes - context_id = id_join - if (atm_pg_active) then! we send mesh from mhpgid app - ierr = iMOAB_FreeSenderBuffers(mhpgid, context_id) - else - ierr = iMOAB_FreeSenderBuffers(mhid, context_id) - endif - if (ierr .ne. 0) then - write(logunit,*) subname,' error in freeing send buffers ' - call shr_sys_abort(subname//' ERROR in freeing send buffers') + if ( trim(atm_mesh) == 'none' ) then + context_id = id_join + if (atm_pg_active) then! we send mesh from mhpgid app + ierr = iMOAB_FreeSenderBuffers(mhpgid, context_id) + else + ierr = iMOAB_FreeSenderBuffers(mhid, context_id) + endif + if (ierr .ne. 0) then + write(logunit,*) subname,' error in freeing send buffers ' + call shr_sys_abort(subname//' ERROR in freeing send buffers') + endif endif endif @@ -1116,13 +1158,8 @@ subroutine cplcomp_moab_Init(infodata,comp) typeB = 3 ! in this case, we will have cells associated with DOFs as GLOBAL_ID tag endif ATM_PHYS_CID = 200 + id_old ! 200 + 5 for atm, see line 969 ATM_PHYS = 200 + ATMID ! in - ! components/cam/src/cpl/atm_comp_mct.F90 - if (mphaid >= 0) then - ierr = iMOAB_GetMeshInfo ( mphaid, nvert, nvise, nbl, nsurf, nvisBC ) - comp%mbApCCid = mphaid ! phys atm - comp%mbGridType = 0 ! point cloud - comp%mblsize = nvert(1) ! point cloud - endif + ! components/cam/src/cpl/atm_comp_mct.F90 + ! components/data_comps/datm/src/atm_comp_mct.F90 ! line 177 !! ierr = iMOAB_ComputeCommGraph( mphaid, mbaxid, mpicom_join, mpigrp_old, mpigrp_cplid, & typeA, typeB, ATM_PHYS_CID, id_join) ! ID_JOIN is now 6 @@ -1136,7 +1173,7 @@ subroutine cplcomp_moab_Init(infodata,comp) numco = 1 ! usually 1 value per cell else ! this is not supported now, but leave it here tagname = trim(seq_flds_a2x_ext_fields)//C_NULL_CHAR ! MOAB versions of a2x for spectral - numco = np*np ! usually 16 values per cell, GLL points; should be 4 x 4 = 16 + numco = 16 ! np*np ! usually 16 values per cell, GLL points; should be 4 x 4 = 16 endif ierr = iMOAB_DefineTagStorage(mbaxid, tagname, tagtype, numco, tagindex ) if (ierr .ne. 0) then @@ -1149,6 +1186,13 @@ subroutine cplcomp_moab_Init(infodata,comp) write(logunit,*) subname,' error in defining tags seq_flds_x2a_fields on atm on coupler ' call shr_sys_abort(subname//' ERROR in defining tags ') endif + ! zero out the fields for seq_flds_x2a_fields and seq_flds_a2x_fields, on mbaxid + ! first determine the size of array + ierr = iMOAB_GetMeshInfo ( mbaxid, nvert, nvise, nbl, nsurf, nvisBC ) + if (ierr .ne. 0) then + write(logunit,*) subname,' error in getting mesh info on atm on coupler ' + call shr_sys_abort(subname//' ERROR in getting mesh info on atm on coupler ') + endif !add the normalization tag tagname = trim(seq_flds_dom_fields)//":norm8wt"//C_NULL_CHAR @@ -1157,6 +1201,12 @@ subroutine cplcomp_moab_Init(infodata,comp) write(logunit,*) subname,' error in defining tags seq_flds_dom_fields on atm on coupler ' call shr_sys_abort(subname//' ERROR in defining tags ') endif + if ( trim(atm_mesh) /= 'none' ) then + ! also, frac, area, aream, masks has to come from atm mphaid, not from domain file reader + ! this is hard to digest :( + tagname = 'area:aream:frac:mask'//C_NULL_CHAR + call component_exch_moab(comp, mphaid, mbaxid, 0, tagname) + endif endif @@ -1301,7 +1351,7 @@ subroutine cplcomp_moab_Init(infodata,comp) endif endif endif - ! in case of domain read, we need ot compute the comm graph + ! in case of domain read, we need to compute the comm graph if ( trim(ocn_domain) /= 'none' ) then ! we are now on joint pes, compute comm graph between data ocn and coupler model ocn typeA = 2 ! point cloud on component PEs @@ -1314,7 +1364,7 @@ subroutine cplcomp_moab_Init(infodata,comp) endif ! also, frac, area, aream, masks has to come from ocean mpoid, not from domain file reader ! this is hard to digest :( - tagname = 'area:frac:frac:mask'//C_NULL_CHAR + tagname = 'area:aream:frac:mask'//C_NULL_CHAR call component_exch_moab(comp, mpoid, mboxid, 0, tagname) endif @@ -1732,16 +1782,20 @@ subroutine component_exch_moab(comp, mbAPPid1, mbAppid2, direction, fields ) call shr_sys_abort(subname//' cannot free sender buffers') endif endif - + #ifdef MOABDEBUG + if (direction .eq. 0 ) then + dir = 'c2x' + else + dir = 'x2c' + endif + if (seq_comm_iamroot(CPLID) ) then + write(logunit,'(A)') subname//' '//comp%ntype//' called in direction '//trim(dir)//' for fields '//trim(tagname) + endif if (mbAPPid2 .ge. 0 ) then ! we are on receiving pes, for sure ! number_proj = number_proj+1 ! count the number of projections write(lnum,"(I0.2)") num_moab_exports - if (direction .eq. 0 ) then - dir = 'c2x' - else - dir = 'x2c' - endif + outfile = comp%ntype//'_'//trim(dir)//'_'//trim(lnum)//'.h5m'//C_NULL_CHAR wopts = ';PARALLEL=WRITE_PART'//C_NULL_CHAR ! ierr = iMOAB_WriteMesh(mbAPPid2, trim(outfile), trim(wopts)) diff --git a/driver-moab/main/prep_atm_mod.F90 b/driver-moab/main/prep_atm_mod.F90 index 34197cc3b0e..c8c2de76362 100644 --- a/driver-moab/main/prep_atm_mod.F90 +++ b/driver-moab/main/prep_atm_mod.F90 @@ -35,7 +35,7 @@ module prep_atm_mod use seq_comm_mct, only : seq_comm_getinfo => seq_comm_setptrs use seq_comm_mct, only : num_moab_exports - use dimensions_mod, only : np ! for atmosphere + !use dimensions_mod, only : np ! for atmosphere #ifdef MOABCOMP use component_type_mod, only: compare_mct_av_moab_tag #endif @@ -273,7 +273,8 @@ subroutine prep_atm_init(infodata, ocn_c2_atm, ice_c2_atm, lnd_c2_atm, iac_c2_at call shr_sys_abort(subname//' ERROR in coin defining tags for seq_flds_o2x_fields') endif else ! spectral case, fix later TODO - numco = np*np ! + !numco = np*np ! + numco = 16 endif ! @@ -319,7 +320,7 @@ subroutine prep_atm_init(infodata, ocn_c2_atm, ice_c2_atm, lnd_c2_atm, iac_c2_at else dm2 = "cgll"//C_NULL_CHAR dofnameT="GLOBAL_DOFS"//C_NULL_CHAR - orderT = np ! it should be 4 + orderT = 4 ! np ! it should be 4 endif dm1 = "fv"//C_NULL_CHAR dofnameS="GLOBAL_ID"//C_NULL_CHAR @@ -585,7 +586,7 @@ subroutine prep_atm_init(infodata, ocn_c2_atm, ice_c2_atm, lnd_c2_atm, iac_c2_at else dm2 = "cgll"//C_NULL_CHAR dofnameT="GLOBAL_DOFS"//C_NULL_CHAR - orderT = np ! it should be 4 + orderT = 4 ! np ! it should be 4 endif dm1 = "fv"//C_NULL_CHAR dofnameS="GLOBAL_ID"//C_NULL_CHAR @@ -645,7 +646,8 @@ subroutine prep_atm_init(infodata, ocn_c2_atm, ice_c2_atm, lnd_c2_atm, iac_c2_at 'mapper_Fi2a initialization',esmf_map_flag, no_match) #ifdef HAVE_MOAB - ! now take care of the mapper for MOAB + ! now take care of the mapper for MOAB, only if ice is coupled to atm ! + if (ice_c2_atm) then if ( mapper_Fi2a%src_mbid .gt. -1 ) then if (iamroot_CPLID) then write(logunit,F00) 'overwriting '//trim(mapper_Fi2a%mbname) & @@ -661,6 +663,7 @@ subroutine prep_atm_init(infodata, ocn_c2_atm, ice_c2_atm, lnd_c2_atm, iac_c2_at wgtIdef = 'scalar'//C_NULL_CHAR mapper_Fi2a%weight_identifier = wgtIdef mapper_Fi2a%mbname = 'mapper_Fi2a' + endif #endif endif ! if (ice_present) then call shr_sys_flush(logunit) @@ -765,7 +768,7 @@ subroutine prep_atm_init(infodata, ocn_c2_atm, ice_c2_atm, lnd_c2_atm, iac_c2_at else dm2 = "cgll"//C_NULL_CHAR dofnameT="GLOBAL_DOFS"//C_NULL_CHAR - orderT = np ! it should be 4 + orderT = 4 ! np ! it should be 4 endif dm1 = "fv"//C_NULL_CHAR dofnameS="GLOBAL_ID"//C_NULL_CHAR @@ -796,6 +799,7 @@ subroutine prep_atm_init(infodata, ocn_c2_atm, ice_c2_atm, lnd_c2_atm, iac_c2_at ! we do not compute intersection, so we will have to just send data from atm to land and viceversa, by GLOBAL_ID matching ! so we compute just a comm graph, between lnd and atm dofs, on the coupler; target is atm ! land is point cloud in this case, type1 = 2 + call seq_comm_getinfo(CPLID ,mpigrp=mpigrp_CPLID) ! make sure we have the right MPI group type1 = 3; ! full mesh for land now type2 = 3; ! fv for target atm ierr = iMOAB_ComputeCommGraph( mblxid, mbaxid, mpicom_CPLID, mpigrp_CPLID, mpigrp_CPLID, type1, type2, & diff --git a/driver-moab/main/prep_lnd_mod.F90 b/driver-moab/main/prep_lnd_mod.F90 index 43c213c7385..44ae5490e2c 100644 --- a/driver-moab/main/prep_lnd_mod.F90 +++ b/driver-moab/main/prep_lnd_mod.F90 @@ -21,7 +21,7 @@ module prep_lnd_mod use seq_comm_mct, only: mbaxid ! iMOAB id for atm migrated mesh to coupler pes use seq_comm_mct, only: atm_pg_active ! whether the atm uses FV mesh or not ; made true if fv_nphys > 0 - use dimensions_mod, only: np ! for atmosphere + ! use dimensions_mod, only: np ! for atmosphere use seq_comm_mct, only: seq_comm_getinfo => seq_comm_setptrs use seq_map_type_mod use seq_map_mod @@ -479,7 +479,7 @@ subroutine prep_lnd_init(infodata, atm_c2_lnd, rof_c2_lnd, glc_c2_lnd, iac_c2_ln else dm1 = "cgll"//C_NULL_CHAR dofnameS="GLOBAL_DOFS"//C_NULL_CHAR - orderS = np ! it should be 4 + orderS = 4 ! np ! it should be 4 endif dm2 = "fv"//C_NULL_CHAR dofnameT="GLOBAL_ID"//C_NULL_CHAR diff --git a/driver-moab/main/prep_ocn_mod.F90 b/driver-moab/main/prep_ocn_mod.F90 index afd186d35a6..7514cc40db0 100644 --- a/driver-moab/main/prep_ocn_mod.F90 +++ b/driver-moab/main/prep_ocn_mod.F90 @@ -12,7 +12,6 @@ module prep_ocn_mod use seq_comm_mct, only: CPLID, OCNID, logunit use seq_comm_mct, only: seq_comm_getData=>seq_comm_setptrs - use seq_comm_mct, only: mpoid ! iMOAB pid for ocean mesh on component pes use seq_comm_mct, only: mboxid ! iMOAB id for mpas ocean migrated mesh to coupler pes use seq_comm_mct, only: mbrmapro ! iMOAB id for map read from rof2ocn map file use seq_comm_mct, only: mbrxoid ! iMOAB id for rof on coupler in ocean context; @@ -23,7 +22,7 @@ module prep_ocn_mod use seq_comm_mct, only : mbintxoa ! iMOAB id for intx mesh between ocean and atmosphere use seq_comm_mct, only : mhid ! iMOAB id for atm instance use seq_comm_mct, only : mhpgid ! iMOAB id for atm pgx grid, on atm pes; created with se and gll grids - use dimensions_mod, only : np ! for atmosphere degree + ! use dimensions_mod, only : np ! for atmosphere degree use seq_comm_mct, only : mbixid ! iMOAB for sea-ice migrated to coupler use seq_comm_mct, only : CPLALLICEID use seq_comm_mct, only : seq_comm_iamin @@ -478,7 +477,7 @@ subroutine prep_ocn_init(infodata, atm_c2_ocn, atm_c2_ice, ice_c2_ocn, rof_c2_oc else dm1 = "cgll"//C_NULL_CHAR dofnameS="GLOBAL_DOFS"//C_NULL_CHAR - orderS = np ! it should be 4 + orderS = 4 ! np ! it should be 4 endif dm2 = "fv"//C_NULL_CHAR dofnameT="GLOBAL_ID"//C_NULL_CHAR diff --git a/driver-moab/main/prep_rof_mod.F90 b/driver-moab/main/prep_rof_mod.F90 index a8cce9455a4..59cc61c5889 100644 --- a/driver-moab/main/prep_rof_mod.F90 +++ b/driver-moab/main/prep_rof_mod.F90 @@ -15,7 +15,7 @@ module prep_rof_mod use seq_comm_mct, only: mboxid use seq_comm_mct, only: mbintxlr ! iMOAB id for intx mesh between land and river use seq_comm_mct, only : atm_pg_active ! whether the atm uses FV mesh or not ; made true if fv_nphys > 0 - use dimensions_mod, only : np ! for atmosphere degree + !use dimensions_mod, only : np ! for atmosphere degree use seq_comm_mct, only: seq_comm_getData=>seq_comm_setptrs use seq_infodata_mod, only: seq_infodata_type, seq_infodata_getdata use shr_log_mod , only: errMsg => shr_log_errMsg @@ -264,8 +264,9 @@ subroutine prep_rof_init(infodata, lnd_c2_rof, atm_c2_rof, ocn_c2_rof) l2racc_lx_cnt = 0 #ifdef HAVE_MOAB ! this l2racc_lm will be over land size ? - sharedFieldsLndRof=trim( mct_aVect_exportRList2c(l2racc_lx(1)) ) + sharedFieldsLndRof='' nfields_sh_lr = mct_aVect_nRAttr(l2racc_lx(1)) + if( nfields_sh_lr /= 0 ) sharedFieldsLndRof=trim( mct_aVect_exportRList2c(l2racc_lx(1)) ) tagname = trim(sharedFieldsLndRof)//C_NULL_CHAR ! find the size of land mesh locally ! find out the number of local elements in moab mesh lnd instance on coupler @@ -340,12 +341,12 @@ subroutine prep_rof_init(infodata, lnd_c2_rof, atm_c2_rof, ocn_c2_rof) call shr_sys_abort(subname//' ERROR in computing comm graph , lnd-rof') endif ! context for rearrange is target in this case - if ( mapper_Fl2r%src_mbid .gt. -1 ) then - if (iamroot_CPLID) then - write(logunit,F00) 'overwriting '//trim(mapper_Fl2r%mbname) & - //' mapper_Fl2r' - endif - endif + if ( mapper_Fl2r%src_mbid .gt. -1 ) then + if (iamroot_CPLID) then + write(logunit,F00) 'overwriting '//trim(mapper_Fl2r%mbname) & + //' mapper_Fl2r' + endif + endif mapper_Fl2r%src_mbid = mblxid mapper_Fl2r%tgt_mbid = mbrxid mapper_Fl2r%src_context = lnd(1)%cplcompid @@ -373,12 +374,12 @@ subroutine prep_rof_init(infodata, lnd_c2_rof, atm_c2_rof, ocn_c2_rof) call shr_sys_abort(subname//' ERROR in computing comm graph for second hop, lnd-rof') endif ! now take care of the mapper - if ( mapper_Fl2r%src_mbid .gt. -1 ) then - if (iamroot_CPLID) then - write(logunit,F00) 'overwriting '//trim(mapper_Fl2r%mbname) & - //' mapper_Fl2r' - endif - endif + if ( mapper_Fl2r%src_mbid .gt. -1 ) then + if (iamroot_CPLID) then + write(logunit,F00) 'overwriting '//trim(mapper_Fl2r%mbname) & + //' mapper_Fl2r' + endif + endif mapper_Fl2r%src_mbid = mblxid mapper_Fl2r%tgt_mbid = mbrxid mapper_Fl2r%intx_mbid = mbintxlr @@ -435,7 +436,6 @@ subroutine prep_rof_init(infodata, lnd_c2_rof, atm_c2_rof, ocn_c2_rof) endif #endif end if ! if ((mblxid .ge. 0) .and. (mbrxid .ge. 0)) - ! endif HAVE_MOAB endif ! samegrid_lr #endif ! We'll map irrigation specially, so exclude this from the list of l2r fields @@ -469,9 +469,10 @@ subroutine prep_rof_init(infodata, lnd_c2_rof, atm_c2_rof, ocn_c2_rof) a2racc_ax_cnt = 0 #ifdef HAVE_MOAB ! this a2racc_am will be over atm size - sharedFieldsAtmRof=trim( mct_aVect_exportRList2c(a2racc_ax(1)) ) - tagname = trim(sharedFieldsAtmRof)//C_NULL_CHAR + sharedFieldsAtmRof='' nfields_sh_ar = mct_aVect_nRAttr(a2racc_ax(1)) + if (nfields_sh_ar /= 0 ) sharedFieldsAtmRof = trim( mct_aVect_exportRList2c(a2racc_ax(1)) ) + tagname = trim(sharedFieldsAtmRof)//C_NULL_CHAR ! find the size of atm mesh locally ! find out the number of local elements in moab mesh atm instance on coupler ierr = iMOAB_GetMeshInfo ( mbaxid, nvert, nvise, nbl, nsurf, nvisBC ) @@ -582,7 +583,7 @@ subroutine prep_rof_init(infodata, lnd_c2_rof, atm_c2_rof, ocn_c2_rof) else ! this part does not work, anyway dm1 = "cgll"//C_NULL_CHAR dofnameS="GLOBAL_DOFS"//C_NULL_CHAR - orderS = np ! it should be 4 + orderS = 4 ! np ! it should be 4 endif dm2 = "fv"//C_NULL_CHAR dofnameT="GLOBAL_ID"//C_NULL_CHAR @@ -675,9 +676,10 @@ subroutine prep_rof_init(infodata, lnd_c2_rof, atm_c2_rof, ocn_c2_rof) #ifdef HAVE_MOAB ! this o2racc_om will be over ocn size - sharedFieldsOcnRof=trim( mct_aVect_exportRList2c(o2racc_ox(1)) ) - tagname = trim(sharedFieldsOcnRof)//C_NULL_CHAR + sharedFieldsOcnRof='' nfields_sh_or = mct_aVect_nRAttr(o2racc_ox(1)) + if ( nfields_sh_or /= 0 ) sharedFieldsOcnRof = trim( mct_aVect_exportRList2c(o2racc_ox(1)) ) + tagname = trim(sharedFieldsOcnRof)//C_NULL_CHAR ! find the size of ocn mesh locally ! find out the number of local elements in moab mesh ocn instance on coupler @@ -1033,10 +1035,12 @@ subroutine prep_rof_accum_avg_moab() tagname = trim(sharedFieldsLndRof)//C_NULL_CHAR arrsize = nfields_sh_lr * lsize_lm ent_type = 1 ! cell type - ierr = iMOAB_SetDoubleTagStorage ( mblxid, tagname, arrsize , ent_type, l2racc_lm) - if (ierr .ne. 0) then - call shr_sys_abort(subname//' error in setting accumulated shared fields on rof on land instance ') - endif + if (arrsize > 0) then + ierr = iMOAB_SetDoubleTagStorage ( mblxid, tagname, arrsize , ent_type, l2racc_lm) + if (ierr .ne. 0) then + call shr_sys_abort(subname//' error in setting accumulated shared fields on rof on land instance ') + endif + endif #ifdef MOABDEBUG if (mblxid .ge. 0 ) then ! we are on coupler pes, for sure @@ -1058,10 +1062,12 @@ subroutine prep_rof_accum_avg_moab() tagname = trim(sharedFieldsAtmRof)//C_NULL_CHAR arrsize = nfields_sh_ar * lsize_am ent_type = 1 ! cell type - ierr = iMOAB_SetDoubleTagStorage ( mbaxid, tagname, arrsize , ent_type, a2racc_am) - if (ierr .ne. 0) then - call shr_sys_abort(subname//' error in setting accumulated shared fields on rof on atm instance ') - endif + if (arrsize > 0) then + ierr = iMOAB_SetDoubleTagStorage ( mbaxid, tagname, arrsize , ent_type, a2racc_am) + if (ierr .ne. 0) then + call shr_sys_abort(subname//' error in setting accumulated shared fields on rof on atm instance ') + endif + endif #ifdef MOABDEBUG if (mbaxid .ge. 0 ) then ! we are on coupler pes, for sure write(lnum,"(I0.2)")num_moab_exports @@ -1081,10 +1087,12 @@ subroutine prep_rof_accum_avg_moab() tagname = trim(sharedFieldsOcnRof)//C_NULL_CHAR arrsize = nfields_sh_or * lsize_om ent_type = 1 ! cell type - ierr = iMOAB_SetDoubleTagStorage ( mboxid, tagname, arrsize , ent_type, o2racc_om) - if (ierr .ne. 0) then - call shr_sys_abort(subname//' error in setting accumulated shared fields on rof on ocn instance ') - endif + if (arrsize > 0 ) then + ierr = iMOAB_SetDoubleTagStorage ( mboxid, tagname, arrsize , ent_type, o2racc_om) + if (ierr .ne. 0) then + call shr_sys_abort(subname//' error in setting accumulated shared fields on rof on ocn instance ') + endif + endif #ifdef MOABDEBUG if (mboxid .ge. 0 ) then ! we are on coupler pes, for sure write(lnum,"(I0.2)")num_moab_exports diff --git a/driver-moab/main/seq_diag_mct.F90 b/driver-moab/main/seq_diag_mct.F90 index 2a7d999ccc5..8534008f9be 100644 --- a/driver-moab/main/seq_diag_mct.F90 +++ b/driver-moab/main/seq_diag_mct.F90 @@ -138,13 +138,13 @@ module seq_diag_mct integer(in),parameter :: f_hlatf = 8 ! heat : latent, fusion, snow integer(in),parameter :: f_hioff = 9 ! heat : latent, fusion, frozen runoff integer(in),parameter :: f_hsen =10 ! heat : sensible - integer(in),parameter :: f_hberg =11 ! heat : data icebergs + integer(in),parameter :: f_hpolar =11 ! heat : AIS imbalance integer(in),parameter :: f_hh2ot =12 ! heat : water temperature integer(in),parameter :: f_wfrz =13 ! water: freezing integer(in),parameter :: f_wmelt =14 ! water: melting integer(in),parameter :: f_wrain =15 ! water: precip, liquid integer(in),parameter :: f_wsnow =16 ! water: precip, frozen - integer(in),parameter :: f_wberg =17 ! water: data icebergs + integer(in),parameter :: f_wpolar =17 ! water: AIS imbalance integer(in),parameter :: f_wevap =18 ! water: evaporation integer(in),parameter :: f_wroff =19 ! water: runoff/flood integer(in),parameter :: f_wioff =20 ! water: frozen runoff @@ -189,8 +189,8 @@ module seq_diag_mct (/' area',' hfreeze',' hmelt',' hnetsw',' hlwdn', & ' hlwup',' hlatvap',' hlatfus',' hiroff',' hsen', & - ' hberg',' hh2otemp',' wfreeze',' wmelt',' wrain', & - ' wsnow',' wberg',' wevap',' wrunoff',' wfrzrof', & + ' hpolar',' hh2otemp',' wfreeze',' wmelt',' wrain', & + ' wsnow',' wpolar',' wevap',' wrunoff',' wfrzrof', & ' wirrig', & ' wfreeze_16O',' wmelt_16O',' wrain_16O',' wsnow_16O', & ' wevap_16O',' wrunoff_16O',' wfrzrof_16O', & @@ -286,7 +286,15 @@ module seq_diag_mct integer :: index_o2x_Faoo_h2otemp integer :: index_o2x_Fioo_frazil + integer :: index_o2x_Foxo_frazil_li integer :: index_o2x_Fioo_q + integer :: index_o2x_Foxo_q_li + + integer :: index_o2x_Foxo_ismw + integer :: index_o2x_Foxo_rrofl + integer :: index_o2x_Foxo_rrofi + integer :: index_o2x_Foxo_ismh + integer :: index_o2x_Foxo_rrofih integer :: index_xao_Faox_lwup integer :: index_xao_Faox_lat @@ -311,8 +319,6 @@ module seq_diag_mct integer :: index_i2x_Fioi_melth integer :: index_i2x_Fioi_meltw - integer :: index_i2x_Fioi_bergh - integer :: index_i2x_Fioi_bergw integer :: index_i2x_Fioi_salt integer :: index_i2x_Faii_swnet integer :: index_i2x_Fioi_swpen @@ -1337,9 +1343,10 @@ subroutine seq_diag_ocn_mct( ocn, xao_o, frac_o, infodata, do_o2x, do_x2o, do_xa integer(in) :: kArea ! index of area field in aVect integer(in) :: ko,ki ! fraction indices integer(in) :: lSize ! size of aVect - real(r8) :: ca_i,ca_o ! area of a grid cell + real(r8) :: ca_i,ca_o,ca_c ! area of a grid cell logical,save :: first_time = .true. logical,save :: flds_wiso_ocn = .false. + logical,save :: flds_polar = .false. !----- formats ----- character(*),parameter :: subName = '(seq_diag_ocn_mct) ' @@ -1371,8 +1378,18 @@ subroutine seq_diag_ocn_mct( ocn, xao_o, frac_o, infodata, do_o2x, do_x2o, do_xa if (present(do_o2x)) then if (first_time) then index_o2x_Fioo_frazil = mct_aVect_indexRA(o2x_o,'Fioo_frazil') + index_o2x_Foxo_frazil_li= mct_aVect_indexRA(o2x_o,'Foxo_frazil_li',perrWith='quiet') index_o2x_Fioo_q = mct_aVect_indexRA(o2x_o,'Fioo_q') + index_o2x_Foxo_q_li = mct_aVect_indexRA(o2x_o,'Foxo_q_li',perrWith='quiet') index_o2x_Faoo_h2otemp = mct_aVect_indexRA(o2x_o,'Faoo_h2otemp') + index_o2x_Foxo_ismw = mct_aVect_indexRA(o2x_o,'Foxo_ismw',perrWith='quiet') + if ( index_o2x_Foxo_ismw /= 0 ) flds_polar = .true. + if ( flds_polar ) then + index_o2x_Foxo_rrofl = mct_aVect_indexRA(o2x_o,'Foxo_rrofl',perrWith='quiet') + index_o2x_Foxo_rrofi = mct_aVect_indexRA(o2x_o,'Foxo_rrofi',perrWith='quiet') + index_o2x_Foxo_ismh = mct_aVect_indexRA(o2x_o,'Foxo_ismh',perrWith='quiet') + index_o2x_Foxo_rrofih = mct_aVect_indexRA(o2x_o,'Foxo_rrofih',perrWith='quiet') + end if end if lSize = mct_avect_lSize(o2x_o) @@ -1380,10 +1397,20 @@ subroutine seq_diag_ocn_mct( ocn, xao_o, frac_o, infodata, do_o2x, do_x2o, do_xa do n=1,lSize ca_o = dom_o%data%rAttr(kArea,n) * frac_o%rAttr(ko,n) ca_i = dom_o%data%rAttr(kArea,n) * frac_o%rAttr(ki,n) + ca_c = dom_o%data%rAttr(kArea,n) nf = f_area; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + ca_o nf = f_wfrz; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) - (ca_o+ca_i)*max(0.0_r8,o2x_o%rAttr(index_o2x_Fioo_frazil,n)) nf = f_hfrz; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + (ca_o+ca_i)*max(0.0_r8,o2x_o%rAttr(index_o2x_Fioo_q,n)) nf = f_hh2ot; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + (ca_o+ca_i)*o2x_o%rAttr(index_o2x_Faoo_h2otemp,n) + if (flds_polar) then + nf = f_wpolar;budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) - ca_c*o2x_o%rAttr(index_o2x_Foxo_frazil_li,n) + nf = f_wpolar;budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + ca_c*o2x_o%rAttr(index_o2x_Foxo_ismw,n) + nf = f_wpolar;budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) - (ca_o+ca_i)*o2x_o%rAttr(index_o2x_Foxo_rrofl,n) + nf = f_wpolar;budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) - (ca_o+ca_i)*o2x_o%rAttr(index_o2x_Foxo_rrofi,n) + nf = f_hpolar;budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + ca_c*o2x_o%rAttr(index_o2x_Foxo_q_li,n) + nf = f_hpolar;budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + ca_c*o2x_o%rAttr(index_o2x_Foxo_ismh,n) + nf = f_hpolar;budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + ca_c*o2x_o%rAttr(index_o2x_Foxo_rrofih,n) + end if end do end if @@ -1490,11 +1517,11 @@ subroutine seq_diag_ocn_mct( ocn, xao_o, frac_o, infodata, do_o2x, do_x2o, do_xa nf = f_hmelt ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + (ca_o+ca_i)*x2o_o%rAttr(index_x2o_Fioi_melth,n) nf = f_hswnet; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + (ca_o+ca_i)*x2o_o%rAttr(index_x2o_Foxx_swnet,n) nf = f_hlwdn ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + (ca_o+ca_i)*x2o_o%rAttr(index_x2o_Faxa_lwdn,n) - nf = f_hberg ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + (ca_o+ca_i)*x2o_o%rAttr(index_x2o_Fioi_bergh,n) + nf = f_hpolar; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + (ca_o+ca_i)*x2o_o%rAttr(index_x2o_Fioi_bergh,n) nf = f_wmelt ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + (ca_o+ca_i)*x2o_o%rAttr(index_x2o_Fioi_meltw,n) nf = f_wrain ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + (ca_o+ca_i)*x2o_o%rAttr(index_x2o_Faxa_rain,n) nf = f_wsnow ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + (ca_o+ca_i)*x2o_o%rAttr(index_x2o_Faxa_snow,n) - nf = f_wberg ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + (ca_o+ca_i)*x2o_o%rAttr(index_x2o_Fioi_bergw,n) + nf = f_wpolar; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + (ca_o+ca_i)*x2o_o%rAttr(index_x2o_Fioi_bergw,n) nf = f_wroff ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + (ca_o+ca_i)*x2o_o%rAttr(index_x2o_Foxx_rofl,n) nf = f_wioff ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + (ca_o+ca_i)*x2o_o%rAttr(index_x2o_Foxx_rofi,n) @@ -1613,8 +1640,6 @@ subroutine seq_diag_ice_mct( ice, frac_i, infodata, do_i2x, do_x2i) if (present(do_i2x)) then index_i2x_Fioi_melth = mct_aVect_indexRA(i2x_i,'Fioi_melth') index_i2x_Fioi_meltw = mct_aVect_indexRA(i2x_i,'Fioi_meltw') - index_i2x_Fioi_bergh = mct_aVect_indexRA(i2x_i,'PFioi_bergh') - index_i2x_Fioi_bergw = mct_aVect_indexRA(i2x_i,'PFioi_bergw') index_i2x_Fioi_swpen = mct_aVect_indexRA(i2x_i,'Fioi_swpen') index_i2x_Faii_swnet = mct_aVect_indexRA(i2x_i,'Faii_swnet') index_i2x_Faii_lwup = mct_aVect_indexRA(i2x_i,'Faii_lwup') @@ -1650,9 +1675,7 @@ subroutine seq_diag_ice_mct( ice, frac_i, infodata, do_i2x, do_x2i) nf = f_hlwup ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + ca_i*i2x_i%rAttr(index_i2x_Faii_lwup,n) nf = f_hlatv ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + ca_i*i2x_i%rAttr(index_i2x_Faii_lat,n) nf = f_hsen ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + ca_i*i2x_i%rAttr(index_i2x_Faii_sen,n) - nf = f_hberg ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) - (ca_o+ca_i)*i2x_i%rAttr(index_i2x_Fioi_bergh,n) nf = f_wmelt ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) - ca_i*i2x_i%rAttr(index_i2x_Fioi_meltw,n) - nf = f_wberg ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) - (ca_o+ca_i)*i2x_i%rAttr(index_i2x_Fioi_bergw,n) nf = f_wevap ; budg_dataL(nf,ic,ip) = budg_dataL(nf,ic,ip) + ca_i*i2x_i%rAttr(index_i2x_Faii_evap,n) if ( flds_wiso_ice )then diff --git a/driver-moab/main/seq_map_mod.F90 b/driver-moab/main/seq_map_mod.F90 index 82da0474402..be47473f444 100644 --- a/driver-moab/main/seq_map_mod.F90 +++ b/driver-moab/main/seq_map_mod.F90 @@ -423,7 +423,8 @@ subroutine seq_map_map( mapper, av_s, av_d, fldlist, norm, avwts_s, avwtsfld_s, else ! Extract character strings from attribute vector nfields = mct_aVect_nRAttr(av_s) - fldlist_moab = trim(mct_aVect_exportRList2c(av_s)) + fldlist_moab = '' + if ( nfields /= 0 ) fldlist_moab = trim(mct_aVect_exportRList2c(av_s)) endif if (mbnorm) then @@ -1244,9 +1245,11 @@ subroutine seq_map_avNormArr(mapper, av_i, av_o, norm_i, rList, norm) call mct_aVect_init(avp_i, rList=trim( rList)//trim(appnd), lsize=lsize_i) call mct_aVect_init(avp_o, rList=trim( rList)//trim(appnd), lsize=lsize_o) else - lrList = mct_aVect_exportRList2c(av_i) + lrList = '' + if(mct_aVect_nRAttr(av_i) /= 0) lrList = mct_aVect_exportRList2c(av_i) call mct_aVect_init(avp_i, rList=trim(lrList)//trim(appnd), lsize=lsize_i) - lrList = mct_aVect_exportRList2c(av_o) + lrList = '' + if(mct_aVect_nRAttr(av_o) /= 0) lrList = mct_aVect_exportRList2c(av_o) call mct_aVect_init(avp_o, rList=trim(lrList)//trim(appnd), lsize=lsize_o) endif diff --git a/driver-moab/shr/seq_flds_mod.F90 b/driver-moab/shr/seq_flds_mod.F90 index e03771a7a9c..84e200b0d35 100644 --- a/driver-moab/shr/seq_flds_mod.F90 +++ b/driver-moab/shr/seq_flds_mod.F90 @@ -293,6 +293,8 @@ module seq_flds_mod ! namelist variables logical :: nan_check_component_fields + public moab_set_tag_from_av ! will be caled usually from data models, to set moab tags from data fields in AVs + !---------------------------------------------------------------------------- contains !---------------------------------------------------------------------------- @@ -395,10 +397,11 @@ subroutine seq_flds_set(nmlfile, ID, infodata) logical :: flds_co2_dmsa logical :: flds_bgc_oi logical :: flds_wiso + logical :: flds_polar integer :: glc_nec namelist /seq_cplflds_inparm/ & - flds_co2a, flds_co2b, flds_co2c, flds_co2_dmsa, flds_wiso, glc_nec, & + flds_co2a, flds_co2b, flds_co2c, flds_co2_dmsa, flds_wiso, flds_polar, glc_nec, & ice_ncat, seq_flds_i2o_per_cat, flds_bgc_oi, & nan_check_component_fields, rof_heat, atm_flux_method, atm_gustiness, & rof2ocn_nutrients, lnd_rof_two_way, ocn_rof_two_way, rof_sed @@ -435,6 +438,7 @@ subroutine seq_flds_set(nmlfile, ID, infodata) flds_co2_dmsa = .false. flds_bgc_oi = .false. flds_wiso = .false. + flds_polar = .false. glc_nec = 0 ice_ncat = 1 seq_flds_i2o_per_cat = .false. @@ -468,6 +472,7 @@ subroutine seq_flds_set(nmlfile, ID, infodata) call shr_mpi_bcast(flds_co2_dmsa, mpicom) call shr_mpi_bcast(flds_bgc_oi , mpicom) call shr_mpi_bcast(flds_wiso , mpicom) + call shr_mpi_bcast(flds_polar , mpicom) call shr_mpi_bcast(glc_nec , mpicom) call shr_mpi_bcast(ice_ncat , mpicom) call shr_mpi_bcast(seq_flds_i2o_per_cat, mpicom) @@ -1602,6 +1607,69 @@ subroutine seq_flds_set(nmlfile, ID, infodata) attname = 'PFioi_bergw' call metadata_set(attname, longname, stdname, units) + !-------------------------------- + ! ocn<->cpl only exchange - Polar + !-------------------------------- + if (flds_polar) then + + ! Ocean Land ice freeze potential + call seq_flds_add(o2x_fluxes,"Foxo_q_li") + longname = 'Ocean land ice freeze potential' + stdname = 'ice_shelf_cavity_ice_heat_flux' + units = 'W m-2' + attname = 'Foxo_q_li' + call metadata_set(attname, longname, stdname, units) + + ! Ocean land ice frazil production + call seq_flds_add(o2x_fluxes,"Foxo_frazil_li") + longname = 'Ocean land ice frazil production' + stdname = 'ocean_land_ice_frazil_ice_production' + units = 'kg m-2 s-1' + attname = 'Foxo_frazil_li' + call metadata_set(attname, longname, stdname, units) + + ! Water flux from ice shelf melt + call seq_flds_add(o2x_fluxes,"Foxo_ismw") + longname = 'Water flux due to basal melting of ice shelves' + stdname = 'basal_iceshelf_melt_flux' + units = 'kg m-2 s-1' + attname = 'Foxo_ismw' + call metadata_set(attname, longname, stdname, units) + + ! Heat flux from ice shelf melt + call seq_flds_add(o2x_fluxes,"Foxo_ismh") + longname = 'Heat flux due to basal melting of ice shelves' + stdname = 'basal_iceshelf_heat_flux' + units = 'W m-2' + attname = 'Foxo_ismh' + call metadata_set(attname, longname, stdname, units) + + ! Water flux from removed liquid runoff + call seq_flds_add(o2x_fluxes,"Foxo_rrofl") + longname = 'Water flux due to removed liqiud runoff' + stdname = 'removed_liquid_runoff_flux' + units = 'kg m-2 s-1' + attname = 'Foxo_rrofl' + call metadata_set(attname, longname, stdname, units) + + ! Water flux from removed solid runoff + call seq_flds_add(o2x_fluxes,"Foxo_rrofi") + longname = 'Water flux due to removed solid runoff' + stdname = 'removed_solid_runoff_flux' + units = 'kg m-2 s-1' + attname = 'Foxo_rrofi' + call metadata_set(attname, longname, stdname, units) + + ! Heat flux from removed solid runoff + call seq_flds_add(o2x_fluxes,"Foxo_rrofih") + longname = 'Heat flux due to removed solid runoff' + stdname = 'removed_solid_runoff_heat_flux' + units = 'W m-2' + attname = 'Foxo_rrofih' + call metadata_set(attname, longname, stdname, units) + + end if + ! Salt flux call seq_flds_add(i2x_fluxes,"Fioi_salt") call seq_flds_add(x2o_fluxes,"Fioi_salt") @@ -4369,4 +4437,32 @@ subroutine seq_flds_esmf_metadata_get(shortname, longname, stdname, units) end subroutine seq_flds_esmf_metadata_get +#ifdef HAVE_MOAB + !=============================================================================== + + subroutine moab_set_tag_from_av(tagname, avx, index, mbapid, dataarr, lsize) + + ! !DESCRIPTION: set field method for data atm model + use iMOAB, only: iMOAB_SetDoubleTagStorage + use shr_kind_mod , only: r8 => SHR_KIND_R8 + implicit none + + integer :: ierr, lsize + character(len=*), intent(in) :: tagname + type(mct_aVect), intent(in) :: avx + integer, intent(in) :: index + integer, intent(in) :: mbapid ! moab app id + real(R8), intent(inout) :: dataarr(:) + + !write(*,* ) "Setting data for tag: ", tagname, " with size = ", lsize + dataarr(:) = avx%rAttr(index, :) + ierr = iMOAB_SetDoubleTagStorage ( mbapid, tagname, lsize, & + 0, & ! data on vertices + dataarr ) + if (ierr > 0 ) & + call shr_sys_abort('Error: fail to set tag values for '//tagname) + + end subroutine moab_set_tag_from_av + +#endif end module seq_flds_mod diff --git a/driver-moab/shr/seq_infodata_mod.F90 b/driver-moab/shr/seq_infodata_mod.F90 index deb63205728..77236e027cc 100644 --- a/driver-moab/shr/seq_infodata_mod.F90 +++ b/driver-moab/shr/seq_infodata_mod.F90 @@ -233,6 +233,7 @@ MODULE seq_infodata_mod character(SHR_KIND_CL) :: lnd_domain ! path to land domain file character(SHR_KIND_CL) :: rof_mesh ! path to river mesh file character(SHR_KIND_CL) :: ocn_domain ! path to ocean domain file, used by data ocean models only + character(SHR_KIND_CL) :: atm_mesh ! path to atmosphere domain/mesh file, used by data atm models only !--- set via components and may be time varying --- real(SHR_KIND_R8) :: nextsw_cday ! calendar of next atm shortwave @@ -792,6 +793,8 @@ SUBROUTINE seq_infodata_Init( infodata, nmlfile, ID, pioid, cpl_tag) infodata%lnd_domain = 'none' infodata%rof_mesh = 'none' infodata%ocn_domain = 'none' ! will be used for ocean data models only; will be used as a signal + infodata%atm_mesh = 'none' ! will be used for atmosphere data models only; will be used as a signal + ! not sure if it exists always actually infodata%nextsw_cday = -1.0_SHR_KIND_R8 infodata%precip_fact = 1.0_SHR_KIND_R8 @@ -1034,7 +1037,8 @@ SUBROUTINE seq_infodata_GetData_explicit( infodata, cime_model, case_name, case_ glc_phase, rof_phase, atm_phase, lnd_phase, ocn_phase, ice_phase, & wav_phase, iac_phase, esp_phase, wav_nx, wav_ny, atm_nx, atm_ny, & lnd_nx, lnd_ny, rof_nx, rof_ny, ice_nx, ice_ny, ocn_nx, ocn_ny, & - iac_nx, iac_ny, glc_nx, glc_ny, lnd_domain, rof_mesh, ocn_domain, eps_frac, & + iac_nx, iac_ny, glc_nx, glc_ny, lnd_domain, rof_mesh, ocn_domain, & + atm_mesh, eps_frac, & eps_amask, eps_agrid, eps_aarea, eps_omask, eps_ogrid, eps_oarea, & reprosum_use_ddpdd, reprosum_allow_infnan, & reprosum_diffmax, reprosum_recompute, & @@ -1209,6 +1213,7 @@ SUBROUTINE seq_infodata_GetData_explicit( infodata, cime_model, case_name, case_ character(SHR_KIND_CL), optional, intent(OUT) :: lnd_domain character(SHR_KIND_CL), optional, intent(OUT) :: rof_mesh character(SHR_KIND_CL), optional, intent(OUT) :: ocn_domain + character(SHR_KIND_CL), optional, intent(OUT) :: atm_mesh real(SHR_KIND_R8), optional, intent(OUT) :: nextsw_cday ! calendar of next atm shortwave real(SHR_KIND_R8), optional, intent(OUT) :: precip_fact ! precip factor @@ -1397,6 +1402,7 @@ SUBROUTINE seq_infodata_GetData_explicit( infodata, cime_model, case_name, case_ if ( present(lnd_domain) ) lnd_domain = infodata%lnd_domain if ( present(rof_mesh) ) rof_mesh = infodata%rof_mesh if ( present(ocn_domain) ) ocn_domain = infodata%ocn_domain + if ( present(atm_mesh) ) atm_mesh = infodata%atm_mesh if ( present(nextsw_cday) ) nextsw_cday = infodata%nextsw_cday if ( present(precip_fact) ) precip_fact = infodata%precip_fact @@ -1592,7 +1598,8 @@ SUBROUTINE seq_infodata_PutData_explicit( infodata, cime_model, case_name, case_ wav_phase, iac_phase, esp_phase, wav_nx, wav_ny, atm_nx, atm_ny, & lnd_nx, lnd_ny, rof_nx, rof_ny, ice_nx, ice_ny, ocn_nx, ocn_ny, & iac_nx, iac_ny, glc_nx, glc_ny, eps_frac, eps_amask, lnd_domain, & - rof_mesh, ocn_domain, eps_agrid, eps_aarea, eps_omask, eps_ogrid, eps_oarea, & + rof_mesh, ocn_domain, atm_mesh, eps_agrid, eps_aarea, eps_omask, & + eps_ogrid, eps_oarea, & reprosum_use_ddpdd, reprosum_allow_infnan, & reprosum_diffmax, reprosum_recompute, & mct_usealltoall, mct_usevector, glc_valid_input, nlmaps_verbosity) @@ -1765,6 +1772,7 @@ SUBROUTINE seq_infodata_PutData_explicit( infodata, cime_model, case_name, case_ character(SHR_KIND_CL), optional, intent(IN) :: lnd_domain character(SHR_KIND_CL), optional, intent(IN) :: rof_mesh character(SHR_KIND_CL), optional, intent(IN) :: ocn_domain + character(SHR_KIND_CL), optional, intent(IN) :: atm_mesh real(SHR_KIND_R8), optional, intent(IN) :: nextsw_cday ! calendar of next atm shortwave real(SHR_KIND_R8), optional, intent(IN) :: precip_fact ! precip factor @@ -1952,6 +1960,7 @@ SUBROUTINE seq_infodata_PutData_explicit( infodata, cime_model, case_name, case_ if ( present(lnd_domain) ) infodata%lnd_domain = lnd_domain if ( present(rof_mesh) ) infodata%rof_mesh = rof_mesh if ( present(ocn_domain) ) infodata%ocn_domain = ocn_domain + if ( present(atm_mesh) ) infodata%atm_mesh = atm_mesh if ( present(nextsw_cday) ) infodata%nextsw_cday = nextsw_cday if ( present(precip_fact) ) infodata%precip_fact = precip_fact @@ -2263,6 +2272,7 @@ subroutine seq_infodata_bcast(infodata,mpicom) call shr_mpi_bcast(infodata%lnd_domain, mpicom) call shr_mpi_bcast(infodata%rof_mesh, mpicom) call shr_mpi_bcast(infodata%ocn_domain, mpicom) + call shr_mpi_bcast(infodata%atm_mesh, mpicom) call shr_mpi_bcast(infodata%nextsw_cday, mpicom) call shr_mpi_bcast(infodata%precip_fact, mpicom) call shr_mpi_bcast(infodata%atm_phase, mpicom) @@ -2480,6 +2490,7 @@ subroutine seq_infodata_Exchange(infodata,ID,type) call shr_mpi_bcast(infodata%atm_nx, mpicom, pebcast=cmppe) call shr_mpi_bcast(infodata%atm_ny, mpicom, pebcast=cmppe) call shr_mpi_bcast(infodata%atm_aero, mpicom, pebcast=cmppe) + call shr_mpi_bcast(infodata%atm_mesh, mpicom, pebcast=cmppe) ! dead_comps is true if it's ever set to true deads = infodata%dead_comps call shr_mpi_bcast(deads, mpicom, pebcast=cmppe) @@ -2980,6 +2991,7 @@ SUBROUTINE seq_infodata_print( infodata ) write(logunit,F0I) subname,'lnd_domain = ', infodata%lnd_domain write(logunit,F0I) subname,'rof_mesh = ', infodata%rof_mesh write(logunit,F0I) subname,'ocn_domain = ', infodata%ocn_domain + write(logunit,F0I) subname,'atm_mesh = ', infodata%atm_mesh write(logunit,F0R) subname,'nextsw_cday = ', infodata%nextsw_cday write(logunit,F0R) subname,'precip_fact = ', infodata%precip_fact diff --git a/externals/ekat b/externals/ekat index 0811e6cad49..fb4babcf3a2 160000 --- a/externals/ekat +++ b/externals/ekat @@ -1 +1 @@ -Subproject commit 0811e6cad49b0f10d6c343bb6fed97e6e98fb794 +Subproject commit fb4babcf3a24c14e9e94d71df152a7f097805c14 diff --git a/mkdocs.yaml b/mkdocs.yaml index aaeefb4c81f..3c7a2f93bdb 100644 --- a/mkdocs.yaml +++ b/mkdocs.yaml @@ -1,9 +1,20 @@ site_name: E3SM nav: - - Introduction: 'index.md' - - 'Developing Docs': 'https://acme-climate.atlassian.net/wiki/spaces/DOC/pages/3924787306/Developing+Documentation' + - Home: 'index.md' + - E3SM Basics: + - 'index.md' + - Installation: 'installation.md' + - User Guide: 'user-guide/index.md' + - Development: 'development.md' - Components: '*include ./components/*/mkdocs.yml' + - Tools: '*include ./tools/*/mkdocs.yml' + - More Information: + - 'E3SM-Project' : 'http://docs.e3sm.org' + - 'e3sm.org' : 'http://e3sm.org' + +repo_name: E3SM-Project/E3SM +repo_url: https://github.com/E3SM-Project/E3SM theme: name: material @@ -18,15 +29,30 @@ theme: toggle: icon: material/weather-night name: Switch to light mode + icon: + admonition: + note: octicons/tag-16 features: - - navigation.indices + - navigation.indexes - navigation.instant + - navigation.instant.prefetch - navigation.sections + - navigation.path + - navigation.tracking - navigation.top -# - navigation.tabs + - search.suggest + - search.highlight + - search.share + - content.code.select + - content.code.copy + - content.action.view + - content.tooltips + markdown_extensions: + - admonition - footnotes + - pymdownx.details - pymdownx.highlight - pymdownx.superfences - pymdownx.tabbed: @@ -34,11 +60,13 @@ markdown_extensions: - pymdownx.arithmatex: generic: true - md_in_html + - tables plugins: - monorepo + - search - bibtex: - bib_file: components/elm/docs/refs.bib + bib_dir: docs/refs extra_javascript: - javascript/mathjax.js diff --git a/share/build/buildlib.spio b/share/build/buildlib.spio index d65d5547936..49b898202f7 100755 --- a/share/build/buildlib.spio +++ b/share/build/buildlib.spio @@ -106,6 +106,9 @@ def buildlib(bldroot, installpath, case): if "ADIOS2_ROOT" in os.environ: cmake_opts += "-DWITH_ADIOS2:BOOL=ON " + if "FROM_CREATE_TEST" in os.environ and os.environ["FROM_CREATE_TEST"] == "True": + cmake_opts += "-DADIOS_BP2NC_TEST:BOOL=ON " + if debug: cmake_opts += "-DPIO_ENABLE_LOGGING=ON " # Case changes for NetCDF/NETCDF forces us to do this. For other packages diff --git a/tools/generate_domain_files/docs/index.md b/tools/generate_domain_files/docs/index.md new file mode 100644 index 00000000000..57858205140 --- /dev/null +++ b/tools/generate_domain_files/docs/index.md @@ -0,0 +1,47 @@ +# Generating Domain Files + +Domain files are needed at runtime by the coupler, data models, and land model. The land model uses the mask to determine where to run and the coupler use the land fraction to merge fluxes from multiple surface types to the atmosphere above them. + +Domain files are created from a conservative, monotone mapping file from the ocean grid (where the mask is defined) to the atmosphere grid. + +## Environment + +The new domain generation tool requires a few special packages, such as xarray, numba, and itertools. These are all included in the E3SM unified environment: + + +Alternatively, a simple conda environment can be created with the following command: + +```shell +conda create --name example_env --channel conda-forge xarray numpy numba scikit-learn netcdf4 +``` + +## Map File Generation + +The map file used to generate the domain 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 +ncremap -5 -a traave --src_grd=${OCN_GRID} --dst_grd=${ATM_GRID} --map_file=${MAP_FILE} +``` + +Note that existing ocean grid files can be found in the inputdata repository: `inputdata/ocn/mpas-o//` + +The 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_FILE_PATH}/ne${NE}.g +GenerateVolumetricMesh --in ${GRID_FILE_PATH}/ne${NE}.g --out ${GRID_FILE_PATH}/ne${NE}pg2.g --np 2 --uniform +ConvertMeshToSCRIP --in ${GRID_FILE_PATH}/ne${NE}pg2.g --out ${GRID_FILE_PATH}/ne${NE}pg2_scrip.nc +``` + +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.). + +## Running the Domain Generation Tool + +Below is a typical example of how to invoke the domain generation tool from the command line: + +```shell +NE=30 +MAP_FILE=${MAP_FILE_ROOT}/map_oEC60to30v3_to_ne${NE}pg2_traave.20240313.nc +python generate_domain_files_E3SM.py -m ${MAP_FILE} -o oEC60to30v3 -l ne${NE}pg2 --date-stamp=9999 --output-root=${OUTPUT_ROOT} +``` diff --git a/tools/generate_domain_files/generate_domain_files_E3SM.py b/tools/generate_domain_files/generate_domain_files_E3SM.py new file mode 100644 index 00000000000..efaa7c60c15 --- /dev/null +++ b/tools/generate_domain_files/generate_domain_files_E3SM.py @@ -0,0 +1,367 @@ +#!/usr/bin/env python3 +#--------------------------------------------------------------------------------------------------- +''' +This is a replacement for the legacy gen_domain tool created for CESM. +Most legacy functionality is reproduced, with the notable exception of +the pole point latitude adjustment needed for the CESM FV grid. + +Created April, 2024 by Walter Hannah (LLNL) +''' +#--------------------------------------------------------------------------------------------------- +''' +The map file used to generate the domain 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 + + ncremap -5 -a traave --src_grd=${OCN_GRID} --dst_grd=${ATM_GRID} --map_file=${MAP_FILE} + +''' +#--------------------------------------------------------------------------------------------------- +import datetime, os, numpy as np, xarray as xr, numba, itertools +user, host = os.getenv('USER'), os.getenv('HOST') +source_code_meta = 'generate_domain_E3SM.py' +#--------------------------------------------------------------------------------------------------- +class clr:END,RED,GREEN,MAGENTA,CYAN = '\033[0m','\033[31m','\033[32m','\033[35m','\033[36m' +#--------------------------------------------------------------------------------------------------- +usage = ''' +python generate_domain_files_E3SM.py -m + -o + -l + [--output-root ] + [--date-stamp ] + [--fminval ] + [--fmaxval ] + [--set-omask] + +Purpose: + For "bi-grid" configurations of E3SM (land grid is same as atmos): + Given a mapping file from the ocean grid (where the mask is defined) + to the atmosphere grid, this tool creates land and ocean domain files + needed by data model components (ex. datm, dlnd, docn) + + For "tri-grid" configurations of E3SM (land grid is different from atmos/ocn): + In addition to running this tool with the ocn->atm map as above, + a second iteration is needed with a similar ocn->lnd map. + +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 domain files are created: + + domain.lnd._..nc + land domain file on the land/atmos grid with a land fraction + corresponding to (1-ocnfrac) mask mapped to the land grid + + domain.ocn._..nc + ocean domain on the land/atmos grid with an ocean fraction based + on the ocean grid mask mapped to the land/atmos grid for when + atm,lnd,ice,ocn are all on the same grid + (not compatible with MPAS sea-ice) + + domain.ocn...nc + ocean domain on the ocean grid +''' +from optparse import OptionParser +parser = OptionParser(usage=usage) +parser.add_option('-m', + dest='map_file', + default=None, + help='Input mapping file from ocean to atmosphere grid - '+\ + 'This is the primary source from which the ocean and'+\ + 'land domains will be determined') +parser.add_option('-l', + dest='lnd_grid', + default=None, + help='Output land grid name') +parser.add_option('-o', + dest='ocn_grid', + default=None, + help='Output ocean grid name') +parser.add_option('--output-root', + dest='output_root', + default='./', + help='Output path for domain files') +parser.add_option('--date-stamp', + dest='date_stamp', + default=None, + help='Creation date stamp for domain files') +parser.add_option('--fminval', + dest='fminval', + default=1e-3, + help='Minimum allowable land fraction (reset to 0 below fminval)') +parser.add_option('--fmaxval', + dest='fmaxval', + default=1, + help='Maximum allowable land fraction (reset to 1 above fmaxval)') +parser.add_option('--set-omask', + dest='set_omask', + default=False, + action='store_true', + help='If True then an ocean mask is not required and will '+\ + 'simply be set to a vector of 1\'s if mask_a is not '+\ + 'present in the input mapping file. If --set-omask is '+\ + 'omitted, then mask_a is required and an error will be '+\ + 'raised if it does not exist in the input mapping file.') +(opts, args) = parser.parse_args() +#--------------------------------------------------------------------------------------------------- +def main(): + global domain_a_grid_file, domain_b_grid_file, ocn_grid_file, atm_grid_file + #------------------------------------------------------------------------------- + # check for valid input arguments + + if opts.map_file is None: + raise ValueError(f'{clr.RED}input map file was not specified{clr.END}') + if opts.lnd_grid is None: + raise ValueError(f'{clr.RED}land grid name was not specified{clr.END}') + if opts.ocn_grid is None: + raise ValueError(f'{clr.RED}ocean grid name was not specified{clr.END}') + if not os.path.exists(opts.output_root) : + raise ValueError(f'{clr.RED}Output root path does not exist{clr.END}') + + #------------------------------------------------------------------------------- + # 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 names + + domain_file_ocn_on_ocn = f'{opts.output_root}/domain.ocn.{opts.ocn_grid}.{cdate}.nc' + domain_file_lnd_on_atm = f'{opts.output_root}/domain.lnd.{opts.lnd_grid}_{opts.ocn_grid}.{cdate}.nc' + domain_file_ocn_on_atm = f'{opts.output_root}/domain.ocn.{opts.lnd_grid}_{opts.ocn_grid}.{cdate}.nc' + + # cosmetic clean up of file names + domain_file_ocn_on_ocn = domain_file_ocn_on_ocn.replace('//','/') + domain_file_lnd_on_atm = domain_file_lnd_on_atm.replace('//','/') + domain_file_ocn_on_atm = domain_file_ocn_on_atm.replace('//','/') + + #----------------------------------------------------------------------------- + # print some informative stuff + + print(f''' + Input files and parameter values: + {clr.GREEN}map_file {clr.END}: {opts.map_file} + {clr.GREEN}lnd_grid {clr.END}: {opts.lnd_grid} + {clr.GREEN}ocn_grid {clr.END}: {opts.ocn_grid} + {clr.GREEN}fminval {clr.END}: {opts.fminval} + {clr.GREEN}fmaxval {clr.END}: {opts.fmaxval} + {clr.GREEN}set_omask {clr.END}: {opts.set_omask} + ''') + + #----------------------------------------------------------------------------- + # open map file as dataset + + ds = xr.open_dataset(opts.map_file) + + #----------------------------------------------------------------------------- + # read grid meta-data from map file + + if 'domain_a' in ds.attrs.keys(): domain_a_grid_file = ds.attrs['domain_a'] + if 'domain_b' in ds.attrs.keys(): domain_b_grid_file = ds.attrs['domain_b'] + + if 'grid_file_ocn' in ds.attrs.keys(): + ocn_grid_file = ds.attrs['grid_file_ocn'] + else: + ocn_grid_file = ds.attrs['grid_file_src'] + + if 'grid_file_ocn' in ds.attrs.keys(): + atm_grid_file = ds.attrs['grid_file_atm'] + else: + atm_grid_file = ds.attrs['grid_file_dst'] + + #----------------------------------------------------------------------------- + # print some useful information from the map file + + print(f''' + Grid information from map file: + {clr.CYAN}domain_a file {clr.END}: {domain_a_grid_file} + {clr.CYAN}domain_b file {clr.END}: {domain_b_grid_file} + {clr.CYAN}ocn_grid_file {clr.END}: {ocn_grid_file} + {clr.CYAN}atm_grid_file {clr.END}: {atm_grid_file} + {clr.CYAN}ocn grid size (n_a){clr.END}: {len(ds.n_a)} + {clr.CYAN}atm grid size (n_b){clr.END}: {len(ds.n_b)} + {clr.CYAN}sparse mat size (n_s){clr.END}: {len(ds.n_s)} + ''') + + #----------------------------------------------------------------------------- + # Create ocean domain on ocean grid (domain_file_ocn_on_ocn) + + # Get ocn mask on ocn grid + omask = get_mask(ds,opts,suffix='_a') + ofrac = xr.zeros_like(ds['area_a']) + + ds_out = xr.Dataset() + ds_out['xc'] = ds['xc_a'] .expand_dims(dim='nj').rename({'n_a':'ni'}) + ds_out['yc'] = ds['yc_a'] .expand_dims(dim='nj').rename({'n_a':'ni'}) + ds_out['xv'] = ds['xv_a'] .expand_dims(dim='nj').rename({'n_a':'ni','nv_a':'nv'}) + ds_out['yv'] = ds['yv_a'] .expand_dims(dim='nj').rename({'n_a':'ni','nv_a':'nv'}) + ds_out['area'] = ds['area_a'].expand_dims(dim='nj').rename({'n_a':'ni'}) + ds_out['frac'] = ofrac .expand_dims(dim='nj').rename({'n_a':'ni'}) + ds_out['mask'] = omask .expand_dims(dim='nj').rename({'n_a':'ni'}) + + add_metadata(ds_out) + + ds_out.to_netcdf(path=domain_file_ocn_on_ocn,mode='w') + + print(f'successfully created domain file: {clr.MAGENTA}{domain_file_ocn_on_ocn}{clr.END}') + + #----------------------------------------------------------------------------- + # Create land and ocean domains on atmosphere grid + + xc = ds['xc_b'] + yc = ds['yc_b'] + xv = ds['xv_b'] + yv = ds['yv_b'] + area = ds['area_b'] + + mask_a = get_mask(ds,opts,suffix='_a') + frac_a = xr.where( mask_a!=0, xr.ones_like(ds['area_a']), xr.zeros_like(ds['area_a']) ) + + # compute ocn fraction on atm grid + ofrac = compute_ofrac_on_atm( len(ds['n_s']), np.zeros(ds['area_b'].shape), + frac_a.values, ds['S'].values, + ds['row'].values-1, ds['col'].values-1 ) + ofrac = xr.DataArray(ofrac,dims=['n_b']) + + # lfrac is area frac of mask "_a" on grid "_b" or float(mask) + lfrac = xr.zeros_like(ds['area_b']) + + # convert to land fraction + lfrac_min = opts.fmaxval + lfrac_max = opts.fminval + omask = xr.ones_like(ds['area_b'],dtype=np.int32) + lmask = xr.zeros_like(ds['area_b'],dtype=np.int32) + lfrac = 1 - ofrac + lfrac_min = lfrac.min().values + lfrac_max = lfrac.max().values + lfrac = xr.where( lfrac>opts.fmaxval, 1, lfrac ) + lfrac = xr.where( lfrac