diff --git a/.github/dependabot.yml b/.github/dependabot.yml
index 4fb88c2dc67..94078c40720 100644
--- a/.github/dependabot.yml
+++ b/.github/dependabot.yml
@@ -7,9 +7,6 @@ updates:
schedule:
interval: "weekly"
assignees:
- - "rljacob"
+ - "bartgol"
reviewers:
- "mahf708"
- - "bartgol"
- labels:
- - "AT: Integrate Without Testing"
diff --git a/.github/workflows/e3sm-gh-ci-cime-tests.yml b/.github/workflows/e3sm-gh-ci-cime-tests.yml
index 5c6ff081f73..d973b90dc05 100644
--- a/.github/workflows/e3sm-gh-ci-cime-tests.yml
+++ b/.github/workflows/e3sm-gh-ci-cime-tests.yml
@@ -2,7 +2,9 @@ name: gh
on:
pull_request:
- branches: [ master ]
+ branches:
+ - master
+ - maint-3.0
paths:
# first, yes to these
- '.github/workflows/e3sm-gh-ci-cime-tests.yml'
@@ -40,7 +42,7 @@ jobs:
- SMS_D_Ln5_P4.ne4pg2_oQU480.F2010-SCREAMv1-MPASSI.ghci-oci_gnu
- ERS_Ld5_P4.ne4pg2_oQU480.F2010-SCREAMv1-MPASSI.ghci-oci_gnu.eamxx-prod
container:
- image: ghcr.io/e3sm-project/containers-ghci:ghci-0.2.0
+ image: ghcr.io/e3sm-project/containers-ghci:ghci-0.2.1
steps:
-
diff --git a/.github/workflows/e3sm-gh-ci-w-cime-tests.yml b/.github/workflows/e3sm-gh-ci-w-cime-tests.yml
index f51aa88a34c..0e30fc4e0a8 100644
--- a/.github/workflows/e3sm-gh-ci-w-cime-tests.yml
+++ b/.github/workflows/e3sm-gh-ci-w-cime-tests.yml
@@ -2,7 +2,9 @@ name: gh-w
on:
pull_request:
- branches: [ master ]
+ branches:
+ - master
+ - maint-3.0
paths-ignore:
- 'mkdocs.yaml'
- 'docs/**'
@@ -27,7 +29,7 @@ jobs:
- SMS_D_Ld1_P8.ne4pg2_oQU480.WCYCL2010NS.ghci-oci_gnu
- ERS_Ld3_P8.ne4pg2_oQU480.WCYCL2010NS.ghci-oci_gnu.allactive-wcprod_1850
container:
- image: ghcr.io/e3sm-project/containers-ghci:ghci-0.2.0
+ image: ghcr.io/e3sm-project/containers-ghci:ghci-0.2.1
steps:
-
diff --git a/.github/workflows/e3sm-gh-md-linter.yml b/.github/workflows/e3sm-gh-md-linter.yml
index ad24487695e..8be6f87893b 100644
--- a/.github/workflows/e3sm-gh-md-linter.yml
+++ b/.github/workflows/e3sm-gh-md-linter.yml
@@ -7,8 +7,6 @@ on:
branches: ["master"]
paths:
- '**/*.md'
- # for now let's not lint files in eamxx
- - '!components/eamxx/**/*.md'
concurrency:
group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.run_id }}
@@ -27,7 +25,7 @@ jobs:
with:
files: '**/*.md'
separator: ","
- - uses: DavidAnson/markdownlint-cli2-action@v18
+ - uses: DavidAnson/markdownlint-cli2-action@v19
if: steps.changed-files.outputs.any_changed == 'true'
with:
config: 'docs/.markdownlint.json'
diff --git a/.github/workflows/e3sm-gh-pages.yml b/.github/workflows/e3sm-gh-pages.yml
index dec9bc696bf..543295a9030 100644
--- a/.github/workflows/e3sm-gh-pages.yml
+++ b/.github/workflows/e3sm-gh-pages.yml
@@ -4,9 +4,27 @@ on:
# Runs every time master branch is updated
push:
branches: ["master"]
+ # But only if docs-related files are touched
+ paths:
+ - .github/workflows/e3sm-gh-pages.yml
+ - ./mkdocs.yml
+ - ./tools/*/mkdocs.yml
+ - ./tools/docs/**
+ - components/*/mkdocs.yaml
+ - components/*/docs/**
+ - components/eamxx/cime_config/namelist_defaults_scream.xml
# Runs every time a PR is open against master
pull_request:
branches: ["master"]
+ # But only if docs-related files are touched
+ paths:
+ - .github/workflows/e3sm-gh-pages.yml
+ - ./mkdocs.yml
+ - ./tools/*/mkdocs.yml
+ - ./tools/docs/**
+ - components/*/mkdocs.yaml
+ - components/*/docs/**
+ - components/eamxx/cime_config/namelist_defaults_scream.xml
workflow_dispatch:
concurrency:
diff --git a/.github/workflows/e3sm-gh-tools-mkatmsrffile-test.yml b/.github/workflows/e3sm-gh-tools-mkatmsrffile-test.yml
deleted file mode 100644
index cacb951b8a8..00000000000
--- a/.github/workflows/e3sm-gh-tools-mkatmsrffile-test.yml
+++ /dev/null
@@ -1,88 +0,0 @@
-name: mkatmsrffile
-
-on:
- push:
- branches: [ master ]
- pull_request:
- branches: [ master ]
- paths:
- - 'components/eam/tools/mkatmsrffile/mkatmsrffile.py'
- schedule:
- - cron: '00 15 * * 2'
- workflow_dispatch:
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.run_id }}
- cancel-in-progress: true
-
-jobs:
- mkatmsrffile-test:
- if: ${{ github.repository == 'E3SM-Project/E3SM' }}
- runs-on: ubuntu-latest
- defaults:
- run:
- shell: bash -l {0}
- outputs:
- event_name: ${{ github.event_name }}
- steps:
- -
- name: Repository checkout
- uses: actions/checkout@v4
- with:
- show-progress: false
- submodules: false
- -
- name: Conda setup
- uses: conda-incubator/setup-miniconda@v3
- with:
- activate-environment: "envmkatmsrffile"
- miniforge-version: latest
- channel-priority: strict
- auto-update-conda: true
- python-version: 3.11
- -
- name: Install dependencies
- run: |
- echo $CONDA_PREFIX
- conda install -y nco xarray numba numpy netcdf4 -c conda-forge
- -
- name: Run tests
- working-directory: components/eam/tools/mkatmsrffile
- run: |
- echo $CONDA_PREFIX
- wget https://web.lcrc.anl.gov/public/e3sm/inputdata/atm/cam/chem/trop_mozart/dvel/clim_soilw.nc
- wget https://web.lcrc.anl.gov/public/e3sm/inputdata/atm/cam/chem/trop_mozart/dvel/regrid_vegetation.nc
- wget https://web.lcrc.anl.gov/public/e3sm/inputdata/atm/cam/chem/trop_mozart/dvel/map_1x1_to_ne30pg2_traave_c20240903.nc
- python mkatmsrffile.py --map_file=map_1x1_to_ne30pg2_traave_c20240903.nc --vegetation_file=regrid_vegetation.nc --soil_water_file=clim_soilw.nc --dst_grid=ne30pg2
-
- mkatmsrffile-notify:
- needs: mkatmsrffile-test
- if: ${{ failure() && needs.mkatmsrffile-test.outputs.event_name != 'pull_request' }}
- runs-on: ubuntu-latest
- steps:
- - name: Create issue
- run: |
- previous_issue_number=$(gh issue list \
- --label "$LABELS" \
- --json number \
- --jq '.[0].number')
- if [[ -n $previous_issue_number ]]; then
- gh issue comment "$previous_issue_number" \
- --body "$BODY"
- else
- gh issue create \
- --title "$TITLE" \
- --assignee "$ASSIGNEES" \
- --label "$LABELS" \
- --body "$BODY"
- fi
- env:
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- GH_REPO: ${{ github.repository }}
- TITLE: mkatmsrffile test failure
- ASSIGNEES: whannah1
- LABELS: bug,notify-mkatmsrffile-gh-action
- BODY: |
- Workflow failed! There's likely an issue in the mkatmsrffile tool! For more information, please see:
- - Workflow URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} (number ${{ github.run_number }}, attempt ${{ github.run_attempt }})
- - Workflow SHA: ${{ github.sha }}
diff --git a/.github/workflows/eamxx-gh-ci-standalone.yml b/.github/workflows/eamxx-gh-ci-standalone.yml
deleted file mode 100644
index 19a2ec9cd8e..00000000000
--- a/.github/workflows/eamxx-gh-ci-standalone.yml
+++ /dev/null
@@ -1,60 +0,0 @@
-name: gh-standalone
-
-on:
- pull_request:
- branches: [ master ]
- paths:
- # first, yes to these
- - '.github/workflows/eamxx-gh-ci-standalone.yml'
- - 'cime_config/machine/config_machines.xml'
- - 'components/eamxx/**'
- - 'components/homme/**'
- # second, no to these
- - '!components/eamxx/docs/**'
- - '!components/eamxx/mkdocs.yml'
-
- workflow_dispatch:
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.run_id }}
- cancel-in-progress: true
-
-jobs:
-
- ci:
- if: ${{ github.repository == 'E3SM-Project/E3SM' }}
- runs-on: ubuntu-latest
- strategy:
- fail-fast: false
- matrix:
- test:
- - sp
- - opt
- - dbg
- - fpe
- container:
- image: ghcr.io/e3sm-project/containers-standalone-ghci:standalone-ghci-0.1.0
-
- steps:
- -
- name: Checkout
- uses: actions/checkout@v4
- with:
- show-progress: false
- submodules: recursive
- -
- name: standalone
- env:
- SHELL: sh
- run: |
- # TODO: get rid of this extra line if we can?
- git config --global safe.directory '*'
- ./components/eamxx/scripts/test-all-scream -m ghci-oci -t ${{ matrix.test }} -c BUILD_SHARED_LIBS=ON
- -
- name: Artifacts
- uses: actions/upload-artifact@v4
- if: ${{ always() }}
- with:
- name: ${{ matrix.test }}
- path: |
- components/eamxx/ctest-build/*/Testing/Temporary/Last*.log
diff --git a/.github/workflows/eamxx-gh-pages.yml b/.github/workflows/eamxx-gh-pages.yml
deleted file mode 100644
index 2e763c544cd..00000000000
--- a/.github/workflows/eamxx-gh-pages.yml
+++ /dev/null
@@ -1,89 +0,0 @@
-# This workflow aims to automatically rebuild eamxx documentation
-# every time the master branch is updated on github and within every PR
-
-name: EAMxx Docs
-
-on:
- # Runs every time master branch is updated
- push:
- branches: [ master ]
- # Only if docs-related files are touched
- paths:
- - components/eamxx/mkdocs.yaml
- - components/eamxx/docs/**
- - components/eamxx/cime_config/namelist_defaults_scream.xml
- # Runs every time a PR is open against master
- pull_request:
- branches: [ master ]
- # Only if docs-related files are touched
- paths:
- - components/eamxx/mkdocs.yaml
- - components/eamxx/docs/**
- - components/eamxx/cime_config/namelist_defaults_scream.xml
-
- label:
- types:
- - created
-
- workflow_dispatch:
-
-concurrency:
- # Prevent 2+ copies of this workflow from running concurrently
- group: eamxx-docs-action
-
-jobs:
-
- eamxx-docs:
- if: ${{ github.repository == 'E3SM-Project/scream' }}
- runs-on: ubuntu-latest
-
- steps:
- - name: Check out the repository
- uses: actions/checkout@v4
- with:
- persist-credentials: false
- show-progress: false
- # TODO: git rid of dependency on CIME
- # TODO: another option to investigate is a sparse checkout.
- # In the scream repo, all other components do not need to be checked out.
- # And even in the upstream, we mainly need only components/xyz/docs (and a few more places).
- submodules: true
-
- - name: Show action trigger
- run: |
- echo "= The job was automatically triggered by a ${{github.event_name}} event."
-
- - name: Set up Python 3.11
- uses: actions/setup-python@v5
- with:
- python-version: "3.11"
-
- - name: Install Python deps
- run: |
- pip install mkdocs pymdown-extensions mkdocs-material mdutils mkdocs-bibtex
-
- - name: Generate EAMxx params docs
- working-directory: components/eamxx/scripts
- run: |
- ./eamxx-params-docs-autogen
-
- - name: Build docs
- working-directory: components/eamxx
- run: |
- mkdocs build --strict --verbose
-
- # only deploy to the main github page when there is a push to master
- - if: ${{ github.event_name == 'push' }}
- name: GitHub Pages action
- uses: JamesIves/github-pages-deploy-action@v4
- with:
- # Do not remove existing pr-preview pages
- clean-exclude: pr-preview
- folder: ./components/eamxx/site
-
- # If it's a PR from within the same repo, deploy to a preview page
- - if: ${{ github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository }}
- name: Preview docs
- uses: rossjrw/pr-preview-action@v1
- with:
- source-dir: components/eamxx/site/
diff --git a/.github/workflows/eamxx-sa-testing.yml b/.github/workflows/eamxx-sa-testing.yml
index a4397d4fdba..7bc20aeaca5 100644
--- a/.github/workflows/eamxx-sa-testing.yml
+++ b/.github/workflows/eamxx-sa-testing.yml
@@ -5,6 +5,19 @@ on:
pull_request:
branches: [ master ]
types: [opened, synchronize, ready_for_review, reopened]
+ paths:
+ # first, yes to these
+ - '.github/workflows/eamxx-sa-testing.yml'
+ - 'cime_config/machine/config_machines.xml'
+ - 'components/eamxx/**'
+ - 'components/homme/**'
+ - 'externals/ekat'
+ - 'externals/mam4xx'
+ - 'externals/haero'
+ - 'externals/scorpio'
+ # second, no to these
+ - '!components/eamxx/docs/**'
+ - '!components/eamxx/mkdocs.yml'
# Manual run is used to bless
workflow_dispatch:
@@ -40,83 +53,18 @@ concurrency:
env:
# Submit to cdash only for nightlies or if the user explicitly forced a submission via workflow dispatch
submit: ${{ github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && inputs.submit) }}
+ generate: ${{ github.event_name == 'workflow_dispatch' && inputs.bless }}
jobs:
- pre_process_pr:
- if: ${{ github.event_name == 'pull_request' }}
- runs-on: ubuntu-latest # This job can run anywhere
- outputs:
- relevant_paths: ${{ steps.check_paths.outputs.value }}
- labels: ${{ steps.get_labels.outputs.labels }}
- steps:
- - name: Check files modified by PR
- id: check_paths
- run: |
- paths=(
- components/eamxx
- components/eam/src/physics/rrtmgp
- components/eam/src/physics/p3/scream
- components/eam/src/physics/cam
- components/eam/src/physics/rrtmgp/external
- externals/ekat
- externals/scorpio
- externals/haero
- externals/YAKL
- .github/workflows/eamxx-sa-testing.yml
- )
- pattern=$(IFS=\|; echo "${paths[*]}")
-
- # Use the GitHub API to get the list of changed files
- # There are page size limits, so do it in chunks
- page=1
- while true; do
- response=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
- "https://api.github.com/repos/E3SM-Project/scream/pulls/${{ github.event.number }}/files?per_page=100&page=$page")
-
- # Check if the response is empty, and break if it is
- [ -z "$response" ] && break
-
- changed_files+=$(echo "$response" | grep -o '"filename": *"[^"]*"' | sed 's/"filename": *//; s/"//g')$'\n'
-
- # Check if there are more pages, and quite if there aren't
- [[ $(echo "$response" | jq '. | length') -lt 100 ]] && break
-
- page=$((page + 1))
- done
-
- # Check for matches and echo the matching files (or "" if none)
- matching_files=$(echo "$changed_files" | grep -E "^($pattern)" || echo "")
- if [[ -n "$matching_files" ]]; then
- echo "Found relevant files: $matching_files"
- echo "value=true" >> $GITHUB_OUTPUT
- else
- echo "No relevant files touched by this PR."
- echo "value=false" >> $GITHUB_OUTPUT
- fi
- - name: Retrieve PR labels
- id: get_labels
- run: |
- labels="${{ join(github.event.pull_request.labels.*.name, ',') }}"
- echo "labels=${labels}" >> $GITHUB_OUTPUT
gcc-openmp:
- needs: [pre_process_pr]
if: |
- !failure() && !cancelled() &&
- (
- github.event_name == 'schedule' ||
+ ${{
+ github.event_name != 'workflow_dispatch' ||
(
- github.event_name == 'pull_request' &&
- needs.pre_process_pr.outputs.relevant_paths=='true' &&
- !contains(needs.pre_process_pr.outputs.labels,'CI: skip gcc') &&
- !contains(needs.pre_process_pr.outputs.labels,'CI: skip openmp') &&
- !contains(needs.pre_process_pr.outputs.labels,'CI: skip eamxx-sa') &&
- !contains(needs.pre_process_pr.outputs.labels,'CI: skip eamxx-all')
- ) || (
- github.event_name == 'workflow_dispatch' &&
github.event.inputs.job_to_run == 'gcc-openmp' ||
github.event.inputs.job_to_run == 'all'
)
- )
+ }}
runs-on: [self-hosted, ghci-snl-cpu, gcc]
strategy:
fail-fast: false
@@ -132,14 +80,6 @@ jobs:
submodules: recursive
- name: Show action trigger
uses: ./.github/actions/show-workflow-trigger
- - name: Set test-all inputs based on event specs
- run: |
- echo "generate=false" >> $GITHUB_ENV
- if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
- if [ "${{ inputs.bless }}" == "true" ]; then
- echo "generate=true" >> $GITHUB_ENV
- fi
- fi
- name: Run tests
uses: ./.github/actions/test-all-scream
with:
@@ -149,24 +89,14 @@ jobs:
submit: ${{ env.submit }}
cmake-configs: Kokkos_ENABLE_OPENMP=ON
gcc-cuda:
- needs: [pre_process_pr]
if: |
- !failure() && !cancelled() &&
- (
- github.event_name == 'schedule' ||
+ ${{
+ github.event_name != 'workflow_dispatch' ||
(
- github.event_name == 'pull_request' &&
- needs.pre_process_pr.outputs.relevant_paths=='true' &&
- !contains(needs.pre_process_pr.outputs.labels,'CI: skip gcc') &&
- !contains(needs.pre_process_pr.outputs.labels,'CI: skip cuda') &&
- !contains(needs.pre_process_pr.outputs.labels,'CI: skip eamxx-sa') &&
- !contains(needs.pre_process_pr.outputs.labels,'CI: skip eamxx-all')
- ) || (
- github.event_name == 'workflow_dispatch' &&
- github.event.inputs.job_to_run == 'gcc-cuda' ||
+ github.event.inputs.job_to_run == 'gcc-cuda' ||
github.event.inputs.job_to_run == 'all'
)
- )
+ }}
runs-on: [self-hosted, ghci-snl-cuda, cuda, gcc]
strategy:
fail-fast: false
@@ -182,14 +112,6 @@ jobs:
submodules: recursive
- name: Show action trigger
uses: ./.github/actions/show-workflow-trigger
- - name: Set test-all inputs based on event specs
- run: |
- echo "generate=false" >> $GITHUB_ENV
- if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
- if [ "${{ inputs.bless }}" == "true" ]; then
- echo "generate=true" >> $GITHUB_ENV
- fi
- fi
- name: Get CUDA Arch
run: |
# Ensure nvidia-smi is available
diff --git a/.github/workflows/eamxx-scripts-tests.yml b/.github/workflows/eamxx-scripts-tests.yml
index a14cdc4f350..2cdd6f8758f 100644
--- a/.github/workflows/eamxx-scripts-tests.yml
+++ b/.github/workflows/eamxx-scripts-tests.yml
@@ -5,6 +5,10 @@ on:
pull_request:
branches: [ master ]
types: [opened, synchronize, ready_for_review, reopened]
+ paths:
+ - 'components/eamxx/scripts/**'
+ - 'components/eamxx/cime_config/**'
+ - '.github/workflows/eamxx-scripts-tests.yml'
# Manual run for debug purposes only
workflow_dispatch:
@@ -30,68 +34,7 @@ env:
submit: ${{ github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && inputs.submit) }}
jobs:
- pre_process_pr:
- if: ${{ github.event_name == 'pull_request' }}
- runs-on: ubuntu-latest # This job can run anywhere
- outputs:
- relevant_paths: ${{ steps.check_paths.outputs.value}}
- labels: ${{ steps.get_labels.outputs.labels }}
- steps:
- - name: Check files modified by PR
- id: check_paths
- run: |
- paths=(
- components/eamxx/scripts
- components/eamxx/cime_config/eamxx
- components/eamxx/cime_config/build
- components/eamxx/cime_config/yaml_utils.py
- .github/workflows/eamxx-scripts-tests.yml
- )
- pattern=$(IFS=\|; echo "${paths[*]}")
-
- # Use the GitHub API to get the list of changed files
- # There are page size limits, so do it in chunks
- page=1
- while true; do
- response=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
- "https://api.github.com/repos/E3SM-Project/scream/pulls/${{ github.event.number }}/files?per_page=100&page=$page")
-
- # Check if the response is empty, and break if it is
- [ -z "$response" ] && break
-
- changed_files+=$(echo "$response" | grep -o '"filename": *"[^"]*"' | sed 's/"filename": *//; s/"//g')$'\n'
-
- # Check if there are more pages, and quite if there aren't
- [[ $(echo "$response" | jq '. | length') -lt 100 ]] && break
-
- page=$((page + 1))
- done
-
- # Check for matches and echo the matching files (or "" if none)
- matching_files=$(echo "$changed_files" | grep -E "^($pattern)" || echo "")
- if [[ -n "$matching_files" ]]; then
- echo "Found relevant files: $matching_files"
- echo "value=true" >> $GITHUB_OUTPUT
- else
- echo "No relevant files touched by this PR."
- echo "value=false" >> $GITHUB_OUTPUT
- fi
- - name: Retrieve PR labels
- id: get_labels
- run: |
- labels="${{ join(github.event.pull_request.labels.*.name, ',') }}"
- echo "labels=${labels}" >> $GITHUB_OUTPUT
cpu-gcc:
- needs: [pre_process_pr]
- if: |
- !failure() && !cancelled() &&
- (
- github.event_name != 'pull_request' ||
- (
- needs.pre_process_pr.outputs.relevant_paths == 'true' &&
- !contains(needs.pre_process_pr.outputs.labels, 'CI: skip eamxx-all')
- )
- )
runs-on: [self-hosted, gcc, ghci-snl-cpu]
steps:
- name: Check out the repository
diff --git a/.github/workflows/eamxx-v1-testing.yml b/.github/workflows/eamxx-v1-testing.yml
index d55ed8252a5..e738a4adcb9 100644
--- a/.github/workflows/eamxx-v1-testing.yml
+++ b/.github/workflows/eamxx-v1-testing.yml
@@ -5,6 +5,19 @@ on:
pull_request:
branches: [ master ]
types: [opened, synchronize, ready_for_review, reopened]
+ paths:
+ # first, yes to these
+ - '.github/workflows/eamxx-v1-testing.yml'
+ - 'cime_config/machine/config_machines.xml'
+ - 'components/eamxx/**'
+ - 'components/homme/**'
+ - 'externals/ekat'
+ - 'externals/mam4xx'
+ - 'externals/haero'
+ - 'externals/scorpio'
+ # second, no to these
+ - '!components/eamxx/docs/**'
+ - '!components/eamxx/mkdocs.yml'
# Manual run is used to bless
workflow_dispatch:
@@ -28,93 +41,40 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
-jobs:
- pre_process_pr:
- if: ${{ github.event_name == 'pull_request' }}
- runs-on: ubuntu-latest # This job can run anywhere
- outputs:
- relevant_paths: ${{ steps.check_paths.outputs.value }}
- labels: ${{ steps.get_labels.outputs.labels }}
- steps:
- - name: Check files modified by PR
- id: check_paths
- run: |
- paths=(
- components/eamxx
- components/eam/src/physics/rrtmgp
- components/eam/src/physics/p3/scream
- components/eam/src/physics/cam
- components/eam/src/physics/rrtmgp/external
- externals/ekat
- externals/scorpio
- externals/haero
- externals/YAKL
- .github/workflows/eamxx-v1-testing.yml
- )
- pattern=$(IFS=\|; echo "${paths[*]}")
-
- # Use the GitHub API to get the list of changed files
- # There are page size limits, so do it in chunks
- page=1
- while true; do
- response=$(curl -s -H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
- "https://api.github.com/repos/E3SM-Project/scream/pulls/${{ github.event.number }}/files?per_page=100&page=$page")
-
- # Check if the response is empty, and break if it is
- [ -z "$response" ] && break
-
- changed_files+=$(echo "$response" | grep -o '"filename": *"[^"]*"' | sed 's/"filename": *//; s/"//g')$'\n'
-
- # Check if there are more pages, and quite if there aren't
- [[ $(echo "$response" | jq '. | length') -lt 100 ]] && break
+env:
+ # Submit to cdash only for nightlies or if the user explicitly forced a submission via workflow dispatch
+ submit: ${{ github.event_name == 'schedule' || (github.event_name == 'workflow_dispatch' && inputs.submit) }}
+ # Generate only if user requested via workflow_dispatch
+ generate: ${{ github.event_name == 'workflow_dispatch' && inputs.bless }}
+ # Correct case folder suffix for generate/compare, used to find files to upload as artifacts
+ folder_suffix: ${{ github.event_name == 'workflow_dispatch' && inputs.bless && '.G' || '.C' }}
+ # Compare/generate flags for create_test
+ flags: ${{ github.event_name == 'workflow_dispatch' && inputs.bless && '-o -g -b master' || '-c -b master' }}
- page=$((page + 1))
- done
-
- # Check for matches and echo the matching files (or "" if none)
- matching_files=$(echo "$changed_files" | grep -E "^($pattern)" || echo "")
- if [[ -n "$matching_files" ]]; then
- echo "Found relevant files: $matching_files"
- echo "value=true" >> $GITHUB_OUTPUT
- else
- echo "No relevant files touched by this PR."
- echo "value=false" >> $GITHUB_OUTPUT
- fi
- - name: Retrieve PR labels
- id: get_labels
- run: |
- labels="${{ join(github.event.pull_request.labels.*.name, ',') }}"
- echo "labels=${labels}" >> $GITHUB_OUTPUT
+jobs:
cpu-gcc:
- needs: [pre_process_pr]
if: |
- !failure() && !cancelled() &&
- (
- github.event_name == 'schedule' ||
+ ${{
+ github.event_name != 'workflow_dispatch' ||
(
- github.event_name == 'pull_request' &&
- needs.pre_process_pr.outputs.relevant_paths=='true' &&
- !contains(needs.pre_process_pr.outputs.labels,'CI: skip gcc') &&
- !contains(needs.pre_process_pr.outputs.labels,'CI: skip eamxx-v1') &&
- !contains(needs.pre_process_pr.outputs.labels,'CI: skip eamxx-all')
- ) || (
- github.event_name == 'workflow_dispatch' &&
- github.event.inputs.job_to_run == 'cpu-gcc' ||
+ github.event.inputs.job_to_run == 'cpu-gcc' ||
github.event.inputs.job_to_run == 'all'
)
- )
+ }}
runs-on: [self-hosted, gcc, ghci-snl-cpu]
strategy:
matrix:
test:
- - full_name: ERS_Ln9.ne4_ne4.F2000-SCREAMv1-AQP1.ghci-snl-cpu_gnu.scream-output-preset-2
- short_name: ERS_Ln9.ne4_ne4.F2000-SCREAMv1-AQP1.scream-output-preset-2
- - full_name: ERS_P16_Ln22.ne30pg2_ne30pg2.FIOP-SCREAMv1-DP.ghci-snl-cpu_gnu.scream-dpxx-arm97
- short_name: ERS_P16_Ln22.ne30pg2_ne30pg2.FIOP-SCREAMv1-DP.scream-dpxx-arm97
- - full_name: ERS_Ln22.ne4pg2_ne4pg2.F2010-SCREAMv1.ghci-snl-cpu_gnu.scream-small_kernels--scream-output-preset-5
- short_name: ERS_Ln22.ne4pg2_ne4pg2.F2010-SCREAMv1.scream-small_kernels--scream-output-preset-5
- - full_name: SMS_D_Ln5.ne4pg2_oQU480.F2010-SCREAMv1-MPASSI.ghci-snl-cpu_gnu.scream-mam4xx-all_mam4xx_procs
- short_name: SMS_D_Ln5.ne4pg2_oQU480.F2010-SCREAMv1-MPASSI.scream-mam4xx-all_mam4xx_procs
+ - full_name: ERS_Ln9.ne4_ne4.F2000-SCREAMv1-AQP1.ghci-snl-cpu_gnu.eamxx-output-preset-2
+ short_name: ERS_Ln9.ne4_ne4.F2000-SCREAMv1-AQP1.eamxx-output-preset-2
+ - full_name: ERS_P16_Ln22.ne30pg2_ne30pg2.FIOP-SCREAMv1-DP.ghci-snl-cpu_gnu.eamxx-dpxx-arm97
+ short_name: ERS_P16_Ln22.ne30pg2_ne30pg2.FIOP-SCREAMv1-DP.eamxx-dpxx-arm97
+ - full_name: ERS_Ln22.ne4pg2_ne4pg2.F2010-SCREAMv1.ghci-snl-cpu_gnu.eamxx-small_kernels--eamxx-output-preset-5
+ short_name: ERS_Ln22.ne4pg2_ne4pg2.F2010-SCREAMv1.eamxx-small_kernels--eamxx-output-preset-5
+ - full_name: SMS_D_Ln5.ne4pg2_oQU480.F2010-SCREAMv1-MPASSI.ghci-snl-cpu_gnu.eamxx-mam4xx-all_mam4xx_procs
+ short_name: SMS_D_Ln5.ne4pg2_oQU480.F2010-SCREAMv1-MPASSI.eamxx-mam4xx-all_mam4xx_procs
+ - full_name: SMS_Ln3_P4.ne4pg2_oQU480.F2010-MMF2.ghci-snl-cpu_gnu
+ short_name: SMS_Ln3_P4.ne4pg2_oQU480.F2010-MMF2
fail-fast: false
name: cpu-gcc / ${{ matrix.test.short_name }}
steps:
@@ -142,18 +102,6 @@ jobs:
echo "Unsupported Linux distribution"
exit 1
fi
- - name: Establish cmp/gen flag
- run: |
- dir_suffix=".C"
- cmp_gen_flag="-c"
- if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
- if [ ${{ inputs.bless }} ]; then
- cmp_gen_flag="-o -g"
- dir_suffix=".G"
- fi
- fi
- echo "flags=$cmp_gen_flag -b master" >> $GITHUB_ENV
- echo "folder_suffix=$dir_suffix" >> $GITHUB_ENV
- name: Run test
run: |
./cime/scripts/create_test ${{ matrix.test.full_name }} ${{ env.flags }} --wait
diff --git a/.github/workflows/eamxx_default_files.yml b/.github/workflows/eamxx_default_files.yml
deleted file mode 100644
index 38c528306c4..00000000000
--- a/.github/workflows/eamxx_default_files.yml
+++ /dev/null
@@ -1,69 +0,0 @@
-name: inputdata
-
-on:
- push:
- branches: [ master ]
- pull_request:
- branches: [ master ]
- paths:
- - 'components/eamxx/cime_config/namelist_defaults_scream.xml'
- schedule:
- - cron: '00 00 * * *'
- workflow_dispatch:
-
-concurrency:
- group: ${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.run_id }}
- cancel-in-progress: true
-
-jobs:
- scream-defaults:
- if: ${{ github.repository == 'E3SM-Project/E3SM' }}
- runs-on: ubuntu-latest
- outputs:
- event_name: ${{ github.event_name }}
- steps:
- - name: Check out the repository
- uses: actions/checkout@v4
- with:
- show-progress: false
- submodules: false
- - name: Set up Python 3.11
- uses: actions/setup-python@v5
- with:
- python-version: "3.11"
- - name: Run unit tests
- working-directory: components/eamxx/cime_config/
- run: |
- python -m unittest tests/eamxx_default_files.py -v
-
- notify-scream-defaults:
- needs: scream-defaults
- if: ${{ failure() && needs.scream-defaults.outputs.event_name != 'pull_request' }}
- runs-on: ubuntu-latest
- steps:
- - name: Create issue
- run: |
- previous_issue_number=$(gh issue list \
- --label "$LABELS" \
- --json number \
- --jq '.[0].number')
- if [[ -n $previous_issue_number ]]; then
- gh issue comment "$previous_issue_number" \
- --body "$BODY"
- else
- gh issue create \
- --title "$TITLE" \
- --assignee "$ASSIGNEES" \
- --label "$LABELS" \
- --body "$BODY"
- fi
- env:
- GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- GH_REPO: ${{ github.repository }}
- TITLE: Inputdata server file missing
- ASSIGNEES: mahf708,bartgol
- LABELS: bug,input file,notify-file-gh-action
- BODY: |
- Workflow failed! There's likely a missing file specified in the configs! For more information, please see:
- - Workflow URL: https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }} (number ${{ github.run_number }}, attempt ${{ github.run_attempt }})
- - Workflow SHA: ${{ github.sha }}
diff --git a/.mergify.yml b/.mergify.yml
deleted file mode 100644
index 89fcc821e57..00000000000
--- a/.mergify.yml
+++ /dev/null
@@ -1,53 +0,0 @@
-merge_protections:
- - name: Enforce checks passing
- description: Make sure that checks are not failing on the PR, and reviewers approved
- if:
- - base = master
- success_conditions:
- - "#approved-reviews-by >= 1" # At least 1 approval
- - "#changes-requested-reviews-by == 0" # No reviewer asked for changes
- - or:
- - and:
- - check-success="gcc-openmp / dbg"
- - check-success="gcc-openmp / sp"
- - check-success="gcc-openmp / fpe"
- - check-success="gcc-openmp / opt"
- - check-skipped={% raw %}gcc-openmp / ${{ matrix.build_type }}{% endraw %}
- - or:
- - and:
- - check-success="gcc-cuda / dbg"
- - check-success="gcc-cuda / sp"
- - check-success="gcc-cuda / opt"
- - check-skipped={% raw %}gcc-cuda / ${{ matrix.build_type }}{% endraw %}
- - or:
- - and:
- - check-success="cpu-gcc / ERS_Ln9.ne4_ne4.F2000-SCREAMv1-AQP1.scream-output-preset-2"
- - check-success="cpu-gcc / ERS_P16_Ln22.ne30pg2_ne30pg2.FIOP-SCREAMv1-DP.scream-dpxx-arm97"
- - check-success="cpu-gcc / ERS_Ln22.ne4pg2_ne4pg2.F2010-SCREAMv1.scream-small_kernels--scream-output-preset-5"
- - check-success="cpu-gcc / SMS_D_Ln5.ne4pg2_oQU480.F2010-SCREAMv1-MPASSI.scream-mam4xx-all_mam4xx_procs"
- - check-skipped={% raw %}cpu-gcc / ${{ matrix.test.short_name }}{% endraw %}
- - or:
- - check-success=cpu-gcc
- - check-skipped=cpu-gcc
-
-pull_request_rules:
- - name: dismiss stale reviews
- conditions:
- - base=master
- actions:
- dismiss_reviews:
- when: synchronize # Dismiss reviews when synchronize event happens
- - name: Automatic merge when CI passes and approved
- conditions:
- - "label=CI: automerge"
- - base=master
- actions:
- merge:
- method: merge
- commit_message_template: |
- Merge pull request #{{number}} from {{head}}
-
- Automatically merged using mergify
- PR title: {{title}}
- PR author: {{author}}
- PR labels: {{label}}
diff --git a/cime_config/allactive/config_pesall.xml b/cime_config/allactive/config_pesall.xml
index 0d5f2456596..a12a89d5220 100644
--- a/cime_config/allactive/config_pesall.xml
+++ b/cime_config/allactive/config_pesall.xml
@@ -1169,14 +1169,14 @@
improv: any compset on ne30np4 grid
- -4
- -4
- -4
- -4
- -4
- -4
- -4
- -4
+ -6
+ -6
+ -6
+ -6
+ -6
+ -6
+ -6
+ -6
@@ -2065,6 +2065,21 @@
+
+
+ improv+allactive: RRM-WCYCL on 6 nodes
+
+ -6
+ -6
+ -6
+ -6
+ -6
+ -6
+ -6
+ -6
+
+
+
cmod016b64x1 s=2.4
@@ -2202,6 +2217,149 @@
+
+
+
+ allactive+chrysalis: v3.NARRM tri-grid on 10 nodes ~1 sypd
+
+ 576
+ 576
+ 576
+ 576
+ 576
+ 64
+
+
+ 576
+
+
+
+ allactive+chrysalis: v3.NARRM tri-grid on 20 nodes ~2 sypd
+
+ 1152
+ 1152
+ 768
+ 768
+ 384
+ 128
+
+
+ 1152
+ 384
+ 384
+
+
+
+ allactive+chrysalis: v3.NARRM tri-grid on 30 nodes ~3 sypd
+
+ 1792
+ 1792
+ 1280
+ 1280
+ 512
+ 128
+
+
+ 1792
+ 512
+ 512
+
+
+
+ allactive+chrysalis: v3.NARRM tri-grid on 40 nodes ~4 sypd
+
+ 2368
+ 2368
+ 1408
+ 1408
+ 960
+ 192
+
+
+ 2368
+ 1408
+
+
+
+ allactive+chrysalis: v3.NARRM tri-grid on 50 nodes ~5 sypd
+
+ 3008
+ 3008
+ 1856
+ 1856
+ 1152
+ 192
+
+
+ 3008
+ 1152
+ 1152
+
+
+
+ allactive+chrysalis: v3.NARRM tri-grid on 64 nodes ~6 sypd
+
+ 3840
+ 3840
+ 2304
+ 2304
+ 1536
+ 256
+
+
+ 3840
+ 1536
+ 1536
+
+
+
+
+
+ allactive+anvil: v3.NARRM tri-grid on 64 nodes ~1.8 sypd
+
+ 2160
+ 2160
+ 2160
+ 2160
+ 2160
+ 144
+
+
+ 2160
+
+
+
+ allactive+anvil: v3.NARRM tri-grid on 96 nodes ~2.5 sypd
+
+ 3240
+ 3240
+ 1080
+ 1080
+ 2160
+ 216
+
+
+ 3240
+ 2160
+ 2160
+
+
+
+ allactive+anvil: v3.NARRM tri-grid on 128 nodes ~3.2 sypd
+
+ 4320
+ 4320
+ 4320
+ 4320
+ 4320
+ 288
+
+
+ 4320
+
+
+
+
diff --git a/cime_config/config_grids.xml b/cime_config/config_grids.xml
index b093285e59d..45f886588e2 100755
--- a/cime_config/config_grids.xml
+++ b/cime_config/config_grids.xml
@@ -1959,6 +1959,16 @@
IcoswISC30E3r5
+
+ TL319
+ TL319
+ oQU240wLI
+ JRA025
+ mpas.gis20km
+ null
+ oQU240wLI
+
+
TL319
TL319
@@ -1969,6 +1979,16 @@
IcoswISC30E3r5
+
+ TL319
+ TL319
+ IcoswISC30E3r5
+ JRA025
+ mpas.gis1to10kmR2
+ null
+ IcoswISC30E3r5
+
+
ne30np4.pg2
r05
@@ -5660,7 +5680,7 @@
-
+
@@ -5761,15 +5781,15 @@
-
-
+
+
-
-
+
+
@@ -5786,8 +5806,8 @@
-
-
+
+
@@ -5813,9 +5833,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
@@ -5825,8 +5857,9 @@
-
-
+
+
+
@@ -5861,8 +5894,8 @@
-
-
+
+
@@ -5872,8 +5905,8 @@
-
-
+
+
@@ -5915,8 +5948,8 @@
-
-
+
+
@@ -5926,8 +5959,9 @@
-
-
+
+
+
@@ -5955,8 +5989,8 @@
-
-
+
+
@@ -5984,8 +6018,8 @@
-
-
+
+
@@ -5995,8 +6029,8 @@
-
-
+
+
@@ -6024,8 +6058,8 @@
-
-
+
+
@@ -6142,11 +6176,11 @@
-
+
-
+
@@ -6156,8 +6190,8 @@
-
-
+
+
@@ -6167,8 +6201,8 @@
-
-
+
+
diff --git a/cime_config/machines/Depends.crayclanggpu.cmake b/cime_config/machines/Depends.crayclanggpu.cmake
index eaff237a27f..3b0881ccd04 100644
--- a/cime_config/machines/Depends.crayclanggpu.cmake
+++ b/cime_config/machines/Depends.crayclanggpu.cmake
@@ -4,6 +4,8 @@ list(APPEND NOOPT_FILES
elm/src/data_types/VegetationDataType.F90
elm/src/biogeochem/CNNitrogenFluxType.F90
elm/src/biogeochem/CNCarbonFluxType.F90
+ mosart/src/wrm/WRM_subw_IO_mod.F90
+ mosart/src/riverroute/RtmMod.F90
)
# Files added below to mitigate excessive compilation times
diff --git a/cime_config/machines/cmake_macros/crayclanggpu_frontier.cmake b/cime_config/machines/cmake_macros/crayclanggpu_frontier.cmake
index 92567416c56..49463844347 100644
--- a/cime_config/machines/cmake_macros/crayclanggpu_frontier.cmake
+++ b/cime_config/machines/cmake_macros/crayclanggpu_frontier.cmake
@@ -1,6 +1,5 @@
set(MPICC "cc")
set(MPICXX "mpicxx")
-#set(MPICXX "CC")
set(MPIFC "ftn")
set(SCC "cc")
set(SCXX "hipcc")
@@ -34,7 +33,7 @@ set(HAS_F2008_CONTIGUOUS "TRUE")
# -Wl,--allow-shlib-undefined was added to address rocm 5.4.3 Fortran linker issue:
# /opt/rocm-5.4.3/lib/libhsa-runtime64.so.1: undefined reference to `std::condition_variable::wait(std::unique_lock&)@GLIBCXX_3.4.30'
# AMD started building with GCC 12.2.0, which brings in a GLIBCXX symbol that isn't in CCE's default GCC toolchain.
-#string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,--allow-multiple-definition -Wl,--allow-shlib-undefined")
+string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,--allow-shlib-undefined -Wl,--allow-multiple-definition")
# Switching to O3 for performance benchmarking
# Will revisit any failing tests
diff --git a/cime_config/machines/cmake_macros/gnu_chicoma-gpu.cmake b/cime_config/machines/cmake_macros/gnu_chicoma-gpu.cmake
index 807c7d0211e..a6c13942620 100644
--- a/cime_config/machines/cmake_macros/gnu_chicoma-gpu.cmake
+++ b/cime_config/machines/cmake_macros/gnu_chicoma-gpu.cmake
@@ -2,15 +2,10 @@ string(APPEND CONFIG_ARGS " --host=cray")
if (COMP_NAME STREQUAL gptl)
string(APPEND CPPDEFS " -DHAVE_NANOTIME -DBIT64 -DHAVE_SLASHPROC -DHAVE_GETTIMEOFDAY")
endif()
-string(APPEND SLIBS " -lblas -llapack")
-set(CXX_LINKER "FORTRAN")
-if (NOT DEBUG)
- string(APPEND CFLAGS " -O2 -g")
-endif()
-if (NOT DEBUG)
- string(APPEND FFLAGS " -O2 -g")
-endif()
-string(APPEND CXX_LIBS " -lstdc++")
+set(PIO_FILESYSTEM_HINTS "lustre")
+string(APPEND CMAKE_C_FLAGS_RELEASE " -O2 -g")
+string(APPEND CMAKE_Fortran_FLAGS_RELEASE " -O2 -g")
+string(APPEND CMAKE_EXE_LINKER_FLAGS " -Wl,--enable-new-dtags")
set(MPICC "cc")
set(MPICXX "CC")
set(MPIFC "ftn")
diff --git a/cime_config/machines/cmake_macros/oneapi-ifx.cmake b/cime_config/machines/cmake_macros/oneapi-ifx.cmake
index 9ab0cdda7d5..e590456e9f3 100644
--- a/cime_config/machines/cmake_macros/oneapi-ifx.cmake
+++ b/cime_config/machines/cmake_macros/oneapi-ifx.cmake
@@ -4,15 +4,15 @@ if (compile_threaded)
string(APPEND CMAKE_CXX_FLAGS " -qopenmp")
string(APPEND CMAKE_EXE_LINKER_FLAGS " -qopenmp")
endif()
-string(APPEND CMAKE_C_FLAGS_RELEASE " -O2")
-string(APPEND CMAKE_Fortran_FLAGS_RELEASE " -O2")
-string(APPEND CMAKE_CXX_FLAGS_RELEASE " -O2")
-string(APPEND CMAKE_Fortran_FLAGS_DEBUG " -O0 -g -fpe0")
+string(APPEND CMAKE_C_FLAGS_RELEASE " -O2 -gline-tables-only -g")
+string(APPEND CMAKE_Fortran_FLAGS_RELEASE " -O2 -gline-tables-only -g")
+string(APPEND CMAKE_CXX_FLAGS_RELEASE " -fp-model precise -O2 -gline-tables-only -g")
+string(APPEND CMAKE_Fortran_FLAGS_DEBUG " -O0 -g -check uninit -check bounds -check pointers -fpe0 -check noarg_temp_created")
string(APPEND CMAKE_C_FLAGS_DEBUG " -O0 -g")
string(APPEND CMAKE_CXX_FLAGS_DEBUG " -O0 -g")
-string(APPEND CMAKE_C_FLAGS " -fp-model precise -std=gnu99")
-string(APPEND CMAKE_CXX_FLAGS " -fp-model precise")
-string(APPEND CMAKE_Fortran_FLAGS " -traceback -convert big_endian -assume byterecl -assume realloc_lhs -fp-model precise")
+string(APPEND CMAKE_C_FLAGS " -fp-model precise -std=gnu99 -gline-tables-only -g")
+string(APPEND CMAKE_CXX_FLAGS " -fp-model precise -gline-tables-only -g")
+string(APPEND CMAKE_Fortran_FLAGS " -traceback -convert big_endian -assume byterecl -assume realloc_lhs -fp-model precise -gline-tables-only -g")
string(APPEND CPPDEFS " -DFORTRANUNDERSCORE -DNO_R16 -DCPRINTEL -DHAVE_SLASHPROC -DHIDE_MPI")
string(APPEND CMAKE_Fortran_FORMAT_FIXED_FLAG " -fixed -132")
string(APPEND CMAKE_Fortran_FORMAT_FREE_FLAG " -free")
@@ -23,4 +23,6 @@ set(MPICXX "mpicxx")
set(SCC "icx")
set(SCXX "icpx")
set(SFC "ifx")
-set(E3SM_LINK_WITH_FORTRAN "TRUE")
+
+
+#set(E3SM_LINK_WITH_FORTRAN "TRUE")
diff --git a/cime_config/machines/cmake_macros/oneapi-ifx_auroracpu.cmake b/cime_config/machines/cmake_macros/oneapi-ifx_auroracpu.cmake
new file mode 100644
index 00000000000..bd6ec8ed913
--- /dev/null
+++ b/cime_config/machines/cmake_macros/oneapi-ifx_auroracpu.cmake
@@ -0,0 +1,19 @@
+
+string(APPEND CMAKE_EXE_LINKER_FLAGS " -lmkl_intel_lp64 -lmkl_sequential -lmkl_core")
+if (compile_threaded)
+ string(APPEND CMAKE_EXE_LINKER_FLAGS " -fiopenmp -fopenmp-targets=spir64")
+endif()
+
+string(APPEND KOKKOS_OPTIONS " -DCMAKE_CXX_STANDARD=17 -DKokkos_ENABLE_SERIAL=On -DKokkos_ENABLE_EXPLICIT_INSTANTIATION=Off")
+
+#set(SCREAM_MPI_ON_DEVICE OFF CACHE STRING "")
+
+
+
+
+
+
+
+
+
+
diff --git a/cime_config/machines/cmake_macros/oneapi-ifx_sunspotcpu.cmake b/cime_config/machines/cmake_macros/oneapi-ifx_sunspotcpu.cmake
new file mode 100644
index 00000000000..bd6ec8ed913
--- /dev/null
+++ b/cime_config/machines/cmake_macros/oneapi-ifx_sunspotcpu.cmake
@@ -0,0 +1,19 @@
+
+string(APPEND CMAKE_EXE_LINKER_FLAGS " -lmkl_intel_lp64 -lmkl_sequential -lmkl_core")
+if (compile_threaded)
+ string(APPEND CMAKE_EXE_LINKER_FLAGS " -fiopenmp -fopenmp-targets=spir64")
+endif()
+
+string(APPEND KOKKOS_OPTIONS " -DCMAKE_CXX_STANDARD=17 -DKokkos_ENABLE_SERIAL=On -DKokkos_ENABLE_EXPLICIT_INSTANTIATION=Off")
+
+#set(SCREAM_MPI_ON_DEVICE OFF CACHE STRING "")
+
+
+
+
+
+
+
+
+
+
diff --git a/cime_config/machines/cmake_macros/oneapi-ifxgpu.cmake b/cime_config/machines/cmake_macros/oneapi-ifxgpu.cmake
index d7dfae00219..faf8748217a 100644
--- a/cime_config/machines/cmake_macros/oneapi-ifxgpu.cmake
+++ b/cime_config/machines/cmake_macros/oneapi-ifxgpu.cmake
@@ -4,15 +4,17 @@ if (compile_threaded)
string(APPEND CMAKE_CXX_FLAGS " -qopenmp")
string(APPEND CMAKE_EXE_LINKER_FLAGS " -qopenmp")
endif()
-string(APPEND CMAKE_C_FLAGS_RELEASE " -O2")
-string(APPEND CMAKE_Fortran_FLAGS_RELEASE " -O2")
-string(APPEND CMAKE_CXX_FLAGS_RELEASE " -O2")
-string(APPEND CMAKE_Fortran_FLAGS_DEBUG " -O0 -g -fpe0")
+
+#adding -g here leads to linker internal errors
+string(APPEND CMAKE_C_FLAGS_RELEASE " -O2 -g -gline-tables-only")
+string(APPEND CMAKE_Fortran_FLAGS_RELEASE " -O2 -fpscomp logicals -g -gline-tables-only")
+string(APPEND CMAKE_CXX_FLAGS_RELEASE " -fp-model precise -O2 -g -gline-tables-only")
+string(APPEND CMAKE_Fortran_FLAGS_DEBUG " -O0 -g -fpscomp logicals -check uninit -check bounds -check pointers -fpe0 -check noarg_temp_created")
string(APPEND CMAKE_C_FLAGS_DEBUG " -O0 -g")
string(APPEND CMAKE_CXX_FLAGS_DEBUG " -O0 -g")
string(APPEND CMAKE_C_FLAGS " -fp-model precise -std=gnu99")
string(APPEND CMAKE_CXX_FLAGS " -fp-model precise")
-string(APPEND CMAKE_Fortran_FLAGS " -traceback -convert big_endian -assume byterecl -assume realloc_lhs -fp-model precise")
+string(APPEND CMAKE_Fortran_FLAGS " -fpscomp logicals -traceback -convert big_endian -assume byterecl -assume realloc_lhs -fp-model precise")
string(APPEND CPPDEFS " -DFORTRANUNDERSCORE -DNO_R16 -DCPRINTEL -DHAVE_SLASHPROC -DHIDE_MPI")
string(APPEND CMAKE_Fortran_FORMAT_FIXED_FLAG " -fixed -132")
string(APPEND CMAKE_Fortran_FORMAT_FREE_FLAG " -free")
diff --git a/cime_config/machines/cmake_macros/oneapi-ifxgpu_aurora.cmake b/cime_config/machines/cmake_macros/oneapi-ifxgpu_aurora.cmake
index 6835515164f..e5c486f216e 100644
--- a/cime_config/machines/cmake_macros/oneapi-ifxgpu_aurora.cmake
+++ b/cime_config/machines/cmake_macros/oneapi-ifxgpu_aurora.cmake
@@ -1,7 +1,12 @@
-string(APPEND CMAKE_EXE_LINKER_FLAGS " -lmkl_intel_lp64 -lmkl_sequential -lmkl_core")
+string(APPEND CMAKE_EXE_LINKER_FLAGS " -lmkl_intel_lp64 -lmkl_sequential -lmkl_core -fsycl-device-code-split=per_kernel -fsycl-max-parallel-link-jobs=16 -Wl,--no-relax")
if (compile_threaded)
string(APPEND CMAKE_EXE_LINKER_FLAGS " -fiopenmp -fopenmp-targets=spir64")
endif()
+
+string(APPEND KOKKOS_OPTIONS " -DCMAKE_CXX_STANDARD=17 -DKokkos_ENABLE_SERIAL=On -DKokkos_ARCH_INTEL_PVC=On -DKokkos_ENABLE_SYCL=On -DKokkos_ENABLE_EXPLICIT_INSTANTIATION=Off")
string(APPEND SYCL_FLAGS " -\-intel -fsycl -fsycl-targets=spir64_gen -mlong-double-64 -Xsycl-target-backend \"-device 12.60.7\"")
+string(APPEND OMEGA_SYCL_EXE_LINKER_FLAGS " -Xsycl-target-backend \"-device 12.60.7\" ")
string(APPEND CMAKE_CXX_FLAGS " -Xclang -fsycl-allow-virtual-functions")
+
+set(SCREAM_MPI_ON_DEVICE OFF CACHE STRING "")
diff --git a/cime_config/machines/cmake_macros/oneapi-ifxgpu_sunspot-gen.cmake b/cime_config/machines/cmake_macros/oneapi-ifxgpu_sunspot-gen.cmake
new file mode 100644
index 00000000000..9c9eb97add1
--- /dev/null
+++ b/cime_config/machines/cmake_macros/oneapi-ifxgpu_sunspot-gen.cmake
@@ -0,0 +1,30 @@
+
+set(CXX_LINKER "CXX")
+
+execute_process(COMMAND $ENV{NETCDF_PATH}/bin/nf-config --flibs OUTPUT_VARIABLE SHELL_CMD_OUTPUT_BUILD_INTERNAL_IGNORE0 OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+string(APPEND SLIBS " ${SHELL_CMD_OUTPUT_BUILD_INTERNAL_IGNORE0} -Wl,-rpath -Wl,$ENV{NETCDF_PATH}/lib -lmkl_intel_lp64 -lmkl_sequential -lmkl_core")
+
+execute_process(COMMAND $ENV{NETCDF_PATH}/bin/nc-config --libs OUTPUT_VARIABLE SHELL_CMD_OUTPUT_BUILD_INTERNAL_IGNORE0 OUTPUT_STRIP_TRAILING_WHITESPACE)
+
+string(APPEND SLIBS " ${SHELL_CMD_OUTPUT_BUILD_INTERNAL_IGNORE0}")
+string(APPEND SLIBS " -fiopenmp -fopenmp-targets=spir64")
+
+set(NETCDF_PATH "$ENV{NETCDF_PATH}")
+set(PNETCDF_PATH "$ENV{PNETCDF_PATH}")
+
+set(USE_SYCL "TRUE")
+
+string(APPEND KOKKOS_OPTIONS " -DCMAKE_CXX_STANDARD=17 -DKokkos_ENABLE_SERIAL=On -DKokkos_ARCH_INTEL_GEN=On -DKokkos_ENABLE_SYCL=On -DKokkos_ENABLE_EXPLICIT_INSTANTIATION=Off")
+
+string(APPEND SYCL_FLAGS " -\-intel -Xclang -fsycl-allow-virtual-functions -fsycl -mlong-double-64 -fsycl-device-code-split=per_kernel -fno-sycl-id-queries-fit-in-int -fsycl-unnamed-lambda")
+
+#string(APPEND SYCL_FLAGS " -\-intel -fsycl")
+string(APPEND CXX_LDFLAGS " -Wl,-\-defsym,main=MAIN_\_ -lifcore -\-intel -Xclang -fsycl-allow-virtual-functions -fsycl -lsycl -mlong-double-64 -fsycl-link-huge-device-code -fsycl-device-code-split=per_kernel -fsycl-targets=spir64")
+
+SET(CMAKE_CXX_COMPILER "mpicxx" CACHE STRING "")
+SET(CMAKE_C_COMPILER "mpicc" CACHE STRING "")
+SET(CMAKE_FORTRAN_COMPILER "mpifort" CACHE STRING "")
+
+
+
diff --git a/cime_config/machines/cmake_macros/oneapi-ifxgpu_sunspot-pvc.cmake b/cime_config/machines/cmake_macros/oneapi-ifxgpu_sunspot-pvc.cmake
new file mode 100644
index 00000000000..c6afa7c2329
--- /dev/null
+++ b/cime_config/machines/cmake_macros/oneapi-ifxgpu_sunspot-pvc.cmake
@@ -0,0 +1,9 @@
+
+string(APPEND CMAKE_EXE_LINKER_FLAGS " -lmkl_intel_lp64 -lmkl_sequential -lmkl_core -fsycl-device-code-split=per_kernel -fsycl-max-parallel-link-jobs=16 -Wl,--no-relax")
+if (compile_threaded)
+ string(APPEND CMAKE_EXE_LINKER_FLAGS " -fiopenmp -fopenmp-targets=spir64")
+endif()
+string(APPEND KOKKOS_OPTIONS " -DCMAKE_CXX_STANDARD=17 -DKokkos_ENABLE_SERIAL=On -DKokkos_ARCH_INTEL_PVC=On -DKokkos_ENABLE_SYCL=On -DKokkos_ENABLE_EXPLICIT_INSTANTIATION=Off")
+string(APPEND SYCL_FLAGS " -\-intel -fsycl -fsycl-targets=spir64_gen -mlong-double-64 -Xsycl-target-backend \"-device 12.60.7\"")
+
+set(SCREAM_MPI_ON_DEVICE OFF CACHE STRING "")
diff --git a/cime_config/machines/cmake_macros/oneapi-ifxgpu_sunspot.cmake b/cime_config/machines/cmake_macros/oneapi-ifxgpu_sunspot.cmake
index 6835515164f..1ad0d6e6b61 100644
--- a/cime_config/machines/cmake_macros/oneapi-ifxgpu_sunspot.cmake
+++ b/cime_config/machines/cmake_macros/oneapi-ifxgpu_sunspot.cmake
@@ -3,5 +3,6 @@ string(APPEND CMAKE_EXE_LINKER_FLAGS " -lmkl_intel_lp64 -lmkl_sequential -lmkl_c
if (compile_threaded)
string(APPEND CMAKE_EXE_LINKER_FLAGS " -fiopenmp -fopenmp-targets=spir64")
endif()
-string(APPEND SYCL_FLAGS " -\-intel -fsycl -fsycl-targets=spir64_gen -mlong-double-64 -Xsycl-target-backend \"-device 12.60.7\"")
+string(APPEND SYCL_FLAGS " -\-intel -fsycl -fsycl-targets=spir64_gen -mlong-double-64 ")
+string(APPEND OMEGA_SYCL_EXE_LINKER_FLAGS " -Xsycl-target-backend \"-device 12.60.7\" ")
string(APPEND CMAKE_CXX_FLAGS " -Xclang -fsycl-allow-virtual-functions")
diff --git a/cime_config/machines/config_batch.xml b/cime_config/machines/config_batch.xml
index ee271d1f9dc..dcdf52178ef 100644
--- a/cime_config/machines/config_batch.xml
+++ b/cime_config/machines/config_batch.xml
@@ -547,6 +547,30 @@
+
+ /lus/gila/projects/CSC249ADSE15_CNDA/tools/qsub/throttle
+
+ workq
+ debug
+
+
+
+
+ /lus/gila/projects/CSC249ADSE15_CNDA/tools/qsub/throttle
+
+ workq
+ debug
+
+
+
+
+ /lus/gila/projects/CSC249ADSE15_CNDA/tools/qsub/throttle
+
+ workq
+ debug
+
+
+
/lus/flare/projects/CSC249ADSE15_CNDA/tools/qsub/throttle
@@ -555,6 +579,15 @@
workq
+
+
+ /lus/flare/projects/CSC249ADSE15_CNDA/tools/qsub/throttle
+
+ EarlyAppAccess
+ workq-route
+ workq
+
+
/grand/E3SMinput/soft/qsub/throttle
diff --git a/cime_config/machines/config_machines.xml b/cime_config/machines/config_machines.xml
index fce20fca185..cbd857ee154 100644
--- a/cime_config/machines/config_machines.xml
+++ b/cime_config/machines/config_machines.xml
@@ -1069,7 +1069,7 @@
/usr/share/lmod/lmod/libexec/lmod python
- Core Core/24.07
+ Core Core/24.00
PrgEnv-cray PrgEnv-cray/8.3.3
cce cce/15.0.1
@@ -1082,16 +1082,22 @@
- Core Core/24.07
+ Core Core/24.00
PrgEnv-cray PrgEnv-amd/8.3.3
amd amd/5.4.0
+
+
+
- Core Core/24.07
+ Core Core/24.00
PrgEnv-cray PrgEnv-gnu/8.3.3
gcc gcc/12.2.0
@@ -1100,9 +1106,9 @@
rocm/5.4.0
- cray-python/3.11.5
+ cray-python/3.9.13.1
cray-libsci
- cmake/3.27.9
+ cmake/3.21.3
subversion
git
zlib
@@ -2852,7 +2858,7 @@
/lcrc/group/e3sm/soft/improv/pnetcdf/1.12.3/gcc-12.3.0/openmpi-4.1.6/bin:/lcrc/group/e3sm/soft/improv/netcdf-fortran/4.6.1b/gcc-12.3.0/openmpi-4.1.6/bin:/lcrc/group/e3sm/soft/improv/netcdf-c/4.9.2b/gcc-12.3.0/openmpi-4.1.6/bin:/lcrc/group/e3sm/soft/improv/openmpi/4.1.6/gcc-12.3.0/bin:/lcrc/group/e3sm/soft/perl/improv/bin:$ENV{PATH}
$SHELL{lp=/lcrc/group/e3sm/soft/improv/netlib-lapack/3.12.0/gcc-12.3.0:/lcrc/group/e3sm/soft/improv/pnetcdf/1.12.3/gcc-12.3.0/openmpi-4.1.6/lib:/lcrc/group/e3sm/soft/improv/netcdf-fortran/4.6.1b/gcc-12.3.0/openmpi-4.1.6/lib:/lcrc/group/e3sm/soft/improv/netcdf-c/4.9.2b/gcc-12.3.0/openmpi-4.1.6/lib:/opt/pbs/lib:/lcrc/group/e3sm/soft/improv/openmpi/4.1.6/gcc-12.3.0/lib; if [ -z "$LD_LIBRARY_PATH" ]; then echo $lp; else echo "$lp:$LD_LIBRARY_PATH"; fi}
$SHELL{if [ -z "$MOAB_ROOT" ]; then echo /lcrc/soft/climate/moab/improv/gnu; else echo "$MOAB_ROOT"; fi}
- ^lockedfile
+ ^lockedfile,individual
128M
@@ -3116,6 +3122,148 @@
+
+
+ ANL Sunspot Test and Development System (TDS), batch system is pbspro
+ uan-.*
+ LINUX
+ oneapi-ifxgpu
+ mpich
+ CSC249ADSE15_CNDA
+ /gila/CSC249ADSE15_CNDA/performance_archive
+ .*
+ /lus/gila/projects/CSC249ADSE15_CNDA/$USER/scratch
+ /lus/gila/projects/CSC249ADSE15_CNDA/inputdata
+ /lus/gila/projects/CSC249ADSE15_CNDA/inputdata/atm/datm7
+ $CIME_OUTPUT_ROOT/archive/$CASE
+ /lus/gila/projects/CSC249ADSE15_CNDA/baselines/$COMPILER
+ /lus/gila/projects/CSC249ADSE15_CNDA/tools/cprnc/cprnc
+ 16
+ e3sm_developer
+ 4
+ pbspro
+ e3sm
+ 12
+ 12
+ 12
+ 12
+ FALSE
+
+ mpiexec
+
+
+ -np {{ total_tasks }} --label
+ -ppn {{ tasks_per_node }}
+ --no-vni --cpu-bind $ENV{RANKS_BIND} -envall
+ -d $ENV{OMP_NUM_THREADS}
+ $ENV{GPU_TILE_COMPACT}
+
+
+
+ /usr/share/lmod/lmod/init/sh
+ /usr/share/lmod/lmod/init/csh
+ /usr/share/lmod/lmod/init/env_modules_python.py
+ module
+ module
+ /usr/share/lmod/lmod/libexec/lmod python
+
+
+ /soft/modulefiles
+ /soft/restricted/CNDA/updates/modulefiles
+ spack-pe-gcc/0.7.0-24.086.0 cmake
+ python/3.10.11
+
+
+ oneapi/eng-compiler/2024.07.30.002 mpich/icc-all-pmix-gpu/20240717
+
+
+ cray-pals/1.4.0
+ libfabric/1.20.1
+
+
+ $CIME_OUTPUT_ROOT/$CASE/run
+ $CIME_OUTPUT_ROOT/$CASE/bld
+
+ /lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/netcdf
+ /lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/netcdf
+ /lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/pnetcdf
+ /lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/netcdf/lib:$ENV{LD_LIBRARY_PATH}
+ /lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/netcdf/bin:$ENV{PATH}
+
+ list:0-7,104-111:8-15,112-119:16-23,120-127:24-31,128-135:32-39,136-143:40-47,144-151:52-59,156-163:60-67,164-171:68-75,172-179:76-83,180-187:84-91,188-195:92-99,196-203
+
+
+ 1
+
+
+
+
+
+ 1
+ 0
+
+
+
+ 1
+ 1
+ 1
+
+ 131072
+ 20
+
+ disabled
+ 8388608
+
+ 240
+ 240
+
+ disable
+ disable
+
+ level_zero:gpu
+ 1
+
+ 4000MB
+ 0
+
+ /soft/tools/mpi_wrapper_utils/gpu_tile_compact.sh
+
+
+
+
+
+ verbose,granularity=thread,balanced
+ 128M
+
+
+ -1
+
+
+
+
+
+
ALCF Polaris 560 nodes, 2.8 GHz AMD EPYC Milan 7543P 32c CPU, 4 NVIDIA A100 GPUs
polaris-*
@@ -3211,6 +3359,201 @@
+
+
+ ANL Sunspot Test and Development System (TDS), batch system is pbspro
+ uan-.*
+ LINUX
+ oneapi-ifx
+ mpich
+ CSC249ADSE15_CNDA
+ /gila/CSC249ADSE15_CNDA/performance_archive
+ .*
+ /lus/gila/projects/CSC249ADSE15_CNDA/$USER/scratch
+ /lus/gila/projects/CSC249ADSE15_CNDA/inputdata
+ /lus/gila/projects/CSC249ADSE15_CNDA/inputdata/atm/datm7
+ $CIME_OUTPUT_ROOT/archive/$CASE
+ /lus/gila/projects/CSC249ADSE15_CNDA/baselines/$COMPILER
+ /lus/gila/projects/CSC249ADSE15_CNDA/tools/cprnc/cprnc
+ 16
+ e3sm_developer
+ 4
+ pbspro
+ e3sm
+ 208
+ 104
+ FALSE
+
+ mpiexec
+
+
+ -np {{ total_tasks }} --label
+ -ppn {{ tasks_per_node }}
+ --cpu-bind depth -envall
+ -d $ENV{OMP_NUM_THREADS}
+
+
+
+
+ /usr/share/lmod/lmod/init/sh
+ /usr/share/lmod/lmod/init/csh
+ /usr/share/lmod/lmod/init/env_modules_python.py
+ module
+ module
+ /usr/share/lmod/lmod/libexec/lmod python
+
+
+
+ spack-pe-gcc/0.7.0-24.086.0 cmake python/3.10.11
+
+
+
+ oneapi/eng-compiler/2024.04.15.002
+ mpich/icc-all-pmix-gpu/20231026
+
+
+
+
+ cray-pals
+
+ libfabric/1.15.2.0
+
+
+ $CIME_OUTPUT_ROOT/$CASE/run
+ $CIME_OUTPUT_ROOT/$CASE/bld
+
+ /lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/netcdf
+ /lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/netcdf
+ /lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/pnetcdf
+ /lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/netcdf/lib:$ENV{LD_LIBRARY_PATH}
+ /lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/netcdf/bin:$ENV{PATH}
+ list:0-7,104-111:8-15,112-119:16-23,120-127:24-31,128-135:32-39,136-143:40-47,144-151:52-59,156-163:60-67,164-171:68-75,172-179:76-83,180-187:84-91,188-195:92-99,196-203
+
+
+ 1
+
+
+ DISABLED
+
+
+
+
+
+ 131072
+ 20
+ 0
+
+
+ verbose,granularity=thread,balanced
+ 128M
+
+
+ -1
+
+
+
+
+
+
+
+
+
+ ANL Sunspot Test and Development System (TDS), batch system is pbspro
+ uan-.*
+ LINUX
+ oneapi-ifxgpu
+ mpich
+ CSC249ADSE15_CNDA
+ /gila/CSC249ADSE15_CNDA/performance_archive
+ .*
+ /lus/gila/projects/CSC249ADSE15_CNDA/$USER/scratch
+ /lus/gila/projects/CSC249ADSE15_CNDA/inputdata
+ /lus/gila/projects/CSC249ADSE15_CNDA/inputdata/atm/datm7
+ $CIME_OUTPUT_ROOT/archive/$CASE
+ /lus/gila/projects/CSC249ADSE15_CNDA/baselines/$COMPILER
+ /lus/gila/projects/CSC249ADSE15_CNDA/tools/cprnc/cprnc
+ 16
+ e3sm_developer
+ 4
+ pbspro
+ e3sm
+ 12
+ 12
+ 12
+ 12
+ FALSE
+
+ mpiexec
+
+
+ -np {{ total_tasks }} --label
+ -ppn {{ tasks_per_node }}
+ --cpu-bind depth -envall
+ -d $ENV{OMP_NUM_THREADS}
+ $ENV{GPU_TILE_COMPACT}
+
+
+
+ /soft/packaging/lmod/lmod/init/sh
+ /soft/packaging/lmod/lmod/init/csh
+ /soft/packaging/lmod/lmod/init/env_modules_python.py
+ module
+ module
+ /soft/packaging/lmod/lmod/libexec/lmod python
+
+
+ /soft/modulefiles
+ spack cmake/3.24.2 python/3.9.13-gcc-11.2.0-76jlbxs
+ /soft/restricted/CNDA/updates/modulefiles
+
+
+ oneapi/eng-compiler/2023.10.15.002
+ mpich/52.2-256/icc-all-pmix-gpu
+
+
+
+
+
+
+
+ cray-pals
+ append-deps/default
+ libfabric/1.15.2.0
+
+
+ $CIME_OUTPUT_ROOT/$CASE/run
+ $CIME_OUTPUT_ROOT/$CASE/bld
+
+ /lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/netcdf
+ /lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/netcdf
+ /lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/pnetcdf
+
+
+ 1
+
+
+ level_zero:gpu
+ NO_GPU
+ 0
+ disable
+ disable
+ 1
+ 4000MB
+ 0
+ /soft/tools/mpi_wrapper_utils/gpu_tile_compact.sh
+ 131072
+ 20
+
+
+ verbose,granularity=thread,balanced
+ 128M
+
+
+ -1
+
+
+
+
ANL Sunspot Test and Development System (TDS), batch system is pbspro
uan-.*
@@ -3293,7 +3636,6 @@
/soft/tools/mpi_wrapper_utils/gpu_tile_compact.sh
131072
20
- $ENV{KOKKOS_ROOT}
1
0:4,1:4,2:4,3:4:4:4,5:4,6:4,7:4
@@ -3339,9 +3681,9 @@
pbspro
e3sm
208
- 104
+ 12
104
- 48
+ 12
FALSE
mpiexec
@@ -3349,7 +3691,7 @@
-np {{ total_tasks }} --label
-ppn {{ tasks_per_node }}
- -envall
+ --no-vni --cpu-bind $ENV{RANKS_BIND} -envall
-d $ENV{OMP_NUM_THREADS}
$ENV{GPU_TILE_COMPACT}
@@ -3362,17 +3704,18 @@
module
/soft/sunspot_migrate/soft/packaging/lmod/lmod/libexec/lmod python
- cmake
+
+ /soft/modulefiles
+ /soft/restricted/CNDA/updates/modulefiles
+ spack-pe-gcc/0.7.0-24.086.0 cmake
+ python/3.10.11
- oneapi/eng-compiler/2024.04.15.002
+ oneapi/eng-compiler/2024.07.30.002 mpich/icc-all-pmix-gpu/20240717
-
- kokkos/git.7ff87a5-omp-sycl
-
-
- spack-pe-gcc cmake
- gcc/10.3.0
+
+ cray-pals/1.4.0
+ libfabric/1.20.1
$CIME_OUTPUT_ROOT/$CASE/run
@@ -3381,28 +3724,167 @@
/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-c/4.9.2/oneapi.eng.2024.04.15.002
/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-fortran/4.6.1/oneapi.eng.2024.04.15.002
/lus/flare/projects/CSC249ADSE15_CNDA/software/pnetcdf/1.12.3/oneapi.eng.2024.04.15.002
- /lus/flare/projects/CSC249ADSE15_CNDA/software/pnetcdf/1.12.3/oneapi.eng.2024.04.15.002/lib:/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-fortran/4.6.1/oneapi.eng.2024.04.15.002/lib:/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-c/4.9.2/oneapi.eng.2024.04.15.002/lib:$ENV{LD_LIBRARY_PATH}
- /lus/flare/projects/CSC249ADSE15_CNDA/software/pnetcdf/1.12.3/oneapi.eng.2024.04.15.002/bin:/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-fortran/4.6.1/oneapi.eng.2024.04.15.002/bin:/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-c/4.9.2/oneapi.eng.2024.04.15.002/bin:$ENV{PATH}
+ /opt/cray/pe/gcc-libs:/opt/cray/pe/python/3.9.13.1/lib:/lus/flare/projects/CSC249ADSE15_CNDA/software/pnetcdf/1.12.3/oneapi.eng.2024.04.15.002/lib:/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-fortran/4.6.1/oneapi.eng.2024.04.15.002/lib:/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-c/4.9.2/oneapi.eng.2024.04.15.002/lib:$ENV{LD_LIBRARY_PATH}
+ /opt/cray/pe/python/3.9.13.1/bin:/lus/flare/projects/CSC249ADSE15_CNDA/software/pnetcdf/1.12.3/oneapi.eng.2024.04.15.002/bin:/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-fortran/4.6.1/oneapi.eng.2024.04.15.002/bin:/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-c/4.9.2/oneapi.eng.2024.04.15.002/bin:$ENV{PATH}
+ list:0-7,104-111:8-15,112-119:16-23,120-127:24-31,128-135:32-39,136-143:40-47,144-151:52-59,156-163:60-67,164-171:68-75,172-179:76-83,180-187:84-91,188-195:92-99,196-203
1
+
+
+
- level_zero:gpu
- NO_GPU
- 0
- disable
- disable
- 1
+
+ 1
+ 0
+
+
+
+ 1
+ 1
+ 1
+
+ 131072
+ 20
+ cxi
+ disabled
+ 8388608
+
+ 240
+ 240
+
+ disable
+ disable
+
+ level_zero:gpu
+ 1
+
4000MB
0
- /soft/tools/mpi_wrapper_utils/gpu_tile_compact.sh
+
+ /soft/tools/mpi_wrapper_utils/gpu_tile_compact.sh
+
+
+
+
+
+
+ 0
+ DISABLED
131072
20
- $ENV{KOKKOS_ROOT}
- 1
- 0:4,1:4,2:4,3:4:4:4,5:4,6:4,7:4
+ 0
+
+
+
+
+ verbose,granularity=thread,balanced
+ 128M
+
+
+
+ threads
+ 128M
+
+
+ -1
+
+
+
+
+
+
+ ALCF Aurora, 10624 nodes, 2x52c SPR, 6x2s PVC, 2x512GB DDR5, 2x64GB CPU-HBM, 6x128GB GPU-HBM, Slingshot 11, PBSPro
+ aurora-uan-.*
+ LINUX
+ oneapi-ifx
+ mpich
+ CSC249ADSE15_CNDA
+ /lus/flare/projects/CSC249ADSE15_CNDA/performance_archive
+ .*
+ /lus/flare/projects/CSC249ADSE15_CNDA/$USER/scratch
+ /lus/flare/projects/CSC249ADSE15_CNDA/inputdata
+ /lus/flare/projects/CSC249ADSE15_CNDA/inputdata/atm/datm7
+ $CIME_OUTPUT_ROOT/archive/$CASE
+ /lus/flare/projects/CSC249ADSE15_CNDA/baselines/$COMPILER
+ /lus/flare/projects/CSC249ADSE15_CNDA/tools/cprnc/cprnc
+ 16
+ e3sm_developer
+ 4
+ pbspro
+ e3sm
+ 208
+ 104
+ FALSE
+
+ mpiexec
+
+
+ -np {{ total_tasks }} --label
+ -ppn {{ tasks_per_node }}
+ --cpu-bind $ENV{RANKS_BIND} -envall
+ -d $ENV{OMP_NUM_THREADS}
+ $ENV{GPU_TILE_COMPACT}
+
+
+
+ /lus/flare/projects/CSC249ADSE15_CNDA/modules/lmod.sh
+ /soft/sunspot_migrate/soft/packaging/lmod/lmod/init/csh
+ /soft/sunspot_migrate/soft/packaging/lmod/lmod/init/env_modules_python.py
+ module
+ module
+ /soft/sunspot_migrate/soft/packaging/lmod/lmod/libexec/lmod python
+
+
+ /soft/modulefiles
+ /soft/restricted/CNDA/updates/modulefiles
+ spack-pe-gcc/0.6.1-23.275.2 cmake
+ python/3.10.10
+
+
+ oneapi/release/2023.12.15.001
+
+
+ cray-pals/1.3.3
+ libfabric/1.15.2.0
+
+
+ $CIME_OUTPUT_ROOT/$CASE/run
+ $CIME_OUTPUT_ROOT/$CASE/bld
+
+ /lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-c/4.9.2/oneapi.eng.2023.05.15.007
+ /lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-fortran/4.6.1/oneapi.eng.2023.05.15.007
+ /lus/flare/projects/CSC249ADSE15_CNDA/software/pnetcdf/1.12.3/oneapi.eng.2023.05.15.007
+ /opt/cray/pe/gcc-libs:/opt/cray/pe/python/3.9.13.1/lib:/lus/flare/projects/CSC249ADSE15_CNDA/software/pnetcdf/1.12.3/oneapi.eng.2023.05.15.007/lib:/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-fortran/4.6.1/oneapi.eng.2023.05.15.007/lib:/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-c/4.9.2/oneapi.eng.2023.05.15.007/lib:$ENV{LD_LIBRARY_PATH}
+ /opt/cray/pe/python/3.9.13.1/bin:/lus/flare/projects/CSC249ADSE15_CNDA/software/pnetcdf/1.12.3/oneapi.eng.2023.05.15.007/bin:/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-fortran/4.6.1/oneapi.eng.2023.05.15.007/bin:/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-c/4.9.2/oneapi.eng.2023.05.15.007/bin:$ENV{PATH}
+ list:0-7,104-111:8-15,112-119:16-23,120-127:24-31,128-135:32-39,136-143:40-47,144-151:52-59,156-163:60-67,164-171:68-75,172-179:76-83,180-187:84-91,188-195:92-99,196-203
+
+
+ 1
+
0
DISABLED
@@ -3424,6 +3906,15 @@
+
+
+
+
+
+
+
+
+
PNL cluster, OS is Linux, batch system is SLURM
sooty
@@ -4140,8 +4631,7 @@
- Chicoma GPU nodes at LANL IC. Each GPU node has single
-AMD EPYC 7713 64-Core (Milan) (256GB) and 4 nvidia A100'
+ Chicoma GPU nodes at LANL IC. Each GPU node has single AMD EPYC 7713 64-Core (Milan) (256GB) and 4 nvidia A100'
ch-fe*
Linux
gnugpu,gnu,nvidiagpu,nvidia
@@ -4151,7 +4641,7 @@ AMD EPYC 7713 64-Core (Milan) (256GB) and 4 nvidia A100'
/usr/projects/e3sm/inputdata/atm/datm7
/lustre/scratch5/$ENV{USER}/E3SM/archive/$CASE
/lustre/scratch5/$ENV{USER}/E3SM/input_data/ccsm_baselines/$COMPILER
- /usr/projects/climate/SHARED_CLIMATE/software/badger/cprnc
+ /usr/projects/e3sm/software/chicoma-cpu/cprnc
10
e3sm_developer
4
@@ -4175,11 +4665,11 @@ AMD EPYC 7713 64-Core (Milan) (256GB) and 4 nvidia A100'
- /usr/share/lmod/8.3.1/init/perl
+ /usr/share/lmod/lmod/init/perl
- /usr/share/lmod/8.3.1/init/python
- /usr/share/lmod/8.3.1/init/sh
- /usr/share/lmod/8.3.1/init/csh
+ /usr/share/lmod/lmod/init/python
+ /usr/share/lmod/lmod/init/sh
+ /usr/share/lmod/lmod/init/csh
/usr/share/lmod/lmod/libexec/lmod perl
/usr/share/lmod/lmod/libexec/lmod python
module
@@ -4191,32 +4681,35 @@ AMD EPYC 7713 64-Core (Milan) (256GB) and 4 nvidia A100'
cray-parallel-netcdf
cray-netcdf
cray-hdf5
- PrgEnv-gnu
- PrgEnv-intel
- PrgEnv-nvidia
- PrgEnv-cray
- PrgEnv-aocc
intel
intel-oneapi
nvidia
aocc
cudatoolkit
climate-utils
+ cray-libsci
craype-accel-nvidia80
craype-accel-host
perftools-base
perftools
darshan
+ PrgEnv-gnu
+ PrgEnv-intel
+ PrgEnv-nvidia
+ PrgEnv-cray
+ PrgEnv-aocc
- PrgEnv-gnu/8.4.0
- gcc/11.2.0
+ PrgEnv-gnu/8.5.0
+ gcc/12.2.0
+ cray-libsci/23.05.1.4
PrgEnv-nvidia/8.4.0
nvidia/22.7
+ cray-libsci/23.05.1.4
@@ -4239,14 +4732,13 @@ AMD EPYC 7713 64-Core (Milan) (256GB) and 4 nvidia A100'
- cray-libsci/23.05.1.4
+ craype-accel-host
craype/2.7.21
cray-mpich/8.1.26
- libfabric/1.15.2.0
cray-hdf5-parallel/1.12.2.3
cray-netcdf-hdf5parallel/4.9.0.3
cray-parallel-netcdf/1.12.3.3
- cmake/3.25.1
+ cmake/3.27.7
@@ -4269,6 +4761,9 @@ AMD EPYC 7713 64-Core (Milan) (256GB) and 4 nvidia A100'
$ENV{CRAY_PARALLEL_NETCDF_PREFIX}
/usr/projects/e3sm/cudatoolkit:$ENV{PKG_CONFIG_PATH}
+
+ /opt/cray/pe/gcc/12.2.0/snos/lib64:$ENV{LD_LIBRARY_PATH}
+
-1
diff --git a/cime_config/testmods_dirs/config_pes_tests.xml b/cime_config/testmods_dirs/config_pes_tests.xml
index 1ac88ac5fe6..eafc8e2a1fe 100644
--- a/cime_config/testmods_dirs/config_pes_tests.xml
+++ b/cime_config/testmods_dirs/config_pes_tests.xml
@@ -161,31 +161,41 @@
- tests+anvil: --compset WCYCL* --res ne30pg2_IcoswISC30E3r5 on 16 nodes pure-MPI
+ tests+anvil: --compset WCYCL* --res ne30pg2_IcoswISC30E3r5 on 25 nodes pure-MPI
- 396
- 396
- 396
- 396
- 180
- 396
+ 675
+ 324
+ 324
+ 360
+ 216
+ 684
- 396
+ 0
+ 360
+ 360
+ 0
+ 684
+ 0
tests+anvil: --compset BGC* --res ne30pg2_r05_IcoswISC30E3r5 on 30 nodes pure-MPI
675
- 684
- 684
- 684
- 396
+ 324
+ 324
+ 360
+ 216
684
+ 0
+ 360
+ 360
+ 0
684
+ 0
@@ -203,6 +213,17 @@
-6
+
+ "tests+anvil, F compset, 6 nodes"
+
+ -16
+ -16
+ -16
+ -16
+ -16
+ -16
+
+
@@ -241,17 +262,17 @@
- tests+anvil: --compset WCYCL1850 --res northamericax4v1pg2_WC14to60E2r3 on 64 nodes pure-MPI, 2.133 sypd
+ tests+anvil: --compset WCYCL1850 --res northamericax4v1pg2_WC14to60E2r3 on 69 nodes pure-MPI, 2.046 sypd
- 1800
- 1800
- 1800
- 1800
+ 1980
+ 1980
+ 1980
+ 1944
504
- 1800
+ 1980
- 1800
+ 1980
diff --git a/cime_config/tests.py b/cime_config/tests.py
index 46894e6ea96..d67f15e7469 100644
--- a/cime_config/tests.py
+++ b/cime_config/tests.py
@@ -177,7 +177,7 @@
)
},
- "e3sm_p3_developer" : {
+ "e3sm_p3_developer" : {
"tests" : (
"ERP.ne4pg2_oQU480.F2010.eam-p3",
"REP_Ln5.ne4pg2_oQU480.F2010.eam-p3",
@@ -189,6 +189,17 @@
"ERS.ne4pg2_oQU480.F2010.eam-p3"
)
},
+
+ "e3sm_orodrag_developer" : {
+ "tests" : (
+ "ERP.ne4pg2_oQU480.F2010.eam-orodrag_ne4pg2",
+ "REP_Ln5.ne4pg2_oQU480.F2010.eam-orodrag_ne4pg2",
+ "PET.ne4pg2_oQU480.F2010.eam-orodrag_ne4pg2",
+ "PEM_Ln18.ne4pg2_oQU480.F2010.eam-orodrag_ne4pg2",
+ "SMS_Ln5.ne30pg2_EC30to60E2r2.F2010.eam-orodrag_ne30pg2",
+ "SMS_D_Ln5.ne4pg2_oQU480.F2010.eam-orodrag_ne4pg2"
+ )
+ },
"e3sm_atm_integration" : {
"inherit" : ("eam_preqx", "eam_theta"),
@@ -269,6 +280,8 @@
"SMS_D_Ld1.T62_oQU240.GMPAS-IAF.mpaso-harmonic_mean_drag",
"SMS_D_Ld1.T62_oQU240.GMPAS-IAF.mpaso-upwind_advection",
"ERS_Ld5_D.T62_oQU240.GMPAS-IAF.mpaso-conservation_check",
+ "ERS_Ld5_PS.ne30pg2_r05_IcoswISC30E3r5.CRYO1850-DISMF.mpaso-scaled_dib_dismf",
+ "ERS_Ld5.TL319_oQU240wLI_gis20.MPAS_LISIO_JRA1p5.mpaso-ocn_glc_tf_coupling",
)
},
@@ -310,6 +323,8 @@
"ERS_Ld5.TL319_oQU240wLI_ais8to30.MPAS_LISIO_JRA1p5.mpaso-ocn_glcshelf",
"SMS_P12x2.ne4pg2_oQU480.WCYCL1850NS.allactive-mach_mods",
"ERS_Ln9.ne4pg2_ne4pg2.F2010-MMF1.eam-mmf_crmout",
+ "SMS_Lh4.ne4_ne4.F2010-SCREAMv1.eamxx-output-preset-1",
+ "SMS_Lh4.ne4pg2_ne4pg2.F2010-SCREAMv1.eamxx-output-preset-1--eamxx-prod",
)
},
@@ -520,6 +535,7 @@
"SMS.ne4pg2_oQU480.F2010.eam-thetanh_ftype2",
"SMS.ne4pg2_oQU480.F2010.eam-thetanh_ftype4",
"SMS.ne4pg2_oQU480.F2010.eam-thetahy_sl",
+ "ERS.ne4pg2_oQU480.F2010.eam-thetahy_sl_nsubstep2",
"ERS.ne4pg2_oQU480.F2010.eam-thetahy_ftype2",
"ERS.ne4pg2_oQU480.F2010.eam-thetanh_ftype2",
)
@@ -639,17 +655,17 @@
"time" : "03:00:00",
},
- "e3sm_scream" : {
+ "e3sm_eamxx" : {
"time" : "03:00:00",
- "inherit" : ("e3sm_scream_v0"),
+ "inherit" : ("e3sm_eamxx_v0"),
},
- "e3sm_scream_v0" : {
+ "e3sm_eamxx_v0" : {
"time" : "03:00:00",
- "inherit" : ("e3sm_scream_v0_lowres"),
+ "inherit" : ("e3sm_eamxx_v0_lowres"),
},
- "e3sm_scream_v0_lowres" : {
+ "e3sm_eamxx_v0_lowres" : {
"time" : "03:00:00",
"tests" : (
"SMS_D.ne4pg2_ne4pg2.F2010-SCREAM-HR",
@@ -660,69 +676,70 @@
)
},
- "e3sm_scream_v1" : {
+ "e3sm_eamxx_v1" : {
"time" : "03:00:00",
- "inherit" : ("e3sm_scream_v1_lowres", "e3sm_scream_v1_medres", "e3sm_scream_v1_mpassi"),
+ "inherit" : ("e3sm_eamxx_v1_lowres", "e3sm_eamxx_v1_medres", "e3sm_eamxx_v1_mpassi"),
},
- "e3sm_scream_v1_lowres" : {
+ "e3sm_eamxx_v1_lowres" : {
"time" : "01:00:00",
- "inherit" : ("e3sm_scream_mam4xx_v1_lowres"),
+ "inherit" : ("e3sm_eamxx_mam4xx_v1_lowres"),
"tests" : (
- "ERP_D_Lh4.ne4_ne4.F2010-SCREAMv1.scream-output-preset-1",
- "ERS_Ln9.ne4_ne4.F2000-SCREAMv1-AQP1.scream-output-preset-2",
- "SMS_D_Ln9.ne4_ne4.F2010-SCREAMv1-noAero.scream-output-preset-3",
- "ERP_Ln22.ne4pg2_ne4pg2.F2010-SCREAMv1.scream-output-preset-4",
- "ERS_D_Ln22.ne4pg2_ne4pg2.F2010-SCREAMv1.scream-rad_frequency_2--scream-output-preset-5",
- "ERS_Ln22.ne4pg2_ne4pg2.F2010-SCREAMv1.scream-small_kernels--scream-output-preset-5",
- "ERS_Ln22.ne4pg2_ne4pg2.F2010-SCREAMv1.scream-small_kernels_p3--scream-output-preset-5",
- "ERS_Ln22.ne4pg2_ne4pg2.F2010-SCREAMv1.scream-small_kernels_shoc--scream-output-preset-5",
- "SMS_D_Ln5.ne4pg2_oQU480.F2010-SCREAMv1-MPASSI.scream-mam4xx-all_mam4xx_procs",
+ "ERP_D_Lh4.ne4_ne4.F2010-SCREAMv1.eamxx-output-preset-1",
+ "ERS_Ln9.ne4_ne4.F2000-SCREAMv1-AQP1.eamxx-output-preset-2",
+ "SMS_D_Ln9.ne4_ne4.F2010-SCREAMv1-noAero.eamxx-output-preset-3",
+ "ERP_Ln22.ne4pg2_ne4pg2.F2010-SCREAMv1.eamxx-output-preset-4",
+ "ERS_D_Ln22.ne4pg2_ne4pg2.F2010-SCREAMv1.eamxx-rad_frequency_2--eamxx-output-preset-5",
+ "ERS_Ln22.ne4pg2_ne4pg2.F2010-SCREAMv1.eamxx-small_kernels--eamxx-output-preset-5",
+ "ERS_Ln22.ne4pg2_ne4pg2.F2010-SCREAMv1.eamxx-small_kernels_p3--eamxx-output-preset-5",
+ "ERS_Ln22.ne4pg2_ne4pg2.F2010-SCREAMv1.eamxx-small_kernels_shoc--eamxx-output-preset-5",
+ "SMS_D_Ln5.ne4pg2_oQU480.F2010-SCREAMv1-MPASSI.eamxx-mam4xx-all_mam4xx_procs",
)
},
- "e3sm_scream_v1_dp-eamxx" : {
+ "e3sm_eamxx_v1_dp-eamxx" : {
"time" : "01:00:00",
# each test runs with 225 dynamics and 100 physics columns, roughly size of ne2
"tests" : (
- "ERS_P16_Ln22.ne30pg2_ne30pg2.FIOP-SCREAMv1-DP.scream-dpxx-dycomsrf01",
- "ERS_P16_Ln22.ne30pg2_ne30pg2.FIOP-SCREAMv1-DP.scream-dpxx-arm97",
- "ERS_P16_Ln22.ne30pg2_ne30pg2.FIOP-SCREAMv1-DP.scream-dpxx-comble",
+ "ERS_P16_Ln22.ne30pg2_ne30pg2.FIOP-SCREAMv1-DP.eamxx-dpxx-dycomsrf01",
+ "ERS_P16_Ln22.ne30pg2_ne30pg2.FIOP-SCREAMv1-DP.eamxx-dpxx-arm97",
+ "ERS_P16_Ln22.ne30pg2_ne30pg2.FIOP-SCREAMv1-DP.eamxx-dpxx-comble",
"ERS_P16_Ln22.ne30pg2_ne30pg2.FRCE-SCREAMv1-DP",
)
},
- # Tests run on exclusively on mappy for scream AT testing. These tests
+ # Tests run on exclusively on mappy for eamxx AT testing. These tests
# should be fast, so we limit it to low res and add some thread tests
# specifically for mappy.
- "e3sm_scream_v1_at" : {
- "inherit" : ("e3sm_scream_v1_lowres", "e3sm_scream_v1_dp-eamxx"),
- "tests" : ("PET_Ln9_P32x2.ne4pg2_ne4pg2.F2010-SCREAMv1.scream-output-preset-1")
+ "e3sm_eamxx_v1_at" : {
+ "inherit" : ("e3sm_eamxx_v1_lowres", "e3sm_eamxx_v1_dp-eamxx"),
+ "tests" : ("PET_Ln9_P32x2.ne4pg2_ne4pg2.F2010-SCREAMv1.eamxx-output-preset-1")
},
- "e3sm_scream_v1_medres" : {
+ "e3sm_eamxx_v1_medres" : {
"time" : "02:00:00",
"tests" : (
# "SMS_D_Ln2.ne30_ne30.F2000-SCREAMv1-AQP1", # Uncomment once IC file for ne30 is ready
- "ERS_Ln22.ne30_ne30.F2010-SCREAMv1.scream-internal_diagnostics_level--scream-output-preset-3",
- "PEM_Ln90.ne30pg2_ne30pg2.F2010-SCREAMv1.scream-spa_remap--scream-output-preset-4",
- "ERS_Ln90.ne30pg2_ne30pg2.F2010-SCREAMv1.scream-small_kernels--scream-output-preset-5",
- "ERP_Ln22.conusx4v1pg2_r05_oECv3.F2010-SCREAMv1-noAero.scream-bfbhash--scream-output-preset-6",
- "ERS_Ln22.ne30pg2_ne30pg2.F2010-SCREAMv1.scream-L128--scream-output-preset-4",
- "REP_Ld5.ne30pg2_ne30pg2.F2010-SCREAMv1.scream-L128--scream-output-preset-6"
+ "ERS_Ln22.ne30_ne30.F2010-SCREAMv1.eamxx-internal_diagnostics_level--eamxx-output-preset-3",
+ "PEM_Ln90.ne30pg2_ne30pg2.F2010-SCREAMv1.eamxx-spa_remap--eamxx-output-preset-4",
+ "ERS_Ln90.ne30pg2_ne30pg2.F2010-SCREAMv1.eamxx-small_kernels--eamxx-output-preset-5",
+ "ERP_Ln22.conusx4v1pg2_r05_oECv3.F2010-SCREAMv1-noAero.eamxx-bfbhash--eamxx-output-preset-6",
+ "ERS_Ln22.ne30pg2_ne30pg2.F2010-SCREAMv1.eamxx-L128--eamxx-output-preset-4",
+ "REP_Ld5.ne30pg2_ne30pg2.F2010-SCREAMv1.eamxx-L128--eamxx-output-preset-6",
+ "ERS_Ln90.ne30pg2_ne30pg2.F2010-SCREAMv1.eamxx-L128--eamxx-sl_nsubstep2",
)
},
# Used to track performance
- "e3sm_scream_v1_hires" : {
+ "e3sm_eamxx_v1_hires" : {
"time" : "01:00:00",
"tests" : (
- "SMS_Ln300.ne30pg2_ne30pg2.F2010-SCREAMv1.scream-perf_test--scream-output-preset-1"
+ "SMS_Ln300.ne30pg2_ne30pg2.F2010-SCREAMv1.eamxx-perf_test--eamxx-output-preset-1"
)
},
- "e3sm_scream_v1_mpassi" : {
+ "e3sm_eamxx_v1_mpassi" : {
"time" : "01:00:00",
"tests" : (
# "ERP_D_Ln9.ne4_oQU240.F2010-SCREAMv1-MPASSI.atmlndactive-rtm_off",
@@ -730,14 +747,14 @@
# Disable the two 111422-commented tests b/c they fail on pm-gpu and
# we're not using MPASSI right now.
#111422 "ERP_Ln22.ne4pg2_oQU480.F2010-SCREAMv1-MPASSI.atmlndactive-rtm_off",
- "ERS_D_Ln22.ne4pg2_oQU480.F2010-SCREAMv1-MPASSI.atmlndactive-rtm_off--scream-output-preset-1",
+ "ERS_D_Ln22.ne4pg2_oQU480.F2010-SCREAMv1-MPASSI.atmlndactive-rtm_off--eamxx-output-preset-1",
# "ERS_Ln22.ne30_oECv3.F2010-SCREAMv1-MPASSI.atmlndactive-rtm_off",
#111422 "PEM_Ln90.ne30pg2_EC30to60E2r2.F2010-SCREAMv1-MPASSI",
# "ERS_Ln22.ne30pg2_EC30to60E2r2.F2010-SCREAMv1-MPASSI.atmlndactive-rtm_off",
)
},
- "e3sm_scream_v1_long" : {
+ "e3sm_eamxx_v1_long" : {
"time" : "01:00:00",
"tests" : (
"ERP_D_Lh182.ne4pg2_ne4pg2.F2010-SCREAMv1",
@@ -745,7 +762,7 @@
)
},
- "e3sm_scream_v1_long_crusher" : {
+ "e3sm_eamxx_v1_long_crusher" : {
# _D builds take a long longer on crusher than ascent or pm-gpu, so
# don't run the long _D test.
"time" : "01:00:00",
@@ -754,17 +771,31 @@
)
},
- "e3sm_scream_mam4xx_v1_lowres" : {
+ "e3sm_eamxx_mam4xx_v1_lowres" : {
"time" : "01:00:00",
"tests" : (
- "SMS_D_Ln5.ne4pg2_oQU480.F2010-SCREAMv1-MPASSI.scream-mam4xx-optics",
- "SMS_D_Ln5.ne4pg2_oQU480.F2010-SCREAMv1-MPASSI.scream-mam4xx-aci",
- "SMS_D_Ln5.ne4pg2_oQU480.F2010-SCREAMv1-MPASSI.scream-mam4xx-wetscav",
- "SMS_D_Ln5.ne4pg2_oQU480.F2010-SCREAMv1-MPASSI.scream-mam4xx-drydep",
- "SMS_D_Ln5.ne30pg2_oECv3.F2010-SCREAMv1-MPASSI.scream-mam4xx-remap_emiss_ne4_ne30"
+ "SMS_D_Ln5.ne4pg2_oQU480.F2010-SCREAMv1-MPASSI.eamxx-mam4xx-optics",
+ "SMS_D_Ln5.ne4pg2_oQU480.F2010-SCREAMv1-MPASSI.eamxx-mam4xx-aci",
+ "SMS_D_Ln5.ne4pg2_oQU480.F2010-SCREAMv1-MPASSI.eamxx-mam4xx-wetscav",
+ "SMS_D_Ln5.ne4pg2_oQU480.F2010-SCREAMv1-MPASSI.eamxx-mam4xx-drydep",
+ "SMS_D_Ln5.ne30pg2_oECv3.F2010-SCREAMv1-MPASSI.eamxx-mam4xx-remap_emiss_ne4_ne30"
)
},
+ "e3sm_moab_dev" : {
+ "time" : "01:00:00",
+ "tests" : (
+ "ERS_Vmoab_Ld3.ne4pg2_r05_oQU480.WCYCL1850NS",
+ "ERS_Vmoab_Ld3.ne4pg2_oQU480.WCYCL1850NS",
+ "ERS_Vmoab_Ld3.ne4pg2_oQU480.F1850",
+ "ERS_Vmoab_Ld3.ne4pg2_ne4pg2.I1850CNPRDCTCBCTOP",
+ "ERS_Vmoab_Ld3.T62_oQU240wLI.GMPAS-IAF",
+ "ERS_Vmoab_Ld3.T62_oQU120.CMPASO-NYF",
+ "ERS_Vmoab_Ld3.r05_r05.RMOSGPCC",
+ )
+ },
+
+
"e3sm_gpuacc" : {
"tests" : (
diff --git a/components/data_comps/dice/src/ice_comp_mct.F90 b/components/data_comps/dice/src/ice_comp_mct.F90
index f8c48c89240..3cd5557f1f2 100644
--- a/components/data_comps/dice/src/ice_comp_mct.F90
+++ b/components/data_comps/dice/src/ice_comp_mct.F90
@@ -79,16 +79,6 @@ subroutine ice_init_mct( EClock, cdata, x2i, i2x, NLFilename )
logical :: scmMode = .false. ! single column mode
real(R8) :: scmLat = shr_const_SPVAL ! single column lat
real(R8) :: scmLon = shr_const_SPVAL ! single column lon
-#ifdef HAVE_MOAB
- character(CL) :: filePath ! generic file path
- character(CL) :: fileName ! generic file name
- character(CS) :: timeName ! domain file: time variable name
- character(CS) :: lonName ! domain file: lon variable name
- character(CS) :: latName ! domain file: lat variable name
- character(CS) :: hgtName ! domain file: hgt variable name
- character(CS) :: maskName ! domain file: mask variable name
- character(CS) :: areaName ! domain file: area variable name
-#endif
character(*), parameter :: subName = "(ice_init_mct) "
!-------------------------------------------------------------------------------
@@ -171,12 +161,9 @@ subroutine ice_init_mct( EClock, cdata, x2i, i2x, NLFilename )
#ifdef HAVE_MOAB
if (my_task == master_task) then
- call shr_stream_getDomainInfo(SDICE%stream(1), filePath,fileName,timeName,lonName, &
- latName,hgtName,maskName,areaName)
- call shr_stream_getFile(filePath,fileName)
! send path of ice domain to MOAB coupler.
- call seq_infodata_PutData( infodata, ice_domain=fileName)
- write(logunit,*), ' filename: ', filename
+ write(logunit,*), ' file used for ice domain ', SDICE%domainFile
+ call seq_infodata_PutData( infodata, ice_domain=SDICE%domainFile)
endif
#endif
!----------------------------------------------------------------------------
diff --git a/components/data_comps/docn/cime_config/config_component.xml b/components/data_comps/docn/cime_config/config_component.xml
index 431d358f995..68ec6a18c9f 100644
--- a/components/data_comps/docn/cime_config/config_component.xml
+++ b/components/data_comps/docn/cime_config/config_component.xml
@@ -13,10 +13,11 @@
This file may have ocn desc entries.
-->
- DOCN
+ DOCN
null mode
prescribed ocean mode
slab ocean mode
+ relaxed slab ocean mode
aquaplanet slab ocean mode
interannual mode
aquaplanet mode:
@@ -45,12 +46,13 @@
char
- prescribed,sst_aquap1,sst_aquap2,sst_aquap3,sst_aquap4,sst_aquap5,sst_aquap6,sst_aquap7,sst_aquap8,sst_aquap9,sst_aquap10,sst_aquap11,sst_aquap12,sst_aquap13,sst_aquap14,sst_aquap15,sst_aquapfile,som,som_aquap,sst_aquap_constant,interannual,null
+ prescribed,sst_aquap1,sst_aquap2,sst_aquap3,sst_aquap4,sst_aquap5,sst_aquap6,sst_aquap7,sst_aquap8,sst_aquap9,sst_aquap10,sst_aquap11,sst_aquap12,sst_aquap13,sst_aquap14,sst_aquap15,sst_aquapfile,som,rso,som_aquap,sst_aquap_constant,interannual,null
prescribed
null
prescribed
som
+ rso
som_aquap
interannual
sst_aquap1
diff --git a/components/data_comps/docn/cime_config/namelist_definition_docn.xml b/components/data_comps/docn/cime_config/namelist_definition_docn.xml
index a191d088d7f..fb28b7471c5 100644
--- a/components/data_comps/docn/cime_config/namelist_definition_docn.xml
+++ b/components/data_comps/docn/cime_config/namelist_definition_docn.xml
@@ -32,6 +32,7 @@
Currently the following datamods are supported
prescribed SSTDATA (Run with prescribed SST, ICE_COV)
som SOM (Slab ocean model)
+ rso RSO (Relaxed slab ocean model)
null NULL (NULL mode)
-->
@@ -59,6 +60,7 @@
aquapfile
''
som
+ rso
som
interannual
@@ -93,6 +95,7 @@
null
$DIN_LOC_ROOT/ocn/docn7/AQUAPLANET/
$DIN_LOC_ROOT/ocn/docn7/SOM
+ /
$DIN_LOC_ROOT/atm/cam/sst
@@ -106,6 +109,7 @@
null
$DOCN_AQP_FILENAME
$DOCN_SOM_FILENAME
+ $SSTICE_GRID_FILENAME
sst_HadOIBl_bc_1x1_1850_2014_c150416.nc
@@ -145,6 +149,7 @@
null
$DIN_LOC_ROOT/ocn/docn7/AQUAPLANET
$DIN_LOC_ROOT/ocn/docn7/SOM
+ /
$DIN_LOC_ROOT/atm/cam/sst
@@ -158,6 +163,7 @@
null
$DOCN_AQP_FILENAME
$DOCN_SOM_FILENAME
+ $SSTICE_DATA_FILENAME
sst_HadOIBl_bc_1x1_1850_2014_c150416.nc
@@ -181,6 +187,10 @@
hblt h
qdp qbot
+
+ SST_cpl t
+ hblt h
+
SST_cpl t
@@ -213,6 +223,7 @@
$SSTICE_YEAR_ALIGN
0
1
+ $SSTICE_YEAR_ALIGN
1
@@ -227,6 +238,7 @@
$SSTICE_YEAR_START
0
1
+ $SSTICE_YEAR_START
1850
@@ -241,6 +253,7 @@
$SSTICE_YEAR_END
0
1
+ $SSTICE_YEAR_END
2014
@@ -257,7 +270,7 @@
char
streams
shr_strdata_nml
- SSTDATA,SST_AQUAP1,SST_AQUAP2,SST_AQUAP3,SST_AQUAP4,SST_AQUAP5,SST_AQUAP6,SST_AQUAP7,SST_AQUAP8,SST_AQUAP9,SST_AQUAP10,SST_AQUAP11,SST_AQUAP12,SST_AQUAP13,SST_AQUAP14,SST_AQUAP15,SST_AQUAPFILE,SST_AQUAP_CONSTANT,SOM,SOM_AQUAP,IAF,NULL,COPYALL
+ SSTDATA,SST_AQUAP1,SST_AQUAP2,SST_AQUAP3,SST_AQUAP4,SST_AQUAP5,SST_AQUAP6,SST_AQUAP7,SST_AQUAP8,SST_AQUAP9,SST_AQUAP10,SST_AQUAP11,SST_AQUAP12,SST_AQUAP13,SST_AQUAP14,SST_AQUAP15,SST_AQUAPFILE,SST_AQUAP_CONSTANT,SOM,RSO,SOM_AQUAP,IAF,NULL,COPYALL
General method that operates on the data. This is generally
implemented in the data models but is set in the strdata method for
@@ -331,6 +344,7 @@
SST_AQUAPFILE
SST_AQUAP_CONSTANT
SOM
+ RSO
SOM_AQUAP
IAF
@@ -662,4 +676,29 @@
+
+ real(30)
+ docn
+ docn_nml
+
+ Relaxation timescale for relaxed slab ocean (RSO) mode
+
+
+ 691200
+
+
+
+
+ real(30)
+ docn
+ docn_nml
+
+ globally fixed mixed layer depth (MLD) for relaxed slab ocean (RSO) mode
+ use -1 to disable - input data file should have hblt field to override this
+
+
+ 50
+
+
+
diff --git a/components/data_comps/docn/src/docn_comp_mod.F90 b/components/data_comps/docn/src/docn_comp_mod.F90
index 43bac32bff7..00a7ef4338c 100644
--- a/components/data_comps/docn/src/docn_comp_mod.F90
+++ b/components/data_comps/docn/src/docn_comp_mod.F90
@@ -29,6 +29,8 @@ module docn_comp_mod
use docn_shr_mod , only: rest_file ! namelist input
use docn_shr_mod , only: rest_file_strm ! namelist input
use docn_shr_mod , only: sst_constant_value ! namelist input
+ use docn_shr_mod , only: RSO_relax_tau ! namelist input for relaxed slab ocean (RSO)
+ use docn_shr_mod , only: RSO_fixed_MLD ! namelist input for relaxed slab ocean (RSO)
use docn_shr_mod , only: nullstr
#ifdef HAVE_MOAB
@@ -70,6 +72,8 @@ module docn_comp_mod
integer(IN) :: kt,ks,ku,kv,kdhdx,kdhdy,kq,kswp ! field indices
integer(IN) :: kswnet,klwup,klwdn,ksen,klat,kmelth,ksnow,krofi
integer(IN) :: kh,kqbot
+ integer(IN) :: k10uu ! index for u10
+ integer(IN) :: kRSO_bckgrd_sst ! index for background SST (relaxed slab ocean)
integer(IN) :: index_lat, index_lon
integer(IN) :: kmask, kfrac ! frac and mask field indices of docn domain
integer(IN) :: ksomask ! So_omask field index
@@ -93,7 +97,7 @@ module docn_comp_mod
character(12) , parameter :: avofld(1:ktrans) = &
(/ "So_t ","So_u ","So_v ","So_dhdx ",&
"So_dhdy ","So_s ","strm_h ","strm_qbot "/)
- character(len=*), parameter :: flds_strm = 'strm_h:strm_qbot'
+ character(len=*),parameter :: flds_strm = 'strm_h:strm_qbot:So_t'
!--------------------------------------------------------------------------
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -281,7 +285,7 @@ subroutine docn_comp_init(Eclock, x2o, o2x, &
kdhdx = mct_aVect_indexRA(o2x,'So_dhdx')
kdhdy = mct_aVect_indexRA(o2x,'So_dhdy')
kswp = mct_aVect_indexRA(o2x,'So_fswpen', perrwith='quiet')
- kq = mct_aVect_indexRA(o2x,'Fioo_q')
+ kq = mct_aVect_indexRA(o2x,'Fioo_q') ! ocn freezing melting potential
call mct_aVect_init(x2o, rList=seq_flds_x2o_fields, lsize=lsize)
call mct_aVect_zero(x2o)
@@ -294,12 +298,14 @@ subroutine docn_comp_init(Eclock, x2o, o2x, &
klwdn = mct_aVect_indexRA(x2o,'Faxa_lwdn')
ksnow = mct_aVect_indexRA(x2o,'Faxa_snow')
kmelth = mct_aVect_indexRA(x2o,'Fioi_melth')
+ k10uu = mct_aVect_indexRA(x2o,'So_duu10n')
call mct_aVect_init(avstrm, rList=flds_strm, lsize=lsize)
call mct_aVect_zero(avstrm)
kh = mct_aVect_indexRA(avstrm,'strm_h')
kqbot = mct_aVect_indexRA(avstrm,'strm_qbot')
+ kRSO_bckgrd_sst = mct_aVect_indexRA(avstrm,'So_t')
allocate(somtp(lsize))
allocate(tfreeze(lsize))
@@ -472,14 +478,17 @@ subroutine docn_comp_init(Eclock, x2o, o2x, &
call shr_mpi_bcast(exists,mpicom,'exists')
call shr_mpi_bcast(exists1,mpicom,'exists1')
- if (trim(datamode) == 'SOM' .or. trim(datamode) == 'SOM_AQUAP') then
- if (exists1) then
- if (my_task == master_task) write(logunit,F00) ' reading ',trim(rest_file)
- call shr_pcdf_readwrite('read',SDOCN%pio_subsystem, SDOCN%io_type, &
- trim(rest_file), mpicom, gsmap=gsmap, rf1=somtp, rf1n='somtp', io_format=SDOCN%io_format)
- else
- if (my_task == master_task) write(logunit,F00) ' file not found, skipping ',trim(rest_file)
- endif
+ if ( trim(datamode) == 'SOM' & ! Traditional slab ocean
+ .or. trim(datamode) == 'RSO' & ! Relaxed slab ocean
+ .or. trim(datamode) == 'SOM_AQUAP' & ! Aquaplanet slab ocean
+ ) then
+ if (exists1) then
+ if (my_task == master_task) write(logunit,F00) ' reading ',trim(rest_file)
+ call shr_pcdf_readwrite('read',SDOCN%pio_subsystem, SDOCN%io_type, &
+ trim(rest_file), mpicom, gsmap=gsmap, rf1=somtp, rf1n='somtp', io_format=SDOCN%io_format)
+ else
+ if (my_task == master_task) write(logunit,F00) ' file not found, skipping ',trim(rest_file)
+ endif
endif
if (exists) then
@@ -562,7 +571,18 @@ subroutine docn_comp_run(EClock, x2o, o2x, &
integer(IN) :: idt ! integer timestep
real(R8) :: dt ! timestep
integer(IN) :: nu ! unit number
- real(R8) :: hn ! h field
+ real(R8) :: hn ! h field - mixed layer depth (MLD)
+ ! relaxed slab ocean mode variables
+ real(R8) :: RSO_bckgrd_sst ! background SST
+ real(R8) :: RSO_X_cool ! logistics function weight
+ real(R8) :: u10 ! 10 m wind
+ ! relaxed slab ocean fixed parameters
+ integer, parameter :: RSO_slab_option = 0 ! Option for setting RSO_X_cool
+ real(R8), parameter :: RSO_R_cool = 11.75_r8/86400._r8 ! base cooling rate [K/s]
+ real(R8), parameter :: RSO_Tdeep = 271.0_r8 ! deep water temperature [K]
+ real(R8), parameter :: RSO_dT_o = 27.0_r8 ! scaling temperature gradient
+ real(R8), parameter :: RSO_h_o = 30.0_r8 ! scaling mixed layer depth
+
character(len=18) :: date_str
character(len=CL) :: local_case_name
real(R8), parameter :: &
@@ -768,6 +788,65 @@ subroutine docn_comp_run(EClock, x2o, o2x, &
enddo
endif ! firstcall
+ ! Relaxed Slab Ocean based on Zarzycki(2016)
+ ! Zarzycki, C. M., 2016: Tropical Cyclone Intensity Errors Associated with Lack of Two-Way Ocean Coupling in High-Resolution Global Simulations. J. Climate, 29, 8589–8610.
+ ! https://journals.ametsoc.org/view/journals/clim/29/23/jcli-d-16-0273.1.xml
+ case('RSO')
+ lsize = mct_avect_lsize(o2x)
+ do n = 1,SDOCN%nstreams
+ call shr_dmodel_translateAV(SDOCN%avs(n),avstrm,avifld,avofld,rearr)
+ enddo
+ if (firstcall) then
+ do n = 1,lsize
+ if (.not. read_restart) then
+ somtp(n) = o2x%rAttr(kt,n) + TkFrz
+ endif
+ o2x%rAttr(kt,n) = somtp(n)
+ o2x%rAttr(kq,n) = 0.0_R8
+ enddo
+ else ! firstcall
+ tfreeze = shr_frz_freezetemp(o2x%rAttr(ks,:)) + TkFrz
+ do n = 1,lsize
+ if (imask(n) /= 0) then
+ !*******************************************************************
+ if (RSO_fixed_MLD>=0) then
+ hn = RSO_fixed_MLD
+ else
+ hn = avstrm%rAttr(kh,n)
+ endif
+ ! Get "background" temperature for relaxation
+ RSO_bckgrd_sst = avstrm%rAttr(kRSO_bckgrd_sst,n) + TkFrz
+ u10 = SQRT(x2o%rAttr(k10uu,n))
+ !*******************************************************************
+ ! Calculate scaling function - see Eq 3 in Zarzycki (2016)
+ if (RSO_slab_option==0) RSO_X_cool = 1._r8/(1._r8+EXP(-0.5_r8*(u10-30._r8)) ) ! SLAB1
+ if (RSO_slab_option==1) RSO_X_cool =(1._r8/(1._r8+EXP(-0.2_r8*(u10-30._r8)) ))*(u10*2.4_r8/80._r8) ! SLAB2
+ if (RSO_slab_option==2) RSO_X_cool = 0.0_r8 ! THERMO
+ !*******************************************************************
+ ! compute new ocean surface temperature
+ o2x%rAttr(kt,n) = somtp(n) &
+ ! Thermodynamic terms
+ +( x2o%rAttr(kswnet,n) & ! shortwave net
+ +x2o%rAttr(klwup ,n) & ! longwave up
+ +x2o%rAttr(klwdn ,n) & ! longwave down
+ +x2o%rAttr(ksen ,n) & ! sfc sensible heat flux
+ +x2o%rAttr(klat ,n) & ! sfc latent heat flux
+ -x2o%rAttr(ksnow ,n)*latice & ! latent heat from snow
+ -x2o%rAttr(krofi ,n)*latice & ! latent heat from runoff
+ ) * dt/(cpsw*rhosw*hn) &
+ - RSO_X_cool*RSO_R_cool*((somtp(n)-RSO_Tdeep)/RSO_dT_o)*(RSO_h_o/hn)*dt & ! Turb mixing
+ + (1_r8/RSO_relax_tau)*(RSO_bckgrd_sst - somtp(n))*dt ! Newtonian Relaxation
+ !*******************************************************************
+ ! Ignore ice formed or melt potential
+ o2x%rAttr(kq,n) = 0.0
+ ! Cap SSTs to freezing
+ o2x%rAttr(kt,n) = max( TkFrzSw, o2x%rAttr(kt,n) )
+ ! Save temperature to send back to coupler
+ somtp(n) = o2x%rAttr(kt,n)
+ endif ! imask /= 0
+ enddo ! lsize
+ endif ! firstcall
+
case('SOM_AQUAP')
lsize = mct_avect_lsize(o2x)
do n = 1,SDOCN%nstreams
@@ -912,7 +991,10 @@ subroutine docn_comp_run(EClock, x2o, o2x, &
close(nu)
call shr_file_freeUnit(nu)
endif
- if (trim(datamode) == 'SOM' .or. trim(datamode) == 'SOM_AQUAP') then
+ if ( trim(datamode) == 'SOM' & ! Traditional slab ocean
+ .or. trim(datamode) == 'RSO' & ! Relaxed slab ocean
+ .or. trim(datamode) == 'SOM_AQUAP' & ! Aquaplanet slab ocean
+ ) then
if (my_task == master_task) write(logunit,F04) ' writing ',trim(rest_file),target_ymd,target_tod
call shr_pcdf_readwrite('write', SDOCN%pio_subsystem, SDOCN%io_type,&
trim(rest_file), mpicom, gsmap, clobber=.true., rf1=somtp,rf1n='somtp')
diff --git a/components/data_comps/docn/src/docn_shr_mod.F90 b/components/data_comps/docn/src/docn_shr_mod.F90
index cf59dbc7f62..fef714c83b4 100644
--- a/components/data_comps/docn/src/docn_shr_mod.F90
+++ b/components/data_comps/docn/src/docn_shr_mod.F90
@@ -35,6 +35,8 @@ module docn_shr_mod
character(CL) , public :: datamode ! mode
integer(IN) , public :: aquap_option
real(R8) , public :: sst_constant_value
+ real(R8) , public :: RSO_relax_tau ! relaxed slab ocean relaxation timescale [sec]
+ real(R8) , public :: RSO_fixed_MLD ! relaxed slab ocean globally fixed mixed layer depth (MLD)
character(len=*), public, parameter :: nullstr = 'undefined'
!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CONTAINS
@@ -77,7 +79,8 @@ subroutine docn_shr_read_namelists(mpicom, my_task, master_task, &
!----- define namelist -----
namelist / docn_nml / &
- decomp, restfilm, restfils, force_prognostic_true, sst_constant_value
+ decomp, restfilm, restfils, force_prognostic_true, sst_constant_value, &
+ RSO_fixed_MLD, RSO_relax_tau
!----------------------------------------------------------------------------
! Determine input filenamname
@@ -110,12 +113,16 @@ subroutine docn_shr_read_namelists(mpicom, my_task, master_task, &
write(logunit,F00)' restfils = ',trim(restfils)
write(logunit,F0L)' force_prognostic_true = ',force_prognostic_true
write(logunit,*) ' sst_constant_value = ',sst_constant_value
+ write(logunit,*) ' RSO_fixed_MLD = ',RSO_fixed_MLD
+ write(logunit,*) ' RSO_relax_tau = ',RSO_relax_tau
endif
call shr_mpi_bcast(decomp ,mpicom,'decomp')
call shr_mpi_bcast(restfilm,mpicom,'restfilm')
call shr_mpi_bcast(restfils,mpicom,'restfils')
call shr_mpi_bcast(force_prognostic_true,mpicom,'force_prognostic_true')
call shr_mpi_bcast(sst_constant_value ,mpicom,'sst_constant_value')
+ call shr_mpi_bcast(RSO_fixed_MLD ,mpicom,'RSO_fixed_MLD')
+ call shr_mpi_bcast(RSO_relax_tau ,mpicom,'RSO_relax_tau')
rest_file = trim(restfilm)
rest_file_strm = trim(restfils)
@@ -152,8 +159,9 @@ subroutine docn_shr_read_namelists(mpicom, my_task, master_task, &
trim(datamode) == 'SST_AQUAP_CONSTANT' .or. &
trim(datamode) == 'COPYALL' .or. &
trim(datamode) == 'IAF' .or. &
- trim(datamode) == 'SOM' .or. &
- trim(datamode) == 'SOM_AQUAP') then
+ trim(datamode) == 'SOM' .or. & ! Traditional slab ocean
+ trim(datamode) == 'RSO' .or. & ! Relaxed slab ocean
+ trim(datamode) == 'SOM_AQUAP') then ! Aquaplanet slab ocean
if (my_task == master_task) then
write(logunit,F00) ' docn datamode = ',trim(datamode)
end if
@@ -181,9 +189,9 @@ subroutine docn_shr_read_namelists(mpicom, my_task, master_task, &
ocn_prognostic = .true.
ocnrof_prognostic = .true.
endif
- if (trim(datamode) == 'SOM' .or. trim(datamode) == 'SOM_AQUAP') then
- ocn_prognostic = .true.
- endif
+ if (trim(datamode) == 'SOM') ocn_prognostic = .true. ! Traditional slab ocean
+ if (trim(datamode) == 'RSO') ocn_prognostic = .true. ! Relaxed slab ocean
+ if (trim(datamode) == 'SOM_AQUAP') ocn_prognostic = .true. ! Aquaplanet slab ocean
end subroutine docn_shr_read_namelists
diff --git a/components/data_comps/docs/index.md b/components/data_comps/docs/index.md
new file mode 100644
index 00000000000..adef0842673
--- /dev/null
+++ b/components/data_comps/docs/index.md
@@ -0,0 +1,13 @@
+# Data Models
+
+The E3SM data models are key components to support many different scenarios:
+
+- AMIP style experiments with observed sea surface temperatures
+- component model spin-up, such as land forced by atmospheric reanalysis
+- idealized experiments, such as aquaplanet or radiative-convective equilibrium
+
+More details can be found for each component below.
+
+- [Data Atmosphere](user-guide/data-atmos.md)
+- [Data Land](user-guide/data-land.md)
+- [Data Ocean](user-guide/data-ocean.md)
diff --git a/components/data_comps/docs/user-guide/data-atmos.md b/components/data_comps/docs/user-guide/data-atmos.md
new file mode 100644
index 00000000000..d74710598ee
--- /dev/null
+++ b/components/data_comps/docs/user-guide/data-atmos.md
@@ -0,0 +1,4 @@
+# The E3SM Data Atmosphere Model
+
+!!!WARNING
+ This page is still under construction
diff --git a/components/data_comps/docs/user-guide/data-land.md b/components/data_comps/docs/user-guide/data-land.md
new file mode 100644
index 00000000000..3b07f59793e
--- /dev/null
+++ b/components/data_comps/docs/user-guide/data-land.md
@@ -0,0 +1,4 @@
+# The E3SM Data Land Model
+
+!!!WARNING
+ This page is still under construction
diff --git a/components/data_comps/docs/user-guide/data-ocean.md b/components/data_comps/docs/user-guide/data-ocean.md
new file mode 100644
index 00000000000..de232d665e8
--- /dev/null
+++ b/components/data_comps/docs/user-guide/data-ocean.md
@@ -0,0 +1,123 @@
+# The E3SM Data Ocean Model
+
+
+
+
+The E3SM data ocean has several different modes to support various realistic and idealized experiments. Sea surface temperatures (SST) can be either prescribed or prognostic. Prescribed SSTs are specified either through a data stream or analytically. Prognostic modes allow the SST field to evolve and respond to atmospheric conditions. The guides below provide more details on how to use these capabilities.
+
+- Prescribed
+ - [SST from Observations](#sst-from-observations)
+ - [Idealized SST](#idealized-sst)
+- Prognostic
+ - [Traditional Slab Ocean Model](#traditional-slab-ocean-model) (SOM)
+ - [Relaxed Slab Ocean](#relaxed-slab-ocean) (RSO)
+
+## SST from Observations
+
+Using SST data derived from observations is the most common use of the data ocean model, often for AMIP style experiments to reproduce historical periods.
+
+Example compsets that use this capability are `F2010` and `F20TR`. These compsets use the `_DOCN%DOM_` compset modifier, which sets the `DOCN_MODE` variable in `env_run.xml` to "prescribed".
+
+Several additional XML variables need to be set in order to use this capability, which are set to defaults for common configurations, such as `F2010` at `ne30pg2` atmospheric resolution.
+
+```text
+SSTICE_DATA_FILENAME Prescribed SST and ice coverage data file name
+SSTICE_GRID_FILENAME Grid file in "domain" format corresponding to SSTICE_DATA_FILENAME
+SSTICE_YEAR_ALIGN The model year that corresponds to SSTICE_YEAR_START on the data file
+SSTICE_YEAR_START The first year of data to use from SSTICE_DATA_FILENAME
+SSTICE_YEAR_END The last year of data to use from SSTICE_DATA_FILENAME
+```
+
+Most users will not need to edit these values from their defaults, but many scenarios require non-standard SST data, such as tropical cyclone hindcasts where the daily evolution of high-resolution SST data may be desireable.
+
+## Idealized SST
+
+The two main uses of idealized SST modes are aquaplanet (AQP) and radiative-convective equilibrium (RCE). The latter is just a special case of an aquaplanet where the SST is [usually] a constant value everywhere, traditionally used in conjunction with special modifications to homogenize radiation and disable rotation. There are several analytically specified SST patterns established by model intercomparison projects such as the Aqua-Planet Experiment (APE)[@blackburn_APE_context_2013] and RCEMIP[@wing_rcemip1_2018,@wing_rcemip2_2024].
+
+### Idealized SST compsets
+
+The following list shows the currently defined E3SM compsets that utilize idealized SST.
+
+```text
+FAQP
+FAQP-MMF1
+FAQP-MMF2
+F-SCREAM-LR-AQP1
+F-SCREAM-HR-AQP1
+FRCE
+FRCE-MMF1
+FRCE-MMF2
+FRCE-MW_295dT1p25
+FRCE-MW_300dT0p625
+FRCE-MW_300dT1p25
+FRCE-MW_300dT2p5
+FRCE-MW_305dT1p25
+FRCE-MW-MMF1_295dT1p25
+FRCE-MW-MMF1_300dT0p625
+FRCE-MW-MMF1_300dT1p25
+FRCE-MW-MMF1_300dT2p5
+FRCE-MW-MMF1_305dT1p25
+```
+
+These all use "analytic" SST patterns that are specified via the `docn_comp_run()` subroutine in `components/data_comps/docn/src/docn_comp_mod.F90`. The `AQP` compsets currently only use the basic aquaplanet pattern that is symmetric about the equator. Other APE patterns introduce different meridional gradients and/or asymmetries. The various analytic SST patterns can be selected by changing the data ocean specifier: `_DOCN%AQP1_`.
+
+The first 10 analytic aquaplanet SST patterns correspond to the aqua-planet experiment (APE) protocol as follows
+
+```text
+AQP1 = control symmetric SST pattern
+AQP2 = Flat
+AQP3 = Qobs = average of AQP1 and AQP2
+AQP4 = Peaked
+AQP5 = Control+5N
+AQP6 = 1KEQ - small warm pool
+AQP7 = 3KEQ - small warm pool
+AQP8 = 3KW1 - large warm pool
+AQP9 = Control+10N
+AQP10 = Control+15N
+```
+
+!!!NOTE
+ When using aquaplanet mode the orbital parameters will take on the idealized values shown below such that there are no seasonal variations, but there is still a diurnal cycle.
+ ```text
+ orb_eccen = 0
+ orb_obliq = 0
+ orb_mvelp = 0
+ orb_mode = "fixed_parameters"
+ ```
+
+The basic RCE compsets use the `_DOCN%AQPCONST_` modifier to produce a globally constant SST value, which is set by the `DOCN_AQPCONST_VALUE` variable in `env_run.xml`. The "FRCE-MW" compsets were designed for RCEMIP-II to produce a "mock walker-cell" configuration, in which sinusoidal SST variations are applied to promote a coherent large-scale circulation.
+
+### SST Data File
+
+In addition to the analytic SST modes the user can also specify an idealized aquaplanet SST pattern via the `_DOCN%AQPFILE_` option. The `aquapfile` namelist variable is used to specify the SST pattern in this mode. Note that this option has not been used or tested recently, so the user may experience difficulty trying to use this feature.
+
+## Traditional Slab Ocean Model
+
+A slab ocean model (SOM) allows responsive SSTs to address the "infinite heat source" problem associated with prescribed SSTs, but is much cheaper than running with a full ocean model. The traditional SOM appraoch requires special inputs, such as a specified mixed layer depth pattern that can vary in time and a prescribed heat flux to account for the missing effects of ocean dynamics often referred to as "Q-flux". The Q-flux data is often estimated from a fully coupled simulation with active ocean and sea-ice so that the SOM simulation will resemble the full model.
+
+Currently, we do not have Q-flux data to drive the SOM in E3SM. An alternative appraoch is to use a "relaxed" slab ocean (RSO) in which a specified relaxation time scale is used to bring the SST field back to a target SST field. The RSO mode is much simpler to use, but carries caveats that the user should be aware of before using. See [Data Ocean - Relaxed Slab Ocean](#relaxed-slab-ocean) for more information.
+
+## Relaxed Slab Ocean
+
+The relaxed slab ocean (RSO) is similar in many ways to the [traditional slab ocean model](#traditional-slab-ocean-model), but uses a specified relaxation time scale to avoid the need for specified "Q-flux" data to represent the effects of ocean transport. The RSO implementation in E3SM was inspired by Zarzycki (2016)[@Zarzycki_TC-ocn-cpl_2016].
+
+A key consideration for the user is whether they need to use a realistic distribution of mixed layer depths (MLD), or whether their use case can benefit from the simplicity of a globally uniform MLD.
+
+The RSO mode has the following namelist variables to influence the ocean behavior:
+
+```text
+RSO_relax_tau SST relaxation timescale
+RSO_fixed_MLD globally uniform MLD value (use -1 for realistic MLD)
+```
+
+Other RSO parameter values are hardcoded in `components/data_comps/docn/src/docn_comp_mod.F90`.
+
+```text
+RSO_slab_option = 0 ! Option for setting RSO_X_cool
+RSO_R_cool = 11.75/86400 ! base cooling rate [K/s]
+RSO_Tdeep = 271.00 ! deep water temperature [K]
+RSO_dT_o = 27.0 ! scaling temperature gradient
+RSO_h_o = 30.0 ! scaling mixed layer depth
+```
+
+The RSO mode uses the `SSTICE_DATA_FILENAME` in `env_run.xml` for its data stream. For a globally uniform MLD this file only need to contain a `SST_cpl` variable for the SST that will act as the target SST value for relaxation. If a realistic MLD pattern is desired then the `hblt` variable must also be present. This data can be derived a number of ways, but we currently do not have a dedicated tool or workflow.
diff --git a/components/data_comps/mkdocs.yml b/components/data_comps/mkdocs.yml
new file mode 100644
index 00000000000..89f5e6dca7b
--- /dev/null
+++ b/components/data_comps/mkdocs.yml
@@ -0,0 +1,7 @@
+site_name: Data-Models
+
+nav:
+ - Introduction: 'index.md'
+ - Atmosphere: user-guide/data-atmos.md
+ - Land: user-guide/data-land.md
+ - Ocean: user-guide/data-ocean.md
diff --git a/components/eam/bld/build-namelist b/components/eam/bld/build-namelist
index 8dc532b6a3d..ee450573c36 100755
--- a/components/eam/bld/build-namelist
+++ b/components/eam/bld/build-namelist
@@ -830,6 +830,10 @@ add_default($nl,'use_hetfrz_classnuc');
add_default($nl,'hist_hetfrz_classnuc');
add_default($nl,'gw_convect_hcf') if (get_default_value('gw_convect_hcf'));
add_default($nl,'hdepth_scaling_factor') if (get_default_value('hdepth_scaling_factor'));
+add_default($nl,'gw_convect_hdepth_min') if (get_default_value('gw_convect_hdepth_min'));
+add_default($nl,'gw_convect_storm_speed_min') if (get_default_value('gw_convect_storm_speed_min'));
+add_default($nl,'gw_convect_plev_src_wind') if (get_default_value('gw_convect_plev_src_wind'));
+add_default($nl,'use_gw_convect_old', 'val'=>'.true.');
add_default($nl,'linoz_psc_T');
if ($cfg->get('microphys') =~ /^mg2/) {
add_default($nl,'micro_mg_dcs_tdep');
@@ -4089,13 +4093,24 @@ if ($waccm_phys or $cfg->get('nlev') >= 60) {
add_default($nl, 'use_gw_oro' , 'val'=>'.true.');
add_default($nl, 'use_gw_front' , 'val'=>'.true.');
add_default($nl, 'use_gw_convect', 'val'=>'.true.');
+ add_default($nl, 'use_od_ls', 'val'=>'.false.');
+ add_default($nl, 'use_od_bl', 'val'=>'.false.');
+ add_default($nl, 'use_od_ss', 'val'=>'.false.');
+ add_default($nl, 'use_od_fd', 'val'=>'.false.');
} else {
add_default($nl, 'use_gw_oro' , 'val'=>'.true.');
add_default($nl, 'use_gw_front' , 'val'=>'.false.');
add_default($nl, 'use_gw_convect', 'val'=>'.false.');
+ add_default($nl, 'use_od_ls', 'val'=>'.false.');
+ add_default($nl, 'use_od_bl', 'val'=>'.false.');
+ add_default($nl, 'use_od_ss', 'val'=>'.false.');
+ add_default($nl, 'use_od_fd', 'val'=>'.false.');
}
add_default($nl, 'pgwv', 'val'=>'32');
add_default($nl, 'gw_dc','val'=>'2.5D0');
+add_default($nl, 'od_ls_ncleff' ,'val'=>'3.D0');
+add_default($nl, 'od_bl_ncd' ,'val'=>'3.D0');
+add_default($nl, 'od_ss_sncleff','val'=>'1.D0');
if ($nl->get_value('use_gw_oro') =~ /$TRUE/io) {
add_default($nl, 'effgw_oro');
diff --git a/components/eam/bld/namelist_files/namelist_defaults_eam.xml b/components/eam/bld/namelist_files/namelist_defaults_eam.xml
index 44e4e7e65ae..7c1a7cd3fd5 100755
--- a/components/eam/bld/namelist_files/namelist_defaults_eam.xml
+++ b/components/eam/bld/namelist_files/namelist_defaults_eam.xml
@@ -127,7 +127,6 @@
atm/cam/topo/USGS-gtopo30_64x128_c050520.nc
-
atm/cam/topo/USGS-gtopo30_ne4np4_16x.c20160612.nc
atm/cam/topo/USGS-gtopo30_ne4np4pg2_16x_converted.c20200527.nc
atm/cam/topo/USGS-gtopo30_ne11np4_16xconsistentSGH.c20160612.nc
@@ -827,7 +826,7 @@
0.5D0
7.0D0
0.001D0
- 0.04D0
+ 0.08D0
2.65D0
0.02D0
0.1D0
@@ -1890,8 +1889,14 @@ with se_tstep, dt_remap_factor, dt_tracer_factor set to -1
10.0
0.50
1.0
+2.5
+10.0
+70000
0.375
.true.
+ 3.D0
+ 3.D0
+ 1.D0
2.5D0
268.15D0
13.8D0
diff --git a/components/eam/bld/namelist_files/namelist_definition.xml b/components/eam/bld/namelist_files/namelist_definition.xml
index 8228c7d8d2e..848e43425b1 100644
--- a/components/eam/bld/namelist_files/namelist_definition.xml
+++ b/components/eam/bld/namelist_files/namelist_definition.xml
@@ -1078,6 +1078,48 @@ Whether or not to enable GWD brute-force energy fix.
Default: set by build-namelist.
+
+Whether or not to enable nonlinear orographic gravity wave drag (oGWD).
+Default: set by build-namelist.
+
+
+
+Whether or not to enable flow-blocking drag (FBD).
+Default: set by build-namelist.
+
+
+
+Whether or not to enable small-scale orographic GWD drag (sGWD).
+Default: set by build-namelist.
+
+
+
+Whether or not to enable turbulent orographic form drag (TOFD).
+Default: set by build-namelist.
+
+
+
+Tuning parameter of orographic GWD (oGWD). See use_od_ls.
+Default: set by build-namelist.
+
+
+
+Tuning parameter of flow-blocking drag (FBD). See use_od_bl.
+Default: set by build-namelist.
+
+
+
+Tuning parameter of small-scale GWD (sGWD). See use_od_ss.
+Default: set by build-namelist.
+
+
Gravity wave spectrum dimension (wave numbers are from -pgwv to pgwv).
@@ -1100,16 +1142,40 @@ Default: set by build-namelist.
-Heating rate conversion factor associated with convective gravity waves
+Heating rate conversion factor associated with convective GWD [unitless].
+Also often interpretted as "convective fraction" [%].
Default: 20.0
-Scaling factor for the heating depth
+Scaling factor for the heating depth [unitless]
Default: 1.0
+
+minimum hdepth for for convective GWD spectrum lookup table [km]
+Default: 2.5 km
+
+
+
+minimum convective storm speed in m/s for convective GWD
+Default: 10.0 m/s
+
+
+
+Reference pressure value used for convective storm speed in m/s for convective GWD
+Default: 70000 Pa
+
+
+
+switch to revert to old calculation of Beres scheme for heating depth and max
+
+
Efficiency associated with convective gravity waves from the Beres
@@ -6743,6 +6809,36 @@ example, to apply hyperviscosity to moisture, the first tracer, set the value to
Default: (set by dycore)
+
+Number of element haloes to include in trajectory search. -1 triggers an
+automatic calculation of max(1, dt_tracer_factor/3). This is based on the
+advective CFL condition that governs the dynamics time step.
+Default: -1 (set by dycore)
+
+
+
+Number of substeps to take in computing semi-Lagrangian transport
+trajectories. 0 triggers the original algorithm; 1 or larger triggers the
+enhanced-trajectory algorithm.
+Default: 0 (set by dycore)
+
+
+
+Number of velocity snapshots to store for use when computing the enhanced
+trajectories. -1 triggers an automatic calculation. 0, 1, 2 all become 2, the
+minimum.
+Default: -1 (set by dycore)
+
+
+
+Optional diagnostic output from transport module.
+Default: 0 (set by dycore)
+
+
FAQP-MMF2
2000_EAM%AQP-MMF2_SLND_SICE_DOCN%AQP1_SROF_SGLC_SWAV
+
+
+
+
+
+
+ F2010-RSO
+ 2010_EAM%CMIP6_ELM%CNPRDCTCBCTOP_MPASSI%PRES_DOCN%RSO_MOSART_SGLC_SWAV
+
diff --git a/components/eam/cime_config/testdefs/testmods_dirs/eam/orodrag_ne30pg2/user_nl_eam b/components/eam/cime_config/testdefs/testmods_dirs/eam/orodrag_ne30pg2/user_nl_eam
new file mode 100644
index 00000000000..8ab37d27978
--- /dev/null
+++ b/components/eam/cime_config/testdefs/testmods_dirs/eam/orodrag_ne30pg2/user_nl_eam
@@ -0,0 +1,8 @@
+use_gw_oro=.false.
+use_od_ls=.true.
+use_od_bl=.true.
+use_od_ss=.true.
+use_od_fd=.true.
+
+
+bnd_topo='$DIN_LOC_ROOT/atm/cam/topo/USGS-gtopo30_ne30np4pg2_x6t-SGH_forOroDrag.c20241001.nc'
diff --git a/components/eam/cime_config/testdefs/testmods_dirs/eam/orodrag_ne4pg2/user_nl_eam b/components/eam/cime_config/testdefs/testmods_dirs/eam/orodrag_ne4pg2/user_nl_eam
new file mode 100644
index 00000000000..f32cc8a6f93
--- /dev/null
+++ b/components/eam/cime_config/testdefs/testmods_dirs/eam/orodrag_ne4pg2/user_nl_eam
@@ -0,0 +1,7 @@
+use_gw_oro=.false.
+use_od_ls=.true.
+use_od_bl=.true.
+use_od_ss=.true.
+use_od_fd=.true.
+
+bnd_topo='$DIN_LOC_ROOT/atm/cam/topo/USGS-gtopo30_ne4np4pg2_16x_converted_forOroDrag.c20241019.nc'
diff --git a/components/eam/cime_config/testdefs/testmods_dirs/eam/thetahy_sl_nsubstep2/user_nl_eam b/components/eam/cime_config/testdefs/testmods_dirs/eam/thetahy_sl_nsubstep2/user_nl_eam
new file mode 100644
index 00000000000..7cfe7f1cb6e
--- /dev/null
+++ b/components/eam/cime_config/testdefs/testmods_dirs/eam/thetahy_sl_nsubstep2/user_nl_eam
@@ -0,0 +1,3 @@
+semi_lagrange_diagnostics = 1
+semi_lagrange_trajectory_nsubstep = 2
+semi_lagrange_trajectory_nvelocity = 3
diff --git a/components/eam/docs/figures/orodrag.png b/components/eam/docs/figures/orodrag.png
new file mode 100644
index 00000000000..de6e5cd8407
Binary files /dev/null and b/components/eam/docs/figures/orodrag.png differ
diff --git a/components/eam/docs/tech-guide/index.md b/components/eam/docs/tech-guide/index.md
index f93b7715570..10e66936799 100644
--- a/components/eam/docs/tech-guide/index.md
+++ b/components/eam/docs/tech-guide/index.md
@@ -16,6 +16,8 @@ This Technical Guide describes the physics of version 3 of the E3SM Atmospheric
- [RRTMG](rrtmg.md): Parameterization of radiation.
+- [ORODRAG](orodrag.md): Parameterization of orographic drag
+
- [MAM](mam.md): Primary parameterization schemes used to represent aerosols.
- [VBS](vbs.md): Parameterization of secondary organic aerosols.
diff --git a/components/eam/docs/tech-guide/orodrag.md b/components/eam/docs/tech-guide/orodrag.md
new file mode 100644
index 00000000000..a0be96e4f75
--- /dev/null
+++ b/components/eam/docs/tech-guide/orodrag.md
@@ -0,0 +1,35 @@
+# Orographic drag scheme
+
+## Overview
+
+The orographic drag schemes includes two main options: the default Gravity Wave Drag scheme of McFarlane (1987)[@mcfarlane_the_1987] and a new suite of orographic drag parameterization schemes. The new suite includes 4 components all combined in one module (i.e. subroutine gwdo2d). The schemes include orographic gravity wave drag (oGWD, Xie et al.,2020)[@xie_an_2020], flow-blocking drag (FBD, Xie et al.,2020)[@xie_an_2020], small-scale GWD (sGWD, Tsiringakis et al.,2017)[@tsiringakis_small_2020], and turbulent-scale orographic form drag (TOFD, Beljaars et al., 2004)[@beljaars_a_2020]. The oGWD and TOFD schemes are used to replace the default oGWD (McFarlane, 1987)[@mcfarlane_the_1987] and Turbulent Mountain Stress (TMS, documented on Richter et al., 2010)[@richter_the_2010] module in EAM, while the FBD and sGWD are added enhanced drag schemes. Each of the schemes are used to predict and add enhanced drags from surface to high level that would help decelerate the wind especially over the mountainous regions among the globe. The oGWD, FBD, and sGWD are implemented in gw_drag.F90, while TOFD is implemented in clubb_intr.F90 to join the vertical diffusion process. There are also new topographic parameters (orographic asymmetry [OA], orographic convexity [OC], effective orographic length [OL]) are input into the model for the new oGWD and FBD scheme implmented. The concept of each scheme is illustrate in the figure below. Currently, only the scheme of McFarlane (1987) is turned on as default in E3SMv3.0.
+
+
+
+### Default oGWD scheme
+
+The current default oGWD scheme in E3SMv3.0 is from McFarlane (1987)[@mcfarlane_the_1987]. It is a linear orographic gravity wave drag scheme that parameterizes the subgrid process of vertical propagation of gravity wave originating from orographic source. The output from this scheme is a vertical profile of drag (or deceleration terms) when gravity wave breaks at higher levels and deposits momemtum flux to that level. This scheme is shown to improve the excessive westerly wind bias in the extratropics and the wind bias in the polar region. This scheme is turned on by default in E3SMv3.0.
+
+### Default TMS scheme
+
+The turbulent mountain stress (TMS) scheme is documented on Richter et al.,(2010)[@richter_the_2010]. It parameterizes the turbulent scale form drag (TOFD) through adding enhanced effective roughness length to the model. This method is justified by the observation that area-averaged wind sufficiently far above hilly terrain behave logarithmically. It leads to significant decrease of overspeed surface wind in the model. It is turned OFF in E3SMv3.0.
+
+### New oGWD scheme
+
+The Xie et al.(2020)[@xie_an_2020] oGWD scheme is a nonlinear orographic gravity wave drag scheme that parameterizes the subgrid oGWD (>5km). It includes both the linear oGWD like that of McFarlane (1987)[@mcfarlane_the_1987] and nonlinear oGWD like low-level wave breaking (LLWB). The LLWB downstream often results in downslope windstorm that can enhance the drag by several times that of linear oGWD. The incorporation of the nonlinear drag is by adding an "enhancement factor" that is a function of the higher moments of the orography, e.g. orographic asymmetry (OA), orographic convexity (OC), effective orographic length (OL).
+
+### FBD scheme
+
+The Xie et al.(2020)[@xie_an_2020] FBD scheme parameterizes the drag by flow blocked on the mountain flanks or flowing around the mountain under upstream stable conditions (>5km). It occurs when the mean flow does not have enough kinetic energy to traverse an obstacle and either stops upstream or diverges around the obstacle. This provides drag near the surface where the blocking occurs in addition to the oGWD.
+
+### TOFD scheme
+
+The TOFD scheme (Beljaars et al.,2004)[@beljaars_a_2020] parameterizes the drag generated by the shear stresses in the boundary layer when the flow encounters smaller obstacles (<5km). As airflow encounters an obstacle, it is disrupted, leading to the formation of eddies and vortices. These turbulent structures enhance mixing, allowing different layers of air to interact over a short distance. The intensity of the mixing is typically higher close to the obstacle, with rapid changes in velocity and direction of the airflow and can exhibit large control over the surface wind. It is an alternative scheme to the current TMS in E3SMv3. An important difference between the TOFD and TMS is that TOFD explicitly calculate the stress profile while TMS uses an enhanced effective roughtness length approach.
+
+### sGWD scheme
+
+The Tsiringakis et al.(2017)[@tsiringakis_small_2020] sGWD scheme parameterizes the small-scale orographic gravity wave drag (sGWD) within the relatively shallow stable boundary layer. Models applying the form drag such as TOFD schemes usually lack sufficient cyclonic filling and do not accurately represent the development of cyclones over land (Holstag 2006)[@holtslag_preface_2006]. This caused significant temperature bias that occurs due to runaway cooling at the surface. To bridge the gap of this missing drag in the boundary layer, studies have hypothesized that the missing drag can be generated by sGWD. sGWD occurs under the relative stable boundary layer with low winds where the turbulence is significantly reduced.
+
+## Namelist parameters
+
+[orodrag Namelist Parameters](../user-guide/namelist_parameters.md#orographic-drag-schemes)
diff --git a/components/eam/docs/user-guide/namelist_parameters.md b/components/eam/docs/user-guide/namelist_parameters.md
index b09e8c44ffd..8aa4b40299c 100644
--- a/components/eam/docs/user-guide/namelist_parameters.md
+++ b/components/eam/docs/user-guide/namelist_parameters.md
@@ -156,3 +156,20 @@
| 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` |
+
+## Orographic drag schemes
+
+| Parameter | Description | Default value |
+| ------------------------- | ----------------------------------------------------------------- | ---------------------- |
+| `use_gw_oro` | This namelist controls the default linear orographic gravity wave drag (oGWD) for E3SM, if used, the default oGWD is turned on. | `true` |
+| `do_tms` | This namelist controls the default Turbulent Mountain Stress (TMS) for E3SM, if used, the default TMS is turned on. | `false` |
+| `effgw_oro` | Efficiency associated with orographic gravity waves. | `0.375` |
+| `tms_orocnst` | Turbulent mountain stress parameter used when TMS calculation is turned on | `1.0` |
+| `tms_z0fac` | Factor determining z_0 from orographic standard deviation [ no unit ] for TMS. | `0.75` |
+| `use_od_ls` | This namelist controls the new nonlinear oGWD, if used, the nonlinear oGWD is turned on. use_od_ls should not be used at the same time with use_gw_oro. | `false` |
+| `use_od_bl` | This namelist controls the Flow-blocking drag (FBD) scheme, if used, the FBD scheme is turned on. | `false` |
+| `use_od_ss` | This namelist controls the small-scale GWD (sGWD) scheme, if used, the sGWD scheme is turned on. | `false` |
+| `use_od_fd` | This namelist controls the Turbulent orographic form drag (TOFD) scheme, if used, the TOFD scheme is turned on. | `false` |
+| `od_ls_ncleff` | Tuning parameter of nonlinear oGWD. Stands for effective resolution of the grid for oGWD. Scales the magnitude of nonlinear oGWD. | `3` |
+| `od_bl_ncd` | Tuning parameter of FBD. Stands for bulk drag coefficient. Scales the magnitude of FBD. | `3` |
+| `od_ss_sncleff` | Tuning parameter of sGWD. Stands for effective resolution of the grid for sGWD.Scales the magnitude of sGWD. | `1` |
diff --git a/components/eam/mkdocs.yml b/components/eam/mkdocs.yml
index e41cb614387..d0e23a6e7e8 100644
--- a/components/eam/mkdocs.yml
+++ b/components/eam/mkdocs.yml
@@ -16,6 +16,7 @@ nav:
- tech-guide/clubb.md
- tech-guide/zm.md
- RRTMG: tech-guide/rrtmg.md
+ - tech-guide/orodrag.md
- tech-guide/mam.md
- tech-guide/vbs.md
- tech-guide/dust.md
diff --git a/components/eam/src/chemistry/mozart/rate_diags.F90 b/components/eam/src/chemistry/mozart/rate_diags.F90
index 457ede70307..4ad21392f54 100644
--- a/components/eam/src/chemistry/mozart/rate_diags.F90
+++ b/components/eam/src/chemistry/mozart/rate_diags.F90
@@ -126,7 +126,7 @@ subroutine rate_diags_calc( rxt_rates, vmr, m, ncol, lchnk, pver, pdeldry, mbar
rxt_rates(:ncol,:,rxt_tag_map(i)) = rxt_rates(:ncol,:,rxt_tag_map(i)) * m(:,:)
call outfld( rate_names(i), rxt_rates(:ncol,:,rxt_tag_map(i)), ncol, lchnk )
- if ( .not. history_UCIgaschmbudget_2D .and. .not. history_UCIgaschmbudget_2D_levels) return
+ if (history_UCIgaschmbudget_2D .or. history_UCIgaschmbudget_2D_levels) then
if (rate_names(i) .eq. 'r_lch4') then
!kg/m2/sec
@@ -166,6 +166,8 @@ subroutine rate_diags_calc( rxt_rates, vmr, m, ncol, lchnk, pver, pdeldry, mbar
endif
endif
+
+ endif
enddo
end subroutine rate_diags_calc
diff --git a/components/eam/src/control/runtime_opts.F90 b/components/eam/src/control/runtime_opts.F90
index c52c02a5c23..1fcd84806b7 100644
--- a/components/eam/src/control/runtime_opts.F90
+++ b/components/eam/src/control/runtime_opts.F90
@@ -246,6 +246,7 @@ subroutine read_namelist(single_column_in, scmlon_in, scmlat_in, scm_multcols_in
use uwshcu, only: uwshcu_readnl
use pkg_cld_sediment, only: cld_sediment_readnl
use gw_drag, only: gw_drag_readnl
+ use od_common, only: oro_drag_readnl
use qbo, only: qbo_readnl
use iondrag, only: iondrag_readnl
use phys_debug_util, only: phys_debug_readnl
@@ -516,6 +517,7 @@ subroutine read_namelist(single_column_in, scmlon_in, scmlat_in, scm_multcols_in
call uwshcu_readnl(nlfilename)
call cld_sediment_readnl(nlfilename)
call gw_drag_readnl(nlfilename)
+ call oro_drag_readnl(nlfilename)
call qbo_readnl(nlfilename)
call iondrag_readnl(nlfilename)
call phys_debug_readnl(nlfilename)
diff --git a/components/eam/src/physics/cam/clubb_intr.F90 b/components/eam/src/physics/cam/clubb_intr.F90
index a93331fabdd..33815759e7c 100644
--- a/components/eam/src/physics/cam/clubb_intr.F90
+++ b/components/eam/src/physics/cam/clubb_intr.F90
@@ -20,7 +20,8 @@ module clubb_intr
use shr_kind_mod, only: r8=>shr_kind_r8
use shr_log_mod , only: errMsg => shr_log_errMsg
use ppgrid, only: pver, pverp
- use phys_control, only: phys_getopts
+ use phys_control, only: phys_getopts, use_od_ss, use_od_fd
+ use od_common, only: od_ls_ncleff, od_bl_ncd, od_ss_sncleff
use physconst, only: rair, cpair, gravit, latvap, latice, zvir, rh2o, karman, &
tms_orocnst, tms_z0fac, pi
use cam_logfile, only: iulog
@@ -631,7 +632,8 @@ subroutine clubb_ini_cam(pbuf2d, dp1_in)
use constituents, only: cnst_get_ind
use phys_control, only: phys_getopts
- use parameters_tunable, only: params_list
+ use parameters_tunable, only: params_list
+ use cam_abortutils, only: endrun
#endif
@@ -927,7 +929,25 @@ subroutine clubb_ini_cam(pbuf2d, dp1_in)
call addfld ('VMAGDP', horiz_only, 'A', '-', 'ZM gustiness enhancement')
call addfld ('VMAGCL', horiz_only, 'A', '-', 'CLUBB gustiness enhancement')
call addfld ('TPERTBLT', horiz_only, 'A', 'K', 'perturbation temperature at PBL top')
-
+ !
+ if (use_od_fd) then
+ !added for turbulent orographic form drag (TOFD) output
+ call addfld ('DTAUX3_FD',(/'lev'/),'A','m/s2','U tendency - fd orographic drag')
+ call addfld ('DTAUY3_FD',(/'lev'/),'A','m/s2','V tendency - fd orographic drag')
+ call addfld ('DUSFC_FD',horiz_only,'A','N/m2','fd zonal oro surface stress')
+ call addfld ('DVSFC_FD',horiz_only,'A','N/m2','fd merio oro surface stress')
+ call add_default('DTAUX3_FD', 1, ' ')
+ call add_default('DTAUY3_FD', 1, ' ')
+ call add_default('DUSFC_FD', 1, ' ')
+ call add_default('DVSFC_FD', 1, ' ')
+ if (masterproc) then
+ write(iulog,*)'Using turbulent orographic form drag scheme (TOFD)'
+ end if
+ if (use_od_fd.and.do_tms) then
+ call endrun("clubb_intr: Both TMS and TOFD are turned on, please turn one off&
+ &by setting use_od_fd or do_tms as .false.")
+ end if
+ end if
! Initialize statistics, below are dummy variables
dum1 = 300._r8
dum2 = 1200._r8
@@ -1155,7 +1175,9 @@ subroutine clubb_tend_cam( &
use model_flags, only: ipdf_call_placement
use advance_clubb_core_module, only: ipdf_post_advance_fields
#endif
-
+ use od_common, only: grid_size, oro_drag_interface
+ use hycoef, only: etamid
+ use physconst, only: rh2o,pi,rearth,r_universal
implicit none
! --------------- !
@@ -1519,6 +1541,28 @@ subroutine clubb_tend_cam( &
real(r8) :: sfc_v_diff_tau(pcols) ! Response to tau perturbation, m/s
real(r8), parameter :: pert_tau = 0.1_r8 ! tau perturbation, Pa
+ !variables for turbulent orographic form drag (TOFD) interface
+ real(r8) :: dtaux3_fd(pcols,pver)
+ real(r8) :: dtauy3_fd(pcols,pver)
+ real(r8) :: dusfc_fd(pcols)
+ real(r8) :: dvsfc_fd(pcols)
+ logical :: gwd_ls,gwd_bl,gwd_ss,gwd_fd
+ real(r8) :: dummy_nm(pcols,pver)
+ real(r8) :: dummy_utgw(pcols,pver)
+ real(r8) :: dummy_vtgw(pcols,pver)
+ real(r8) :: dummy_ttgw(pcols,pver)
+ real(r8) :: dummx_ls(pcols,pver)
+ real(r8) :: dummx_bl(pcols,pver)
+ real(r8) :: dummx_ss(pcols,pver)
+ real(r8) :: dummy_ls(pcols,pver)
+ real(r8) :: dummy_bl(pcols,pver)
+ real(r8) :: dummy_ss(pcols,pver)
+ real(r8) :: dummx3_ls(pcols,pver)
+ real(r8) :: dummx3_bl(pcols,pver)
+ real(r8) :: dummx3_ss(pcols,pver)
+ real(r8) :: dummy3_ls(pcols,pver)
+ real(r8) :: dummy3_bl(pcols,pver)
+ real(r8) :: dummy3_ss(pcols,pver)
real(r8) :: inv_exner_clubb_surf
@@ -1947,6 +1991,35 @@ subroutine clubb_tend_cam( &
call t_stopf('compute_tms')
endif
+ if (use_od_fd) then
+ gwd_ls =.false.
+ gwd_bl =.false.
+ gwd_ss =.false.
+ gwd_fd =use_od_fd
+ dummy_nm =0.0_r8
+ dummy_utgw=0.0_r8
+ dummy_vtgw=0.0_r8
+ dummy_ttgw=0.0_r8
+ !sgh30 as the input for turbulent orographic form drag (TOFD) instead of sgh
+ call oro_drag_interface(state,cam_in,sgh30,pbuf,hdtime,dummy_nm,&
+ gwd_ls,gwd_bl,gwd_ss,gwd_fd,&
+ od_ls_ncleff,od_bl_ncd,od_ss_sncleff,&
+ dummy_utgw,dummy_vtgw,dummy_ttgw,&
+ dtaux3_ls=dummx3_ls,dtauy3_ls=dummy3_ls,&
+ dtaux3_bl=dummx3_bl,dtauy3_bl=dummy3_bl,&
+ dtaux3_ss=dummx3_ss,dtauy3_ss=dummy3_ss,&
+ dtaux3_fd=dtaux3_fd,dtauy3_fd=dtauy3_fd,&
+ dusfc_ls=dummx_ls,dvsfc_ls=dummy_ls,&
+ dusfc_bl=dummx_bl,dvsfc_bl=dummy_bl,&
+ dusfc_ss=dummx_ss,dvsfc_ss=dummy_ss,&
+ dusfc_fd=dusfc_fd,dvsfc_fd=dvsfc_fd)
+
+ call outfld ('DTAUX3_FD', dtaux3_fd, pcols, lchnk)
+ call outfld ('DTAUY3_FD', dtauy3_fd, pcols, lchnk)
+ call outfld ('DUSFC_FD', dusfc_fd, pcols, lchnk)
+ call outfld ('DVSFC_FD', dvsfc_fd, pcols, lchnk)
+ endif
+
if (micro_do_icesupersat) then
call physics_ptend_init(ptend_loc,state%psetcols, 'clubb_ice3', ls=.true., lu=.true., lv=.true., lq=lq)
endif
@@ -2067,7 +2140,14 @@ subroutine clubb_tend_cam( &
dum_core_rknd = real((ksrftms(i)*state1%v(i,pver)), kind = core_rknd)
vpwp_sfc = vpwp_sfc-(dum_core_rknd/rho_ds_zm(1))
endif
-
+ ! ------------------------------------------------- !
+ ! Apply TOFD
+ ! ------------------------------------------------- !
+ ! tendency is flipped already
+ if (use_od_fd) then
+ um_forcing(2:pverp)=dtaux3_fd(i,pver:1:-1)
+ vm_forcing(2:pverp)=dtauy3_fd(i,pver:1:-1)
+ endif
! Need to flip arrays around for CLUBB core
do k=1,pverp
um_in(k) = real(um(i,pverp-k+1), kind = core_rknd)
@@ -3091,7 +3171,7 @@ end subroutine clubb_tend_cam
! !
! =============================================================================== !
- subroutine clubb_surface (state, cam_in, ustar, obklen)
+ subroutine clubb_surface (state, cam_in, pbuf, ustar, obklen)
!-------------------------------------------------------------------------------
! Description: Provide the obukhov length and the surface friction velocity
@@ -3108,10 +3188,12 @@ subroutine clubb_surface (state, cam_in, ustar, obklen)
!-------------------------------------------------------------------------------
use physics_types, only: physics_state
- use physconst, only: zvir
+ use physconst, only: zvir,gravit
use ppgrid, only: pver, pcols
use constituents, only: cnst_get_ind
use camsrfexch, only: cam_in_t
+ use hb_diff, only: pblintd_ri
+ use physics_buffer, only: pbuf_get_index, pbuf_get_field, physics_buffer_desc
implicit none
@@ -3119,8 +3201,9 @@ subroutine clubb_surface (state, cam_in, ustar, obklen)
! Input Auguments !
! --------------- !
- type(physics_state), intent(inout) :: state ! Physics state variables
- type(cam_in_t), intent(in) :: cam_in
+ type(physics_state), intent(inout) :: state ! Physics state variables
+ type(cam_in_t), intent(in) :: cam_in
+ type(physics_buffer_desc), pointer, intent(in) :: pbuf(:)
! ---------------- !
! Output Auguments !
@@ -3136,16 +3219,23 @@ subroutine clubb_surface (state, cam_in, ustar, obklen)
! --------------- !
integer :: i ! indicees
+ integer :: k
integer :: ncol ! # of atmospheric columns
real(r8) :: th(pcols) ! surface potential temperature
real(r8) :: thv(pcols) ! surface virtual potential temperature
+ real(r8) :: th_lv(pcols,pver) ! level potential temperature
+ real(r8) :: thv_lv(pcols,pver) ! level virtual potential temperature
real(r8) :: kinheat ! kinematic surface heat flux
real(r8) :: kinwat ! kinematic surface vapor flux
real(r8) :: kbfs ! kinematic surface buoyancy flux
+ real(r8) :: kbfs_pcol(pcols) ! kinematic surface buoyancy flux stored for all pcols
integer :: ixq,ixcldliq !PMA fix for thv
real(r8) :: rrho ! Inverse air density
+ integer :: oro_drag_ribulk_idx ! pbuf index of bulk richardson number for oro drag
+ real(r8), pointer :: oro_drag_ribulk(:) ! pbuf pointer for bulk richardson number
+
#endif
obklen(pcols) = 0.0_r8
@@ -3181,6 +3271,43 @@ subroutine clubb_surface (state, cam_in, ustar, obklen)
kinheat, kinwat, kbfs, obklen(i) )
enddo
+ if (use_od_ss) then
+ !add calculation of bulk richardson number here
+ !compute the whole level th and thv for diagnose of bulk richardson number
+ thv_lv=0.0_r8
+ th_lv =0.0_r8
+
+ !use the same virtual potential temperature formula as above (thv) except for all vertical levels
+ !used for bulk richardson number below in pblintd_ri
+ do i=1,ncol
+ do k=1,pver
+ th_lv(i,k) = state%t(i,k)*state%exner(i,k)
+ if (use_sgv) then
+ thv_lv(i,k) = th_lv(i,k)*(1.0_r8+zvir*state%q(i,k,ixq) &
+ - state%q(i,k,ixcldliq))
+ else
+ thv_lv(i,k) = th_lv(i,k)*(1.0_r8+zvir*state%q(i,k,ixq))
+ end if
+ enddo
+ enddo
+
+ !recalculate the kbfs stored in kbfs_pcol for bulk richardson number in pblintd_ri
+ kbfs_pcol=0.0_r8
+ do i=1,ncol
+ call calc_ustar( state%t(i,pver), state%pmid(i,pver), cam_in%wsx(i), cam_in%wsy(i), rrho, ustar(i) )
+ call calc_obklen( th(i), thv(i), cam_in%cflx(i,1), cam_in%shf(i), rrho, ustar(i), &
+ kinheat, kinwat, kbfs, obklen(i) )
+ kbfs_pcol(i)=kbfs
+ enddo
+
+ oro_drag_ribulk_idx = pbuf_get_index('oro_drag_ribulk')
+ call pbuf_get_field(pbuf, oro_drag_ribulk_idx, oro_drag_ribulk)
+
+ !calculate the bulk richardson number
+ call pblintd_ri(ncol, gravit, thv_lv, state%zm, state%u, state%v, &
+ ustar, obklen, kbfs_pcol, oro_drag_ribulk)
+ endif
+
return
#endif
diff --git a/components/eam/src/physics/cam/gw_convect.F90 b/components/eam/src/physics/cam/gw_convect.F90
index fc2fce99214..dff87eec89c 100644
--- a/components/eam/src/physics/cam/gw_convect.F90
+++ b/components/eam/src/physics/cam/gw_convect.F90
@@ -4,10 +4,10 @@ module gw_convect
! This module handles gravity waves from convection, and was extracted from
! gw_drag in May 2013.
!
-
-use gw_utils, only: r8
-
-use gw_common, only: pver, pgwv
+use cam_logfile, only: iulog
+use spmd_utils, only: masterproc
+use gw_utils, only: r8
+use gw_common, only: pver, pgwv
implicit none
private
@@ -21,8 +21,8 @@ module gw_convect
! Dimension for mean wind in heating.
integer :: maxuh
-! Index for level at 700 mb.
-integer :: k700
+! Index for level for storm/steering flow (usually 700 mb)
+integer :: k_src_wind
! Table of source spectra.
real(r8), allocatable :: mfcc(:,:,:)
@@ -31,19 +31,21 @@ module gw_convect
!==========================================================================
-subroutine gw_convect_init(k700_in, mfcc_in, errstring)
- ! Index at 700 mb.
- integer, intent(in) :: k700_in
- ! Source spectra to keep as table.
- real(r8), intent(in) :: mfcc_in(:,:,:)
- ! Report any errors from this routine.
- character(len=*), intent(out) :: errstring
-
+subroutine gw_convect_init( plev_src_wind, mfcc_in, errstring)
+ use ref_pres, only: pref_edge
+ real(r8), intent(in) :: plev_src_wind ! reference pressure value [Pa] to set k_src_wind (previously hardcoded to 70000._r8)
+ real(r8), intent(in) :: mfcc_in(:,:,:) ! Source spectra to keep as table
+ character(len=*), intent(out) :: errstring ! Report any errors from this routine
integer :: ierr
+ integer :: k
errstring = ""
- k700 = k700_in
+ do k = 0, pver
+ if ( pref_edge(k+1) < plev_src_wind ) k_src_wind = k+1
+ end do
+
+ if (masterproc) write (iulog,*) 'gw_convect: steering flow level = ',k_src_wind
! First dimension is maxh.
maxh = size(mfcc_in,1)
@@ -60,7 +62,9 @@ end subroutine gw_convect_init
subroutine gw_beres_src(ncol, ngwv, lat, u, v, netdt, &
zm, src_level, tend_level, tau, ubm, ubi, xv, yv, c, &
- hdepth, maxq0, CF, hdepth_scaling_factor)
+ hdepth, maxq0_out, maxq0_conversion_factor, hdepth_scaling_factor, &
+ hdepth_min, storm_speed_min, &
+ use_gw_convect_old)
!-----------------------------------------------------------------------
! Driver for multiple gravity wave drag parameterization.
!
@@ -90,11 +94,20 @@ subroutine gw_beres_src(ncol, ngwv, lat, u, v, netdt, &
real(r8), intent(in) :: zm(ncol,pver)
! Heating conversion factor
- real(r8), intent(in) :: CF
+ real(r8), intent(in) :: maxq0_conversion_factor
! Scaling factor for the heating depth
real(r8), intent(in) :: hdepth_scaling_factor
+ ! minimum hdepth for for spectrum lookup table
+ real(r8), intent(in) :: hdepth_min
+
+ ! minimum convective storm speed
+ real(r8), intent(in) :: storm_speed_min
+
+ ! switch for restoring legacy method
+ logical, intent(in) :: use_gw_convect_old
+
! Indices of top gravity wave source level and lowest level where wind
! tendencies are allowed.
integer, intent(out) :: src_level(ncol)
@@ -110,19 +123,19 @@ subroutine gw_beres_src(ncol, ngwv, lat, u, v, netdt, &
real(r8), intent(out) :: c(ncol,-pgwv:pgwv)
! Heating depth and maximum heating in each column.
- real(r8), intent(out) :: hdepth(ncol), maxq0(ncol)
+ real(r8), intent(out) :: hdepth(ncol), maxq0_out(ncol)
!---------------------------Local Storage-------------------------------
! Column and level indices.
integer :: i, k
- ! Zonal/meridional wind at 700mb.
- real(r8) :: u700(ncol), v700(ncol)
+ ! Zonal/meridional source wind
+ real(r8) :: u_src(ncol), v_src(ncol)
! 3.14...
real(r8), parameter :: pi = 4._r8*atan(1._r8)
! Maximum heating rate.
- real(r8) :: q0(ncol)
+ real(r8) :: maxq0(ncol)
! Bottom/top heating range index.
integer :: mini(ncol), maxi(ncol)
@@ -135,36 +148,40 @@ subroutine gw_beres_src(ncol, ngwv, lat, u, v, netdt, &
! Source level tau for a column.
real(r8) :: tau0(-PGWV:PGWV)
! Speed of convective cells relative to storm.
- integer :: CS(ncol)
+ integer :: storm_speed(ncol)
! Index to shift spectra relative to ground.
integer :: shift
- ! Heating rate conversion factor. Change to take the value from caller and controllable by namelist (to tune QBO)
- ! real(r8), parameter :: CF = 20._r8
- ! Averaging length.
- real(r8), parameter :: AL = 1.0e5_r8
+ ! fixed parameters (we may want to expose these in the namelist for tuning)
+ real(r8), parameter :: tau_avg_length = 100e3 ! spectrum averaging length [m]
+ real(r8), parameter :: heating_altitude_max = 20e3 ! max altitude [m] to check for max heating
+
+ ! note: the heating_altitude_max is probably not needed because there is
+ ! rarely any convective heating above this level and the performance impact
+ ! of skipping the iteration over higher levels is likely negilible.
+
+ integer :: ndepth_pos
+ integer :: ndepth_tot
!----------------------------------------------------------------------
! Initialize tau array
!----------------------------------------------------------------------
- tau = 0.0_r8
+ tau = 0.0_r8
hdepth = 0.0_r8
- q0 = 0.0_r8
- tau0 = 0.0_r8
+ maxq0 = 0.0_r8
+ tau0 = 0.0_r8
!------------------------------------------------------------------------
- ! Determine 700 mb layer wind and unit vectors, then project winds.
+ ! Determine source layer wind and unit vectors, then project winds.
!------------------------------------------------------------------------
- ! Just use the 700 mb interface values for the source wind speed and
- ! direction (unit vector).
-
- u700 = u(:,k700)
- v700 = v(:,k700)
+ ! source wind speed and direction
+ u_src = u(:,k_src_wind)
+ v_src = v(:,k_src_wind)
! Get the unit vector components and magnitude at the surface.
- call get_unit_vector(u700, v700, xv, yv, ubi(:,k700))
+ call get_unit_vector(u_src, v_src, xv, yv, ubi(:,k_src_wind))
! Project the local wind at midpoints onto the source wind.
do k = 1, pver
@@ -184,33 +201,62 @@ subroutine gw_beres_src(ncol, ngwv, lat, u, v, netdt, &
! which heating rate is continuously positive.
!-----------------------------------------------------------------------
- ! First find the indices for the top and bottom of the heating range.
+ ! Find indices for the top and bottom of the heating range.
mini = 0
maxi = 0
- do k = pver, 1, -1
- do i = 1, ncol
+
+ if (use_gw_convect_old) then
+ !---------------------------------------------------------------------
+ ! original version used in CAM4/5/6 and EAMv1/2/3
+ do k = pver, 1, -1
+ do i = 1, ncol
if (mini(i) == 0) then
- ! Detect if we are outside the maximum range (where z = 20 km).
- if (zm(i,k) >= 20000._r8) then
- mini(i) = k
- maxi(i) = k
- else
- ! First spot where heating rate is positive.
- if (netdt(i,k) > 0.0_r8) mini(i) = k
- end if
+ ! Detect if we are outside the maximum range (where z = 20 km).
+ if (zm(i,k) >= heating_altitude_max) then
+ mini(i) = k
+ maxi(i) = k
+ else
+ ! First spot where heating rate is positive.
+ if (netdt(i,k) > 0.0_r8) mini(i) = k
+ end if
else if (maxi(i) == 0) then
- ! Detect if we are outside the maximum range (z = 20 km).
- if (zm(i,k) >= 20000._r8) then
- maxi(i) = k
- else
- ! First spot where heating rate is no longer positive.
- if (.not. (netdt(i,k) > 0.0_r8)) maxi(i) = k
- end if
+ ! Detect if we are outside the maximum range (z = 20 km).
+ if (zm(i,k) >= heating_altitude_max) then
+ maxi(i) = k
+ else
+ ! First spot where heating rate is no longer positive.
+ if (.not. (netdt(i,k) > 0.0_r8)) maxi(i) = k
+ end if
end if
- end do
- ! When all done, exit
- if (all(maxi /= 0)) exit
- end do
+ end do
+ ! When all done, exit
+ if (all(maxi /= 0)) exit
+ end do
+ !---------------------------------------------------------------------
+ else
+ !---------------------------------------------------------------------
+ ! cleaner version that addresses bug in original where heating max and
+ ! depth were too low whenever heating <=0 occurred in the middle of
+ ! the heating profile (ex. at the melting level)
+ do i = 1, ncol
+ do k = pver, 1, -1
+ if ( zm(i,k) < heating_altitude_max ) then
+ if ( netdt(i,k) > 0.0_r8 ) then
+ ! Set mini as first spot where heating rate is positive
+ if ( mini(i)==0 ) mini(i) = k
+ ! Set maxi to current level
+ maxi(i) = k
+ end if
+ else
+ ! above the max check if indices were found
+ if ( mini(i)==0 ) mini(i) = k
+ if ( maxi(i)==0 ) maxi(i) = k
+ end if
+ end do
+ end do
+ !---------------------------------------------------------------------
+ end if
+
! Heating depth in km.
hdepth = [ ( (zm(i,maxi(i))-zm(i,mini(i)))/1000._r8, i = 1, ncol ) ]
@@ -223,19 +269,19 @@ subroutine gw_beres_src(ncol, ngwv, lat, u, v, netdt, &
! Maximum heating rate.
do k = minval(maxi), maxval(mini)
where (k >= maxi .and. k <= mini)
- q0 = max(q0, netdt(:ncol,k))
+ maxq0 = max(maxq0, netdt(:ncol,k))
end where
end do
!output max heating rate in K/day
- maxq0 = q0*24._r8*3600._r8
+ maxq0_out = maxq0*24._r8*3600._r8
! Multipy by conversion factor
- q0 = q0 * CF
+ maxq0 = maxq0 * maxq0_conversion_factor
- ! Taking ubm at 700 mb to be the storm speed, find the cell speed where
- ! the storm speed is > 10 m/s.
- CS = int(sign(max(abs(ubm(:,k700))-10._r8, 0._r8), ubm(:,k700)))
+ ! Taking ubm at assumed source level to be the storm speed,
+ ! find the cell speed where the storm speed is > storm_speed_min
+ storm_speed = int(sign(max(abs(ubm(:,k_src_wind))-storm_speed_min, 0._r8), ubm(:,k_src_wind)))
uh = 0._r8
do k = minval(maxi), maxval(mini)
@@ -244,7 +290,7 @@ subroutine gw_beres_src(ncol, ngwv, lat, u, v, netdt, &
end where
end do
- uh = uh - real(CS, r8)
+ uh = uh - real(storm_speed, r8)
! Limit uh to table range.
uh = min(uh, real(maxuh, r8))
@@ -270,8 +316,19 @@ subroutine gw_beres_src(ncol, ngwv, lat, u, v, netdt, &
!---------------------------------------------------------------------
! Look up spectrum only if depth >= 2.5 km, else set tau0 = 0.
!---------------------------------------------------------------------
-
- if ((hdepth(i) >= 2.5_r8) .and. (abs(lat(i)) < (pi/2._r8))) then
+ if ((hdepth(i) >= hdepth_min)) then
+ ndepth_pos = 0
+ ndepth_tot = 0
+ do k = 1,pver
+ if ( k>=maxi(i).and.k<=mini(i) ) then
+ ndepth_tot = ndepth_tot + 1
+ if ( netdt(i,k)>0 ) ndepth_pos = ndepth_pos + 1
+ end if
+ end do
+ ! write (iulog,*) 'WHDEBUG - i: ',i,' Hd: ',hdepth(i),' Hn: ',ndepth_pos,' N: ',ndepth_tot
+ end if
+
+ if ((hdepth(i) >= hdepth_min) .and. (abs(lat(i)) < (pi/2._r8))) then
!------------------------------------------------------------------
! Look up the spectrum using depth and uh.
@@ -280,11 +337,11 @@ subroutine gw_beres_src(ncol, ngwv, lat, u, v, netdt, &
tau0 = mfcc(NINT(hdepth(i)),NINT(uh(i)),:)
! Shift spectrum so that it is relative to the ground.
- shift = -nint(real(CS(i), r8)/dc)
+ shift = -nint(storm_speed(i)/dc)
tau0 = cshift(tau0,shift)
! Adjust magnitude.
- tau0 = tau0*q0(i)*q0(i)/AL
+ tau0 = tau0*maxq0(i)*maxq0(i)/tau_avg_length
! Adjust for critical level filtering.
Umini = max(nint(Umin(i)/dc),-PGWV)
diff --git a/components/eam/src/physics/cam/gw_drag.F90 b/components/eam/src/physics/cam/gw_drag.F90
index 1c6b7920e85..2f3c1652a68 100644
--- a/components/eam/src/physics/cam/gw_drag.F90
+++ b/components/eam/src/physics/cam/gw_drag.F90
@@ -25,18 +25,21 @@ module gw_drag
use shr_kind_mod, only: r8 => shr_kind_r8
use ppgrid, only: pcols, pver
+ use hycoef, only: hyai, hybi, hyam, hybm, etamid
use constituents, only: pcnst
use physics_types, only: physics_state, physics_ptend, physics_ptend_init
use spmd_utils, only: masterproc
use cam_history, only: outfld, hist_fld_active
use cam_logfile, only: iulog
- use cam_abortutils, only: endrun
+ use cam_abortutils,only: endrun
use ref_pres, only: do_molec_diff, ntop_molec, nbot_molec
- use physconst, only: cpair
+ use physconst, only: cpair, rh2o, zvir, pi, rearth, r_universal!zvir is the ep1 in wrf,rearth is the radius of earth(m),r_universal is the gas constant
! These are the actual switches for different gravity wave sources.
- use phys_control, only: use_gw_oro, use_gw_front, use_gw_convect, use_gw_energy_fix
+ ! The orographic control switches are also here
+ use phys_control, only: use_gw_oro, use_gw_front, use_gw_convect, use_gw_energy_fix, use_od_ls, use_od_bl, use_od_ss
+ use od_common, only: od_ls_ncleff, od_bl_ncd, od_ss_sncleff
! Typical module header
implicit none
@@ -47,6 +50,7 @@ module gw_drag
! PUBLIC: interfaces
!
public :: gw_drag_readnl ! Read namelist
+ public :: gw_register ! Register pbuf variables
public :: gw_init ! Initialization
public :: gw_tend ! interface to actual parameterization
@@ -118,6 +122,11 @@ module gw_drag
! namelist
logical :: history_amwg ! output the variables used by the AMWG diag package
+ logical :: use_gw_convect_old ! switch to enable legacy behavior
+ real(r8) :: gw_convect_plev_src_wind ! reference pressure level for source wind for convective GWD [Pa]
+ real(r8) :: gw_convect_hdepth_min ! minimum hdepth for for convective GWD spectrum lookup table [km]
+ real(r8) :: gw_convect_storm_speed_min ! minimum convective storm speed for convective GWD [m/s]
+
!==========================================================================
contains
!==========================================================================
@@ -141,7 +150,9 @@ subroutine gw_drag_readnl(nlfile)
namelist /gw_drag_nl/ pgwv, gw_dc, tau_0_ubc, effgw_beres, effgw_cm, &
effgw_oro, fcrit2, frontgfc, gw_drag_file, taubgnd, gw_convect_hcf, &
- hdepth_scaling_factor
+ hdepth_scaling_factor, gw_convect_hdepth_min, &
+ gw_convect_storm_speed_min, gw_convect_plev_src_wind, &
+ use_gw_convect_old
!----------------------------------------------------------------------
if (masterproc) then
@@ -170,8 +181,12 @@ subroutine gw_drag_readnl(nlfile)
call mpibcast(frontgfc, 1, mpir8, 0, mpicom)
call mpibcast(taubgnd, 1, mpir8, 0, mpicom)
call mpibcast(gw_drag_file, len(gw_drag_file), mpichar, 0, mpicom)
- call mpibcast(gw_convect_hcf, 1, mpir8, 0, mpicom)
- call mpibcast(hdepth_scaling_factor, 1, mpir8, 0, mpicom)
+ call mpibcast(gw_convect_hcf, 1, mpir8, 0, mpicom)
+ call mpibcast(hdepth_scaling_factor, 1, mpir8, 0, mpicom)
+ call mpibcast(gw_convect_hdepth_min, 1, mpir8, 0, mpicom)
+ call mpibcast(gw_convect_storm_speed_min, 1, mpir8, 0, mpicom)
+ call mpibcast(gw_convect_plev_src_wind, 1, mpir8, 0, mpicom)
+ call mpibcast(use_gw_convect_old, 1, mpilog, 0, mpicom)
#endif
dc = gw_dc
@@ -196,7 +211,16 @@ end subroutine gw_drag_readnl
!==========================================================================
-subroutine gw_init()
+subroutine gw_register()
+ use od_common, only: oro_drag_register
+
+ call oro_drag_register()
+
+end subroutine gw_register
+
+!==========================================================================
+
+subroutine gw_init(pbuf2d)
!-----------------------------------------------------------------------
! Time independent initialization for multiple gravity wave
! parameterization.
@@ -205,7 +229,7 @@ subroutine gw_init()
use cam_history, only: addfld, horiz_only, add_default
use interpolate_data, only: lininterp
use phys_control, only: phys_getopts
- use physics_buffer, only: pbuf_get_index
+ use physics_buffer, only: pbuf_get_index, physics_buffer_desc
use ref_pres, only: pref_edge
use physconst, only: gravit, rair
@@ -215,6 +239,9 @@ subroutine gw_init()
use gw_front, only: gw_front_init
use gw_convect, only: gw_convect_init
+ use od_common, only: oro_drag_init
+ !------------------------------Arguments--------------------------------
+ type(physics_buffer_desc), pointer :: pbuf2d(:,:)
!---------------------------Local storage-------------------------------
integer :: l, k
@@ -224,7 +251,6 @@ subroutine gw_init()
! Index for levels at specific pressures.
integer :: kfront
- integer :: k700
! output tendencies and state variables for CAM4 temperature,
! water vapor, cloud ice and cloud liquid budgets.
@@ -288,6 +314,8 @@ subroutine gw_init()
!-----------------------------------------------------------------------
+ call oro_drag_init(pbuf2d)
+
! Set model flags.
do_spectral_waves = (pgwv > 0 .and. (use_gw_front .or. use_gw_convect))
orographic_only = (use_gw_oro .and. .not. do_spectral_waves)
@@ -362,13 +390,21 @@ subroutine gw_init()
errstring)
if (trim(errstring) /= "") call endrun("gw_common_init: "//errstring)
- if (use_gw_oro) then
-
- if (effgw_oro == unset_r8) then
+ if (use_gw_oro.or.&
+ use_od_ls.or.&
+ use_od_bl.or.&
+ use_od_ss) then
+ !
+ if (use_gw_oro.and.effgw_oro == unset_r8) then
call endrun("gw_drag_init: Orographic gravity waves enabled, &
&but effgw_oro was not set.")
end if
-
+ !
+ if (use_gw_oro.and.use_od_ls) then
+ call endrun("gw_drag_init: Both orographic gravity waves schemes are turned on, &
+ &please turn one off by setting use_gw_oro or use_od_ls as .false.")
+ end if
+ !
call gw_oro_init(errstring)
if (trim(errstring) /= "") call endrun("gw_oro_init: "//errstring)
@@ -383,6 +419,36 @@ subroutine gw_init()
'Zonal gravity wave surface stress')
call addfld ('TAUGWY',horiz_only, 'A','N/m2', &
'Meridional gravity wave surface stress')
+ if (use_od_ls.or.&
+ use_od_bl.or.&
+ use_od_ss) then
+ !added for orographic drag
+ call addfld ('DTAUX3_LS',(/'lev'/),'A','m/s2','U tendency - ls orographic drag')
+ call addfld ('DTAUY3_LS',(/'lev'/),'A','m/s2','V tendency - ls orographic drag')
+ call addfld ('DTAUX3_BL',(/'lev'/),'A','m/s2','U tendency - bl orographic drag')
+ call addfld ('DTAUY3_BL',(/'lev'/),'A','m/s2','V tendency - bl orographic drag')
+ call addfld ('DTAUX3_SS',(/'lev'/),'A','m/s2','U tendency - ss orographic drag')
+ call addfld ('DTAUY3_SS',(/'lev'/),'A','m/s2','V tendency - ss orographic drag')
+ call addfld ('DUSFC_LS',horiz_only,'A', 'N/m2', 'ls zonal oro surface stress')
+ call addfld ('DVSFC_LS',horiz_only,'A', 'N/m2', 'ls merio oro surface stress')
+ call addfld ('DUSFC_BL',horiz_only,'A', 'N/m2', 'bl zonal oro surface stress')
+ call addfld ('DVSFC_BL',horiz_only,'A', 'N/m2', 'bl merio oro surface stress')
+ call addfld ('DUSFC_SS',horiz_only,'A', 'N/m2', 'ss zonal oro surface stress')
+ call addfld ('DVSFC_SS',horiz_only,'A', 'N/m2', 'ss merio oro surface stress')
+ call add_default('DTAUX3_LS ', 1,' ')
+ call add_default('DTAUY3_LS ', 1,' ')
+ call add_default('DTAUX3_BL ', 1,' ')
+ call add_default('DTAUY3_BL ', 1,' ')
+ call add_default('DTAUX3_SS ', 1,' ')
+ call add_default('DTAUY3_SS ', 1,' ')
+ call add_default ('DUSFC_LS ', 1,' ')
+ call add_default ('DVSFC_LS ', 1,' ')
+ call add_default ('DUSFC_BL ', 1,' ')
+ call add_default ('DVSFC_BL ', 1,' ')
+ call add_default ('DUSFC_SS ', 1,' ')
+ call add_default ('DVSFC_SS ', 1,' ')
+ !added for orographic drag output
+ endif
if (history_amwg) then
call add_default('TAUGWX ', 1, ' ')
@@ -451,20 +517,10 @@ subroutine gw_init()
ttend_dp_idx = pbuf_get_index('TTEND_DP')
- do k = 0, pver
- ! 700 hPa index
- if (pref_edge(k+1) < 70000._r8) k700 = k+1
- end do
-
- if (masterproc) then
- write (iulog,*) 'K700 =',k700
- end if
-
! Initialization of Beres' parameterization parameters
call gw_init_beres(mfcc)
- call gw_convect_init(k700, mfcc, errstring)
- if (trim(errstring) /= "") &
- call endrun("gw_convect_init: "//errstring)
+ call gw_convect_init(gw_convect_plev_src_wind, mfcc, errstring)
+ if (trim(errstring) /= "") call endrun("gw_convect_init: "//errstring)
! Output for gravity waves from the Beres scheme.
call gw_spec_addflds(prefix=beres_pf, scheme="Beres", &
@@ -583,12 +639,15 @@ subroutine gw_tend(state, sgh, pbuf, dt, ptend, cam_in)
use camsrfexch, only: cam_in_t
! Location-dependent cpair
use physconst, only: cpairv
+ use od_common, only: oro_drag_interface
use gw_common, only: gw_prof, momentum_energy_conservation, &
gw_drag_prof
use gw_oro, only: gw_oro_src
use gw_front, only: gw_cm_src
use gw_convect, only: gw_beres_src
use dycore, only: dycore_is
+ use phys_grid, only: get_rlat_all_p
+ use physconst, only: gravit,rair
!------------------------------Arguments--------------------------------
type(physics_state), intent(in) :: state ! physics state structure
! Standard deviation of orography.
@@ -598,6 +657,26 @@ subroutine gw_tend(state, sgh, pbuf, dt, ptend, cam_in)
! Parameterization net tendencies.
type(physics_ptend), intent(out):: ptend
type(cam_in_t), intent(in) :: cam_in
+ !locally added gw and bl drag
+ real(r8) :: dtaux3_ls(pcols,pver)
+ real(r8) :: dtauy3_ls(pcols,pver)
+ real(r8) :: dtaux3_bl(pcols,pver)
+ real(r8) :: dtauy3_bl(pcols,pver)
+ real(r8) :: dtaux3_ss(pcols,pver)
+ real(r8) :: dtauy3_ss(pcols,pver)
+ real(r8) :: dummx3_fd(pcols,pver)
+ real(r8) :: dummy3_fd(pcols,pver)
+ !
+ real(r8) :: dusfc_ls(pcols)
+ real(r8) :: dvsfc_ls(pcols)
+ real(r8) :: dusfc_bl(pcols)
+ real(r8) :: dvsfc_bl(pcols)
+ real(r8) :: dusfc_ss(pcols)
+ real(r8) :: dvsfc_ss(pcols)
+ real(r8) :: dummx_fd(pcols)
+ real(r8) :: dummy_fd(pcols)
+ !
+ real(r8) :: dx(pcols),dy(pcols)
!---------------------------Local storage-------------------------------
@@ -765,7 +844,9 @@ subroutine gw_tend(state, sgh, pbuf, dt, ptend, cam_in)
! Determine wave sources for Beres04 scheme
call gw_beres_src(ncol, pgwv, state1%lat(:ncol), u, v, ttend_dp, &
zm, src_level, tend_level, tau, ubm, ubi, xv, yv, c, &
- hdepth, maxq0, gw_convect_hcf, hdepth_scaling_factor)
+ hdepth, maxq0, gw_convect_hcf, hdepth_scaling_factor, &
+ gw_convect_hdepth_min, gw_convect_storm_speed_min, &
+ use_gw_convect_old)
do_latitude_taper = .false.
@@ -879,7 +960,6 @@ subroutine gw_tend(state, sgh, pbuf, dt, ptend, cam_in)
!---------------------------------------------------------------------
! Orographic stationary gravity waves
!---------------------------------------------------------------------
-
! Determine the orographic wave source
call gw_oro_src(ncol, &
u, v, t, sgh(:ncol), pmid, pint, dpm, zm, nm, &
@@ -893,11 +973,35 @@ subroutine gw_tend(state, sgh, pbuf, dt, ptend, cam_in)
piln, rhoi, nm, ni, ubm, ubi, xv, yv, &
effgw_oro, c, kvtt, q, dse, tau, utgw, vtgw, &
ttgw, qtgw, taucd, egwdffi, gwut(:,:,0:0), dttdf, dttke)
-
- ! Add the orographic tendencies to the spectrum tendencies
- ! Compute the temperature tendency from energy conservation
- ! (includes spectrum).
-
+ endif
+ !
+ if ( use_od_ls .or. use_od_bl .or. use_od_ss) then
+ utgw=0.0_r8
+ vtgw=0.0_r8
+ ttgw=0.0_r8
+ call oro_drag_interface(state,cam_in,sgh,pbuf,dt,nm,&
+ use_od_ls,use_od_bl,use_od_ss,.false.,&
+ od_ls_ncleff,od_bl_ncd,od_ss_sncleff,&
+ utgw,vtgw,ttgw,&
+ dtaux3_ls=dtaux3_ls,dtauy3_ls=dtauy3_ls,&
+ dtaux3_bl=dtaux3_bl,dtauy3_bl=dtauy3_bl,&
+ dtaux3_ss=dtaux3_ss,dtauy3_ss=dtauy3_ss,&
+ dtaux3_fd=dummx3_fd,dtauy3_fd=dummy3_fd,&
+ dusfc_ls=dusfc_ls,dvsfc_ls=dvsfc_ls,&
+ dusfc_bl=dusfc_bl,dvsfc_bl=dvsfc_bl,&
+ dusfc_ss=dusfc_ss,dvsfc_ss=dvsfc_ss,&
+ dusfc_fd=dummx_fd,dvsfc_fd=dummy_fd)
+ endif
+ !
+ ! Add the orographic tendencies to the spectrum tendencies
+ ! Compute the temperature tendency from energy conservation
+ ! (includes spectrum).
+ ! both old and new gwd scheme will add the tendency to circulation
+ !
+ if (use_gw_oro.or.&
+ use_od_ls .or.&
+ use_od_bl .or.&
+ use_od_ss) then
if(.not. use_gw_energy_fix) then
!original
do k = 1, pver
@@ -906,11 +1010,11 @@ subroutine gw_tend(state, sgh, pbuf, dt, ptend, cam_in)
vtgw(:,k) = vtgw(:,k) * cam_in%landfrac(:ncol)
ptend%v(:ncol,k) = ptend%v(:ncol,k) + vtgw(:,k)
ptend%s(:ncol,k) = ptend%s(:ncol,k) + ttgw(:,k) &
- -(ptend%u(:ncol,k) * (u(:,k) + ptend%u(:ncol,k)*0.5_r8*dt) &
- +ptend%v(:ncol,k) * (v(:,k) + ptend%v(:ncol,k)*0.5_r8*dt))
+ -(ptend%u(:ncol,k) * (u(:,k) + ptend%u(:ncol,k)*0.5_r8*dt) &
+ +ptend%v(:ncol,k) * (v(:,k) + ptend%v(:ncol,k)*0.5_r8*dt))
ttgw(:,k) = ttgw(:,k) &
- -(ptend%u(:ncol,k) * (u(:,k) + ptend%u(:ncol,k)*0.5_r8*dt) &
- +ptend%v(:ncol,k) * (v(:,k) + ptend%v(:ncol,k)*0.5_r8*dt))
+ -(ptend%u(:ncol,k) * (u(:,k) + ptend%u(:ncol,k)*0.5_r8*dt) &
+ +ptend%v(:ncol,k) * (v(:,k) + ptend%v(:ncol,k)*0.5_r8*dt))
ttgw(:,k) = ttgw(:,k) / cpairv(:ncol, k, lchnk)
end do
else
@@ -947,12 +1051,34 @@ subroutine gw_tend(state, sgh, pbuf, dt, ptend, cam_in)
call outfld('UTGWORO', utgw, ncol, lchnk)
call outfld('VTGWORO', vtgw, ncol, lchnk)
call outfld('TTGWORO', ttgw, ncol, lchnk)
+ !
+ if (use_gw_oro) then
+ !old gwd scheme
tau0x = tau(:,0,pver) * xv * effgw_oro
tau0y = tau(:,0,pver) * yv * effgw_oro
call outfld('TAUGWX', tau0x, ncol, lchnk)
call outfld('TAUGWY', tau0y, ncol, lchnk)
+ endif
+ !
call outfld('SGH ', sgh,pcols, lchnk)
-
+ !
+ if (use_od_ls.or.&
+ use_od_bl.or.&
+ use_od_ss) then
+ call outfld ('DTAUX3_LS', dtaux3_ls, pcols, lchnk)
+ call outfld ('DTAUY3_LS', dtauy3_ls, pcols, lchnk)
+ call outfld ('DTAUX3_BL', dtaux3_bl, pcols, lchnk)
+ call outfld ('DTAUY3_BL', dtauy3_bl, pcols, lchnk)
+ call outfld ('DTAUX3_SS', dtaux3_ss, pcols, lchnk)
+ call outfld ('DTAUY3_SS', dtauy3_ss, pcols, lchnk)
+ call outfld ('DUSFC_LS', dusfc_ls, pcols, lchnk)
+ call outfld ('DVSFC_LS', dvsfc_ls, pcols, lchnk)
+ call outfld ('DUSFC_BL', dusfc_bl, pcols, lchnk)
+ call outfld ('DVSFC_BL', dvsfc_bl, pcols, lchnk)
+ call outfld ('DUSFC_SS', dusfc_ss, pcols, lchnk)
+ call outfld ('DVSFC_SS', dvsfc_ss, pcols, lchnk)
+ endif
+ !
end if
! Convert the tendencies for the dry constituents to dry air basis.
diff --git a/components/eam/src/physics/cam/hb_diff.F90 b/components/eam/src/physics/cam/hb_diff.F90
index fdebeb1ee93..3d18ce50280 100644
--- a/components/eam/src/physics/cam/hb_diff.F90
+++ b/components/eam/src/physics/cam/hb_diff.F90
@@ -36,6 +36,8 @@ module hb_diff
public init_hb_diff
public compute_hb_diff
public pblintd
+ !added for separation calculation of monin-obklen length
+ public pblintd_ri
!
! PBL limits
!
@@ -764,5 +766,121 @@ subroutine austausch_pbl(lchnk ,ncol , &
end do
return
end subroutine austausch_pbl
+ !===============================================================================
+ subroutine pblintd_ri(ncol ,gravit , &
+ thv ,z ,u ,v , &
+ ustar ,obklen ,kbfs ,rino_bulk)
+ use pbl_utils, only: virtem, calc_ustar, calc_obklen
+ integer, intent(in) :: ncol ! number of atmospheric columns
+ real(r8), intent(in) :: gravit
+ real(r8), intent(in) :: thv(pcols,pver) ! virtual temperature
+ real(r8), intent(in) :: z(pcols,pver) ! height above surface [m]
+ real(r8), intent(in) :: u(pcols,pver) ! windspeed x-direction [m/s]
+ real(r8), intent(in) :: v(pcols,pver) ! windspeed y-direction [m/s]
+ real(r8), intent(in) :: ustar(pcols) ! surface friction velocity [m/s]
+ real(r8), intent(in) :: obklen(pcols) ! Obukhov length
+ real(r8), intent(in) :: kbfs(pcols) ! sfc kinematic buoyancy flux [m^2/s^3]
+ !
+ ! Output arguments
+ !
+ real(r8) :: wstar(pcols) ! convective sclae velocity [m/s]
+ real(r8) :: pblh(pcols) ! boundary-layer height [m]
+ real(r8) :: bge(pcols) ! buoyancy gradient enhancment
+ real(r8), intent(out) :: rino_bulk(pcols) ! bulk Richardson no. surface level
+ !
+ !---------------------------Local parameters----------------------------
+ !
+ real(r8), parameter :: tiny = 1.e-36_r8 ! lower bound for wind magnitude
+ real(r8), parameter :: fac = 100._r8 ! ustar parameter in height diagnosis
+ !
+ !---------------------------Local workspace-----------------------------
+ !
+ integer :: i ! longitude index
+ integer :: k ! level index
+ real(r8) :: phiminv(pcols) ! inverse phi function for momentum
+ real(r8) :: phihinv(pcols) ! inverse phi function for heat
+ real(r8) :: rino(pcols,pver) ! bulk Richardson no. from level to ref lev
+ real(r8) :: tlv(pcols) ! ref. level pot tmp + tmp excess
+ real(r8) :: tref(pcols) ! ref. level pot tmp
+ real(r8) :: vvk ! velocity magnitude squared
+ logical :: unstbl(pcols) ! pts w/unstbl pbl (positive virtual ht flx)
+ logical :: check(pcols) ! True=>chk if Richardson no.>critcal
+ !
+ do i=1,ncol
+ check(i) = .true.
+ rino(i,pver) = 0.0_r8
+ rino_bulk(i) = 0.0_r8
+ pblh(i) = z(i,pver)
+ tref(i) = thv(i,pver)!if not excess then tref is equal to lowest level thv_lv
+ end do
+ !
+ ! PBL height calculation: Scan upward until the Richardson number between
+ ! the first level and the current level exceeds the "critical" value.
+ !
+ do k=pver-1,pver-npbl+1,-1
+ do i=1,ncol
+ if (check(i)) then
+ vvk = (u(i,k) - u(i,pver))**2 + (v(i,k) - v(i,pver))**2 + fac*ustar(i)**2
+ vvk = max(vvk,tiny)
+ rino(i,k) = gravit*(thv(i,k) - thv(i,pver))*(z(i,k)-z(i,pver))/(thv(i,pver)*vvk)
+ if (rino(i,k) >= ricr) then
+ pblh(i) = z(i,k+1) + (ricr - rino(i,k+1))/(rino(i,k) - rino(i,k+1)) * &
+ (z(i,k) - z(i,k+1))
+ check(i) = .false.
+ end if
+ end if
+ end do
+ end do
+ !
+ ! Estimate an effective surface temperature to account for surface fluctuations
+ !
+ do i=1,ncol
+ if (check(i)) pblh(i) = z(i,pverp-npbl)
+ unstbl(i) = (kbfs(i) > 0._r8)
+ check(i) = (kbfs(i) > 0._r8)
+ if (check(i)) then
+ phiminv(i) = (1._r8 - binm*pblh(i)/obklen(i))**onet
+ rino(i,pver) = 0.0_r8
+ tlv(i) = thv(i,pver) + kbfs(i)*fak/( ustar(i)*phiminv(i) )
+ tref(i) = tlv(i)
+ end if
+ end do
+ !
+ ! Improve pblh estimate for unstable conditions using the convective temperature excess:
+ !
+ do i = 1,ncol
+ bge(i) = 1.e-8_r8
+ end do
+ do k=pver-1,pver-npbl+1,-1
+ do i=1,ncol
+ if (check(i)) then
+ vvk = (u(i,k) - u(i,pver))**2 + (v(i,k) - v(i,pver))**2 + fac*ustar(i)**2
+ vvk = max(vvk,tiny)
+ rino(i,k) = gravit*(thv(i,k) - tlv(i))*(z(i,k)-z(i,pver))/(thv(i,pver)*vvk)
+ if (rino(i,k) >= ricr) then
+ pblh(i) = z(i,k+1) + (ricr - rino(i,k+1))/(rino(i,k) - rino(i,k+1))* &
+ (z(i,k) - z(i,k+1))
+ bge(i) = 2._r8*gravit/(thv(i,k)+thv(i,k+1))*(thv(i,k)-thv(i,k+1))/(z(i,k)-z(i,k+1))*pblh(i)
+ if (bge(i).lt.0._r8) then
+ bge(i) = 1.e-8_r8
+ endif
+ check(i) = .false.
+ end if
+ end if
+ end do
+ end do
+ !
+ !calculate bulk richardson number in the surface layer
+ !following Holstag and Boville (1993) equation (2.8)
+ !
+ do i=1,ncol
+ vvk = u(i,pver)**2 + v(i,pver)**2 + fac*ustar(i)**2
+ vvk = max(vvk,tiny)
+ rino_bulk(i)=gravit*(thv(i,pver) - tref(i))*z(i,pver)/(thv(i,pver)*vvk)
+ enddo
+ !
+ return
+ end subroutine pblintd_ri
+ !===============================================================================
end module hb_diff
diff --git a/components/eam/src/physics/cam/od_common.F90 b/components/eam/src/physics/cam/od_common.F90
new file mode 100644
index 00000000000..52658d2dbec
--- /dev/null
+++ b/components/eam/src/physics/cam/od_common.F90
@@ -0,0 +1,1693 @@
+module od_common
+!==========================================================================
+! This module contains code common to different orographic drag
+! parameterizations.
+! It includes 4 parts:
+! orographic gravity wave drag (Xie et al.,2020),
+! flow-blocking drag (Xie et al.,2020),
+! small-scale orographic gravity wave drag (Tsiringakis et al. 2017),
+! turbulent orographic form drag (Beljaars et al.,2004).
+!==========================================================================
+use shr_kind_mod, only: i8 => shr_kind_i8, r8 => shr_kind_r8
+use shr_sys_mod, only: shr_sys_flush
+use ppgrid, only: pcols, pver, begchunk, endchunk
+use cam_logfile, only: iulog
+use cam_abortutils,only: endrun
+use spmd_utils, only: masterproc
+use pio, only: file_desc_t
+use phys_control, only: use_od_ls, use_od_bl, use_od_ss
+use physics_buffer,only: dtype_r8, physics_buffer_desc, pbuf_get_chunk
+use physics_buffer,only: pbuf_get_index, pbuf_get_field, pbuf_add_field, pbuf_set_field
+
+implicit none
+private
+save
+
+! Public interface.
+public :: oro_drag_readnl
+public :: oro_drag_register
+public :: oro_drag_init
+public :: oro_drag_interface
+public :: od_gsd,pblh_get_level_idx,grid_size
+
+type(file_desc_t), pointer :: topo_file_ncid
+
+! dimensions for topo shape data
+integer, parameter :: ndir_asymmetry = 2+1 ! add 1 to avoid bug reading file - not sure why this happens
+integer, parameter :: ndir_efflength = 180 ! 1-degree resolution with opposite directions mirrored
+
+! pbuf indices for data read in from topo data file
+integer :: oro_drag_convexity_idx = -1 ! Convexity
+integer :: oro_drag_asymmetry_idx = -1 ! Asymmetry
+integer :: oro_drag_efflength_idx = -1 ! Effective length
+integer :: oro_drag_ribulk_idx = -1 ! bulk richardson number (calculated in CLUBB)
+
+!tunable parameter to the od schemes
+real(r8),public, protected :: od_ls_ncleff = 3._r8 !tunable parameter for oGWD
+real(r8),public, protected :: od_bl_ncd = 3._r8 !tunable parameter for FBD
+real(r8),public, protected :: od_ss_sncleff= 1._r8 !tunable parameter for sGWD
+
+contains
+
+!==========================================================================
+
+subroutine oro_drag_readnl(nlfile)
+
+ use namelist_utils, only: find_group_name
+ use units, only: getunit, freeunit
+ use mpishorthand
+
+ ! File containing namelist input.
+ character(len=*), intent(in) :: nlfile
+
+ ! Local variables
+ integer :: unitn, ierr
+ character(len=*), parameter :: subname = 'oro_drag_readnl'
+
+ ! More specific name for dc to prevent a name clash or confusion in the
+ ! namelist.
+
+ namelist /oro_drag_nl/ od_ls_ncleff, od_bl_ncd, od_ss_sncleff
+ !---------------------------------------------------------------------
+ !read oro_drag_nl only when use the od schemes
+ if (use_od_ls.or.use_od_bl.or.use_od_ss) then
+ if (masterproc) then
+ unitn = getunit()
+ open( unitn, file=trim(nlfile), status='old' )
+ call find_group_name(unitn, 'oro_drag_nl', status=ierr)
+ if (ierr == 0) then
+ read(unitn, oro_drag_nl, iostat=ierr)
+ if (ierr /= 0) then
+ call endrun(subname // ':: ERROR reading namelist')
+ end if
+ end if
+ close(unitn)
+ call freeunit(unitn)
+ end if
+
+ if (masterproc) write(iulog,*) "oro_drag_readnl od_ls_ncleff, od_bl_ncd, od_ss_sncleff ",od_ls_ncleff,od_bl_ncd,od_ss_sncleff
+
+#ifdef SPMD
+ ! Broadcast namelist variables
+ call mpibcast(od_ls_ncleff, 1, mpir8, 0, mpicom)
+ call mpibcast(od_bl_ncd, 1, mpir8, 0, mpicom)
+ call mpibcast(od_ss_sncleff, 1, mpir8, 0, mpicom)
+#endif
+ !
+ endif
+
+end subroutine oro_drag_readnl
+
+!==========================================================================
+
+subroutine oro_drag_open_topo_file()
+ use filenames, only: bnd_topo
+ use ioFileMod, only: getfil
+ use cam_pio_utils,only: cam_pio_openfile
+ use pio, only: pio_nowrite
+ include 'netcdf.inc'
+ !-----------------------------------------------------------------------
+ character(len=256) :: bnd_topo_loc ! filepath of topo file on local disk
+ allocate(topo_file_ncid)
+ call getfil(bnd_topo, bnd_topo_loc)
+ call cam_pio_openfile(topo_file_ncid, bnd_topo_loc, PIO_NOWRITE)
+end subroutine oro_drag_open_topo_file
+
+!==========================================================================
+
+subroutine oro_drag_close_topo_file
+ use pio, only: pio_closefile
+ call pio_closefile(topo_file_ncid)
+ deallocate(topo_file_ncid)
+ nullify(topo_file_ncid)
+end subroutine oro_drag_close_topo_file
+
+!==========================================================================
+
+subroutine oro_drag_register()
+ !-----------------------------------------------------------------------
+ ! Register pbuf variables for orographic drag parameterizations
+ !-----------------------------------------------------------------------
+ ! create pbuf variables to hold oro drag data
+ if (use_od_ls.or.use_od_bl) then
+ call pbuf_add_field('oro_drag_convexity','physpkg',dtype_r8,(/pcols/), oro_drag_convexity_idx)
+ call pbuf_add_field('oro_drag_asymmetry','physpkg',dtype_r8,(/pcols,ndir_asymmetry/),oro_drag_asymmetry_idx)
+ call pbuf_add_field('oro_drag_efflength','physpkg',dtype_r8,(/pcols,ndir_efflength/),oro_drag_efflength_idx)
+ end if
+ if (use_od_ss) then
+ call pbuf_add_field('oro_drag_ribulk', 'physpkg',dtype_r8,(/pcols/), oro_drag_ribulk_idx)
+ end if
+
+end subroutine oro_drag_register
+
+!==========================================================================
+
+subroutine oro_drag_init(pbuf2d)
+ !-----------------------------------------------------------------------
+ ! Initialization for orographic drag parameterizations
+ !-----------------------------------------------------------------------
+ use pio, only: file_desc_t
+ use ncdio_atm, only: infld
+ use cam_grid_support, only: cam_grid_check, cam_grid_get_decomp, cam_grid_id,cam_grid_get_dim_names
+ use infnan, only: nan, assignment(=)
+ !-----------------------------------------------------------------------
+ type(physics_buffer_desc), pointer :: pbuf2d(:,:)
+ !-----------------------------------------------------------------------
+ logical :: found
+ character(len=8) :: dim1name, dim2name
+ character*11 :: subname='oro_drag_init'
+ integer :: grid_id
+ integer :: c
+
+ real(r8), allocatable:: oro_drag_convexity_tmp(:,:)
+ real(r8), allocatable:: oro_drag_asymmetry_tmp(:,:,:)
+ real(r8), allocatable:: oro_drag_efflength_tmp(:,:,:)
+
+ type(physics_buffer_desc), pointer :: pbuf_chunk(:) ! temporary pbuf pointer for single chunk
+ !-----------------------------------------------------------------------
+ if (.not.(use_od_ls.or.use_od_bl)) return
+
+ grid_id = cam_grid_id('physgrid')
+ if (.not. cam_grid_check(grid_id)) then
+ call endrun(trim(subname)//': Internal error, no "physgrid" grid')
+ end if
+
+ ! Alocate variables for reading oro drag data
+ allocate( oro_drag_convexity_tmp(pcols,begchunk:endchunk) )
+ allocate( oro_drag_asymmetry_tmp(pcols,ndir_asymmetry,begchunk:endchunk) )
+ allocate( oro_drag_efflength_tmp(pcols,ndir_efflength,begchunk:endchunk) )
+ oro_drag_convexity_tmp(:,:) = nan
+ oro_drag_asymmetry_tmp(:,:,:) = nan
+ oro_drag_efflength_tmp(:,:,:) = nan
+
+ ! Read special orographic shape fields from topo file
+ call cam_grid_get_dim_names(grid_id, dim1name, dim2name)
+ call oro_drag_open_topo_file()
+
+ found=.false.
+ call infld( 'OC', topo_file_ncid, dim1name, dim2name, 1, pcols, &
+ begchunk, endchunk, oro_drag_convexity_tmp(:,:), found, gridname='physgrid')
+ if(.not. found) call endrun('ERROR - oro_drag_init: topo file read error - OC')
+
+ found=.false.
+ call infld( 'OA', topo_file_ncid, dim1name, 'ndir_asymmetry', dim2name, 1, pcols, 1, ndir_asymmetry, &
+ begchunk, endchunk, oro_drag_asymmetry_tmp(:,:,:), found, gridname='physgrid')
+ if(.not. found) call endrun('ERROR - oro_drag_init: topo file read error - OA')
+
+ found=.false.
+ call infld( 'OL', topo_file_ncid, dim1name, 'ndir_efflength', dim2name, 1, pcols, 1, ndir_efflength, &
+ begchunk, endchunk, oro_drag_efflength_tmp(:,:,:), found, gridname='physgrid')
+ if(.not. found) call endrun('ERROR - oro_drag_init: topo file read error - OL')
+
+ call oro_drag_close_topo_file()
+
+ ! copy the oro drag data in pbuf
+ do c=begchunk,endchunk
+ pbuf_chunk => pbuf_get_chunk(pbuf2d, c)
+ call pbuf_set_field(pbuf_chunk, oro_drag_convexity_idx, oro_drag_convexity_tmp(:,c) )
+ call pbuf_set_field(pbuf_chunk, oro_drag_asymmetry_idx, oro_drag_asymmetry_tmp(:,:,c) )
+ call pbuf_set_field(pbuf_chunk, oro_drag_efflength_idx, oro_drag_efflength_tmp(:,:,c) )
+ end do
+
+ deallocate(oro_drag_convexity_tmp)
+ deallocate(oro_drag_asymmetry_tmp)
+ deallocate(oro_drag_efflength_tmp)
+
+end subroutine oro_drag_init
+!==========================================================================
+
+subroutine oro_drag_interface(state, cam_in, sgh, pbuf, dtime, nm, &
+ gwd_ls, gwd_bl, gwd_ss, gwd_fd, &
+ od_ls_ncleff, od_bl_ncd,od_ss_sncleff, &
+ utgw, vtgw, ttgw, &
+ dtaux3_ls,dtauy3_ls,dtaux3_bl,dtauy3_bl, &
+ dtaux3_ss,dtauy3_ss,dtaux3_fd,dtauy3_fd, &
+ dusfc_ls, dvsfc_ls ,dusfc_bl, dvsfc_bl, &
+ dusfc_ss, dvsfc_ss ,dusfc_fd, dvsfc_fd)
+ use physics_types, only: physics_state
+ use camsrfexch, only: cam_in_t
+ use ppgrid, only: pcols,pver,pverp
+ use physconst, only: gravit,rair,cpair,rh2o,zvir,pi
+ use hycoef, only: etamid
+ !-----------------------------------------------------------------------
+ type(physics_state), intent(in) :: state ! physics state structure
+ type(cam_in_t), intent(in) :: cam_in
+ real(r8), intent(in) :: sgh(pcols)
+ type(physics_buffer_desc), pointer :: pbuf(:) ! Physics buffer
+ real(r8), intent(in) :: dtime
+ real(r8), intent(in) :: nm(state%ncol,pver) ! midpoint Brunt-Vaisalla frequency
+ !options for the 4 schemes
+ logical , intent(in) :: gwd_ls
+ logical , intent(in) :: gwd_bl
+ logical , intent(in) :: gwd_ss
+ logical , intent(in) :: gwd_fd
+ !tunable parameter from namelist
+ real(r8), intent(in) :: od_ls_ncleff
+ real(r8), intent(in) :: od_bl_ncd
+ real(r8), intent(in) :: od_ss_sncleff
+ !vertical profile of the momentum tendencies
+ real(r8), intent(out), optional :: utgw(state%ncol,pver)
+ real(r8), intent(out), optional :: vtgw(state%ncol,pver)
+ real(r8), intent(out), optional :: ttgw(state%ncol,pver)
+ !output drag terms in 3D and surface
+ real(r8), intent(out), optional :: dtaux3_ls(pcols,pver)
+ real(r8), intent(out), optional :: dtauy3_ls(pcols,pver)
+ real(r8), intent(out), optional :: dtaux3_bl(pcols,pver)
+ real(r8), intent(out), optional :: dtauy3_bl(pcols,pver)
+ real(r8), intent(out), optional :: dtaux3_ss(pcols,pver)
+ real(r8), intent(out), optional :: dtauy3_ss(pcols,pver)
+ real(r8), intent(out), optional :: dtaux3_fd(pcols,pver)
+ real(r8), intent(out), optional :: dtauy3_fd(pcols,pver)
+ real(r8), intent(out), optional :: dusfc_ls(pcols)
+ real(r8), intent(out), optional :: dvsfc_ls(pcols)
+ real(r8), intent(out), optional :: dusfc_bl(pcols)
+ real(r8), intent(out), optional :: dvsfc_bl(pcols)
+ real(r8), intent(out), optional :: dusfc_ss(pcols)
+ real(r8), intent(out), optional :: dvsfc_ss(pcols)
+ real(r8), intent(out), optional :: dusfc_fd(pcols)
+ real(r8), intent(out), optional :: dvsfc_fd(pcols)
+
+ real(r8) :: ztop(pcols,pver) ! top interface height asl (m)
+ real(r8) :: zbot(pcols,pver) ! bottom interface height asl (m)
+ real(r8) :: zmid(pcols,pver) ! middle interface height asl (m)
+ real(r8) :: dz(pcols,pver) ! model layer height
+
+ integer :: pblh_idx = 0
+ integer :: kpbl2d_in(pcols)
+ integer :: kpbl2d_reverse_in(pcols)
+ real(r8), pointer :: pblh(:)
+ real(r8) :: dx(pcols),dy(pcols)
+
+ real(r8), pointer :: oro_drag_convexity(:)
+ real(r8), pointer :: oro_drag_asymmetry(:,:)
+ real(r8), pointer :: oro_drag_efflength(:,:)
+ real(r8), pointer :: oro_drag_ribulk(:) ! pbuf pointer for bulk richardson number
+
+ integer :: ncol
+ integer :: i
+ integer :: k
+ !-----------------------------------------------------------------------
+
+ ncol=state%ncol
+ !convert heights above surface to heights above sea level
+ !obtain z,dz,dx,dy,and k for pblh
+ kpbl2d_in=0_r8
+ kpbl2d_reverse_in=0_r8
+ ztop=0._r8
+ zbot=0._r8
+ zmid=0._r8
+ dusfc_ls=0._r8
+ dvsfc_ls=0._r8
+ dusfc_bl=0._r8
+ dvsfc_bl=0._r8
+ dusfc_ss=0._r8
+ dvsfc_ss=0._r8
+ dusfc_fd=0._r8
+ dvsfc_fd=0._r8
+ dtaux3_ls=0._r8
+ dtaux3_bl=0._r8
+ dtauy3_ls=0._r8
+ dtauy3_bl=0._r8
+ dtaux3_ss=0._r8
+ dtaux3_fd=0._r8
+ dtauy3_ss=0._r8
+ dtauy3_fd=0._r8
+
+ do k=1,pver
+ do i=1,ncol
+ ! assign values for level top/bottom
+ ztop(i,k)=state%zi(i,k)
+ zbot(i,k)=state%zi(i,k+1)
+ enddo
+ end do
+
+ !transform adding the pressure
+ !transfer from surface to sea level
+ do k=1,pver
+ do i=1,ncol
+ ztop(i,k)=ztop(i,k)+state%phis(i)/gravit
+ zbot(i,k)=zbot(i,k)+state%phis(i)/gravit
+ zmid(i,k)=state%zm(i,k)+state%phis(i)/gravit
+ !dz is from bottom to top already for gw_drag
+ dz(i,k)=ztop(i,k)-zbot(i,k)
+ end do
+ end do
+ !get the layer index of pblh in layer for input in drag scheme
+ pblh_idx = pbuf_get_index('pblh')
+ call pbuf_get_field(pbuf, pblh_idx, pblh)
+ do i=1,pcols
+ kpbl2d_in(i)=pblh_get_level_idx(zbot(i,:)-(state%phis(i)/gravit),pblh(i))
+ kpbl2d_reverse_in(i)=pverp-kpbl2d_in(i)!pverp-k
+ end do
+
+ call pbuf_get_field(pbuf, oro_drag_convexity_idx, oro_drag_convexity )
+ call pbuf_get_field(pbuf, oro_drag_asymmetry_idx, oro_drag_asymmetry )
+ call pbuf_get_field(pbuf, oro_drag_efflength_idx, oro_drag_efflength )
+ call pbuf_get_field(pbuf, oro_drag_ribulk_idx, oro_drag_ribulk)
+
+ !get grid size for dx,dy
+ call grid_size(state,dx,dy)
+
+ !interface for orographic drag
+ call od_gsd(u3d=state%u(:ncol,pver:1:-1),v3d=state%v(:ncol,pver:1:-1),t3d=state%t(:ncol,pver:1:-1),&
+ qv3d=state%q(:ncol,pver:1:-1,1),p3d=state%pmid(:ncol,pver:1:-1),p3di=state%pint(:ncol,pver+1:1:-1),&
+ pi3d=state%exner(:ncol,pver:1:-1),z=zbot(:ncol,pver:1:-1),&
+ od_ls_ncleff=od_ls_ncleff,od_bl_ncd=od_bl_ncd,od_ss_sncleff=od_ss_sncleff,&
+ rublten=utgw(:ncol,pver:1:-1),rvblten=vtgw(:ncol,pver:1:-1),rthblten=ttgw(:ncol,pver:1:-1),&
+ dtaux3d_ls=dtaux3_ls(:ncol,pver:1:-1),dtauy3d_ls=dtauy3_ls(:ncol,pver:1:-1),&
+ dtaux3d_bl=dtaux3_bl(:ncol,pver:1:-1),dtauy3d_bl=dtauy3_bl(:ncol,pver:1:-1),&
+ dtaux3d_ss=dtaux3_ss(:ncol,pver:1:-1),dtauy3d_ss=dtauy3_ss(:ncol,pver:1:-1),&
+ dtaux3d_fd=dtaux3_fd(:ncol,pver:1:-1),dtauy3d_fd=dtauy3_fd(:ncol,pver:1:-1),&
+ dusfcg_ls=dusfc_ls(:ncol),dvsfcg_ls=dvsfc_ls(:ncol),&
+ dusfcg_bl=dusfc_bl(:ncol),dvsfcg_bl=dvsfc_bl(:ncol),&
+ dusfcg_ss=dusfc_ss(:ncol),dvsfcg_ss=dvsfc_ss(:ncol),&
+ dusfcg_fd=dusfc_fd(:ncol),dvsfcg_fd=dvsfc_fd(:ncol),&
+ xland=cam_in%landfrac,br=oro_drag_ribulk(:ncol),&
+ var2d=sgh(:ncol),&
+ oc12d=oro_drag_convexity(:ncol),&
+ oa2d=oro_drag_asymmetry(:ncol,:),&
+ ol2d=oro_drag_efflength(:ncol,:),&
+ znu=etamid(pver:1:-1),dz=dz(:ncol,pver:1:-1),pblh=pblh(:ncol),&
+ cp=cpair,g=gravit,rd=rair,rv=rh2o,ep1=zvir,pi=pi,bnvbg=nm(:ncol,pver:1:-1),&
+ dt=dtime,dx=dx,dy=dy,&
+ kpbl2d=kpbl2d_reverse_in,gwd_opt=0,&
+ ids=1,ide=ncol,jds=0,jde=0,kds=1,kde=pver, &
+ ims=1,ime=ncol,jms=0,jme=0,kms=1,kme=pver, &
+ its=1,ite=ncol,jts=0,jte=0,kts=1,kte=pver, &
+ gwd_ls=gwd_ls,gwd_bl=gwd_bl,gwd_ss=gwd_ss,gwd_fd=gwd_fd )
+
+end subroutine oro_drag_interface
+
+!==========================================================================
+
+function pblh_get_level_idx(height_array,pblheight)
+ implicit none
+ real(r8),intent(in),dimension(pver) :: height_array
+ real(r8),intent(in) :: pblheight
+ integer :: pblh_get_level_idx
+ !local
+ integer :: k
+ logical :: found
+
+ pblh_get_level_idx = -1
+ found=.false.
+ !get the pblh level index and return
+ do k = 1, pver
+ if((pblheight >= height_array(k+1).and.pblheight 300._r8) then
+ kpbl2 = k
+ IF (k == kpbl(i)) then
+ hpbl2 = hpbl(i)+10._r8
+ ELSE
+ hpbl2 = za(i,k)+10._r8
+ ENDIF
+ exit
+ ENDIF
+ enddo
+
+ if(xland1(i).gt.0._r8 .and. 2._r8*var(i).le.hpbl(i))then
+ if(br1(i).gt.0._r8 .and. thvx(i,kpbl2)-thvx(i,kts) > 0._r8)then
+ cleff = sqrt(dxy(i)**2_r8 + dxyp(i)**2_r8)
+ cleff = (2.0_r8/sncleff) * max(dxmax_ss,cleff)
+ coefm(i) = (1._r8 + ol(i)) ** (oa1(i)+1._r8)
+ xlinv(i) = coefm(i) / cleff
+ govrth(i)=g/(0.5_r8*(thvx(i,kpbl2)+thvx(i,kts)))
+ bnrf=sqrt(govrth(i)*(thvx(i,kpbl2)-thvx(i,kts))/hpbl2)
+
+ if(abs(bnrf/u1(i,kpbl2)).gt.xlinv(i))then
+ tauwavex0=0.5_r8*bnrf*xlinv(i)*(2._r8*MIN(var(i),varmax))**2_r8*ro(i,kvar)*u1(i,kvar)
+ tauwavex0=tauwavex0*ss_taper ! "Scale-awareness"
+ else
+ tauwavex0=0._r8
+ endif
+
+ if(abs(bnrf/v1(i,kpbl2)).gt.xlinv(i))then
+ tauwavey0=0.5_r8*bnrf*xlinv(i)*(2._r8*MIN(var(i),varmax))**2._r8*ro(i,kvar)*v1(i,kvar)
+ tauwavey0=tauwavey0*ss_taper ! "Scale-awareness"
+ else
+ tauwavey0=0._r8
+ endif
+
+ do k=kts,kpbl(i) !MIN(kpbl2+1,kte-1)
+ utendwave(i,k)=-1._r8*tauwavex0*2._r8*max((1._r8-za(i,k)/hpbl2),0._r8)/hpbl2
+ vtendwave(i,k)=-1._r8*tauwavey0*2._r8*max((1._r8-za(i,k)/hpbl2),0._r8)/hpbl2
+ enddo
+ endif
+ endif
+ enddo ! end i loop
+
+ do k = kts,kte
+ do i = its,ite
+ dudt(i,k) = dudt(i,k) + utendwave(i,k)
+ dvdt(i,k) = dvdt(i,k) + vtendwave(i,k)
+ dtaux2d_ss(i,k) = utendwave(i,k)
+ dtauy2d_ss(i,k) = vtendwave(i,k)
+ dusfc_ss(i) = dusfc_ss(i) + utendwave(i,k) * del(i,k)
+ dvsfc_ss(i) = dvsfc_ss(i) + vtendwave(i,k) * del(i,k)
+ enddo
+ enddo
+
+ ENDIF ! end if gsd_gwd_ss == .true.
+ !================================================================
+ !add Beljaars et al. (2004, QJRMS, equ. 16) form drag:
+ !================================================================
+ IF (gsd_gwd_fd.and.(ss_taper.GT.1.E-02) ) THEN
+
+ utendform=0._r8
+ vtendform=0._r8
+ zq=0._r8
+
+ if (.not.gsd_gwd_ss.and.(ss_taper.GT.1.E-02) ) THEN
+ ! Defining layer height. This is already done above is small-scale GWD is used
+ do k = kts,kte
+ do i = its,ite
+ zq(i,k+1) = dz2(i,k)+zq(i,k)
+ enddo
+ enddo
+
+ do k = kts,kte
+ do i = its,ite
+ za(i,k) = 0.5_r8*(zq(i,k)+zq(i,k+1))
+ enddo
+ enddo
+ endif
+
+ do i=its,ite
+ if (xland1(i) .gt. 0..and.2._r8*var(i).gt.0) then
+ ! refer to Beljaars (2004) eq.16.
+ a1=0.00026615161_r8*var(i)**2_r8
+ a2=a1*0.005363_r8
+ do k=kts,kte
+ wsp=SQRT(u1(i,k)**2_r8 + v1(i,k)**2_r8)
+ ! refer to Beljaars (2004) eq.16.
+ ! alpha*beta*Cmd*Ccorr*2.109 = 12.*1.*0.005*0.6*2.109 = 0.0759
+ utendform(i,k)=-0.0759_r8*wsp*u1(i,k)* &
+ EXP(-(za(i,k)/1500._r8)**1.5_r8)*a2*za(i,k)**(-1.2_r8)*ss_taper
+ vtendform(i,k)=-0.0759_r8*wsp*v1(i,k)* &
+ EXP(-(za(i,k)/1500._r8)**1.5_r8)*a2*za(i,k)**(-1.2_r8)*ss_taper
+ enddo
+ endif
+ enddo
+
+ do k = kts,kte
+ do i = its,ite
+ dudt(i,k) = dudt(i,k) + utendform(i,k)
+ dvdt(i,k) = dvdt(i,k) + vtendform(i,k)
+ !limit drag tendency
+ !some tendency is likely to even overturn the wind,
+ !making wind reverse in 1 timestep and reverse again in next,
+ !this limitation may help to make model stable,
+ !and no more wind reversal due to drag,
+ !which is suppose to decelerate, not accelerate
+ utendform(i,k) = sign(min(abs(utendform(i,k)),abs(u1(i,k))/deltim),utendform(i,k))
+ vtendform(i,k) = sign(min(abs(vtendform(i,k)),abs(v1(i,k))/deltim),vtendform(i,k))
+ dtaux2d_fd(i,k) = utendform(i,k)
+ dtauy2d_fd(i,k) = vtendform(i,k)
+ dusfc_fd(i) = dusfc_fd(i) + utendform(i,k) * del(i,k)
+ dvsfc_fd(i) = dvsfc_fd(i) + vtendform(i,k) * del(i,k)
+ enddo
+ enddo
+ ENDIF ! end if gsd_gwd_fd == .true.
+ !=======================================================
+ ! More for the large-scale gwd component
+ !=======================================================
+ IF (gsd_gwd_ls.and.(ls_taper.GT.1.E-02) ) THEN
+ !
+ ! now compute vertical structure of the stress.
+ !
+ do k = kts,kpblmax
+ do i = its,ite
+ if (k .le. kbl(i)) taup(i,k) = taub(i)
+ enddo
+ enddo
+
+ if (scorer_on) then
+ !
+ !determination of the interface height for scorer adjustment
+ !
+ do i=its,ite
+ iint=.false.
+ do k=kpblmin,kte-1
+ if (k.gt.kbl(i).and.usqj(i,k)-usqj(i,k-1).lt.0.and.(.not.iint)) then
+ iint=.true.
+ zl_hint(i)=zl(i,k+1)
+ endif
+ enddo
+ enddo
+ endif
+
+ do k = kpblmin, kte-1 ! vertical level k loop!
+ kp1 = k + 1
+ do i = its,ite
+ !
+ ! unstablelayer if ri < ric
+ ! unstable layer if upper air vel comp along surf vel <=0 (crit lay)
+ ! at (u-c)=0. crit layer exists and bit vector should be set (.le.)
+ !
+ if (k .ge. kbl(i)) then
+ !we modify the criteria for unstable layer
+ !that the lv is critical under 0.25
+ !while we keep wave breaking ric for
+ !other larger lv
+ icrilv(i) = icrilv(i) .or. ( usqj(i,k) .lt. ric_rig)&
+ .or. (velco(i,k) .le. 0.0_r8)
+ brvf(i) = max(bnv2(i,k),bnv2min) ! brunt-vaisala frequency squared
+ brvf(i) = sqrt(brvf(i)) ! brunt-vaisala frequency
+ endif
+ enddo
+
+ do i = its,ite
+ if (k .ge. kbl(i) .and. (.not. ldrag(i))) then
+ if (.not.icrilv(i) .and. taup(i,k) .gt. 0.0_r8 ) then
+ temv = 1.0_r8 / velco(i,k)
+ tem1 = coefm(i)/(dxy(i)/ncleff)*(ro(i,kp1)+ro(i,k))*brvf(i)*velco(i,k)*0.5_r8
+ hd = sqrt(taup(i,k) / tem1)
+ fro = brvf(i) * hd * temv
+ !
+ ! rim is the minimum-richardson number by shutts (1985)
+ !
+ tem2 = sqrt(usqj(i,k))
+ tem = 1._r8 + tem2 * fro
+ rim = usqj(i,k) * (1._r8-fro) / (tem * tem)
+
+ !
+ ! check stability to employ the 'saturation hypothesis'
+ ! of lindzen (1981) except at tropospheric downstream regions
+ !
+ if (rim .le. ric) then ! saturation hypothesis!
+ if ((oa1(i) .le. 0._r8).or.(kp1 .ge. kpblmin )) then
+ temc = 2.0_r8 + 1.0_r8 / tem2
+ hd = velco(i,k) * (2.0_r8*sqrt(temc)-temc) / brvf(i)
+ taup(i,kp1) = tem1 * hd * hd
+ !
+ ! taup is restricted to monotoncally decrease
+ ! to avoid unexpected high taup in calculation
+ !
+ taup(i,kp1)=min(tem1*hd*hd,taup(i,k))
+ !
+ ! add vertical decrease at low level below hint (Kim and Doyle 2005)
+ ! where Ri first decreases
+ !
+ if (scorer_on.and.k.gt.klowtop(i).and.zl(i,k).le.zl_hint(i).and.k.lt.kte-1) then
+ l1=(9.81_r8*bnv2(i,kp1)/velco(i,kp1)**2)
+ l2=(9.81_r8*bnv2(i,k)/velco(i,k)**2)
+ taup(i,kp1)=min(taup(i,k),taup(i,k)*(l1/l2),tem1*hd*hd)
+ endif
+ endif
+ else ! no wavebreaking!
+ taup(i,kp1) = taup(i,k)
+ endif
+ endif
+ endif
+ enddo
+ enddo
+
+ if(lcap.lt.kte) then
+ do klcap = lcapp1,kte
+ do i = its,ite
+ taup(i,klcap) = prsi(i,klcap) / prsi(i,lcap) * taup(i,lcap)
+ enddo
+ enddo
+ endif
+
+ ENDIF !END LARGE-SCALE TAU CALCULATION
+ !===============================================================
+ !COMPUTE BLOCKING COMPONENT
+ !===============================================================
+ IF (gsd_gwd_bl.and.(ls_taper .GT. 1.E-02)) THEN
+
+ do i = its,ite
+ if(.not.ldrag(i)) then
+ !
+ !------- determine the height of flow-blocking layer
+ !
+ kblk = 0
+ pe = 0.0_r8
+
+ do k = kte, kpblmin, -1
+ if(kblk.eq.0 .and. k.le.komax(i)) then
+ !flow block appears within the reference level
+ !compare potential energy and kinetic energy
+ !divided by g*ro is to turn del(pa) into height
+ pe = pe + bnv2(i,k)*(zl(i,komax(i))-zl(i,k))*del(i,k)/g/ro(i,k)
+ ke = 0.5_r8*((rcs*u1(i,k))**2._r8+(rcs*v1(i,k))**2._r8)
+ !
+ !---------- apply flow-blocking drag when pe >= ke
+ !
+ if(pe.ge.ke) then
+ kblk = k
+ kblk = min(kblk,kbl(i))
+ zblk = zl(i,kblk)-zl(i,kts)
+ endif
+ endif
+ enddo
+
+ if(kblk.ne.0) then
+ !
+ !--------- compute flow-blocking stress
+ !
+
+ !dxmax_ls is different than the usual one
+ !because the taper is very different
+ !dxy is a length scale mostly in the direction of the flow to the ridge
+ !so it is good and not needed for an uneven grid area
+ !ref Lott and Miller (1997) original scheme
+ cd = max(2.0_r8-1.0_r8/od(i),0.0_r8)
+ !
+ !tuning of the drag magnitude
+ cd=ncd*cd
+ !
+ taufb(i,kts) = 0.5_r8 * roll(i) * coefm(i) / max(dxmax_ls,dxy(i))**2 * cd * dxyp(i) &
+ * olp(i) * zblk * ulow(i)**2
+ !changed grid box area into dy*dy
+ tautem = taufb(i,kts)/float(kblk-kts)
+ do k = kts+1, kblk
+ taufb(i,k) = taufb(i,k-1) - tautem
+ enddo
+
+ !
+ !----------sum orographic GW stress and flow-blocking stress
+ !
+ !taup(i,:) = taup(i,:) + taufb(i,:) ! Keep taup and taufb separate for now
+ endif
+ endif
+ enddo
+
+ ENDIF ! end blocking drag
+!===========================================================
+ IF (gsd_gwd_ls.OR.gsd_gwd_bl.and.(ls_taper .GT. 1.E-02)) THEN
+ !
+ ! calculate - (g)*d(tau)/d(pressure) and deceleration terms dtaux, dtauy
+ !
+ do k = kts,kte
+ do i = its,ite
+ taud_ls(i,k) = 1._r8 * (taup(i,k+1) - taup(i,k)) * csg / del(i,k)
+ taud_bl(i,k) = 1._r8 * (taufb(i,k+1) - taufb(i,k)) * csg / del(i,k)
+ enddo
+ enddo
+ !
+ ! limit de-acceleration (momentum deposition ) at top to 1/2 value
+ ! the idea is some stuff must go out the 'top'
+ !
+ do klcap = lcap,kte
+ do i = its,ite
+ taud_ls(i,klcap) = taud_ls(i,klcap) * factop
+ taud_bl(i,klcap) = taud_bl(i,klcap) * factop
+ enddo
+ enddo
+ !
+ ! if the gravity wave drag would force a critical line
+ ! in the lower ksmm1 layers during the next deltim timestep,
+ ! then only apply drag until that critical line is reached.
+ !
+ do k = kts,kpblmax-1
+ do i = its,ite
+ if (k .le. kbl(i)) then
+ if((taud_ls(i,k)+taud_bl(i,k)).ne.0._r8) &
+ dtfac(i) = min(dtfac(i),abs(velco(i,k) &
+ /(deltim*rcs*(taud_ls(i,k)+taud_bl(i,k)))))
+ endif
+ enddo
+ enddo
+
+ do k = kts,kte
+ do i = its,ite
+ taud_ls(i,k) = taud_ls(i,k) * dtfac(i) * ls_taper
+ !apply limiter for ogwd
+ !1.dudt < |c-u|/dt, so u-c cannot change sign(u^n+1 = u^n + du/dt * dt)
+ !2.dudtchk if Richardson no.>critcal
-#ifdef SCREAM_CONFIG_IS_CMAKE
- if (use_cxx) then
- call pblintd_f(&
- shcol,nlev,nlevi,npbl,& ! Input
- z,zi,thl,ql,& ! Input
- q,u,v,& ! Input
- ustar,obklen,kbfs,cldn,& ! Input
- pblh) ! Output
- return
- endif
-#endif
-
!
! Compute Obukhov length virtual temperature flux and various arrays for use later:
!
@@ -4343,9 +3927,6 @@ subroutine pblintd_init_pot(&
shcol,nlev,& ! Input
thl,ql,q,& ! Input
thv) ! Output
-#ifdef SCREAM_CONFIG_IS_CMAKE
- use shoc_iso_f, only: shoc_pblintd_init_pot_f
-#endif
!------------------------------Arguments--------------------------------
!
! Input arguments
@@ -4364,13 +3945,6 @@ subroutine pblintd_init_pot(&
integer :: k ! level index
real(rtype) :: th
-#ifdef SCREAM_CONFIG_IS_CMAKE
- if (use_cxx) then
- call shoc_pblintd_init_pot_f(shcol,nlev,thl,ql,q,& ! Input
- thv) ! Output
- return
- endif
-#endif
! Compute virtual potential temperature
do k=1,nlev
do i=1,shcol
@@ -4418,10 +3992,6 @@ subroutine pblintd_height(&
thv,thv_ref,& ! Input
pblh,rino,check) ! Output
-#ifdef SCREAM_CONFIG_IS_CMAKE
- use shoc_iso_f, only: pblintd_height_f
-#endif
-
!------------------------------Arguments--------------------------------
!
! Input arguments
@@ -4450,14 +4020,6 @@ subroutine pblintd_height(&
integer :: k ! level index
real(rtype) :: vvk ! velocity magnitude squared
-#ifdef SCREAM_CONFIG_IS_CMAKE
- if (use_cxx) then
- call pblintd_height_f(shcol,nlev,npbl,z,u,v,ustar,thv,thv_ref,& ! Input
- pblh,rino,check) ! Output
- return
- endif
-#endif
-
!
! PBL height calculation: Scan upward until the Richardson number between
! the first level and the current level exceeds the "critical" value.
@@ -4485,10 +4047,6 @@ subroutine pblintd_surf_temp(&
tlv,& ! Output
pblh,check,rino) ! InOutput
-#ifdef SCREAM_CONFIG_IS_CMAKE
- use shoc_iso_f, only: pblintd_surf_temp_f
-#endif
-
!------------------------------Arguments--------------------------------
! Input arguments
!
@@ -4519,15 +4077,6 @@ subroutine pblintd_surf_temp(&
real(rtype), parameter :: sffrac= 0.1_rtype ! Surface layer fraction of boundary layer
real(rtype), parameter :: binm = betam*sffrac ! betam * sffrac
-#ifdef SCREAM_CONFIG_IS_CMAKE
- if (use_cxx) then
- call pblintd_surf_temp_f(shcol,nlev,nlevi,& ! Input
- z,ustar,obklen,kbfs,thv,& ! Input
- tlv,pblh,check,rino) ! InOutput
- return
- endif
-#endif
-
!
! Estimate an effective surface temperature to account for surface
! fluctuations
@@ -4550,10 +4099,6 @@ subroutine pblintd_check_pblh(&
z,ustar,check,& ! Input
pblh) ! Output
-#ifdef SCREAM_CONFIG_IS_CMAKE
- use shoc_iso_f, only: pblintd_check_pblh_f
-#endif
-
!------------------------------Arguments--------------------------------
! Input arguments
!
@@ -4573,13 +4118,6 @@ subroutine pblintd_check_pblh(&
!
integer :: i ! longitude index
-#ifdef SCREAM_CONFIG_IS_CMAKE
- if (use_cxx) then
- call pblintd_check_pblh_f(shcol,nlev,nlevi,npbl,z,ustar,check,pblh)
- return
- endif
-#endif
-
!
! PBL height must be greater than some minimum mechanical mixing depth
! Several investigators have proposed minimum mechanical mixing depth
@@ -4606,10 +4144,6 @@ subroutine pblintd_cldcheck( &
zi,cldn, & ! Input
pblh) ! InOutput
-#ifdef SCREAM_CONFIG_IS_CMAKE
- use shoc_iso_f, only: shoc_pblintd_cldcheck_f
-#endif
-
!------------------------------Arguments--------------------------------
! Input arguments
!
@@ -4629,13 +4163,6 @@ subroutine pblintd_cldcheck( &
integer :: i ! longitude index
logical(btype) :: cldcheck(shcol) ! True=>if cloud in lowest layer
-#ifdef SCREAM_CONFIG_IS_CMAKE
- if (use_cxx) then
- call shoc_pblintd_cldcheck_f(shcol, nlev, nlevi, zi, cldn, pblh)
- return
- endif
-#endif
-
!
! Final requirement on PBL heightis that it must be greater than the depth
! of the lowest model level if there is any cloud diagnosed in
@@ -4660,10 +4187,6 @@ end subroutine pblintd_cldcheck
subroutine linear_interp(x1,x2,y1,y2,km1,km2,ncol,minthresh)
-#ifdef SCREAM_CONFIG_IS_CMAKE
- use shoc_iso_f, only: linear_interp_f
-#endif
-
implicit none
integer, intent(in) :: km1, km2
@@ -4675,13 +4198,6 @@ subroutine linear_interp(x1,x2,y1,y2,km1,km2,ncol,minthresh)
integer :: k1, k2, i
-#ifdef SCREAM_CONFIG_IS_CMAKE
- if (use_cxx) then
- call linear_interp_f(x1,x2,y1,y2,km1,km2,ncol,minthresh)
- return
- endif
-#endif
-
#if 1
!i = check_grid(x1,x2,km1,km2,ncol)
if (km1 .eq. km2+1) then
@@ -4749,10 +4265,6 @@ subroutine compute_brunt_shoc_length(nlev,nlevi,shcol,dz_zt,thv,thv_zi,brunt)
!
! Computes the brunt_visala frequency
-#ifdef SCREAM_CONFIG_IS_CMAKE
- use shoc_iso_f, only: compute_brunt_shoc_length_f
-#endif
-
implicit none
integer, intent(in) :: nlev, nlevi, shcol
! Grid difference centereted on thermo grid [m]
@@ -4765,13 +4277,6 @@ subroutine compute_brunt_shoc_length(nlev,nlevi,shcol,dz_zt,thv,thv_zi,brunt)
real(rtype), intent(out) :: brunt(shcol, nlev)
integer k, i
-#ifdef SCREAM_CONFIG_IS_CMAKE
- if (use_cxx) then
- call compute_brunt_shoc_length_f(nlev,nlevi,shcol,dz_zt,thv,thv_zi,brunt)
- return
- endif
-#endif
-
do k=1,nlev
do i=1,shcol
brunt(i,k) = (ggr/thv(i,k)) * (thv_zi(i,k) - thv_zi(i,k+1))/dz_zt(i,k)
@@ -4785,10 +4290,6 @@ subroutine compute_l_inf_shoc_length(nlev,shcol,zt_grid,dz_zt,tke,l_inf)
!=========================================================
!
-#ifdef SCREAM_CONFIG_IS_CMAKE
- use shoc_iso_f, only: compute_l_inf_shoc_length_f
-#endif
-
implicit none
integer, intent(in) :: nlev, shcol
real(rtype), intent(in) :: zt_grid(shcol,nlev), dz_zt(shcol,nlev), tke(shcol,nlev)
@@ -4796,13 +4297,6 @@ subroutine compute_l_inf_shoc_length(nlev,shcol,zt_grid,dz_zt,tke,l_inf)
real(rtype) :: tkes, numer(shcol), denom(shcol)
integer k, i
-#ifdef SCREAM_CONFIG_IS_CMAKE
- if (use_cxx) then
- call compute_l_inf_shoc_length_f(nlev,shcol,zt_grid,dz_zt,tke,l_inf)
- return
- endif
-#endif
-
numer(:) = 0._rtype
denom(:) = 0._rtype
@@ -4822,10 +4316,6 @@ end subroutine compute_l_inf_shoc_length
subroutine compute_shoc_mix_shoc_length(nlev,shcol,tke,brunt,zt_grid,l_inf,shoc_mix)
-#ifdef SCREAM_CONFIG_IS_CMAKE
- use shoc_iso_f, only: compute_shoc_mix_shoc_length_f
-#endif
-
implicit none
integer, intent(in) :: nlev, shcol
@@ -4848,14 +4338,6 @@ subroutine compute_shoc_mix_shoc_length(nlev,shcol,tke,brunt,zt_grid,l_inf,shoc_
! Turnover timescale [s]
real(rtype), parameter :: tscale = 400._rtype
-#ifdef SCREAM_CONFIG_IS_CMAKE
- if (use_cxx) then
- call compute_shoc_mix_shoc_length_f(nlev,shcol,tke,brunt,zt_grid,l_inf,& !Input
- shoc_mix) ! Ouptut
- return
- endif
-#endif
-
brunt2(:,:) = 0.0
do k=1,nlev
@@ -4876,10 +4358,6 @@ subroutine check_length_scale_shoc_length(nlev,shcol,host_dx,host_dy,shoc_mix)
! Do checks on the length scale. Make sure it is not
! larger than the grid mesh of the host model.
-#ifdef SCREAM_CONFIG_IS_CMAKE
- use shoc_iso_f, only: check_length_scale_shoc_length_f
-#endif
-
implicit none
integer, intent(in) :: nlev, shcol
real(rtype), intent(in) :: host_dx(shcol), host_dy(shcol)
@@ -4887,13 +4365,6 @@ subroutine check_length_scale_shoc_length(nlev,shcol,host_dx,host_dy,shoc_mix)
real(rtype), intent(inout) :: shoc_mix(shcol, nlev)
integer k, i
-#ifdef SCREAM_CONFIG_IS_CMAKE
- if (use_cxx) then
- call check_length_scale_shoc_length_f(nlev,shcol,host_dx,host_dy,shoc_mix)
- return
- endif
-#endif
-
do k=1,nlev
do i=1,shcol
shoc_mix(i,k)=min(maxlen,shoc_mix(i,k))
diff --git a/components/eam/src/physics/clubb/advance_windm_edsclrm_module.F90 b/components/eam/src/physics/clubb/advance_windm_edsclrm_module.F90
index 72d2e4d214b..970de0b4d7f 100644
--- a/components/eam/src/physics/clubb/advance_windm_edsclrm_module.F90
+++ b/components/eam/src/physics/clubb/advance_windm_edsclrm_module.F90
@@ -3,6 +3,9 @@
!===============================================================================
module advance_windm_edsclrm_module
+ !options for turbulent orographic form drag in wind forcing
+ use phys_control, only: use_od_fd
+
implicit none
private ! Set Default Scope
@@ -1571,8 +1574,12 @@ subroutine compute_uv_tndcy( solve_type, fcor, perp_wind_m, perp_wind_g, xm_forc
endif
else ! implemented in a host model.
-
- xm_tndcy = 0.0_core_rknd
+ !use forcing when using turbulent orographic form drag (TOFD) forcing
+ if (use_od_fd) then
+ xm_tndcy(1:gr%nz) = xm_forcing(1:gr%nz)
+ else
+ xm_tndcy = 0.0_core_rknd
+ endif
endif
diff --git a/components/eam/src/physics/crm/dummy_modules/clubb_intr.F90 b/components/eam/src/physics/crm/dummy_modules/clubb_intr.F90
new file mode 100644
index 00000000000..d6729e33f6b
--- /dev/null
+++ b/components/eam/src/physics/crm/dummy_modules/clubb_intr.F90
@@ -0,0 +1,31 @@
+module clubb_intr
+!-------------------------------------------------------------------------------
+! Dummy module to override src/physics/cam/clubb_intr.F90
+!-------------------------------------------------------------------------------
+use shr_kind_mod, only: r8=>shr_kind_r8
+public :: clubb_implements_cnst
+public :: clubb_init_cnst
+public :: clubb_readnl
+contains
+!===============================================================================
+function clubb_implements_cnst(name)
+ ! Return true if specified constituent is implemented
+ character(len=*), intent(in) :: name ! constituent name
+ logical :: clubb_implements_cnst ! return value
+ clubb_implements_cnst = .false.
+end function clubb_implements_cnst
+!===============================================================================
+subroutine clubb_init_cnst(name, q, gcid)
+ ! Initialize the state if clubb_do_adv
+ character(len=*), intent(in) :: name ! constituent name
+ real(r8), intent(out) :: q(:,:) ! mass mixing ratio (gcol, plev)
+ integer, intent(in) :: gcid(:) ! global column id
+ return
+end subroutine clubb_init_cnst
+!===============================================================================
+subroutine clubb_readnl(nlfile)
+ character(len=*), intent(in) :: nlfile ! filepath for file containing namelist input
+ return
+end subroutine clubb_readnl
+!===============================================================================
+end module clubb_intr
diff --git a/components/eam/src/physics/crm/pam/external b/components/eam/src/physics/crm/pam/external
index 1c37054d1ff..6b162a8892e 160000
--- a/components/eam/src/physics/crm/pam/external
+++ b/components/eam/src/physics/crm/pam/external
@@ -1 +1 @@
-Subproject commit 1c37054d1ff9b160290cc286dcbd3cdc6cd7e7f6
+Subproject commit 6b162a8892e788d0a672d519374a3c82a0de2a5b
diff --git a/components/eam/src/physics/crm/pam/pam_driver.cpp b/components/eam/src/physics/crm/pam/pam_driver.cpp
index c7038343f08..e3070cce240 100644
--- a/components/eam/src/physics/crm/pam/pam_driver.cpp
+++ b/components/eam/src/physics/crm/pam/pam_driver.cpp
@@ -20,7 +20,6 @@
// Needed for p3_init
#include "p3_functions.hpp"
-#include "p3_f90.hpp"
#include "pam_debug.h"
bool constexpr enable_check_state = false;
@@ -203,7 +202,8 @@ extern "C" void pam_driver() {
#if defined(P3_CXX)
if (is_first_step || is_restart) {
auto am_i_root = coupler.get_option("am_i_root");
- scream::p3::p3_init(/*write_tables=*/false, am_i_root);
+ using P3F = scream::p3::Functions;
+ P3F::p3_init(/*write_tables=*/false, am_i_root);
pam::p3_init_lookup_tables(); // Load P3 lookup table data - avoid re-loading every CRM call
}
#endif
diff --git a/components/eam/src/physics/crm/physpkg.F90 b/components/eam/src/physics/crm/physpkg.F90
index 33fab14066d..6ad53894f4e 100644
--- a/components/eam/src/physics/crm/physpkg.F90
+++ b/components/eam/src/physics/crm/physpkg.F90
@@ -638,7 +638,7 @@ subroutine phys_init( phys_state, phys_tend, pbuf2d, cam_out )
if (co2_transport()) call co2_init()
call co2_diags_init(phys_state)
- call gw_init()
+ call gw_init(pbuf2d)
call rayleigh_friction_init()
diff --git a/components/eam/src/physics/p3/eam/micro_p3.F90 b/components/eam/src/physics/p3/eam/micro_p3.F90
index e668cbaa494..e82c4fa0a96 100644
--- a/components/eam/src/physics/p3/eam/micro_p3.F90
+++ b/components/eam/src/physics/p3/eam/micro_p3.F90
@@ -4350,7 +4350,6 @@ subroutine ice_sedimentation(kts,kte,ktop,kbot,kdir, &
dt_left, prt_accum, inv_dz, inv_rho, rho, num_arrays, vs, fluxes, qnr, dt_sub)
do k = k_qxbot,k_qxtop,kdir
- precip_ice_flux(k+1) = precip_ice_flux(k+1) + flux_qit(k)*dt_sub ! shanyp
sflx(k+1) = sflx(k+1) + flux_qit(k)*dt_sub
enddo
@@ -4363,7 +4362,6 @@ subroutine ice_sedimentation(kts,kte,ktop,kbot,kdir, &
bm_incld(:) = bm(:)/cld_frac_i(:)
enddo substep_sedi_i
- precip_ice_flux(:)=precip_ice_flux(:)*inv_dt
sflx(:)=sflx(:)*inv_dt
precip_ice_surf = precip_ice_surf + prt_accum*inv_rho_h2o*inv_dt
diff --git a/components/eamxx/CMakeLists.txt b/components/eamxx/CMakeLists.txt
index 07c3cda7672..cb49f41ddf2 100644
--- a/components/eamxx/CMakeLists.txt
+++ b/components/eamxx/CMakeLists.txt
@@ -97,6 +97,7 @@ option (Kokkos_ENABLE_SERIAL "" ON)
set (EAMXX_ENABLE_GPU FALSE CACHE BOOL "")
set (CUDA_BUILD FALSE CACHE BOOL "") #needed for yakl if kokkos vars are not visible there?
set (HIP_BUILD FALSE CACHE BOOL "") #needed for yakl if kokkos vars are not visible there?
+set (SYCL_BUILD FALSE CACHE BOOL "") #needed for yakl if kokkos vars are not visible there?
# Determine if this is a Cuda build.
if (Kokkos_ENABLE_CUDA)
@@ -106,7 +107,7 @@ if (Kokkos_ENABLE_CUDA)
set (CUDA_BUILD TRUE CACHE BOOL "" FORCE) #needed for yakl if kokkos vars are not visible there?
endif ()
-# Determine if this is a Cuda build.
+# Determine if this is a HIP build.
if (Kokkos_ENABLE_HIP)
# Add CUDA as a language for CUDA builds
enable_language(HIP)
@@ -114,6 +115,13 @@ if (Kokkos_ENABLE_HIP)
set (HIP_BUILD TRUE CACHE BOOL "" FORCE) #needed for yakl if kokkos vars are not visible there?
endif ()
+# Determine if this is a sycl build.
+if (Kokkos_ENABLE_SYCL)
+ #enable_language(SYCL)
+ set (EAMXX_ENABLE_GPU TRUE CACHE BOOL "" FORCE)
+ set (SYCL_BUILD TRUE CACHE BOOL "" FORCE) #needed for yakl if kokkos vars are not visible there?
+endif ()
+
if( NOT "${CMAKE_CXX_COMPILER_ID}" MATCHES "[Cc]lang" )
set (CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -cpp")
endif()
@@ -178,7 +186,7 @@ elseif(MACH)
endif()
set(DEFAULT_SMALL_KERNELS FALSE)
-if (Kokkos_ENABLE_HIP)
+if (Kokkos_ENABLE_HIP OR Kokkos_ENABLE_SYCL)
set(DEFAULT_SMALL_KERNELS TRUE)
endif()
@@ -197,7 +205,7 @@ set(NetCDF_Fortran_PATH ${DEFAULT_NetCDF_Fortran_PATH} CACHE FILEPATH "Path to n
set(NetCDF_C_PATH ${DEFAULT_NetCDF_C_PATH} CACHE FILEPATH "Path to netcdf C installation")
set(SCREAM_MACHINE ${DEFAULT_SCREAM_MACHINE} CACHE STRING "The CIME/SCREAM name for the current machine")
option(SCREAM_MPI_ON_DEVICE "Whether to use device pointers for MPI calls" ON)
-option(SCREAM_ENABLE_MAM "Whether to enable MAM aerosol support" ON)
+option(SCREAM_ENABLE_MAM "Whether to enable MAM aerosol support" OFF)
set(SCREAM_SMALL_KERNELS ${DEFAULT_SMALL_KERNELS} CACHE STRING "Use small, non-monolothic kokkos kernels for ALL components that support them")
set(SCREAM_P3_SMALL_KERNELS ${SCREAM_SMALL_KERNELS} CACHE STRING "Use small, non-monolothic kokkos kernels for P3 only")
set(SCREAM_SHOC_SMALL_KERNELS ${SCREAM_SMALL_KERNELS} CACHE STRING "Use small, non-monolothic kokkos kernels for SHOC only")
@@ -212,8 +220,8 @@ endif()
# #cmakedefine RRTMGP_EXPENSIVE_CHECKS
option (SCREAM_RRTMGP_DEBUG "Turn on extra debug checks in RRTMGP" ${SCREAM_DEBUG})
-option(SCREAM_RRTMGP_ENABLE_YAKL "Use YAKL under rrtmgp" TRUE)
-option(SCREAM_RRTMGP_ENABLE_KOKKOS "Use Kokkos under rrtmgp" FALSE)
+option(SCREAM_RRTMGP_ENABLE_YAKL "Use YAKL under rrtmgp" FALSE)
+option(SCREAM_RRTMGP_ENABLE_KOKKOS "Use Kokkos under rrtmgp" TRUE)
if (SCREAM_RRTMGP_ENABLE_YAKL)
add_definitions("-DRRTMGP_ENABLE_YAKL")
endif()
@@ -453,10 +461,6 @@ if (NOT SCREAM_LIB_ONLY)
# for LONG use 100. It is *completely* up to the test to decide what short, medium, and long mean.
if (EKAT_ENABLE_COVERAGE OR EKAT_ENABLE_CUDA_MEMCHECK OR EKAT_ENABLE_VALGRIND OR EKAT_ENABLE_COMPUTE_SANITIZER)
set (SCREAM_TEST_SIZE_DEFAULT SHORT)
- # also set thread_ing=$max_thread - 1, so we test at most 2 threading configurations
- if (SCREAM_TEST_MAX_THREADS GREATER 1)
- math (EXPR SCREAM_TEST_THREAD_INC ${SCREAM_TEST_MAX_THREADS}-1)
- endif()
else()
set (SCREAM_TEST_SIZE_DEFAULT MEDIUM)
endif()
@@ -588,9 +592,6 @@ if (NOT DEFINED ENV{SCREAM_FAKE_ONLY})
${CMAKE_CURRENT_BINARY_DIR}/src/scream_config.h
F90_FILE ${CMAKE_CURRENT_BINARY_DIR}/src/scream_config.f)
- # Build any tools in the scripts/ dir.
- add_subdirectory(scripts)
-
# Generate scream_config.h and scream_config.f
include (EkatUtils)
EkatConfigFile(${CMAKE_CURRENT_SOURCE_DIR}/src/scream_config.h.in
diff --git a/components/eamxx/cime_config/namelist_defaults_scream.xml b/components/eamxx/cime_config/namelist_defaults_scream.xml
index 6d4c36b81bd..f7778cea5fd 100644
--- a/components/eamxx/cime_config/namelist_defaults_scream.xml
+++ b/components/eamxx/cime_config/namelist_defaults_scream.xml
@@ -199,10 +199,10 @@ be lost if SCREAM_HACK_XML is not enabled.
740.0e3
${DIN_LOC_ROOT}/atm/scream/tables/p3_lookup_table_1.dat-v4.1.1,
- ${DIN_LOC_ROOT}/atm/scream/tables/mu_r_table_vals.dat8,
- ${DIN_LOC_ROOT}/atm/scream/tables/revap_table_vals.dat8,
- ${DIN_LOC_ROOT}/atm/scream/tables/vn_table_vals.dat8,
- ${DIN_LOC_ROOT}/atm/scream/tables/vm_table_vals.dat8
+ ${DIN_LOC_ROOT}/atm/scream/tables/mu_r_table_vals_v2.dat8,
+ ${DIN_LOC_ROOT}/atm/scream/tables/revap_table_vals_v2.dat8,
+ ${DIN_LOC_ROOT}/atm/scream/tables/vn_table_vals_v2.dat8,
+ ${DIN_LOC_ROOT}/atm/scream/tables/vm_table_vals_v2.dat8
1350.0
2.47
@@ -223,6 +223,10 @@ be lost if SCREAM_HACK_XML is not enabled.
0.304
1.0
true
+
+ false
+ false
+ false
@@ -230,7 +234,7 @@ be lost if SCREAM_HACK_XML is not enabled.
false
false
0.001
- 0.04
+ 0.08
2.65
0.02
1.0
@@ -427,6 +431,9 @@ be lost if SCREAM_HACK_XML is not enabled.
false
+
+
+
1,2
@@ -556,6 +563,7 @@ be lost if SCREAM_HACK_XML is not enabled.
mac_aero_mic,rrtmgp
+ iop_forcing,mac_aero_mic,rrtmgp
@@ -717,6 +725,7 @@ be lost if SCREAM_HACK_XML is not enabled.
0
+ false
@@ -855,6 +864,7 @@ be lost if SCREAM_HACK_XML is not enabled.
6
6
12
+ 0
2
none
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/L128/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/L128/shell_commands
similarity index 100%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/L128/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/L128/shell_commands
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/L72/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/L72/shell_commands
similarity index 100%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/L72/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/L72/shell_commands
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/bfbhash/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/bfbhash/shell_commands
similarity index 100%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/bfbhash/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/bfbhash/shell_commands
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/dpxx/arm97/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/dpxx/arm97/shell_commands
similarity index 100%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/dpxx/arm97/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/dpxx/arm97/shell_commands
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/dpxx/comble/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/dpxx/comble/shell_commands
similarity index 100%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/dpxx/comble/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/dpxx/comble/shell_commands
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/dpxx/dycomsrf01/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/dpxx/dycomsrf01/shell_commands
similarity index 100%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/dpxx/dycomsrf01/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/dpxx/dycomsrf01/shell_commands
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/internal_diagnostics_level/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/internal_diagnostics_level/shell_commands
similarity index 100%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/internal_diagnostics_level/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/internal_diagnostics_level/shell_commands
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/aci/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/aci/shell_commands
similarity index 95%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/aci/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/aci/shell_commands
index 492bda019fc..4928859e4e8 100644
--- a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/aci/shell_commands
+++ b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/aci/shell_commands
@@ -3,7 +3,7 @@
# MAM4xx adds additionaltracers to the simulation
# Increase number of tracers for MAM4xx simulations
#------------------------------------------------------
-$CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/update_eamxx_num_tracers.sh
+$CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/update_eamxx_num_tracers.sh
# Add spa as RRTMG needs spa
$CIMEROOT/../components/eamxx/scripts/atmchange physics::atm_procs_list="mac_aero_mic,spa,rrtmgp" -b
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/aero_microphysics/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/aero_microphysics/shell_commands
similarity index 92%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/aero_microphysics/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/aero_microphysics/shell_commands
index ac1709f7dca..81b3d44b221 100644
--- a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/aero_microphysics/shell_commands
+++ b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/aero_microphysics/shell_commands
@@ -5,7 +5,7 @@
# Increase number of tracers for MAM4xx simulations
#------------------------------------------------------
-$CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/update_eamxx_num_tracers.sh -b
+$CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/update_eamxx_num_tracers.sh -b
#------------------------------------------------------
# Add microphysics process
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/all_mam4xx_procs/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/all_mam4xx_procs/shell_commands
similarity index 96%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/all_mam4xx_procs/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/all_mam4xx_procs/shell_commands
index 8ef80aef633..366f9afdd28 100644
--- a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/all_mam4xx_procs/shell_commands
+++ b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/all_mam4xx_procs/shell_commands
@@ -2,7 +2,7 @@
# MAM4xx adds additional tracers to the simulation
# Increase the number of tracers for MAM4xx simulations
#------------------------------------------------------
-$CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/update_eamxx_num_tracers.sh
+$CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/update_eamxx_num_tracers.sh
#modify initial condition file to get aerosol species ICs
$CIMEROOT/../components/eamxx/scripts/atmchange initial_conditions::Filename='$DIN_LOC_ROOT/atm/scream/init/screami_mam4xx_ne4np4L72_c20240208.nc' -b
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/drydep/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/drydep/shell_commands
similarity index 92%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/drydep/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/drydep/shell_commands
index ea2d56ab53f..02b4594dbc9 100644
--- a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/drydep/shell_commands
+++ b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/drydep/shell_commands
@@ -5,7 +5,7 @@
# Increase number of tracers for MAM4xx simulations
#------------------------------------------------------
-$CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/update_eamxx_num_tracers.sh -b
+$CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/update_eamxx_num_tracers.sh -b
#------------------------------------------------------
# Add drydep process
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/optics/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/optics/shell_commands
similarity index 90%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/optics/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/optics/shell_commands
index 9bbcfaea898..b62620e7fe0 100644
--- a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/optics/shell_commands
+++ b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/optics/shell_commands
@@ -2,7 +2,7 @@
# MAM4xx adds additionaltracers to the simulation
# Increase number of tracers for MAM4xx simulations
#------------------------------------------------------
-$CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/update_eamxx_num_tracers.sh
+$CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/update_eamxx_num_tracers.sh
$CIMEROOT/../components/eamxx/scripts/atmchange physics::atm_procs_list="mac_aero_mic,mam4_optics,rrtmgp" -b
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/remap_emiss_ne4_ne30/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/remap_emiss_ne4_ne30/shell_commands
similarity index 98%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/remap_emiss_ne4_ne30/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/remap_emiss_ne4_ne30/shell_commands
index b2d0286b870..9d0bbd39d97 100644
--- a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/remap_emiss_ne4_ne30/shell_commands
+++ b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/remap_emiss_ne4_ne30/shell_commands
@@ -5,7 +5,7 @@
# Increase number of tracers for MAM4xx simulations
#------------------------------------------------------
-$CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/update_eamxx_num_tracers.sh -b
+$CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/update_eamxx_num_tracers.sh -b
#------------------------------------------------------
# Add aerosol microphysics process, force ne4pg2
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/srf_online_emiss_constituent_fluxes/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/srf_online_emiss_constituent_fluxes/shell_commands
similarity index 92%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/srf_online_emiss_constituent_fluxes/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/srf_online_emiss_constituent_fluxes/shell_commands
index 500d0bf660a..249d7c2371e 100644
--- a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/srf_online_emiss_constituent_fluxes/shell_commands
+++ b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/srf_online_emiss_constituent_fluxes/shell_commands
@@ -5,7 +5,7 @@
# Increase number of tracers for MAM4xx simulations
#------------------------------------------------------
-$CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/update_eamxx_num_tracers.sh -b
+$CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/update_eamxx_num_tracers.sh -b
#------------------------------------------------------
# Add the processes
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/update_eamxx_num_tracers.sh b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/update_eamxx_num_tracers.sh
similarity index 100%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/update_eamxx_num_tracers.sh
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/update_eamxx_num_tracers.sh
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/wetscav/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/wetscav/shell_commands
similarity index 92%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/wetscav/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/wetscav/shell_commands
index 2cdf303a582..d8436d38450 100644
--- a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/wetscav/shell_commands
+++ b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/wetscav/shell_commands
@@ -4,7 +4,7 @@
# Increase number of tracers for MAM4xx simulations
#------------------------------------------------------
-$CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/scream/mam4xx/update_eamxx_num_tracers.sh -b
+$CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/mam4xx/update_eamxx_num_tracers.sh -b
#------------------------------------------------------
# Add wetscav process
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/README b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/README
similarity index 100%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/README
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/README
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/diags/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/diags/shell_commands
similarity index 100%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/diags/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/diags/shell_commands
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/hremap_to_ne4/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/hremap_to_ne4/shell_commands
similarity index 100%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/hremap_to_ne4/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/hremap_to_ne4/shell_commands
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/phys/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/phys/shell_commands
similarity index 100%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/phys/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/phys/shell_commands
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/phys_dyn/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/phys_dyn/shell_commands
similarity index 100%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/phys_dyn/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/phys_dyn/shell_commands
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/preset/1/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/preset/1/shell_commands
similarity index 92%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/preset/1/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/preset/1/shell_commands
index 74bd2a4d021..216f5c73628 100644
--- a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/preset/1/shell_commands
+++ b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/preset/1/shell_commands
@@ -1,7 +1,7 @@
# This preset uses the three output streams (phys_dyn, phys, and diags)
# It does not add remap, and uses INSTANT output
-SCRIPTS_DIR=$CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/scream/output
+SCRIPTS_DIR=$CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output
# Add the three streams
. $SCRIPTS_DIR/phys/shell_commands
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/preset/2/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/preset/2/shell_commands
similarity index 93%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/preset/2/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/preset/2/shell_commands
index aea7feb5bbd..24b71ba0aa9 100644
--- a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/preset/2/shell_commands
+++ b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/preset/2/shell_commands
@@ -1,7 +1,7 @@
# This preset uses the three output streams (phys_dyn, phys, and diags)
# It does not add remap, and uses AVERAGE output
-SCRIPTS_DIR=$CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/scream/output
+SCRIPTS_DIR=$CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output
# Add the three streams
. $SCRIPTS_DIR/phys/shell_commands
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/preset/3/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/preset/3/shell_commands
similarity index 93%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/preset/3/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/preset/3/shell_commands
index da1d02dc5de..5d27192d525 100644
--- a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/preset/3/shell_commands
+++ b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/preset/3/shell_commands
@@ -1,7 +1,7 @@
# This preset uses the three output streams (phys, and diags)
# It adds horiz remap, and uses INSTANT output
-SCRIPTS_DIR=$CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/scream/output
+SCRIPTS_DIR=$CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output
# Add the phys/diags streams (cannot add phys_dyn, b/c we use horiz remap)
. $SCRIPTS_DIR/phys/shell_commands
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/preset/4/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/preset/4/shell_commands
similarity index 94%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/preset/4/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/preset/4/shell_commands
index 521ada7f508..6746cf1d46e 100644
--- a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/preset/4/shell_commands
+++ b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/preset/4/shell_commands
@@ -1,7 +1,7 @@
# This preset uses the three output streams (phys, and diags)
# It adds horizontal remap, and uses AVERAGE output
-SCRIPTS_DIR=$CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/scream/output
+SCRIPTS_DIR=$CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output
# Add the phys/diags streams (cannot add phys_dyn, b/c we use horiz remap)
. $SCRIPTS_DIR/phys/shell_commands
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/preset/5/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/preset/5/shell_commands
similarity index 94%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/preset/5/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/preset/5/shell_commands
index bd60a0472a8..3c63c1abd8f 100644
--- a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/preset/5/shell_commands
+++ b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/preset/5/shell_commands
@@ -1,7 +1,7 @@
# This preset uses the three output streams (phys_dyn, phys, and diags)
# It adds vertical remap, and uses AVERAGE output
-SCRIPTS_DIR=$CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/scream/output
+SCRIPTS_DIR=$CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output
# Add the phys/dyn/diags streams
. $SCRIPTS_DIR/phys/shell_commands
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/preset/6/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/preset/6/shell_commands
similarity index 94%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/preset/6/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/preset/6/shell_commands
index 937d1646851..442f8b9df8f 100644
--- a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/preset/6/shell_commands
+++ b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/preset/6/shell_commands
@@ -1,7 +1,7 @@
# This preset uses the three output streams (phys, and diags)
# It adds horizontal and remap, and uses AVERAGE output
-SCRIPTS_DIR=$CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/scream/output
+SCRIPTS_DIR=$CIMEROOT/../components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output
# Add the phys/diags streams (cannot add phys_dyn, b/c we use horiz remap)
. $SCRIPTS_DIR/phys/shell_commands
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/set_avg/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/set_avg/shell_commands
similarity index 100%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/set_avg/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/set_avg/shell_commands
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/vremap/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/vremap/shell_commands
similarity index 100%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/output/vremap/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/output/vremap/shell_commands
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/perf_test/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/perf_test/shell_commands
similarity index 100%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/perf_test/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/perf_test/shell_commands
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/rad_frequency_2/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/rad_frequency_2/shell_commands
similarity index 100%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/rad_frequency_2/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/rad_frequency_2/shell_commands
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/scream_example_testmod_atmchange/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/scream_example_testmod_atmchange/shell_commands
similarity index 100%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/scream_example_testmod_atmchange/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/scream_example_testmod_atmchange/shell_commands
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/scream_example_testmod_cmake/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/scream_example_testmod_cmake/shell_commands
similarity index 100%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/scream_example_testmod_cmake/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/scream_example_testmod_cmake/shell_commands
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/sl_nsubstep2/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/sl_nsubstep2/shell_commands
new file mode 100644
index 00000000000..71cdd9b691c
--- /dev/null
+++ b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/sl_nsubstep2/shell_commands
@@ -0,0 +1,3 @@
+ATMCHANGE=$CIMEROOT/../components/eamxx/scripts/atmchange
+
+$ATMCHANGE semi_lagrange_trajectory_nsubstep=2 -b
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/small_kernels/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/small_kernels/shell_commands
similarity index 100%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/small_kernels/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/small_kernels/shell_commands
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/small_kernels_p3/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/small_kernels_p3/shell_commands
similarity index 100%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/small_kernels_p3/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/small_kernels_p3/shell_commands
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/small_kernels_shoc/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/small_kernels_shoc/shell_commands
similarity index 100%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/small_kernels_shoc/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/small_kernels_shoc/shell_commands
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/spa_remap/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/spa_remap/shell_commands
similarity index 100%
rename from components/eamxx/cime_config/testdefs/testmods_dirs/scream/spa_remap/shell_commands
rename to components/eamxx/cime_config/testdefs/testmods_dirs/eamxx/spa_remap/shell_commands
diff --git a/components/eamxx/cime_config/testdefs/testmods_dirs/scream/sunspot_run/shell_commands b/components/eamxx/cime_config/testdefs/testmods_dirs/scream/sunspot_run/shell_commands
new file mode 100644
index 00000000000..6ca33b486f9
--- /dev/null
+++ b/components/eamxx/cime_config/testdefs/testmods_dirs/scream/sunspot_run/shell_commands
@@ -0,0 +1,6 @@
+
+$CIMEROOT/../components/eamxx/scripts/atmchange transport_alg=0 -b
+$CIMEROOT/../components/eamxx/scripts/atmchange hypervis_subcycle_q=1 -b
+$CIMEROOT/../components/eamxx/scripts/atmchange dt_tracer_factor=1 -b
+$CIMEROOT/../components/eamxx/scripts/atmchange tstep_type=9 -b
+$CIMEROOT/../components/eamxx/scripts/atmchange theta_hydrostatic_mode=False -b
diff --git a/components/eamxx/cime_config/tests/eamxx_default_files.py b/components/eamxx/cime_config/tests/eamxx_default_files.py
deleted file mode 100644
index b39d2d5c155..00000000000
--- a/components/eamxx/cime_config/tests/eamxx_default_files.py
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/usr/bin/env python3
-
-import os
-import http
-import pathlib
-import unittest
-import urllib.request
-import xml.etree.ElementTree as ET
-
-
-class testNamelistDefaultsScream(unittest.TestCase):
- def setUp(self):
- """
- Set up the environment for the test by setting the DIN_LOC_ROOT
- environment variable. Parse the 'namelist_defaults_scream.xml'
- file and extract the files of interest based on the DIN_LOC_ROOT
- variable or the array(file) type. Assign the extracted files
- to the 'my_files' attribute of the test instance.
- """
-
- os.environ["DIN_LOC_ROOT"] = "https://web.lcrc.anl.gov/public/e3sm/inputdata/"
-
- scream_defaults_path = pathlib.Path(__file__)
- tree = ET.parse(f"{scream_defaults_path.parent.parent}/namelist_defaults_scream.xml")
- root = tree.getroot()
-
- files_of_interest = [
- child.text for child in root.findall(".//")
- if child.text and child.text.startswith("${DIN_LOC_ROOT}")
- ]
-
- more_files_of_interest = [
- child.text for child in root.findall(".//")
- if child.text and "type" in child.attrib.keys() and child.attrib["type"]=="array(file)"
- ]
-
- files_of_interest.extend(
- text.strip() for text_list in more_files_of_interest for text in text_list.split(",")
- if text.strip().startswith("${DIN_LOC_ROOT}")
- )
-
- self.my_files = [
- file.replace("${DIN_LOC_ROOT}/", "")
- for file in files_of_interest
- ]
-
- self.my_lines = []
- with open(
- f"{scream_defaults_path.parent.parent}/namelist_defaults_scream.xml",
- "r"
- ) as the_file:
- for a_line in the_file:
- self.my_lines.append(a_line)
-
- def test_ascii_lines(self):
- """
- Test that all lines are ASCII
- """
-
- for i_line, a_line in enumerate(self.my_lines):
- with self.subTest(i_line=i_line):
- self.assertTrue(
- a_line.isascii(),
- msg=f"\nERROR! This line is not ASCII!\n{a_line}"
- )
-
- def test_opening_files(self):
- """
- Test the opening of files from the inputdata server.
- """
-
- for i_file in range(len(self.my_files)):
- with self.subTest(i_file=i_file):
- try:
- request_return = urllib.request.urlopen(
- f"{os.environ['DIN_LOC_ROOT']}{self.my_files[i_file]}"
- )
- self.assertIsInstance(request_return, http.client.HTTPResponse)
- except urllib.error.HTTPError:
- file_name = f"{os.environ['DIN_LOC_ROOT']}{self.my_files[i_file]}"
- self.assertTrue(
- False,
- msg=f"\nERROR! This file doesn't exist!\n{file_name}"
- )
-
- def test_expected_fail(self):
- """
- Test an expected failure by manipulating the file name.
- """
-
- with self.assertRaises(urllib.error.HTTPError):
- some_phony_file = f"{self.my_files[5][:-5]}some_phony_file.nc"
- urllib.request.urlopen(
- f"{os.environ['DIN_LOC_ROOT']}{some_phony_file}"
- )
-
-
-if __name__ == '__main__':
- unittest.main()
diff --git a/components/eamxx/cmake/BuildCprnc.cmake b/components/eamxx/cmake/BuildCprnc.cmake
index 287956c5a9d..05db9b60690 100644
--- a/components/eamxx/cmake/BuildCprnc.cmake
+++ b/components/eamxx/cmake/BuildCprnc.cmake
@@ -18,7 +18,9 @@ macro(BuildCprnc)
configure_file (${SCREAM_BASE_DIR}/cmake/CprncTest.cmake.in
${CMAKE_BINARY_DIR}/bin/CprncTest.cmake @ONLY)
else()
- message(WARNING "Path ${CCSM_CPRNC} does not exist, so we will try to build it")
+ if (NOT "${CCSM_CPRNC}" STREQUAL "")
+ message(WARNING "Path ${CCSM_CPRNC} does not exist, so we will try to build it")
+ endif()
# Make sure this is built only once
if (NOT TARGET cprnc)
if (SCREAM_CIME_BUILD)
diff --git a/components/eamxx/cmake/machine-files/aurora.cmake b/components/eamxx/cmake/machine-files/aurora.cmake
index 59157285bab..e6a32fc72c0 100644
--- a/components/eamxx/cmake/machine-files/aurora.cmake
+++ b/components/eamxx/cmake/machine-files/aurora.cmake
@@ -1,14 +1,29 @@
include(${CMAKE_CURRENT_LIST_DIR}/common.cmake)
common_setup()
-include (${EKAT_MACH_FILES_PATH}/kokkos/serial.cmake)
+include (${EKAT_MACH_FILES_PATH}/kokkos/intel-pvc.cmake)
include (${EKAT_MACH_FILES_PATH}/mpi/other.cmake)
-
set(EKAT_MPIRUN_EXE "mpiexec" CACHE STRING "" FORCE)
set(EKAT_MPI_NP_FLAG "-np" CACHE STRING "" FORCE)
set(EKAT_MPI_EXTRA_ARGS "--label --cpu-bind depth -envall" CACHE STRING "")
set(EKAT_MPI_THREAD_FLAG "-d" CACHE STRING "")
-set(NETCDF_C_PATH "$ENV{NETCDF_C_PATH}")
-set(NETCDF_FORTRAN_PATH "$ENV{NETCDF_FORTRAN_PATH}")
-set(PNETCDF_PATH "$ENV{PNETCDF_PATH}")
+SET(SYCL_COMPILE_FLAGS "-std=c++17 -fsycl -fsycl-device-code-split=per_kernel -fno-sycl-id-queries-fit-in-int -fsycl-unnamed-lambda")
+SET(SYCL_LINK_FLAGS "-fsycl -fsycl-link-huge-device-code -fsycl-device-code-split=per_kernel -fsycl-targets=spir64_gen -Xsycl-target-backend \"-device 12.60.7\"")
+
+set(CMAKE_CXX_FLAGS " -\-intel -Xclang -fsycl-allow-virtual-functions -mlong-double-64 -O3 -DNDEBUG ${SYCL_COMPILE_FLAGS}" CACHE STRING "" FORCE)
+set(CMAKE_Fortran_FLAGS "-fc=ifx -O3 -DNDEBUG -DCPRINTEL -g" CACHE STRING "" FORCE)
+set(CMAKE_C_FLAGS "-O3 -DNDEBUG" CACHE STRING "" FORCE)
+set(CMAKE_EXE_LINKER_FLAGS " -lifcore -\-intel -Xclang -fsycl-allow-virtual-functions -lsycl -mlong-double-64 -DNDEBUG ${SYCL_LINK_FLAGS} -fortlib" CACHE STRING "" FORCE)
+
+#this is needed for cime builds!
+set(NETCDF_PATH "/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-fortran/4.6.1/oneapi.eng.2024.04.15.002")
+set(NETCDF_DIR "/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-fortran/4.6.1/oneapi.eng.2024.04.15.002")
+set(NETCDF_C_PATH "/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-c/4.9.2/oneapi.eng.2024.04.15.002")
+set(NETCDF_C "/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-c/4.9.2/oneapi.eng.2024.04.15.002")
+#this one is for rrtmgp
+set(NetCDF_C_PATH "/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-c/4.9.2/oneapi.eng.2024.04.15.002" CACHE STRING "")
+set(NETCDF_FORTRAN_PATH "/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-fortran/4.6.1/oneapi.eng.2024.04.15.002")
+set(PNETCDF_PATH "/lus/flare/projects/CSC249ADSE15_CNDA/software/pnetcdf/1.12.3/oneapi.eng.2024.04.15.002")
+
+
diff --git a/components/eamxx/cmake/machine-files/auroracpu.cmake b/components/eamxx/cmake/machine-files/auroracpu.cmake
new file mode 100644
index 00000000000..d620dcb3a0d
--- /dev/null
+++ b/components/eamxx/cmake/machine-files/auroracpu.cmake
@@ -0,0 +1,31 @@
+include(${CMAKE_CURRENT_LIST_DIR}/common.cmake)
+common_setup()
+
+include (${EKAT_MACH_FILES_PATH}/kokkos/serial.cmake)
+# kokkos sycl is on in the above file
+#include (${EKAT_MACH_FILES_PATH}/kokkos/sycl.cmake)
+include (${EKAT_MACH_FILES_PATH}/mpi/srun.cmake)
+
+#AB flags from ekat
+# -fsycl -fsycl-unnamed-lambda -sycl-std=2020 -qopenmp-simd -Wsycl-strict -fsycl-device-code-split=per_kernel
+
+#SET(MPICH_DIR "/soft/restricted/CNDA/updates/mpich/52.2/mpich-ofi-all-icc-default-pmix-gpu-drop52/" CACHE STRING "")
+
+set(CMAKE_CXX_FLAGS " -\-intel -Xclang -fsycl-allow-virtual-functions -mlong-double-64 -O3 -DNDEBUG" CACHE STRING "" FORCE)
+set(CMAKE_Fortran_FLAGS "-fc=ifx -O3 -DNDEBUG -DCPRINTEL -g" CACHE STRING "" FORCE)
+set(CMAKE_C_FLAGS "-O3 -DNDEBUG" CACHE STRING "" FORCE)
+set(CMAKE_EXE_LINKER_FLAGS " -lifcore -\-intel -Xclang -mlong-double-64 -DNDEBUG -fortlib" CACHE STRING "" FORCE)
+#set(CMAKE_EXE_LINKER_FLAGS " -Wl,-\-defsym,main=MAIN_\_ -lifcore -\-intel -Xclang -fsycl-allow-virtual-functions -lsycl -mlong-double-64 -DNDEBUG ${SYCL_LINK_FLAGS} -fortlib -L${MPICH_DIR}/lib" CACHE STRING "" FORCE)
+
+#this is needed for cime builds!
+set(NETCDF_PATH "/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-fortran/4.6.1/oneapi.eng.2023.05.15.007")
+set(NETCDF_DIR "/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-fortran/4.6.1/oneapi.eng.2023.05.15.007")
+set(NETCDF_C_PATH "/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-c/4.9.2/oneapi.eng.2023.05.15.007")
+set(NETCDF_C "/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-c/4.9.2/oneapi.eng.2023.05.15.007")
+#this one is for rrtmgp
+set(NetCDF_C_PATH "/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-c/4.9.2/oneapi.eng.2023.05.15.007" CACHE STRING "")
+set(NETCDF_FORTRAN_PATH "/lus/flare/projects/CSC249ADSE15_CNDA/software/netcdf-fortran/4.6.1/oneapi.eng.2023.05.15.007")
+set(PNETCDF_PATH "/lus/flare/projects/CSC249ADSE15_CNDA/software/pnetcdf/1.12.3/oneapi.eng.2023.05.15.007")
+
+
+
diff --git a/components/eamxx/cmake/machine-files/ghci-snl-cuda.cmake b/components/eamxx/cmake/machine-files/ghci-snl-cuda.cmake
index 72a352f09d7..83d1d20c627 100644
--- a/components/eamxx/cmake/machine-files/ghci-snl-cuda.cmake
+++ b/components/eamxx/cmake/machine-files/ghci-snl-cuda.cmake
@@ -12,3 +12,6 @@ set(EKAT_MPI_NP_FLAG "-n" CACHE STRING "The mpirun flag for designating the tota
# TODO: rebuild cuda image with cuda-aware MPI, so we can set this to ON
option(SCREAM_MPI_ON_DEVICE "Whether to use device pointers for MPI calls" OFF)
+
+# Currently, we have 2 GPUs/node on Blake, and we run a SINGLE build per node, so we can fit 2 ranks there
+set(SCREAM_TEST_MAX_RANKS 2 CACHE STRING "Upper limit on ranks for mpi tests")
diff --git a/components/eamxx/cmake/machine-files/ghci-snl.cmake b/components/eamxx/cmake/machine-files/ghci-snl.cmake
index ac4db2a39f1..9782036d92c 100644
--- a/components/eamxx/cmake/machine-files/ghci-snl.cmake
+++ b/components/eamxx/cmake/machine-files/ghci-snl.cmake
@@ -17,3 +17,5 @@ option (EKAT_TEST_LAUNCHER_MANAGE_RESOURCES "" ON)
# Needed by EkatCreateUnitTest
set (EKAT_MPIRUN_EXE "mpirun" CACHE STRING "")
set (EKAT_MPI_NP_FLAG "-n" CACHE STRING "")
+
+set(EKAT_VALGRIND_SUPPRESSION_FILE "/projects/e3sm/baselines/scream/ghci-snl-cpu/eamxx-valgrind.supp" CACHE FILEPATH "Use this valgrind suppression file if valgrind is enabled.")
diff --git a/components/eamxx/cmake/machine-files/sunspot-gen.cmake b/components/eamxx/cmake/machine-files/sunspot-gen.cmake
new file mode 100644
index 00000000000..3e33ac7b461
--- /dev/null
+++ b/components/eamxx/cmake/machine-files/sunspot-gen.cmake
@@ -0,0 +1,31 @@
+include(${CMAKE_CURRENT_LIST_DIR}/common.cmake)
+common_setup()
+
+include (${EKAT_MACH_FILES_PATH}/kokkos/intel-gen.cmake)
+include (${EKAT_MACH_FILES_PATH}/kokkos/sycl.cmake)
+include (${EKAT_MACH_FILES_PATH}/mpi/srun.cmake)
+
+#AB flags from ekat
+# -fsycl -fsycl-unnamed-lambda -sycl-std=2020 -qopenmp-simd -Wsycl-strict -fsycl-device-code-split=per_kernel
+SET(SYCL_COMPILE_FLAGS "-std=c++17 -fsycl -fsycl-device-code-split=per_kernel -fno-sycl-id-queries-fit-in-int -fsycl-unnamed-lambda")
+SET(SYCL_LINK_FLAGS "-fsycl -fsycl-link-huge-device-code -fsycl-device-code-split=per_kernel -fsycl-targets=spir64")
+
+#SET(MPICH_DIR "/soft/restricted/CNDA/updates/mpich/52.2/mpich-ofi-all-icc-default-pmix-gpu-drop52/" CACHE STRING "")
+
+set(CMAKE_CXX_FLAGS " -\-intel -Xclang -fsycl-allow-virtual-functions -mlong-double-64 -O3 -DNDEBUG ${SYCL_COMPILE_FLAGS}" CACHE STRING "" FORCE)
+set(CMAKE_Fortran_FLAGS "-fc=ifx -O3 -DNDEBUG -DCPRINTEL -g" CACHE STRING "" FORCE)
+set(CMAKE_C_FLAGS "-O3 -DNDEBUG" CACHE STRING "" FORCE)
+set(CMAKE_EXE_LINKER_FLAGS " -lifcore -\-intel -Xclang -fsycl-allow-virtual-functions -lsycl -mlong-double-64 -DNDEBUG ${SYCL_LINK_FLAGS} -fortlib" CACHE STRING "" FORCE)
+#set(CMAKE_EXE_LINKER_FLAGS " -Wl,-\-defsym,main=MAIN_\_ -lifcore -\-intel -Xclang -fsycl-allow-virtual-functions -lsycl -mlong-double-64 -DNDEBUG ${SYCL_LINK_FLAGS} -fortlib -L${MPICH_DIR}/lib" CACHE STRING "" FORCE)
+
+
+
+set(NETCDF_PATH "$ENV{NETCDF_PATH}")
+set(NETCDF_C_PATH "$ENV{NETCDF_PATH}")
+#this one is for rrtmgp
+set(NetCDF_C_PATH "$ENV{NETCDF_PATH}" CACHE STRING "")
+set(NETCDF_FORTRAN_PATH "$ENV{NETCDF_PATH}")
+set(PNETCDF_PATH "$ENV{PNETCDF_PATH}")
+
+
+
diff --git a/components/eamxx/cmake/machine-files/sunspot-pvc.cmake b/components/eamxx/cmake/machine-files/sunspot-pvc.cmake
new file mode 100644
index 00000000000..53740d87e0e
--- /dev/null
+++ b/components/eamxx/cmake/machine-files/sunspot-pvc.cmake
@@ -0,0 +1,28 @@
+include(${CMAKE_CURRENT_LIST_DIR}/common.cmake)
+common_setup()
+
+include (${EKAT_MACH_FILES_PATH}/kokkos/intel-pvc.cmake)
+include (${EKAT_MACH_FILES_PATH}/mpi/other.cmake)
+set(EKAT_MPIRUN_EXE "mpiexec" CACHE STRING "" FORCE)
+set(EKAT_MPI_NP_FLAG "-np" CACHE STRING "" FORCE)
+set(EKAT_MPI_EXTRA_ARGS "--label --cpu-bind depth -envall" CACHE STRING "")
+set(EKAT_MPI_THREAD_FLAG "-d" CACHE STRING "")
+
+SET(SYCL_COMPILE_FLAGS "-std=c++17 -fsycl -fsycl-device-code-split=per_kernel -fno-sycl-id-queries-fit-in-int -fsycl-unnamed-lambda")
+SET(SYCL_LINK_FLAGS "-fsycl -fsycl-link-huge-device-code -fsycl-device-code-split=per_kernel -fsycl-targets=spir64_gen -Xsycl-target-backend \"-device 12.60.7\"")
+
+set(CMAKE_CXX_FLAGS " -\-intel -Xclang -fsycl-allow-virtual-functions -mlong-double-64 -O3 -DNDEBUG ${SYCL_COMPILE_FLAGS}" CACHE STRING "" FORCE)
+set(CMAKE_Fortran_FLAGS "-fc=ifx -O3 -DNDEBUG -DCPRINTEL -g" CACHE STRING "" FORCE)
+set(CMAKE_C_FLAGS "-O3 -DNDEBUG" CACHE STRING "" FORCE)
+set(CMAKE_EXE_LINKER_FLAGS " -lifcore -\-intel -Xclang -fsycl-allow-virtual-functions -lsycl -mlong-double-64 -DNDEBUG ${SYCL_LINK_FLAGS} -fortlib" CACHE STRING "" FORCE)
+
+set(NETCDF_PATH "/lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/netcdf" CACHE STRING "")
+set(NETCDF_DIR "/lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/netcdf" CACHE STRING "")
+set(NETCDF_C_PATH "/lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/netcdf" CACHE STRING "")
+set(NETCDF_C "/lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/netcdf" CACHE STRING "")
+#this one is for rrtmgp
+set(NetCDF_C_PATH "/lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/netcdf" CACHE STRING "")
+set(NETCDF_FORTRAN_PATH "/lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/netcdf" CACHE STRING "")
+set(PNETCDF_PATH "/lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/pnetcdf" CACHE STRING "")
+
+
diff --git a/components/eamxx/cmake/machine-files/sunspotcpu.cmake b/components/eamxx/cmake/machine-files/sunspotcpu.cmake
new file mode 100644
index 00000000000..ff7773daae1
--- /dev/null
+++ b/components/eamxx/cmake/machine-files/sunspotcpu.cmake
@@ -0,0 +1,34 @@
+include(${CMAKE_CURRENT_LIST_DIR}/common.cmake)
+common_setup()
+
+include (${EKAT_MACH_FILES_PATH}/kokkos/serial.cmake)
+# kokkos sycl is on in the above file
+#include (${EKAT_MACH_FILES_PATH}/kokkos/sycl.cmake)
+include (${EKAT_MACH_FILES_PATH}/mpi/srun.cmake)
+
+#AB flags from ekat
+# -fsycl -fsycl-unnamed-lambda -sycl-std=2020 -qopenmp-simd -Wsycl-strict -fsycl-device-code-split=per_kernel
+
+#SET(MPICH_DIR "/soft/restricted/CNDA/updates/mpich/52.2/mpich-ofi-all-icc-default-pmix-gpu-drop52/" CACHE STRING "")
+
+set(CMAKE_CXX_FLAGS " -\-intel -Xclang -fsycl-allow-virtual-functions -mlong-double-64 -O3 -DNDEBUG -gline-tables-only -g" CACHE STRING "" FORCE)
+set(CMAKE_Fortran_FLAGS "-fc=ifx -O3 -DNDEBUG -DCPRINTEL -g -gline-tables-only" CACHE STRING "" FORCE)
+set(CMAKE_C_FLAGS "-O3 -DNDEBUG -gline-tables-only -g" CACHE STRING "" FORCE)
+set(CMAKE_EXE_LINKER_FLAGS " -lifcore -\-intel -Xclang -mlong-double-64 -DNDEBUG -fortlib" CACHE STRING "" FORCE)
+#set(CMAKE_EXE_LINKER_FLAGS " -Wl,-\-defsym,main=MAIN_\_ -lifcore -\-intel -Xclang -fsycl-allow-virtual-functions -lsycl -mlong-double-64 -DNDEBUG ${SYCL_LINK_FLAGS} -fortlib -L${MPICH_DIR}/lib" CACHE STRING "" FORCE)
+
+
+
+set(NETCDF_PATH "/lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/netcdf" CACHE STRING "")
+set(NETCDF_DIR "/lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/netcdf" CACHE STRING "")
+set(NETCDF_C_PATH "/lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/netcdf" CACHE STRING "")
+set(NETCDF_C "/lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/netcdf" CACHE STRING "")
+#this one is for rrtmgp
+set(NetCDF_C_PATH "/lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/netcdf" CACHE STRING "")
+set(NETCDF_FORTRAN_PATH "/lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/netcdf" CACHE STRING "")
+set(PNETCDF_PATH "/lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/pnetcdf" CACHE STRING "")
+
+
+set(PNETCDF_DIR "/lus/gila/projects/CSC249ADSE15_CNDA/software/oneAPI.2022.12.30.003/pnetcdf" CACHE STRING "")
+
+
diff --git a/components/eamxx/docs/developer/index.md b/components/eamxx/docs/developer/index.md
index 69673b12ebd..7216d6057cb 100644
--- a/components/eamxx/docs/developer/index.md
+++ b/components/eamxx/docs/developer/index.md
@@ -1 +1,16 @@
-# SCREAM Developer Guide
+# EAMxx Developer Guide
+
+### [Installation](../common/installation.md)
+### [Style Guide](style_guide.md)
+### [Kokkos and EKAT](kokkos_ekat.md)
+### [Source Tree](source_tree.md)
+### Important Data Structures
+ * [Fields](field.md)
+ * [Grids and Remappers](grid.md)
+ * [Atmosphere Processes](processes.md)
+ * [Managers](managers.md)
+### [I/O](io.md)
+### Testing
+ * [Standalone](standalone_testing.md)
+ * [Full Model](cime_testing.md)
+ * [CI and Nightly Testing](ci_nightly.md)
diff --git a/components/eamxx/docs/developer/kokkos_ekat.md b/components/eamxx/docs/developer/kokkos_ekat.md
index a736384b2c6..6ebf23ba1aa 100644
--- a/components/eamxx/docs/developer/kokkos_ekat.md
+++ b/components/eamxx/docs/developer/kokkos_ekat.md
@@ -57,8 +57,8 @@ where
run-time dimensions). E.g., a 2D view of doubles will have `DataType =
double**`. There is also an ability to define compile-time dimensions by
using `[]`, see
- [Kokkos wiki section on views]
- ().
+ [Kokkos wiki section on views]
+ (_f)"
+ lambda *x : "The f90 to cxx function declaration(_host)"
)),
("cxx_f2c_bind_impl" , (
- lambda phys, sub, gb: f"{phys}_functions_f90.cpp",
+ lambda phys, sub, gb: f"tests/infra/{phys}_test_data.cpp",
lambda phys, sub, gb: expect_exists(phys, sub, gb, "cxx_f2c_bind_impl"),
lambda phys, sub, gb: get_namespace_close_regex(phys), # insert at end of namespace
- lambda phys, sub, gb: get_cxx_function_begin_regex(sub + "_f"), # cxx_f
+ lambda phys, sub, gb: get_cxx_function_begin_regex(sub + "_host"), # cxx_f
lambda phys, sub, gb: get_cxx_close_block_regex(at_line_start=True), # terminating }
- lambda *x : "The f90 to cxx function implementation(_f)"
+ lambda *x : "The f90 to cxx function implementation(_host)"
)),
("cxx_func_decl", (
@@ -455,6 +455,12 @@ def get_cxx_struct_begin_regex(struct):
struct_regex_str = fr"^\s*struct\s+{struct}([\W]|$)"
return re.compile(struct_regex_str)
+###############################################################################
+def get_plain_comment_regex(comment):
+###############################################################################
+ comment_regex_str = fr"^\s*//\s*{comment}"
+ return re.compile(comment_regex_str)
+
###############################################################################
def get_data_struct_name(sub):
###############################################################################
@@ -1169,6 +1175,21 @@ def split_by_type(arg_data):
return reals, ints, logicals
+###############################################################################
+def split_by_scalar_vs_view(arg_data):
+###############################################################################
+ """
+ Take arg data and split into two lists of names based on scalar/not-scalar: [scalars] [non-scalars]
+ """
+ scalars, non_scalars = [], []
+ for name, _, _, dims in arg_data:
+ if dims is not None:
+ non_scalars.append(name)
+ else:
+ scalars.append(name)
+
+ return scalars, non_scalars
+
###############################################################################
def gen_cxx_data_args(physics, arg_data):
###############################################################################
@@ -1441,6 +1462,30 @@ def check_existing_piece(lines, begin_regex, end_regex):
return None if begin_idx is None else (begin_idx, end_idx+1)
+###############################################################################
+def get_data_by_name(arg_data, arg_name, data_idx):
+###############################################################################
+ for name, a, b, c in arg_data:
+ if name == arg_name:
+ return [name, a, b, c][data_idx]
+
+ expect(False, f"Name {arg_name} not found")
+
+###############################################################################
+def get_rank_map(arg_data, arg_names):
+###############################################################################
+ # Create map of rank -> [args]
+ rank_map = {}
+ for arg in arg_names:
+ dims = get_data_by_name(arg_data, arg, ARG_DIMS)
+ rank = len(dims)
+ if rank in rank_map:
+ rank_map[rank].append(arg)
+ else:
+ rank_map[rank] = [arg]
+
+ return rank_map
+
#
# Main classes
#
@@ -1505,10 +1550,10 @@ def _get_db(self, phys):
db = parse_origin(origin_file.open(encoding="utf-8").read(), self._subs)
self._db[phys].update(db)
if self._verbose:
- print("For physics {}, found:")
+ print(f"For physics {phys}, found:")
for sub in self._subs:
if sub in db:
- print(" For subroutine {}, found args:")
+ print(f" For subroutine {sub}, found args:")
for name, argtype, intent, dims in db[sub]:
print(" name:{} type:{} intent:{} dims:({})".\
format(name, argtype, intent, ",".join(dims) if dims else "scalar"))
@@ -1729,7 +1774,7 @@ def gen_cxx_f2c_bind_decl(self, phys, sub, force_arg_data=None):
arg_data = force_arg_data if force_arg_data else self._get_arg_data(phys, sub)
arg_decls = gen_arg_cxx_decls(arg_data)
- return f"void {sub}_f({', '.join(arg_decls)});"
+ return f"void {sub}_host({', '.join(arg_decls)});"
###########################################################################
def gen_cxx_f2c_bind_impl(self, phys, sub, force_arg_data=None):
@@ -1809,8 +1854,166 @@ def gen_cxx_f2c_bind_impl(self, phys, sub, force_arg_data=None):
impl = ""
if has_arrays(arg_data):
- # TODO
- impl += " // TODO"
+ #
+ # Steps:
+ # 1) Set up typedefs
+ # 2) Sync to device
+ # 3) Unpack view array
+ # 4) Get nk_pack and policy
+ # 5) Get subviews
+ # 6) Call fn
+ # 7) Sync back to host
+ #
+ inputs, inouts, outputs = split_by_intent(arg_data)
+ reals, ints, bools = split_by_type(arg_data)
+ scalars, views = split_by_scalar_vs_view(arg_data)
+ all_inputs = inputs + inouts
+ all_outputs = inouts + outputs
+
+ vreals = list(sorted(set(reals) & set(views)))
+ vints = list(sorted(set(ints) & set(views)))
+ vbools = list(sorted(set(bools) & set(views)))
+
+ sreals = list(sorted(set(reals) & set(scalars)))
+ sints = list(sorted(set(ints) & set(scalars)))
+ sbools = list(sorted(set(bools) & set(scalars)))
+
+ ivreals = list(sorted(set(vreals) & set(all_inputs)))
+ ivints = list(sorted(set(vints) & set(all_inputs)))
+ ivbools = list(sorted(set(vbools) & set(all_inputs)))
+
+ ovreals = list(sorted(set(vreals) & set(all_outputs)))
+ ovints = list(sorted(set(vints) & set(all_outputs)))
+ ovbools = list(sorted(set(vbools) & set(all_outputs)))
+
+ isreals = list(sorted(set(sreals) & set(all_inputs)))
+ isints = list(sorted(set(sints) & set(all_inputs)))
+ isbools = list(sorted(set(sbools) & set(all_inputs)))
+
+ osreals = list(sorted(set(sreals) & set(all_outputs)))
+ osints = list(sorted(set(sints) & set(all_outputs)))
+ osbools = list(sorted(set(sbools) & set(all_outputs)))
+
+ #
+ # 1) Set up typedefs
+ #
+
+ # set up basics
+ impl += "#if 0\n" # There's no way to guarantee this code compiles
+ impl += " using SHF = Functions;\n"
+ impl += " using Scalar = typename SHF::Scalar;\n"
+ impl += " using Spack = typename SHF::Spack;\n"
+ impl += " using KT = typename SHF::KT;\n"
+ impl += " using ExeSpace = typename KT::ExeSpace;\n"
+ impl += " using MemberType = typename SHF::MemberType;\n\n"
+
+ prefix_list = ["", "i", "b"]
+ type_list = ["Real", "Int", "bool"]
+ ktype_list = ["Spack", "Int", "bool"]
+
+ # make necessary view types. Anything that's an array needs a view type
+ for view_group, prefix_char, typename in zip([vreals, vints, vbools], prefix_list, type_list):
+ if view_group:
+ rank_map = get_rank_map(arg_data, view_group)
+ for rank in rank_map:
+ if typename == "Real" and rank > 1:
+ # Probably this should be packed data
+ impl += f" using {prefix_char}view_{rank}d = typename SHF::view_{rank}d;\n"
+ else:
+ impl += f" using {prefix_char}view_{rank}d = typename SHF::view_{rank}d<{typename}>;\n"
+
+ impl += "\n"
+
+ #
+ # 2) Sync to device. Do ALL views, not just inputs
+ #
+
+ for input_group, prefix_char, typename in zip([vreals, vints, vbools], prefix_list, type_list):
+ if input_group:
+ rank_map = get_rank_map(arg_data, input_group)
+
+ for rank, arg_list in rank_map.items():
+ impl += f" static constexpr Int {prefix_char}num_arrays_{rank} = {len(arg_list)};\n"
+ impl += f" std::vector<{prefix_char}view_{rank}d> {prefix_char}temp_d_{rank}({prefix_char}num_arrays_{rank});\n"
+ for rank_itr in range(rank):
+ dims = [get_data_by_name(arg_data, arg_name, ARG_DIMS)[rank_itr] for arg_name in arg_list]
+ impl += f" std::vector {prefix_char}dim_{rank}_{rank_itr}_sizes = {{{', '.join(dims)}}};\n"
+ dim_vectors = [f"{prefix_char}dim_{rank}_{rank_itr}_sizes" for rank_itr in range(rank)]
+ funcname = "ekat::host_to_device" if (typename == "Real" and rank > 1) else "ScreamDeepCopy::copy_to_device"
+ impl += f" {funcname}({{{', '.join(arg_list)}}}, {', '.join(dim_vectors)}, {prefix_char}temp_d_{rank});\n\n"
+
+ #
+ # 3) Unpack view array
+ #
+
+ for input_group, prefix_char, typename in zip([vreals, vints, vbools], prefix_list, type_list):
+ if input_group:
+ rank_map = get_rank_map(arg_data, input_group)
+
+ for rank, arg_list in rank_map.items():
+ impl += f" {prefix_char}view_{rank}d\n"
+ for idx, input_item in enumerate(arg_list):
+ impl += f" {input_item}_d({prefix_char}temp_d_{rank}[{idx}]){';' if idx == len(arg_list) - 1 else ','}\n"
+ impl += "\n"
+
+
+ #
+ # 4) Get nk_pack and policy, launch kernel
+ #
+ impl += " const Int nk_pack = ekat::npack(nlev);\n"
+ impl += " const auto policy = ekat::ExeSpaceUtils::get_default_team_policy(shcol, nk_pack);\n"
+ impl += " Kokkos::parallel_for(policy, KOKKOS_LAMBDA(const MemberType& team) {\n"
+ impl += " const Int i = team.league_rank();\n\n"
+
+ #
+ # 5) Get subviews
+ #
+ for view_group, prefix_char, typename in zip([vreals, vints, vbools], prefix_list, type_list):
+ if view_group:
+ for view_arg in view_group:
+ dims = get_data_by_name(arg_data, view_arg, ARG_DIMS)
+ if "shcol" in dims:
+ if len(dims) == 1:
+ impl += f" const Scalar {view_arg}_s = {view_arg}_d(i);\n"
+ else:
+ impl += f" const auto {view_arg}_s = ekat::subview({view_arg}_d, i);\n"
+
+ impl += "\n"
+
+ #
+ # 6) Call fn
+ #
+ kernel_arg_names = []
+ for arg_name in arg_names:
+ if arg_name in views:
+ if "shcol" in dims:
+ kernel_arg_names.append(f"{arg_name}_s")
+ else:
+ kernel_arg_names.append(f"{arg_name}_d")
+ else:
+ kernel_arg_names.append(arg_name)
+
+ impl += f" SHF::{sub}({', '.join(kernel_arg_names)});\n"
+ impl += " });\n"
+
+ #
+ # 7) Sync back to host
+ #
+ for output_group, prefix_char, typename in zip([ovreals, ovints, ovbools], prefix_list, type_list):
+ if output_group:
+ rank_map = get_rank_map(arg_data, output_group)
+
+ for rank, arg_list in rank_map.items():
+ impl += f" std::vector<{prefix_char}view_{rank}d> {prefix_char}tempout_d_{rank}({prefix_char}num_arrays_{rank});\n"
+ for rank_itr in range(rank):
+ dims = [get_data_by_name(arg_data, arg_name, ARG_DIMS)[rank_itr] for arg_name in arg_list]
+ impl += f" std::vector {prefix_char}dim_{rank}_{rank_itr}_out_sizes = {{{', '.join(dims)}}};\n"
+ dim_vectors = [f"{prefix_char}dim_{rank}_{rank_itr}_out_sizes" for rank_itr in range(rank)]
+ funcname = "ekat::device_to_host" if (typename == "Real" and rank > 1) else "ScreamDeepCopy::copy_to_host"
+ impl += f" {funcname}({{{', '.join(arg_list)}}}, {', '.join(dim_vectors)}, {prefix_char}tempout_d_{rank});\n\n"
+
+ impl += "#endif\n"
+
else:
inputs, inouts, outputs = split_by_intent(arg_data)
reals, ints, logicals = split_by_type(arg_data)
diff --git a/components/eamxx/scripts/machines_specs.py b/components/eamxx/scripts/machines_specs.py
index c9c9f973022..dbb9363381c 100644
--- a/components/eamxx/scripts/machines_specs.py
+++ b/components/eamxx/scripts/machines_specs.py
@@ -124,7 +124,7 @@ def setup_pm(cls,partition):
cls.batch += "--time 00:30:00 --nodes=1 -q debug"
else:
cls.batch += "--time 02:00:00 --nodes=4 --gpus-per-node=4 --gpu-bind=none --exclusive -q regular"
-
+
cls.baselines_dir = f"/global/cfs/cdirs/e3sm/baselines/{compiler}/scream/{cls.name}"
###############################################################################
@@ -214,6 +214,7 @@ class GHCISNLCPU(Machine):
def setup(cls):
super().setup_base("ghci-snl-cpu")
cls.baselines_dir = "/projects/e3sm/baselines/scream/ghci-snl-cpu"
+ cls.env_setup = ["export GATOR_INITIAL_MB=4000MB"]
###############################################################################
class GHCISNLCuda(Machine):
diff --git a/components/eamxx/scripts/CMakeLists.txt b/components/eamxx/scripts/query-cf-database/CMakeLists.txt
similarity index 67%
rename from components/eamxx/scripts/CMakeLists.txt
rename to components/eamxx/scripts/query-cf-database/CMakeLists.txt
index 377452229b9..91200760602 100644
--- a/components/eamxx/scripts/CMakeLists.txt
+++ b/components/eamxx/scripts/query-cf-database/CMakeLists.txt
@@ -1,8 +1,8 @@
-# Generate the source file for the CF validator and build it.
+# Build the CF validator tool
-set (CF_STANDARD_NAME_FILE "${PROJECT_SOURCE_DIR}/data/cf-standard-name-table.yaml"
+set (CF_STANDARD_NAME_FILE "${CMAKE_CURRENT_SOURCE_DIR}/cf-standard-name-table.yaml"
CACHE STRING "Location of the cf standard name yaml table")
-set (CF_SCREAM_NAME_FILE "${PROJECT_SOURCE_DIR}/data/cf-scream-name-table.yaml"
+set (CF_SCREAM_NAME_FILE "${CMAKE_CURRENT_SOURCE_DIR}/cf-scream-name-table.yaml"
CACHE STRING "Location of the scream-specific cf name yaml table")
add_executable(query-cf-database query-cf-database.cpp)
@@ -10,5 +10,6 @@ target_compile_definitions(query-cf-database PUBLIC
CF_STANDARD_NAME_FILE=${CF_STANDARD_NAME_FILE}
CF_SCREAM_NAME_FILE=${CF_SCREAM_NAME_FILE})
+find_package (ekat HINTS ${EKAT_ROOT})
find_package (yaml-cpp HINTS ${YAML_CPP_ROOT})
target_link_libraries(query-cf-database ekat yaml-cpp)
diff --git a/components/eamxx/data/cf-scream-name-table.yaml b/components/eamxx/scripts/query-cf-database/cf-scream-name-table.yaml
similarity index 100%
rename from components/eamxx/data/cf-scream-name-table.yaml
rename to components/eamxx/scripts/query-cf-database/cf-scream-name-table.yaml
diff --git a/components/eamxx/data/cf-standard-name-table.yaml b/components/eamxx/scripts/query-cf-database/cf-standard-name-table.yaml
similarity index 100%
rename from components/eamxx/data/cf-standard-name-table.yaml
rename to components/eamxx/scripts/query-cf-database/cf-standard-name-table.yaml
diff --git a/components/eamxx/scripts/cf-xml-to-yaml b/components/eamxx/scripts/query-cf-database/cf-xml-to-yaml
similarity index 100%
rename from components/eamxx/scripts/cf-xml-to-yaml
rename to components/eamxx/scripts/query-cf-database/cf-xml-to-yaml
diff --git a/components/eamxx/scripts/query-cf-database.cpp b/components/eamxx/scripts/query-cf-database/query-cf-database.cpp
similarity index 100%
rename from components/eamxx/scripts/query-cf-database.cpp
rename to components/eamxx/scripts/query-cf-database/query-cf-database.cpp
diff --git a/components/eamxx/scripts/scripts-tests b/components/eamxx/scripts/scripts-tests
index e83ce9308ae..67416b23d2b 100755
--- a/components/eamxx/scripts/scripts-tests
+++ b/components/eamxx/scripts/scripts-tests
@@ -292,12 +292,13 @@ class TestTestAllScream(TestBaseOuter.TestBase):
self._machine)
run_cmd_assert_result(self, cmd, from_dir=TEST_DIR)
builddir = "compute_sanitizer_memcheck" if self._machine.gpu_arch=="cuda" else "valgrind"
- test_cmake_cache_contents(self, builddir, "CMAKE_BUILD_TYPE", "Debug")
test_cmake_cache_contents(self, builddir, "SCREAM_TEST_SIZE", "SHORT")
if self._machine.gpu_arch=="cuda":
+ test_cmake_cache_contents(self, builddir, "CMAKE_BUILD_TYPE", "Debug")
test_cmake_cache_contents(self, builddir, "EKAT_ENABLE_COMPUTE_SANITIZER", "TRUE")
test_cmake_cache_contents(self, builddir, "EKAT_COMPUTE_SANITIZER_OPTIONS", "--tool=memcheck")
else:
+ test_cmake_cache_contents(self, builddir, "CMAKE_BUILD_TYPE", "RelWithDebInfo")
test_cmake_cache_contents(self, builddir, "EKAT_ENABLE_VALGRIND", "TRUE")
else:
self.skipTest("Skipping config-only run for jenkins test")
diff --git a/components/eamxx/scripts/test_factory.py b/components/eamxx/scripts/test_factory.py
index a4d7bceea82..47ae4736721 100644
--- a/components/eamxx/scripts/test_factory.py
+++ b/components/eamxx/scripts/test_factory.py
@@ -153,8 +153,11 @@ def __init__(self, tas):
TestProperty.__init__(
self,
"valgrind",
- "debug with valgrind",
- [("CMAKE_BUILD_TYPE", "Debug"), ("EKAT_ENABLE_VALGRIND", "True")],
+ "Release build where tests run through valgrind",
+ [("CMAKE_BUILD_TYPE", "RelWithDebInfo"),
+ ("EKAT_ENABLE_VALGRIND", "True"),
+ ("SCREAM_PACK_SIZE", "1"),
+ ("SCREAM_TEST_MAX_THREADS", "2")],
uses_baselines=False,
on_by_default=False,
default_test_len="short"
diff --git a/components/eamxx/src/control/atmosphere_driver.cpp b/components/eamxx/src/control/atmosphere_driver.cpp
index 0f1cb1e31ab..23da9630b27 100644
--- a/components/eamxx/src/control/atmosphere_driver.cpp
+++ b/components/eamxx/src/control/atmosphere_driver.cpp
@@ -4,6 +4,7 @@
#include "physics/share/physics_constants.hpp"
+#include "share/scream_config.hpp"
#include "share/atm_process/atmosphere_process_group.hpp"
#include "share/atm_process/atmosphere_process_dag.hpp"
#include "share/field/field_utils.hpp"
@@ -180,24 +181,24 @@ init_time_stamps (const util::TimeStamp& run_t0, const util::TimeStamp& case_t0,
}
void AtmosphereDriver::
-setup_iop ()
+setup_iop_data_manager ()
{
// At this point, must have comm, params, initialized timestamps created.
check_ad_status(s_comm_set | s_params_set | s_ts_inited);
// Check to make sure iop is not already initialized
- EKAT_REQUIRE_MSG(not m_iop, "Error! setup_iop() is called, but IOP already set up.\n");
+ EKAT_REQUIRE_MSG(not m_iop_data_manager, "Error! setup_iop_data_manager() is called, but IOP already set up.\n");
// This function should only be called if we are enabling IOP
const bool enable_iop =
m_atm_params.sublist("driver_options").get("enable_iop", false);
- EKAT_REQUIRE_MSG(enable_iop, "Error! setup_iop() is called, but enable_iop=false "
+ EKAT_REQUIRE_MSG(enable_iop, "Error! setup_iop_data_manager() is called, but enable_iop=false "
"in driver_options parameters.\n");
// Params must include iop_options sublist.
const auto iop_sublist_exists = m_atm_params.isSublist("iop_options");
EKAT_REQUIRE_MSG(iop_sublist_exists,
- "Error! setup_iop() is called, but no iop_options "
+ "Error! setup_iop_data_manager() is called, but no iop_options "
"defined in parameters.\n");
const auto iop_params = m_atm_params.sublist("iop_options");
@@ -206,15 +207,15 @@ setup_iop ()
const auto hyam = phys_grid->get_geometry_data("hyam");
const auto hybm = phys_grid->get_geometry_data("hybm");
- m_iop = std::make_shared(m_atm_comm,
- iop_params,
- m_run_t0,
- nlevs,
- hyam,
- hybm);
+ m_iop_data_manager = std::make_shared(m_atm_comm,
+ iop_params,
+ m_run_t0,
+ nlevs,
+ hyam,
+ hybm);
// Set IOP object in atm processes
- m_atm_process_group->set_iop(m_iop);
+ m_atm_process_group->set_iop_data_manager(m_iop_data_manager);
}
void AtmosphereDriver::create_atm_processes()
@@ -295,7 +296,7 @@ void AtmosphereDriver::create_grids()
const bool enable_iop =
m_atm_params.sublist("driver_options").get("enable_iop", false);
if (enable_iop) {
- setup_iop ();
+ setup_iop_data_manager ();
}
// Set the grids in the processes. Do this by passing the grids manager.
@@ -685,8 +686,68 @@ void AtmosphereDriver::create_fields()
fm->add_to_group(fid.name(),"RESTART");
}
+ auto& driver_options_pl = m_atm_params.sublist("driver_options");
+ const int verb_lvl = driver_options_pl.get("atmosphere_dag_verbosity_level",-1);
+ if (verb_lvl>0) {
+ // now that we've got fields, generate a DAG with fields and dependencies
+ // NOTE: at this point, fields provided by initial conditions may (will)
+ // appear as unmet dependencies
+ AtmProcDAG dag;
+ // First, add all atm processes
+ dag.create_dag(*m_atm_process_group);
+ // Write a dot file for visualizing the DAG
+ if (m_atm_comm.am_i_root()) {
+ std::string filename = "scream_atm_createField_dag";
+ if (is_scream_standalone()) {
+ filename += ".np" + std::to_string(m_atm_comm.size());
+ }
+ filename += ".dot";
+ dag.write_dag(filename, verb_lvl);
+ }
+ }
+
m_ad_status |= s_fields_created;
+ // If the user requested it, we can save a dictionary of the FM fields to file
+ if (driver_options_pl.get("save_field_manager_content",false)) {
+ auto pg = m_grids_manager->get_grid("Physics");
+ const auto& fm = m_field_mgrs.at(pg->name());
+ ekat::ParameterList pl_out("field_manager_content");
+ pl_out.sublist("provenance") = m_atm_params.sublist("provenance");
+ DefaultMetadata std_names;
+ std::string desc;
+ desc = "content of the EAMxx FieldManager corresponding to the 'Physics' grid.\n"
+ "The dict keys are the field names as used in EAMxx.\n"
+ "For each field, we add the following entries:\n"
+ " - standard_name: the name commonly used to refer to this field in atm sciences (if applicable)\n"
+ " - units: the units for this field used in EAMxx\n"
+ " - layout: the names of the dimensions for this field (time excluded)\n"
+ " - providers: the atm processes that update/compute this field\n"
+ " - customers: the atm processes that require this field as an input\n";
+ pl_out.set("description", desc);
+ auto& dict = pl_out.sublist("fields");
+ for (const auto& it : *fm) {
+ const auto& fid = it.second->get_header().get_identifier();
+ auto& pl = dict.sublist(fid.name());
+
+ pl.set("units",fid.get_units().to_string());
+ pl.set("layout",fid.get_layout().names());
+ pl.set("standard_name",std_names.get_standardname(fid.name()));
+ std::vector providers,customers;
+ const auto& track = it.second->get_header().get_tracking();
+ for (auto ap : track.get_providers()) {
+ providers.push_back(ap.lock()->name());
+ }
+ for (auto ap : track.get_customers()) {
+ customers.push_back(ap.lock()->name());
+ }
+ pl.set("providers",providers);
+ pl.set("customers",customers);
+ }
+
+ ekat::write_yaml_file("eamxx_field_manager_content.yaml",pl_out);
+ }
+
stop_timer("EAMxx::create_fields");
stop_timer("EAMxx::init");
m_atm_logger->info("[EAMxx] create_fields ... done!");
@@ -861,28 +922,6 @@ initialize_fields ()
TraceGasesWorkaround::singleton().run_type = m_run_type;
}
- // See if we need to print a DAG. We do this first, cause if any input
- // field is missing from the initial condition file, an error will be thrown.
- // By printing the DAG first, we give the user the possibility of seeing
- // what fields are inputs to the atm time step, so he/she can fix the i.c. file.
- // TODO: would be nice to do the IC input first, and mark the fields in the
- // DAG node "Begin of atm time step" in red if there's no initialization
- // mechanism set for them. That is, allow field XYZ to not be found in
- // the IC file, and throw an error when the dag is created.
-
- auto& driver_options_pl = m_atm_params.sublist("driver_options");
- const int verb_lvl = driver_options_pl.get("atmosphere_dag_verbosity_level",-1);
- if (verb_lvl>0) {
- // Check the atm DAG for missing stuff
- AtmProcDAG dag;
-
- // First, add all atm processes
- dag.create_dag(*m_atm_process_group);
-
- // Write a dot file for visualization
- dag.write_dag("scream_atm_dag.dot",std::max(verb_lvl,0));
- }
-
// Initialize fields
if (m_run_type==RunType::Restart) {
restart_model ();
@@ -1060,7 +1099,6 @@ void AtmosphereDriver::set_initial_conditions ()
// Check which fields need to have an initial condition.
std::map> ic_fields_names;
std::vector ic_fields_to_copy;
- std::map> fields_inited;
// Check which fields should be loaded from the topography file
std::map> topography_file_fields_names;
@@ -1089,7 +1127,7 @@ void AtmosphereDriver::set_initial_conditions ()
EKAT_ERROR_MSG ("ERROR: invalid assignment for variable " + fname + ", only scalar "
"double or string, or vector double arguments are allowed");
}
- fields_inited[grid_name].push_back(fname);
+ m_fields_inited[grid_name].push_back(fname);
} else if (fname == "phis" or fname == "sgh30") {
// Both phis and sgh30 need to be loaded from the topography file
auto& this_grid_topo_file_fnames = topography_file_fields_names[grid_name];
@@ -1105,7 +1143,7 @@ void AtmosphereDriver::set_initial_conditions ()
grid_name == "Point Grid") {
this_grid_topo_file_fnames.push_back("PHIS_d");
this_grid_topo_eamxx_fnames.push_back(fname);
- fields_inited[grid_name].push_back(fname);
+ m_fields_inited[grid_name].push_back(fname);
} else {
EKAT_ERROR_MSG ("Error! Requesting phis on an unknown grid: " + grid_name + ".\n");
}
@@ -1117,7 +1155,7 @@ void AtmosphereDriver::set_initial_conditions ()
" topo file only has sgh30 for Physics PG2.\n");
topography_file_fields_names[grid_name].push_back("SGH30");
topography_eamxx_fields_names[grid_name].push_back(fname);
- fields_inited[grid_name].push_back(fname);
+ m_fields_inited[grid_name].push_back(fname);
}
} else if (not (fvphyshack and grid_name == "Physics PG2")) {
// The IC file is written for the GLL grid, so we only load
@@ -1129,7 +1167,7 @@ void AtmosphereDriver::set_initial_conditions ()
// If this field is the parent of other subfields, we only read from file the subfields.
if (not ekat::contains(this_grid_ic_fnames,fname)) {
this_grid_ic_fnames.push_back(fname);
- fields_inited[grid_name].push_back(fname);
+ m_fields_inited[grid_name].push_back(fname);
}
} else if (fvphyshack and grid_name == "Physics GLL") {
// [CGLL ICs in pg2] I tried doing something like this in
@@ -1146,7 +1184,7 @@ void AtmosphereDriver::set_initial_conditions ()
} else {
this_grid_ic_fnames.push_back(fname);
}
- fields_inited[grid_name].push_back(fname);
+ m_fields_inited[grid_name].push_back(fname);
}
}
}
@@ -1192,7 +1230,7 @@ void AtmosphereDriver::set_initial_conditions ()
auto p = f.get_header().get_parent().lock();
if (p) {
const auto& pname = p->get_identifier().name();
- if (ekat::contains(fields_inited[grid_name],pname)) {
+ if (ekat::contains(m_fields_inited[grid_name],pname)) {
// The parent is already inited. No need to init this field as well.
names.erase(it2);
run_again = true;
@@ -1203,7 +1241,7 @@ void AtmosphereDriver::set_initial_conditions ()
}
}
- if (m_iop) {
+ if (m_iop_data_manager) {
// For runs with IOP, call to setup io grids and lat
// lon information needed for reading from file
// We use a single topo file for both GLL and PG2 runs. All
@@ -1213,13 +1251,13 @@ void AtmosphereDriver::set_initial_conditions ()
for (const auto& it : m_field_mgrs) {
const auto& grid_name = it.first;
if (ic_fields_names[grid_name].size() > 0 or
- topography_eamxx_fields_names[grid_name].size() > 0) {
+ topography_eamxx_fields_names[grid_name].size() > 0) {
const auto& file_name = grid_name == "Physics GLL"
?
ic_pl.get("Filename")
:
ic_pl.get("topography_filename");
- m_iop->setup_io_info(file_name, it.second->get_grid());
+ m_iop_data_manager->setup_io_info(file_name, it.second->get_grid());
}
}
}
@@ -1231,12 +1269,12 @@ void AtmosphereDriver::set_initial_conditions ()
m_atm_logger->info(" [EAMxx] IC filename: " + file_name);
for (const auto& it : m_field_mgrs) {
const auto& grid_name = it.first;
- if (not m_iop) {
+ if (not m_iop_data_manager) {
read_fields_from_file (ic_fields_names[grid_name],it.second->get_grid(),file_name,m_current_ts);
} else {
// For IOP enabled, we load from file and copy data from the closest
// lat/lon column to every other column
- m_iop->read_fields_from_file_for_iop(file_name,
+ m_iop_data_manager->read_fields_from_file_for_iop(file_name,
ic_fields_names[grid_name],
m_current_ts,
it.second);
@@ -1306,7 +1344,7 @@ void AtmosphereDriver::set_initial_conditions ()
m_atm_logger->info(" filename: " + file_name);
for (const auto& it : m_field_mgrs) {
const auto& grid_name = it.first;
- if (not m_iop) {
+ if (not m_iop_data_manager) {
// Topography files always use "ncol_d" for the GLL grid value of ncol.
// To ensure we read in the correct value, we must change the name for that dimension
auto io_grid = it.second->get_grid();
@@ -1322,7 +1360,7 @@ void AtmosphereDriver::set_initial_conditions ()
} else {
// For IOP enabled, we load from file and copy data from the closest
// lat/lon column to every other column
- m_iop->read_fields_from_file_for_iop(file_name,
+ m_iop_data_manager->read_fields_from_file_for_iop(file_name,
topography_file_fields_names[grid_name],
topography_eamxx_fields_names[grid_name],
m_current_ts,
@@ -1347,16 +1385,16 @@ void AtmosphereDriver::set_initial_conditions ()
m_atm_params.sublist("provenance").set("topography_file","NONE");
}
- if (m_iop) {
+ if (m_iop_data_manager) {
// Load IOP data file data for initial time stamp
- m_iop->read_iop_file_data(m_current_ts);
+ m_iop_data_manager->read_iop_file_data(m_current_ts);
// Now that ICs are processed, set appropriate fields using IOP file data.
// Since ICs are loaded on GLL grid, we set those fields only and dynamics
// will take care of the rest (for PG2 case).
if (m_field_mgrs.count("Physics GLL") > 0) {
const auto& fm = m_field_mgrs.at("Physics GLL");
- m_iop->set_fields_from_iop_data(fm);
+ m_iop_data_manager->set_fields_from_iop_data(fm);
}
}
@@ -1415,7 +1453,7 @@ void AtmosphereDriver::set_initial_conditions ()
// Loop through fields and apply perturbation.
for (size_t f=0; fget_grid()->name()], fname),
+ EKAT_REQUIRE_MSG(ekat::contains(m_fields_inited[fm->get_grid()->name()], fname),
"Error! Attempting to apply perturbation to field not in initial_conditions.\n"
" - Field: "+fname+"\n"
" - Grid: "+fm->get_grid()->name()+"\n");
@@ -1614,6 +1652,28 @@ void AtmosphereDriver::initialize_atm_procs ()
m_atm_logger->info("[EAMxx] initialize_atm_procs ... done!");
report_res_dep_memory_footprint ();
+
+ auto& driver_options_pl = m_atm_params.sublist("driver_options");
+ const int verb_lvl = driver_options_pl.get("atmosphere_dag_verbosity_level",-1);
+ if (verb_lvl>0) {
+ // now that we've got fields, generate a DAG with fields and dependencies
+ // NOTE: at this point, fields provided by initial conditions may (will)
+ // appear as unmet dependencies
+ AtmProcDAG dag;
+ // First, add all atm processes
+ dag.create_dag(*m_atm_process_group);
+ // process the initial conditions to maybe fulfill unmet dependencies
+ dag.process_initial_conditions(m_fields_inited);
+ // Write a dot file for visualizing the DAG
+ if (m_atm_comm.am_i_root()) {
+ std::string filename = "scream_atm_initProc_dag";
+ if (is_scream_standalone()) {
+ filename += ".np" + std::to_string(m_atm_comm.size());
+ }
+ filename += ".dot";
+ dag.write_dag(filename, verb_lvl);
+ }
+ }
}
void AtmosphereDriver::
@@ -1754,7 +1814,7 @@ void AtmosphereDriver::finalize ( /* inputs? */ ) {
}
// Destroy iop
- m_iop = nullptr;
+ m_iop_data_manager = nullptr;
// Destroy the buffer manager
m_memory_buffer = nullptr;
diff --git a/components/eamxx/src/control/atmosphere_driver.hpp b/components/eamxx/src/control/atmosphere_driver.hpp
index a3acfba5d94..408b82437e4 100644
--- a/components/eamxx/src/control/atmosphere_driver.hpp
+++ b/components/eamxx/src/control/atmosphere_driver.hpp
@@ -2,7 +2,6 @@
#define SCREAM_ATMOSPHERE_DRIVER_HPP
#include "control/surface_coupling_utils.hpp"
-#include "share/iop/intensive_observation_period.hpp"
#include "share/field/field_manager.hpp"
#include "share/grid/grids_manager.hpp"
#include "share/util/scream_time_stamp.hpp"
@@ -11,6 +10,7 @@
#include "share/io/scorpio_input.hpp"
#include "share/atm_process/ATMBufferManager.hpp"
#include "share/atm_process/SCDataManager.hpp"
+#include "share/atm_process/IOPDataManager.hpp"
#include "ekat/logging/ekat_logger.hpp"
#include "ekat/mpi/ekat_comm.hpp"
@@ -72,8 +72,8 @@ class AtmosphereDriver
// Set AD params
void init_scorpio (const int atm_id = 0);
- // Setup IntensiveObservationPeriod
- void setup_iop ();
+ // Setup IOPDataManager
+ void setup_iop_data_manager ();
// Create atm processes, without initializing them
void create_atm_processes ();
@@ -217,7 +217,7 @@ class AtmosphereDriver
std::shared_ptr m_surface_coupling_import_data_manager;
std::shared_ptr m_surface_coupling_export_data_manager;
- std::shared_ptr m_iop;
+ std::shared_ptr m_iop_data_manager;
// This is the time stamp at the beginning of the time step.
util::TimeStamp m_current_ts;
@@ -264,6 +264,8 @@ class AtmosphereDriver
// Current simulation casename
std::string m_casename;
+ // maps grid name to a vector of its initialized fields
+ std::map> m_fields_inited;
};
} // namespace control
diff --git a/components/eamxx/src/control/atmosphere_surface_coupling_exporter.hpp b/components/eamxx/src/control/atmosphere_surface_coupling_exporter.hpp
index ca7772fdf1b..6471974bebb 100644
--- a/components/eamxx/src/control/atmosphere_surface_coupling_exporter.hpp
+++ b/components/eamxx/src/control/atmosphere_surface_coupling_exporter.hpp
@@ -23,7 +23,7 @@ namespace scream
*/
// enum to track how exported fields will be set.
-enum ExportType {
+enum ExportType:int {
FROM_MODEL = 0, // Variable will be derived from atmosphere model state
FROM_FILE = 1, // Variable will be set given data from a file
CONSTANT = 2 // Set variable to a constant value
diff --git a/components/eamxx/src/control/atmosphere_surface_coupling_importer.cpp b/components/eamxx/src/control/atmosphere_surface_coupling_importer.cpp
index 2c3360a3b4f..385e57cae55 100644
--- a/components/eamxx/src/control/atmosphere_surface_coupling_importer.cpp
+++ b/components/eamxx/src/control/atmosphere_surface_coupling_importer.cpp
@@ -208,8 +208,8 @@ void SurfaceCouplingImporter::do_import(const bool called_during_initialization)
});
#endif
- if (m_iop) {
- if (m_iop->get_params().get("iop_srf_prop")) {
+ if (m_iop_data_manager) {
+ if (m_iop_data_manager->get_params().get("iop_srf_prop")) {
// Overwrite imports with data from IOP file
overwrite_iop_imports(called_during_initialization);
}
@@ -221,9 +221,12 @@ void SurfaceCouplingImporter::overwrite_iop_imports (const bool called_during_in
using policy_type = KokkosTypes::RangePolicy;
using C = physics::Constants;
- const auto has_lhflx = m_iop->has_iop_field("lhflx");
- const auto has_shflx = m_iop->has_iop_field("shflx");
- const auto has_Tg = m_iop->has_iop_field("Tg");
+ const auto has_lhflx = m_iop_data_manager->has_iop_field("lhflx");
+ const auto has_shflx = m_iop_data_manager->has_iop_field("shflx");
+ const auto has_Tg = m_iop_data_manager->has_iop_field("Tg");
+
+ // Read IOP file for current time step, if necessary
+ m_iop_data_manager->read_iop_file_data(timestamp());
static constexpr Real latvap = C::LatVap;
static constexpr Real stebol = C::stebol;
@@ -243,19 +246,19 @@ void SurfaceCouplingImporter::overwrite_iop_imports (const bool called_during_in
// Store IOP surf data into col_val
Real col_val(std::nan(""));
if (fname == "surf_evap" && has_lhflx) {
- const auto f = m_iop->get_iop_field("lhflx");
+ const auto f = m_iop_data_manager->get_iop_field("lhflx");
f.sync_to_host();
col_val = f.get_view()()/latvap;
} else if (fname == "surf_sens_flux" && has_shflx) {
- const auto f = m_iop->get_iop_field("shflx");
+ const auto f = m_iop_data_manager->get_iop_field("shflx");
f.sync_to_host();
col_val = f.get_view()();
} else if (fname == "surf_radiative_T" && has_Tg) {
- const auto f = m_iop->get_iop_field("Tg");
+ const auto f = m_iop_data_manager->get_iop_field("Tg");
f.sync_to_host();
col_val = f.get_view()();
} else if (fname == "surf_lw_flux_up" && has_Tg) {
- const auto f = m_iop->get_iop_field("Tg");
+ const auto f = m_iop_data_manager->get_iop_field("Tg");
f.sync_to_host();
col_val = stebol*std::pow(f.get_view()(), 4);
} else {
diff --git a/components/eamxx/src/diagnostics/CMakeLists.txt b/components/eamxx/src/diagnostics/CMakeLists.txt
index be51f434615..0795f9e5469 100644
--- a/components/eamxx/src/diagnostics/CMakeLists.txt
+++ b/components/eamxx/src/diagnostics/CMakeLists.txt
@@ -1,11 +1,16 @@
set(DIAGNOSTIC_SRCS
+ aerocom_cld.cpp
+ aodvis.cpp
+ atm_backtend.cpp
atm_density.cpp
dry_static_energy.cpp
exner.cpp
field_at_height.cpp
field_at_level.cpp
field_at_pressure_level.cpp
+ horiz_avg.cpp
longwave_cloud_forcing.cpp
+ number_path.cpp
potential_temperature.cpp
precip_surf_mass_flux.cpp
relative_humidity.cpp
@@ -17,15 +22,11 @@ set(DIAGNOSTIC_SRCS
virtual_temperature.cpp
water_path.cpp
wind_speed.cpp
- aodvis.cpp
- number_path.cpp
- aerocom_cld.cpp
- atm_backtend.cpp
)
add_library(diagnostics ${DIAGNOSTIC_SRCS})
target_link_libraries(diagnostics PUBLIC scream_share)
-if (NOT SCREAM_LIB_ONLY)
+if (NOT SCREAM_LIB_ONLY AND NOT SCREAM_ONLY_GENERATE_BASELINES)
add_subdirectory(tests)
endif()
diff --git a/components/eamxx/src/diagnostics/aerocom_cld.cpp b/components/eamxx/src/diagnostics/aerocom_cld.cpp
index 8606e065b9e..cca55f6c19f 100644
--- a/components/eamxx/src/diagnostics/aerocom_cld.cpp
+++ b/components/eamxx/src/diagnostics/aerocom_cld.cpp
@@ -22,8 +22,6 @@ AeroComCld::AeroComCld(const ekat::Comm &comm,
"to be 'Bot' or 'Top' in its input parameters.\n");
}
-std::string AeroComCld::name() const { return "AeroComCld" + m_topbot; }
-
void AeroComCld::set_grids(
const std::shared_ptr grids_manager) {
using namespace ekat::units;
@@ -76,7 +74,8 @@ void AeroComCld::set_grids(
m_dz.allocate_view();
// Construct and allocate the output field
- FieldIdentifier fid(name(), vector1d_layout, nondim, grid_name);
+
+ FieldIdentifier fid("AeroComCld"+m_topbot, vector1d_layout, nondim, grid_name);
m_diagnostic_output = Field(fid);
m_diagnostic_output.allocate_view();
diff --git a/components/eamxx/src/diagnostics/aerocom_cld.hpp b/components/eamxx/src/diagnostics/aerocom_cld.hpp
index 694eed76f09..53a9a7f8e1b 100644
--- a/components/eamxx/src/diagnostics/aerocom_cld.hpp
+++ b/components/eamxx/src/diagnostics/aerocom_cld.hpp
@@ -15,7 +15,7 @@ class AeroComCld : public AtmosphereDiagnostic {
AeroComCld(const ekat::Comm &comm, const ekat::ParameterList ¶ms);
// The name of the diagnostic
- std::string name() const override;
+ std::string name() const override { return "AeroComCld"; }
// Set the grid
void set_grids(
diff --git a/components/eamxx/src/diagnostics/field_at_height.cpp b/components/eamxx/src/diagnostics/field_at_height.cpp
index f61cd3a76c1..db780f5a79f 100644
--- a/components/eamxx/src/diagnostics/field_at_height.cpp
+++ b/components/eamxx/src/diagnostics/field_at_height.cpp
@@ -45,21 +45,16 @@ FieldAtHeight (const ekat::Comm& comm, const ekat::ParameterList& params)
" - surface reference: " + surf_ref + "\n"
" - valid options: sealevel, surface\n");
m_z_name = (surf_ref == "sealevel") ? "z" : "height";
- const auto& location = m_params.get("vertical_location");
- auto chars_start = location.find_first_not_of("0123456789.");
- EKAT_REQUIRE_MSG (chars_start!=0 && chars_start!=std::string::npos,
- "Error! Invalid string for height value for FieldAtHeight.\n"
- " - input string : " + location + "\n"
- " - expected format: Nm, with N integer\n");
- const auto z_str = location.substr(0,chars_start);
- m_z = std::stod(z_str);
-
- const auto units = location.substr(chars_start);
+
+ const auto units = m_params.get("height_units");
EKAT_REQUIRE_MSG (units=="m",
- "Error! Invalid string for height value for FieldAtHeight.\n"
- " - input string : " + location + "\n"
- " - expected format: Nm, with N integer\n");
- m_diag_name = m_field_name + "_at_" + m_params.get("vertical_location") + "_above_" + surf_ref;
+ "Error! Invalid units for FieldAtHeight.\n"
+ " - input units: " + units + "\n"
+ " - valid units: m\n");
+
+ auto z_val = m_params.get("height_value");
+ m_z = std::stod(z_val);
+ m_diag_name = m_field_name + "_at_" + z_val + units + "_above_" + surf_ref;
}
void FieldAtHeight::
@@ -89,7 +84,9 @@ initialize_impl (const RunType /*run_type*/)
EKAT_REQUIRE_MSG (layout.rank()>=2 && layout.rank()<=3,
"Error! Field rank not supported by FieldAtHeight.\n"
" - field name: " + fid.name() + "\n"
- " - field layout: " + layout.to_string() + "\n");
+ " - field layout: " + layout.to_string() + "\n"
+ "NOTE: if you requested something like 'field_horiz_avg_at_Y',\n"
+ " you can avoid this error by requesting 'fieldX_at_Y_horiz_avg' instead.\n");
const auto tag = layout.tags().back();
EKAT_REQUIRE_MSG (tag==LEV || tag==ILEV,
"Error! FieldAtHeight diagnostic expects a layout ending with 'LEV'/'ILEV' tag.\n"
diff --git a/components/eamxx/src/diagnostics/field_at_height.hpp b/components/eamxx/src/diagnostics/field_at_height.hpp
index e6198153f94..91f6ae3eb1b 100644
--- a/components/eamxx/src/diagnostics/field_at_height.hpp
+++ b/components/eamxx/src/diagnostics/field_at_height.hpp
@@ -18,7 +18,7 @@ class FieldAtHeight : public AtmosphereDiagnostic
FieldAtHeight (const ekat::Comm& comm, const ekat::ParameterList& params);
// The name of the diagnostic
- std::string name () const { return m_diag_name; }
+ std::string name () const { return "FieldAtHeight"; }
// Set the grid
void set_grids (const std::shared_ptr grids_manager);
diff --git a/components/eamxx/src/diagnostics/field_at_level.cpp b/components/eamxx/src/diagnostics/field_at_level.cpp
index 87ecf7ad910..b842429a8d6 100644
--- a/components/eamxx/src/diagnostics/field_at_level.cpp
+++ b/components/eamxx/src/diagnostics/field_at_level.cpp
@@ -30,10 +30,12 @@ initialize_impl (const RunType /*run_type*/)
using namespace ShortFieldTagsNames;
const auto& fid = f.get_header().get_identifier();
const auto& layout = fid.get_layout();
- EKAT_REQUIRE_MSG (layout.rank()>1 && layout.rank()<=6,
+ EKAT_REQUIRE_MSG (layout.rank()>=2 && layout.rank()<=6,
"Error! Field rank not supported by FieldAtLevel.\n"
" - field name: " + fid.name() + "\n"
- " - field layout: " + layout.to_string() + "\n");
+ " - field layout: " + layout.to_string() + "\n"
+ "NOTE: if you requested something like 'field_horiz_avg_at_Y',\n"
+ " you can avoid this error by requesting 'fieldX_at_Y_horiz_avg' instead.\n");
const auto tag = layout.tags().back();
EKAT_REQUIRE_MSG (tag==LEV || tag==ILEV,
"Error! FieldAtLevel diagnostic expects a layout ending with 'LEV'/'ILEV' tag.\n"
diff --git a/components/eamxx/src/diagnostics/field_at_level.hpp b/components/eamxx/src/diagnostics/field_at_level.hpp
index b63cda0a1a3..3ab9bee1557 100644
--- a/components/eamxx/src/diagnostics/field_at_level.hpp
+++ b/components/eamxx/src/diagnostics/field_at_level.hpp
@@ -21,7 +21,7 @@ class FieldAtLevel : public AtmosphereDiagnostic
FieldAtLevel (const ekat::Comm& comm, const ekat::ParameterList& params);
// The name of the diagnostic
- std::string name () const { return m_diag_name; }
+ std::string name () const { return "FieldAtLevel"; }
// Set the grid
void set_grids (const std::shared_ptr grids_manager);
diff --git a/components/eamxx/src/diagnostics/field_at_pressure_level.cpp b/components/eamxx/src/diagnostics/field_at_pressure_level.cpp
index 21c1ac78dd9..78ed921e758 100644
--- a/components/eamxx/src/diagnostics/field_at_pressure_level.cpp
+++ b/components/eamxx/src/diagnostics/field_at_pressure_level.cpp
@@ -15,30 +15,22 @@ FieldAtPressureLevel (const ekat::Comm& comm, const ekat::ParameterList& params)
{
m_field_name = m_params.get("field_name");
- // Figure out the pressure value
- const auto& location = m_params.get("vertical_location");
- auto chars_start = location.find_first_not_of("0123456789.");
- EKAT_REQUIRE_MSG (chars_start!=0 && chars_start!=std::string::npos,
- "Error! Invalid string for pressure value for FieldAtPressureLevel.\n"
- " - input string : " + location + "\n"
- " - expected format: Nxyz, with N integer, and xyz='mb', 'hPa', or 'Pa'\n");
- const auto press_str = location.substr(0,chars_start);
- m_pressure_level = std::stod(press_str);
-
- const auto units = location.substr(chars_start);
+ const auto units = m_params.get("pressure_units");
EKAT_REQUIRE_MSG (units=="mb" or units=="hPa" or units=="Pa",
- "Error! Invalid string for pressure value for FieldAtPressureLevel.\n"
- " - input string : " + location + "\n"
- " - expected format: Nxyz, with N integer, and xyz='mb', 'hPa', or 'Pa'\n");
+ "Error! Invalid units for FieldAtPressureLevel.\n"
+ " - input units: " + units + "\n"
+ " - valid units: 'mb', 'hPa', 'Pa'\n");
+
+ // Figure out the pressure value, and convert to Pa if needed
+ auto p_value = m_params.get("pressure_value");
- // Convert pressure level to Pa, the units of pressure in the simulation
if (units=="mb" || units=="hPa") {
- m_pressure_level *= 100;
+ m_pressure_level = std::stod(p_value)*100;
+ } else {
+ m_pressure_level = std::stod(p_value);
}
- m_mask_val = m_params.get("mask_value",Real(constants::DefaultFillValue::value));
-
- m_diag_name = m_field_name + "_at_" + location;
+ m_diag_name = m_field_name + "_at_" + p_value + units;
}
void FieldAtPressureLevel::
@@ -64,7 +56,9 @@ initialize_impl (const RunType /*run_type*/)
EKAT_REQUIRE_MSG (layout.rank()>=2 && layout.rank()<=3,
"Error! Field rank not supported by FieldAtPressureLevel.\n"
" - field name: " + fid.name() + "\n"
- " - field layout: " + layout.to_string() + "\n");
+ " - field layout: " + layout.to_string() + "\n"
+ "NOTE: if you requested something like 'field_horiz_avg_at_Y',\n"
+ " you can avoid this error by requesting 'fieldX_at_Y_horiz_avg' instead.\n");
const auto tag = layout.tags().back();
EKAT_REQUIRE_MSG (tag==LEV || tag==ILEV,
"Error! FieldAtPressureLevel diagnostic expects a layout ending with 'LEV'/'ILEV' tag.\n"
@@ -91,6 +85,8 @@ initialize_impl (const RunType /*run_type*/)
// Add a field representing the mask as extra data to the diagnostic field.
auto nondim = ekat::units::Units::nondimensional();
const auto& gname = fid.get_grid_name();
+ m_mask_val = m_params.get("mask_value",Real(constants::DefaultFillValue::value));
+
std::string mask_name = name() + " mask";
FieldLayout mask_layout( {COL}, {num_cols});
diff --git a/components/eamxx/src/diagnostics/field_at_pressure_level.hpp b/components/eamxx/src/diagnostics/field_at_pressure_level.hpp
index 950c0c5e2ee..58e476ec83b 100644
--- a/components/eamxx/src/diagnostics/field_at_pressure_level.hpp
+++ b/components/eamxx/src/diagnostics/field_at_pressure_level.hpp
@@ -20,7 +20,7 @@ class FieldAtPressureLevel : public AtmosphereDiagnostic
FieldAtPressureLevel (const ekat::Comm& comm, const ekat::ParameterList& params);
// The name of the diagnostic
- std::string name () const { return m_diag_name; }
+ std::string name () const { return "FieldAtPressureLevel"; }
// Set the grid
void set_grids (const std::shared_ptr grids_manager);
diff --git a/components/eamxx/src/diagnostics/horiz_avg.cpp b/components/eamxx/src/diagnostics/horiz_avg.cpp
new file mode 100644
index 00000000000..8bfe068c635
--- /dev/null
+++ b/components/eamxx/src/diagnostics/horiz_avg.cpp
@@ -0,0 +1,65 @@
+#include "diagnostics/horiz_avg.hpp"
+
+#include "share/field/field_utils.hpp"
+
+namespace scream {
+
+HorizAvgDiag::HorizAvgDiag(const ekat::Comm &comm,
+ const ekat::ParameterList ¶ms)
+ : AtmosphereDiagnostic(comm, params) {
+ const auto &fname = m_params.get("field_name");
+ m_diag_name = fname + "_horiz_avg";
+}
+
+void HorizAvgDiag::set_grids(
+ const std::shared_ptr grids_manager) {
+ const auto &fn = m_params.get("field_name");
+ const auto &gn = m_params.get("grid_name");
+ const auto g = grids_manager->get_grid("Physics");
+
+ add_field(fn, gn);
+
+ // first clone the area unscaled, we will scale it later in initialize_impl
+ m_scaled_area = g->get_geometry_data("area").clone();
+}
+
+void HorizAvgDiag::initialize_impl(const RunType /*run_type*/) {
+ using namespace ShortFieldTagsNames;
+ const auto &f = get_fields_in().front();
+ const auto &fid = f.get_header().get_identifier();
+ const auto &layout = fid.get_layout();
+
+ EKAT_REQUIRE_MSG(layout.rank() >= 1 && layout.rank() <= 3,
+ "Error! Field rank not supported by HorizAvgDiag.\n"
+ " - field name: " +
+ fid.name() +
+ "\n"
+ " - field layout: " +
+ layout.to_string() + "\n");
+ EKAT_REQUIRE_MSG(layout.tags()[0] == COL,
+ "Error! HorizAvgDiag diagnostic expects a layout starting "
+ "with the 'COL' tag.\n"
+ " - field name : " +
+ fid.name() +
+ "\n"
+ " - field layout: " +
+ layout.to_string() + "\n");
+
+ FieldIdentifier d_fid(m_diag_name, layout.clone().strip_dim(COL),
+ fid.get_units(), fid.get_grid_name());
+ m_diagnostic_output = Field(d_fid);
+ m_diagnostic_output.allocate_view();
+
+ // scale the area field
+ auto total_area = field_sum(m_scaled_area, &m_comm);
+ m_scaled_area.scale(sp(1.0) / total_area);
+}
+
+void HorizAvgDiag::compute_diagnostic_impl() {
+ const auto &f = get_fields_in().front();
+ const auto &d = m_diagnostic_output;
+ // Call the horiz_contraction impl that will take care of everything
+ horiz_contraction(d, f, m_scaled_area, &m_comm);
+}
+
+} // namespace scream
diff --git a/components/eamxx/src/diagnostics/horiz_avg.hpp b/components/eamxx/src/diagnostics/horiz_avg.hpp
new file mode 100644
index 00000000000..6ceac09103b
--- /dev/null
+++ b/components/eamxx/src/diagnostics/horiz_avg.hpp
@@ -0,0 +1,43 @@
+#ifndef EAMXX_HORIZ_AVERAGE_HPP
+#define EAMXX_HORIZ_AVERAGE_HPP
+
+#include "share/atm_process/atmosphere_diagnostic.hpp"
+
+namespace scream {
+
+/*
+ * This diagnostic will calculate the area-weighted average of a field
+ * across the COL tag dimension, producing an N-1 dimensional field
+ * that is area-weighted average of the input field.
+ */
+
+class HorizAvgDiag : public AtmosphereDiagnostic {
+ public:
+ // Constructors
+ HorizAvgDiag(const ekat::Comm &comm, const ekat::ParameterList ¶ms);
+
+ // The name of the diagnostic
+ std::string name() const { return m_diag_name; }
+
+ // Set the grid
+ void set_grids(const std::shared_ptr grids_manager);
+
+ protected:
+#ifdef KOKKOS_ENABLE_CUDA
+ public:
+#endif
+ void compute_diagnostic_impl();
+
+ protected:
+ void initialize_impl(const RunType /*run_type*/);
+
+ // Name of each field (because the diagnostic impl is generic)
+ std::string m_diag_name;
+
+ // Need area field, let's store it scaled by its norm
+ Field m_scaled_area;
+};
+
+} // namespace scream
+
+#endif // EAMXX_HORIZ_AVERAGE_HPP
diff --git a/components/eamxx/src/diagnostics/number_path.cpp b/components/eamxx/src/diagnostics/number_path.cpp
index d4df2f1bc22..70e18c6dee3 100644
--- a/components/eamxx/src/diagnostics/number_path.cpp
+++ b/components/eamxx/src/diagnostics/number_path.cpp
@@ -33,8 +33,6 @@ NumberPathDiagnostic::NumberPathDiagnostic(const ekat::Comm &comm,
}
}
-std::string NumberPathDiagnostic::name() const { return m_kind + "NumberPath"; }
-
void NumberPathDiagnostic::set_grids(
const std::shared_ptr grids_manager) {
using namespace ekat::units;
@@ -55,7 +53,7 @@ void NumberPathDiagnostic::set_grids(
add_field(m_nname, scalar3d, 1 / kg, grid_name);
// Construct and allocate the diagnostic field
- FieldIdentifier fid(name(), scalar2d, kg/(kg*m2), grid_name);
+ FieldIdentifier fid(m_kind + "NumberPath", scalar2d, kg/(kg*m2), grid_name);
m_diagnostic_output = Field(fid);
m_diagnostic_output.allocate_view();
}
diff --git a/components/eamxx/src/diagnostics/number_path.hpp b/components/eamxx/src/diagnostics/number_path.hpp
index 4888d3601f4..30b383b9452 100644
--- a/components/eamxx/src/diagnostics/number_path.hpp
+++ b/components/eamxx/src/diagnostics/number_path.hpp
@@ -16,7 +16,7 @@ class NumberPathDiagnostic : public AtmosphereDiagnostic {
const ekat::ParameterList ¶ms);
// The name of the diagnostic
- std::string name() const;
+ std::string name() const override { return "NumberPath"; }
// Set the grid
void set_grids(const std::shared_ptr grids_manager);
diff --git a/components/eamxx/src/diagnostics/potential_temperature.cpp b/components/eamxx/src/diagnostics/potential_temperature.cpp
index 67260e647f6..8cc45078de7 100644
--- a/components/eamxx/src/diagnostics/potential_temperature.cpp
+++ b/components/eamxx/src/diagnostics/potential_temperature.cpp
@@ -24,11 +24,6 @@ PotentialTemperatureDiagnostic::PotentialTemperatureDiagnostic (const ekat::Comm
}
}
-std::string PotentialTemperatureDiagnostic::name() const
-{
- return m_ptype;
-}
-
// =========================================================================================
void PotentialTemperatureDiagnostic::set_grids(const std::shared_ptr grids_manager)
{
@@ -51,7 +46,7 @@ void PotentialTemperatureDiagnostic::set_grids(const std::shared_ptr("qc", scalar3d_layout_mid, kg/kg, grid_name, ps);
// Construct and allocate the diagnostic field
- FieldIdentifier fid (name(), scalar3d_layout_mid, K, grid_name);
+ FieldIdentifier fid (m_ptype, scalar3d_layout_mid, K, grid_name);
m_diagnostic_output = Field(fid);
auto& C_ap = m_diagnostic_output.get_header().get_alloc_properties();
C_ap.request_allocation(ps);
diff --git a/components/eamxx/src/diagnostics/potential_temperature.hpp b/components/eamxx/src/diagnostics/potential_temperature.hpp
index 37fd1a30806..0ac1a1201d8 100644
--- a/components/eamxx/src/diagnostics/potential_temperature.hpp
+++ b/components/eamxx/src/diagnostics/potential_temperature.hpp
@@ -22,7 +22,7 @@ class PotentialTemperatureDiagnostic : public AtmosphereDiagnostic
PotentialTemperatureDiagnostic (const ekat::Comm& comm, const ekat::ParameterList& params);
// The name of the diagnostic
- std::string name () const;
+ std::string name () const override { return "PotentialTemperature"; }
// Set the grid
void set_grids (const std::shared_ptr grids_manager);
diff --git a/components/eamxx/src/diagnostics/precip_surf_mass_flux.cpp b/components/eamxx/src/diagnostics/precip_surf_mass_flux.cpp
index 068456f0522..329e83b6e9c 100644
--- a/components/eamxx/src/diagnostics/precip_surf_mass_flux.cpp
+++ b/components/eamxx/src/diagnostics/precip_surf_mass_flux.cpp
@@ -47,7 +47,7 @@ set_grids(const std::shared_ptr grids_manager)
}
// Construct and allocate the diagnostic field
- FieldIdentifier fid(name(), scalar2d_layout_mid, m/s, grid_name);
+ FieldIdentifier fid(m_name, scalar2d_layout_mid, m/s, grid_name);
m_diagnostic_output = Field(fid);
m_diagnostic_output.get_header().get_alloc_properties().request_allocation();
m_diagnostic_output.allocate_view();
diff --git a/components/eamxx/src/diagnostics/precip_surf_mass_flux.hpp b/components/eamxx/src/diagnostics/precip_surf_mass_flux.hpp
index 68dd1251646..6ff3458398d 100644
--- a/components/eamxx/src/diagnostics/precip_surf_mass_flux.hpp
+++ b/components/eamxx/src/diagnostics/precip_surf_mass_flux.hpp
@@ -17,7 +17,7 @@ class PrecipSurfMassFlux : public AtmosphereDiagnostic
PrecipSurfMassFlux (const ekat::Comm& comm, const ekat::ParameterList& params);
// The name of the diagnostic
- std::string name () const { return m_name; }
+ std::string name () const { return "PrecipSurfMassFlux"; }
// Set the grid
void set_grids (const std::shared_ptr grids_manager);
diff --git a/components/eamxx/src/diagnostics/register_diagnostics.hpp b/components/eamxx/src/diagnostics/register_diagnostics.hpp
index 45a04eebeb1..67119416705 100644
--- a/components/eamxx/src/diagnostics/register_diagnostics.hpp
+++ b/components/eamxx/src/diagnostics/register_diagnostics.hpp
@@ -24,6 +24,7 @@
#include "diagnostics/number_path.hpp"
#include "diagnostics/aerocom_cld.hpp"
#include "diagnostics/atm_backtend.hpp"
+#include "diagnostics/horiz_avg.hpp"
namespace scream {
@@ -36,13 +37,6 @@ inline void register_diagnostics () {
diag_factory.register_product("AtmosphereDensity",&create_atmosphere_diagnostic);
diag_factory.register_product("Exner",&create_atmosphere_diagnostic);
diag_factory.register_product("VirtualTemperature",&create_atmosphere_diagnostic);
- diag_factory.register_product("z_int",&create_atmosphere_diagnostic);
- diag_factory.register_product("z_mid",&create_atmosphere_diagnostic);
- diag_factory.register_product("geopotential_int",&create_atmosphere_diagnostic);
- diag_factory.register_product("geopotential_mid",&create_atmosphere_diagnostic);
- diag_factory.register_product("height_int",&create_atmosphere_diagnostic);
- diag_factory.register_product("height_mid",&create_atmosphere_diagnostic);
- diag_factory.register_product("dz",&create_atmosphere_diagnostic);
diag_factory.register_product("DryStaticEnergy",&create_atmosphere_diagnostic);
diag_factory.register_product("SeaLevelPressure",&create_atmosphere_diagnostic);
diag_factory.register_product("WaterPath",&create_atmosphere_diagnostic);
@@ -50,6 +44,7 @@ inline void register_diagnostics () {
diag_factory.register_product("LongwaveCloudForcing",&create_atmosphere_diagnostic);
diag_factory.register_product("RelativeHumidity",&create_atmosphere_diagnostic);
diag_factory.register_product("VaporFlux",&create_atmosphere_diagnostic);
+ diag_factory.register_product("VerticalLayer",&create_atmosphere_diagnostic);
diag_factory.register_product("precip_surf_mass_flux",&create_atmosphere_diagnostic);
diag_factory.register_product("surface_upward_latent_heat_flux",&create_atmosphere_diagnostic);
diag_factory.register_product("wind_speed",&create_atmosphere_diagnostic);
@@ -57,7 +52,9 @@ inline void register_diagnostics () {
diag_factory.register_product("NumberPath",&create_atmosphere_diagnostic);
diag_factory.register_product("AeroComCld",&create_atmosphere_diagnostic);
diag_factory.register_product("AtmBackTendDiag",&create_atmosphere_diagnostic);
+ diag_factory.register_product("HorizAvgDiag",&create_atmosphere_diagnostic);
}
} // namespace scream
+
#endif // SCREAM_REGISTER_DIAGNOSTICS_HPP
diff --git a/components/eamxx/src/diagnostics/tests/CMakeLists.txt b/components/eamxx/src/diagnostics/tests/CMakeLists.txt
index a684aa248fc..736253f9bee 100644
--- a/components/eamxx/src/diagnostics/tests/CMakeLists.txt
+++ b/components/eamxx/src/diagnostics/tests/CMakeLists.txt
@@ -1,4 +1,4 @@
-# NOTE: tests inside this if statement won't be built in a baselines-only build
+include(ScreamUtils)
function (createDiagTest test_name test_srcs)
CreateUnitTest(${test_name} "${test_srcs}"
@@ -6,72 +6,71 @@ function (createDiagTest test_name test_srcs)
LABELS diagnostics)
endfunction ()
-if (NOT SCREAM_ONLY_GENERATE_BASELINES)
- include(ScreamUtils)
+# Test extracting a single level of a field
+CreateDiagTest(field_at_level "field_at_level_tests.cpp")
- # Test extracting a single level of a field
- CreateDiagTest(field_at_level "field_at_level_tests.cpp")
+# Test interpolating a field onto a single pressure level
+CreateDiagTest(field_at_pressure_level "field_at_pressure_level_tests.cpp")
- # Test interpolating a field onto a single pressure level
- CreateDiagTest(field_at_pressure_level "field_at_pressure_level_tests.cpp")
- # Test interpolating a field at a specific height
- CreateDiagTest(field_at_height "field_at_height_tests.cpp")
+# Test interpolating a field at a specific height
+CreateDiagTest(field_at_height "field_at_height_tests.cpp")
- # Test potential temperature diagnostic
- CreateDiagTest(potential_temperature "potential_temperature_test.cpp")
+# Test potential temperature diagnostic
+CreateDiagTest(potential_temperature "potential_temperature_test.cpp")
- # Test exner diagnostic
- CreateDiagTest(exner_function "exner_test.cpp")
+# Test exner diagnostic
+CreateDiagTest(exner_function "exner_test.cpp")
- # Test virtual temperature
- CreateDiagTest(virtual_temperature "virtual_temperature_test.cpp")
+# Test virtual temperature
+CreateDiagTest(virtual_temperature "virtual_temperature_test.cpp")
- # Test atmosphere density
- CreateDiagTest(atmosphere_density "atm_density_test.cpp")
+# Test atmosphere density
+CreateDiagTest(atmosphere_density "atm_density_test.cpp")
- # Test vertical layer (dz, z_int, z_mid)
- CreateDiagTest(vertical_layer "vertical_layer_tests.cpp")
+# Test vertical layer (dz, z_int, z_mid)
+CreateDiagTest(vertical_layer "vertical_layer_tests.cpp")
- # Test dry static energy
- CreateDiagTest(dry_static_energy "dry_static_energy_test.cpp")
+# Test dry static energy
+CreateDiagTest(dry_static_energy "dry_static_energy_test.cpp")
- # Test sea level pressure
- CreateDiagTest(sea_level_pressure "sea_level_pressure_test.cpp")
+# Test sea level pressure
+CreateDiagTest(sea_level_pressure "sea_level_pressure_test.cpp")
- # Test total water path
- CreateDiagTest(water_path "water_path_tests.cpp")
+# Test total water path
+CreateDiagTest(water_path "water_path_tests.cpp")
- # Test shortwave cloud forcing
- CreateDiagTest(shortwave_cloud_forcing "shortwave_cloud_forcing_tests.cpp")
+# Test shortwave cloud forcing
+CreateDiagTest(shortwave_cloud_forcing "shortwave_cloud_forcing_tests.cpp")
- # Test longwave cloud forcing
- CreateDiagTest(longwave_cloud_forcing "longwave_cloud_forcing_tests.cpp")
+# Test longwave cloud forcing
+CreateDiagTest(longwave_cloud_forcing "longwave_cloud_forcing_tests.cpp")
- # Test Relative Humidity
- CreateDiagTest(relative_humidity "relative_humidity_tests.cpp")
+# Test Relative Humidity
+CreateDiagTest(relative_humidity "relative_humidity_tests.cpp")
- # Test Vapor Flux
- CreateDiagTest(vapor_flux "vapor_flux_tests.cpp")
+# Test Vapor Flux
+CreateDiagTest(vapor_flux "vapor_flux_tests.cpp")
- # Test precipitation mass surface flux
- CreateDiagTest(precip_surf_mass_flux "precip_surf_mass_flux_tests.cpp")
+# Test precipitation mass surface flux
+CreateDiagTest(precip_surf_mass_flux "precip_surf_mass_flux_tests.cpp")
- # Test surface latent heat flux
- CreateDiagTest(surface_upward_latent_heat_flux "surf_upward_latent_heat_flux_tests.cpp")
+# Test surface latent heat flux
+CreateDiagTest(surface_upward_latent_heat_flux "surf_upward_latent_heat_flux_tests.cpp")
- # Test wind speed diagnostic
- CreateDiagTest(wind_speed "wind_speed_tests.cpp")
+# Test wind speed diagnostic
+CreateDiagTest(wind_speed "wind_speed_tests.cpp")
- # Test AODVIS
- CreateDiagTest(aodvis "aodvis_test.cpp")
+# Test AODVIS
+CreateDiagTest(aodvis "aodvis_test.cpp")
- # Test "number" paths
- CreateDiagTest(number_paths "number_paths_tests.cpp")
+# Test "number" paths
+CreateDiagTest(number_paths "number_paths_tests.cpp")
- # Test AEROCOM_CLD
- CreateDiagTest(aerocom_cld "aerocom_cld_test.cpp")
+# Test AEROCOM_CLD
+CreateDiagTest(aerocom_cld "aerocom_cld_test.cpp")
- # Test atm_tend
- CreateDiagTest(atm_backtend "atm_backtend_test.cpp")
+# Test atm_tend
+CreateDiagTest(atm_backtend "atm_backtend_test.cpp")
-endif()
+# Test horizontal averaging
+CreateDiagTest(horiz_avg "horiz_avg_test.cpp")
diff --git a/components/eamxx/src/diagnostics/tests/field_at_height_tests.cpp b/components/eamxx/src/diagnostics/tests/field_at_height_tests.cpp
index e26d34dd1a5..6e071e4b201 100644
--- a/components/eamxx/src/diagnostics/tests/field_at_height_tests.cpp
+++ b/components/eamxx/src/diagnostics/tests/field_at_height_tests.cpp
@@ -104,12 +104,13 @@ TEST_CASE("field_at_height")
// Lambda to create and run a diag, and return output
auto run_diag = [&](const Field& f, const Field& z,
- const std::string& loc, const std::string& surf_ref) {
+ const double h, const std::string& surf_ref) {
util::TimeStamp t0 ({2022,1,1},{0,0,0});
auto& factory = AtmosphereDiagnosticFactory::instance();
ekat::ParameterList pl;
pl.set("surface_reference",surf_ref);
- pl.set("vertical_location",loc);
+ pl.set("height_value",std::to_string(h));
+ pl.set("height_units",std::string("m"));
pl.set("field_name",f.name());
pl.set("grid_name",grid->name());
auto diag = factory.create("FieldAtheight",comm,pl);
@@ -173,13 +174,12 @@ TEST_CASE("field_at_height")
// Make sure that an unsupported reference height throws an error.
print(" -> Testing throws error with unsupported reference height...\n");
{
- REQUIRE_THROWS(run_diag (s_mid,h_mid,"1m","foobar"));
+ REQUIRE_THROWS(run_diag (s_mid,h_mid,1.0,"foobar"));
}
print(" -> Testing throws error with unsupported reference height... OK\n");
// Run many times
int z_tgt;
- std::string loc;
for (std::string surf_ref : {"sealevel","surface"}) {
printf(" -> Testing for a reference height above %s...\n",surf_ref.c_str());
const auto mid_src = surf_ref == "sealevel" ? z_mid : h_mid;
@@ -197,32 +197,31 @@ TEST_CASE("field_at_height")
// Set target z-slice for testing to a random value.
z_tgt = pdf_levs(engine)+max_surf_4test;
- loc = std::to_string(z_tgt) + "m";
- printf(" -> test at height of %s.............\n",loc.c_str());
+ printf(" -> test at height of %dm............\n",z_tgt);
{
print(" -> scalar midpoint field...............\n");
- auto d = run_diag(s_mid,mid_src,loc,surf_ref);
+ auto d = run_diag(s_mid,mid_src,z_tgt,surf_ref);
f_z_tgt(inter,slope,z_tgt,mid_src,s_tgt);
REQUIRE (views_are_approx_equal(d,s_tgt,tol));
print(" -> scalar midpoint field............... OK!\n");
}
{
print(" -> scalar interface field...............\n");
- auto d = run_diag (s_int,int_src,loc,surf_ref);
+ auto d = run_diag (s_int,int_src,z_tgt,surf_ref);
f_z_tgt(inter,slope,z_tgt,int_src,s_tgt);
REQUIRE (views_are_approx_equal(d,s_tgt,tol));
print(" -> scalar interface field............... OK!\n");
}
{
print(" -> vector midpoint field...............\n");
- auto d = run_diag (v_mid,mid_src,loc,surf_ref);
+ auto d = run_diag (v_mid,mid_src,z_tgt,surf_ref);
f_z_tgt(inter,slope,z_tgt,mid_src,v_tgt);
REQUIRE (views_are_approx_equal(d,v_tgt,tol));
print(" -> vector midpoint field............... OK!\n");
}
{
print(" -> vector interface field...............\n");
- auto d = run_diag (v_int,int_src,loc,surf_ref);
+ auto d = run_diag (v_int,int_src,z_tgt,surf_ref);
f_z_tgt(inter,slope,z_tgt,int_src,v_tgt);
REQUIRE (views_are_approx_equal(d,v_tgt,tol));
print(" -> vector interface field............... OK!\n");
@@ -230,8 +229,7 @@ TEST_CASE("field_at_height")
{
print(" -> Forced fail, give incorrect location...............\n");
const int z_tgt_adj = (z_tgt+max_surf_4test)/2;
- std::string loc_err = std::to_string(z_tgt_adj) + "m";
- auto d = run_diag(s_int,int_src,loc_err,surf_ref);
+ auto d = run_diag(s_int,int_src,z_tgt_adj,surf_ref);
f_z_tgt(inter,slope,z_tgt,int_src,s_tgt);
REQUIRE (!views_are_approx_equal(d,s_tgt,tol,false));
print(" -> Forced fail, give incorrect location............... OK!\n");
@@ -243,15 +241,13 @@ TEST_CASE("field_at_height")
auto inter = pdf_y0(engine);
f_z_src(inter, slope, int_src, s_int);
z_tgt = 2*z_top;
- std::string loc = std::to_string(z_tgt) + "m";
- auto dtop = run_diag(s_int,int_src,loc,surf_ref);
+ auto dtop = run_diag(s_int,int_src,z_tgt,surf_ref);
f_z_tgt(inter,slope,z_tgt,int_src,s_tgt);
REQUIRE (views_are_approx_equal(dtop,s_tgt,tol));
print(" -> Forced extrapolation at top............... OK!\n");
print(" -> Forced extrapolation at bot...............\n");
z_tgt = 0;
- loc = std::to_string(z_tgt) + "m";
- auto dbot = run_diag(s_int,int_src,loc,surf_ref);
+ auto dbot = run_diag(s_int,int_src,z_tgt,surf_ref);
f_z_tgt(inter,slope,z_tgt,int_src,s_tgt);
REQUIRE (views_are_approx_equal(dbot,s_tgt,tol));
print(" -> Forced extrapolation at bot............... OK!\n");
diff --git a/components/eamxx/src/diagnostics/tests/field_at_pressure_level_tests.cpp b/components/eamxx/src/diagnostics/tests/field_at_pressure_level_tests.cpp
index 4e0deab1dfc..ba733980cad 100644
--- a/components/eamxx/src/diagnostics/tests/field_at_pressure_level_tests.cpp
+++ b/components/eamxx/src/diagnostics/tests/field_at_pressure_level_tests.cpp
@@ -224,7 +224,8 @@ get_test_diag(const ekat::Comm& comm, std::shared_ptr fm, st
ekat::ParameterList params;
params.set("field_name",field.name());
params.set("grid_name",fm->get_grid()->name());
- params.set("vertical_location",std::to_string(plevel) + "Pa");
+ params.set("pressure_value",std::to_string(plevel));
+ params.set("pressure_units",std::string("Pa"));
auto diag = std::make_shared(comm,params);
diag->set_grids(gm);
for (const auto& req : diag->get_required_field_requests()) {
diff --git a/components/eamxx/src/diagnostics/tests/horiz_avg_test.cpp b/components/eamxx/src/diagnostics/tests/horiz_avg_test.cpp
new file mode 100644
index 00000000000..9b9ec2022fa
--- /dev/null
+++ b/components/eamxx/src/diagnostics/tests/horiz_avg_test.cpp
@@ -0,0 +1,166 @@
+#include "catch2/catch.hpp"
+#include "diagnostics/register_diagnostics.hpp"
+#include "share/field/field_utils.hpp"
+#include "share/grid/mesh_free_grids_manager.hpp"
+#include "share/util/scream_setup_random_test.hpp"
+#include "share/util/scream_universal_constants.hpp"
+
+namespace scream {
+
+std::shared_ptr create_gm(const ekat::Comm &comm, const int ncols,
+ const int nlevs) {
+ const int num_global_cols = ncols * comm.size();
+
+ using vos_t = std::vector;
+ ekat::ParameterList gm_params;
+ gm_params.set("grids_names", vos_t{"Point Grid"});
+ auto &pl = gm_params.sublist("Point Grid");
+ pl.set("type", "point_grid");
+ pl.set("aliases", vos_t{"Physics"});
+ pl.set("number_of_global_columns", num_global_cols);
+ pl.set("number_of_vertical_levels", nlevs);
+
+ auto gm = create_mesh_free_grids_manager(comm, gm_params);
+ gm->build_grids();
+
+ return gm;
+}
+
+TEST_CASE("horiz_avg") {
+ using namespace ShortFieldTagsNames;
+ using namespace ekat::units;
+
+ // A numerical tolerance
+ auto tol = std::numeric_limits::epsilon() * 100;
+
+ // A world comm
+ ekat::Comm comm(MPI_COMM_WORLD);
+
+ // A time stamp
+ util::TimeStamp t0({2024, 1, 1}, {0, 0, 0});
+
+ // Create a grids manager - single column for these tests
+ constexpr int nlevs = 3;
+ constexpr int dim3 = 4;
+ const int ngcols = 6 * comm.size();
+
+ auto gm = create_gm(comm, ngcols, nlevs);
+ auto grid = gm->get_grid("Physics");
+
+ // Input (randomized) qc
+ FieldLayout scalar1d_layout{{COL}, {ngcols}};
+ FieldLayout scalar2d_layout{{COL, LEV}, {ngcols, nlevs}};
+ FieldLayout scalar3d_layout{{COL, CMP, LEV}, {ngcols, dim3, nlevs}};
+
+ FieldIdentifier qc1_fid("qc", scalar1d_layout, kg / kg, grid->name());
+ FieldIdentifier qc2_fid("qc", scalar2d_layout, kg / kg, grid->name());
+ FieldIdentifier qc3_fid("qc", scalar3d_layout, kg / kg, grid->name());
+
+ Field qc1(qc1_fid);
+ Field qc2(qc2_fid);
+ Field qc3(qc3_fid);
+
+ qc1.allocate_view();
+ qc2.allocate_view();
+ qc3.allocate_view();
+
+ // Construct random number generator stuff
+ using RPDF = std::uniform_real_distribution;
+ RPDF pdf(sp(0.0), sp(200.0));
+ auto engine = scream::setup_random_test();
+
+ // Construct the Diagnostics
+ std::map> diags;
+ auto &diag_factory = AtmosphereDiagnosticFactory::instance();
+ register_diagnostics();
+
+ ekat::ParameterList params;
+ REQUIRE_THROWS(diag_factory.create("HorizAvgDiag", comm,
+ params)); // No 'field_name' parameter
+
+ // Set time for qc and randomize its values
+ qc1.get_header().get_tracking().update_time_stamp(t0);
+ qc2.get_header().get_tracking().update_time_stamp(t0);
+ qc3.get_header().get_tracking().update_time_stamp(t0);
+ randomize(qc1, engine, pdf);
+ randomize(qc2, engine, pdf);
+ randomize(qc3, engine, pdf);
+
+ // Create and set up the diagnostic
+ params.set("grid_name", grid->name());
+ params.set("field_name", "qc");
+ auto diag1 = diag_factory.create("HorizAvgDiag", comm, params);
+ auto diag2 = diag_factory.create("HorizAvgDiag", comm, params);
+ auto diag3 = diag_factory.create("HorizAvgDiag", comm, params);
+ diag1->set_grids(gm);
+ diag2->set_grids(gm);
+ diag3->set_grids(gm);
+
+ // Clone the area field
+ auto area = grid->get_geometry_data("area").clone();
+
+ // Test the horiz contraction of qc1
+ // Get the diagnostic field
+ diag1->set_required_field(qc1);
+ diag1->initialize(t0, RunType::Initial);
+ diag1->compute_diagnostic();
+ auto diag1_f = diag1->get_diagnostic();
+
+ // Manual calculation
+ FieldIdentifier diag0_fid("qc_horiz_avg_manual",
+ scalar1d_layout.clone().strip_dim(COL), kg / kg,
+ grid->name());
+ Field diag0(diag0_fid);
+ diag0.allocate_view();
+
+ // calculate total area
+ Real atot = field_sum(area, &comm);
+ // scale the area field
+ area.scale(1 / atot);
+
+ // calculate weighted avg
+ horiz_contraction(diag0, qc1, area, &comm);
+ // Compare
+ REQUIRE(views_are_equal(diag1_f, diag0));
+
+ // Try other known cases
+ // Set qc1_v to 1.0 to get weighted average of 1.0
+ Real wavg = 1;
+ qc1.deep_copy(wavg);
+ diag1->compute_diagnostic();
+ auto diag1_v2_host = diag1_f.get_view();
+ REQUIRE_THAT(diag1_v2_host(),
+ Catch::Matchers::WithinRel(
+ wavg, tol)); // Catch2's floating point comparison
+
+ // other diags
+ // Set qc2_v to 5.0 to get weighted average of 5.0
+ wavg = sp(5.0);
+ qc2.deep_copy(wavg);
+ diag2->set_required_field(qc2);
+ diag2->initialize(t0, RunType::Initial);
+ diag2->compute_diagnostic();
+ auto diag2_f = diag2->get_diagnostic();
+
+ auto diag2_v_host = diag2_f.get_view();
+
+ for(int i = 0; i < nlevs; ++i) {
+ REQUIRE_THAT(diag2_v_host(i), Catch::Matchers::WithinRel(wavg, tol));
+ }
+
+ // Try a random case with qc3
+ auto qc3_v = qc3.get_view();
+ FieldIdentifier diag3_manual_fid("qc_horiz_avg_manual",
+ scalar3d_layout.clone().strip_dim(COL),
+ kg / kg, grid->name());
+ Field diag3_manual(diag3_manual_fid);
+ diag3_manual.allocate_view();
+ horiz_contraction(diag3_manual, qc3, area, &comm);
+ diag3->set_required_field(qc3);
+ diag3->initialize(t0, RunType::Initial);
+ diag3->compute_diagnostic();
+ auto diag3_f = diag3->get_diagnostic();
+ REQUIRE(views_are_equal(diag3_f, diag3_manual));
+}
+
+} // namespace scream
diff --git a/components/eamxx/src/diagnostics/tests/vertical_layer_tests.cpp b/components/eamxx/src/diagnostics/tests/vertical_layer_tests.cpp
index fe75114611d..631cb5acd8a 100644
--- a/components/eamxx/src/diagnostics/tests/vertical_layer_tests.cpp
+++ b/components/eamxx/src/diagnostics/tests/vertical_layer_tests.cpp
@@ -50,14 +50,10 @@ void run (const std::string& diag_name, const std::string& location)
// Construct the Diagnostic
ekat::ParameterList params;
- std::string name = diag_name;
- if (location=="midpoints") {
- name += "_mid";
- } else if (location=="interfaces") {
- name += "_int";
- }
- params.set("diag_name", name);
- auto diag = diag_factory.create(name,comm,params);
+
+ params.set("diag_name", diag_name);
+ params.set("vert_location",location);
+ auto diag = diag_factory.create("VerticalLayer",comm,params);
diag->set_grids(gm);
const bool needs_phis = diag_name=="z" or diag_name=="geopotential";
@@ -180,7 +176,7 @@ TEST_CASE("vertical_layer_test", "vertical_layer_test]"){
std::string msg = " -> Testing diag=dz ";
std::string dots (50-msg.size(),'.');
root_print (msg + dots + "\n");
- run("dz", "UNUSED");
+ run("dz", "midpoints");
root_print (msg + dots + " PASS!\n");
};
diff --git a/components/eamxx/src/diagnostics/vapor_flux.cpp b/components/eamxx/src/diagnostics/vapor_flux.cpp
index ce88c144301..b6577bf1205 100644
--- a/components/eamxx/src/diagnostics/vapor_flux.cpp
+++ b/components/eamxx/src/diagnostics/vapor_flux.cpp
@@ -26,11 +26,6 @@ VaporFluxDiagnostic (const ekat::Comm& comm, const ekat::ParameterList& params)
}
}
-std::string VaporFluxDiagnostic::name() const
-{
- return m_component==0 ? "ZonalVapFlux" : "MeridionalVapFlux";
-}
-
void VaporFluxDiagnostic::set_grids(const std::shared_ptr grids_manager)
{
using namespace ekat::units;
@@ -51,7 +46,8 @@ void VaporFluxDiagnostic::set_grids(const std::shared_ptr gr
add_field("horiz_winds", vector3d, m/s, grid_name);
// Construct and allocate the diagnostic field
- FieldIdentifier fid (name(), scalar2d, kg/m/s, grid_name);
+ std::string dname = m_component==0 ? "ZonalVapFlux" : "MeridionalVapFlux";
+ FieldIdentifier fid (dname, scalar2d, kg/m/s, grid_name);
m_diagnostic_output = Field(fid);
m_diagnostic_output.allocate_view();
}
diff --git a/components/eamxx/src/diagnostics/vapor_flux.hpp b/components/eamxx/src/diagnostics/vapor_flux.hpp
index 3d82fd882f8..5bacd78a9b7 100644
--- a/components/eamxx/src/diagnostics/vapor_flux.hpp
+++ b/components/eamxx/src/diagnostics/vapor_flux.hpp
@@ -17,7 +17,7 @@ class VaporFluxDiagnostic : public AtmosphereDiagnostic
VaporFluxDiagnostic (const ekat::Comm& comm, const ekat::ParameterList& params);
// The name of the diagnostic
- std::string name () const;
+ std::string name () const override { return "VaporFlux"; }
// Set the grid
void set_grids (const std::shared_ptr grids_manager);
diff --git a/components/eamxx/src/diagnostics/vertical_layer.cpp b/components/eamxx/src/diagnostics/vertical_layer.cpp
index 32d870da03c..f9ff526dfcd 100644
--- a/components/eamxx/src/diagnostics/vertical_layer.cpp
+++ b/components/eamxx/src/diagnostics/vertical_layer.cpp
@@ -13,25 +13,27 @@ VerticalLayerDiagnostic (const ekat::Comm& comm, const ekat::ParameterList& para
: AtmosphereDiagnostic(comm,params)
{
m_diag_name = params.get("diag_name");
- std::vector supported = {
- "z_int",
- "z_mid",
- "geopotential_int",
- "geopotential_mid",
- "height_int",
- "height_mid",
- "dz"
- };
+ std::vector supported = {"z","geopotential","height","dz"};
EKAT_REQUIRE_MSG(ekat::contains(supported,m_diag_name),
"[VerticalLayerDiagnostic] Error! Invalid diag_name.\n"
" - diag_name : " + m_diag_name + "\n"
" - valid names: " + ekat::join(supported,", ") + "\n");
- m_is_interface_layout = m_diag_name.find("_int") != std::string::npos;
+ auto vert_pos = params.get("vert_location");
+ EKAT_REQUIRE_MSG (vert_pos=="mid" || vert_pos=="int" ||
+ vert_pos=="midpoints" || vert_pos=="interfaces",
+ "[VerticalLayerDiagnostic] Error! Invalid 'vert_location'.\n"
+ " - input value: " + vert_pos + "\n"
+ " - valid names: mid, midpoints, int, interfaces\n");
+ m_is_interface_layout = vert_pos=="int" || vert_pos=="interfaces";
+
+ m_geopotential = m_diag_name=="geopotential";
+ m_from_sea_level = m_diag_name=="z" or m_geopotential;
- m_geopotential = m_diag_name.substr(0,12)=="geopotential";
- m_from_sea_level = m_diag_name[0]=='z' or m_geopotential;
+ if (m_diag_name!="dz") {
+ m_diag_name += m_is_interface_layout ? "_int" : "_mid";
+ }
}
// ========================================================================================
void VerticalLayerDiagnostic::
@@ -88,7 +90,7 @@ initialize_impl (const RunType /*run_type*/)
const auto VLEV = m_is_interface_layout ? ILEV : LEV;
const auto nlevs = m_is_interface_layout ? m_num_levs+1 : m_num_levs;
FieldLayout diag_layout ({COL,VLEV},{m_num_cols,nlevs});
- FieldIdentifier fid (name(), diag_layout, m_geopotential ? m2/s2 : m, grid_name);
+ FieldIdentifier fid (m_diag_name, diag_layout, m_geopotential ? m2/s2 : m, grid_name);
m_diagnostic_output = Field(fid);
auto& diag_fap = m_diagnostic_output.get_header().get_alloc_properties();
diff --git a/components/eamxx/src/diagnostics/vertical_layer.hpp b/components/eamxx/src/diagnostics/vertical_layer.hpp
index 805fd70028f..a440bd6a8ee 100644
--- a/components/eamxx/src/diagnostics/vertical_layer.hpp
+++ b/components/eamxx/src/diagnostics/vertical_layer.hpp
@@ -24,7 +24,7 @@ class VerticalLayerDiagnostic : public AtmosphereDiagnostic
VerticalLayerDiagnostic (const ekat::Comm& comm, const ekat::ParameterList& params);
// The name of the diagnostic.
- std::string name () const { return m_diag_name; }
+ std::string name () const { return "VerticalLayer"; }
// Set the grid
void set_grids (const std::shared_ptr grids_manager);
diff --git a/components/eamxx/src/diagnostics/water_path.cpp b/components/eamxx/src/diagnostics/water_path.cpp
index 15fa5cdef38..bca771e6dab 100644
--- a/components/eamxx/src/diagnostics/water_path.cpp
+++ b/components/eamxx/src/diagnostics/water_path.cpp
@@ -32,11 +32,6 @@ WaterPathDiagnostic (const ekat::Comm& comm, const ekat::ParameterList& params)
}
}
-std::string WaterPathDiagnostic::name() const
-{
- return m_kind + "WaterPath";
-}
-
void WaterPathDiagnostic::
set_grids(const std::shared_ptr grids_manager)
{
@@ -57,7 +52,7 @@ set_grids(const std::shared_ptr grids_manager)
add_field(m_qname, scalar3d, kg/kg, grid_name);
// Construct and allocate the diagnostic field
- FieldIdentifier fid (name(), scalar2d, kg/m2, grid_name);
+ FieldIdentifier fid (m_kind + "WaterPath", scalar2d, kg/m2, grid_name);
m_diagnostic_output = Field(fid);
m_diagnostic_output.allocate_view();
}
diff --git a/components/eamxx/src/diagnostics/water_path.hpp b/components/eamxx/src/diagnostics/water_path.hpp
index 0b9515e0b42..722a51a3133 100644
--- a/components/eamxx/src/diagnostics/water_path.hpp
+++ b/components/eamxx/src/diagnostics/water_path.hpp
@@ -17,7 +17,7 @@ class WaterPathDiagnostic : public AtmosphereDiagnostic
WaterPathDiagnostic (const ekat::Comm& comm, const ekat::ParameterList& params);
// The name of the diagnostic
- std::string name () const;
+ std::string name () const override { return "WaterPath"; }
// Set the grid
void set_grids (const std::shared_ptr grids_manager);
diff --git a/components/eamxx/src/dynamics/homme/CMakeLists.txt b/components/eamxx/src/dynamics/homme/CMakeLists.txt
index b6a69a3605f..ffad3a4111f 100644
--- a/components/eamxx/src/dynamics/homme/CMakeLists.txt
+++ b/components/eamxx/src/dynamics/homme/CMakeLists.txt
@@ -23,7 +23,8 @@ set(BUILD_HOMME_PREQX_KOKKOS OFF CACHE BOOL "")
set(BUILD_HOMME_PESE OFF CACHE BOOL "")
set(BUILD_HOMME_SWIM OFF CACHE BOOL "")
set(BUILD_HOMME_PRIM OFF CACHE BOOL "")
-set(HOMME_ENABLE_COMPOSE ON CACHE BOOL "")
+#set(HOMME_ENABLE_COMPOSE ON CACHE BOOL "")
+set(HOMME_ENABLE_COMPOSE OFF CACHE BOOL "")
set(BUILD_HOMME_TOOL OFF CACHE BOOL "")
if (NOT Kokkos_ENABLE_SERIAL)
@@ -146,7 +147,6 @@ macro (CreateDynamicsLib HOMME_TARGET NP PLEV QSIZE)
${SCREAM_DYNAMICS_SRC_DIR}/eamxx_homme_process_interface.cpp
${SCREAM_DYNAMICS_SRC_DIR}/eamxx_homme_fv_phys.cpp
${SCREAM_DYNAMICS_SRC_DIR}/eamxx_homme_rayleigh_friction.cpp
- ${SCREAM_DYNAMICS_SRC_DIR}/eamxx_homme_iop.cpp
${SCREAM_DYNAMICS_SRC_DIR}/physics_dynamics_remapper.cpp
${SCREAM_DYNAMICS_SRC_DIR}/homme_grids_manager.cpp
${SCREAM_DYNAMICS_SRC_DIR}/interface/homme_context_mod.F90
diff --git a/components/eamxx/src/dynamics/homme/eamxx_homme_iop.cpp b/components/eamxx/src/dynamics/homme/eamxx_homme_iop.cpp
deleted file mode 100644
index 9c04a3f1ba6..00000000000
--- a/components/eamxx/src/dynamics/homme/eamxx_homme_iop.cpp
+++ /dev/null
@@ -1,610 +0,0 @@
-#include "eamxx_homme_process_interface.hpp"
-
-// EAMxx includes
-#include "dynamics/homme/homme_dimensions.hpp"
-#include "dynamics/homme/homme_dynamics_helpers.hpp"
-#include "physics/share/physics_constants.hpp"
-#include "share/iop/intensive_observation_period.hpp"
-#include "share/util/scream_column_ops.hpp"
-
-// Homme includes
-#include "Context.hpp"
-#include "ColumnOps.hpp"
-#include "HommexxEnums.hpp"
-#include "HybridVCoord.hpp"
-#include "SimulationParams.hpp"
-#include "Types.hpp"
-
-// SCREAM includes
-#include "share/util/scream_common_physics_functions.hpp"
-
-// EKAT includes
-#include "ekat/ekat_workspace.hpp"
-#include "ekat/kokkos/ekat_kokkos_types.hpp"
-
-namespace scream {
-
-// Compute effects of large scale subsidence on T, q, u, and v.
-KOKKOS_FUNCTION
-void HommeDynamics::
-advance_iop_subsidence(const KT::MemberType& team,
- const int nlevs,
- const Real dt,
- const Real ps,
- const view_1d& pmid,
- const view_1d& pint,
- const view_1d& pdel,
- const view_1d& omega,
- const Workspace& workspace,
- const view_1d& u,
- const view_1d& v,
- const view_1d& T,
- const view_2d& Q)
-{
- using ColOps = ColumnOps;
- using C = physics::Constants;
- constexpr Real Rair = C::Rair;
- constexpr Real Cpair = C::Cpair;
-
- const auto n_q_tracers = Q.extent_int(0);
- const auto nlev_packs = ekat::npack(nlevs);
-
- // Get some temporary views from WS
- uview_1d omega_int, delta_u, delta_v, delta_T, tmp;
- workspace.take_many_contiguous_unsafe<4>({"omega_int", "delta_u", "delta_v", "delta_T"},
- {&omega_int, &delta_u, &delta_v, &delta_T});
- const auto delta_Q_slot = workspace.take_macro_block("delta_Q", n_q_tracers);
- uview_2d delta_Q(delta_Q_slot.data(), n_q_tracers, nlev_packs);
-
- auto s_pmid = ekat::scalarize(pmid);
- auto s_omega = ekat::scalarize(omega);
- auto s_delta_u = ekat::scalarize(delta_u);
- auto s_delta_v = ekat::scalarize(delta_v);
- auto s_delta_T = ekat::scalarize(delta_T);
- auto s_delta_Q = ekat::scalarize(delta_Q);
- auto s_omega_int = ekat::scalarize(omega_int);
-
- // Compute omega on the interface grid by using a weighted average in pressure
- const int pack_begin = 1/Pack::n, pack_end = (nlevs-1)/Pack::n;
- Kokkos::parallel_for(Kokkos::TeamVectorRange(team, pack_begin, pack_end+1), [&] (const int k){
- auto range_pack = ekat::range(k*Pack::n);
- range_pack.set(range_pack<1, 1);
- Pack pmid_k, pmid_km1, omega_k, omega_km1;
- ekat::index_and_shift<-1>(s_pmid, range_pack, pmid_k, pmid_km1);
- ekat::index_and_shift<-1>(s_omega, range_pack, omega_k, omega_km1);
-
- const auto weight = (pint(k) - pmid_km1)/(pmid_k - pmid_km1);
- omega_int(k).set(range_pack>=1 and range_pack<=nlevs-1,
- weight*omega_k + (1-weight)*omega_km1);
- });
- omega_int(0)[0] = 0;
- omega_int(nlevs/Pack::n)[nlevs%Pack::n] = 0;
-
- // Compute delta views for u, v, T, and Q (e.g., u(k+1) - u(k), k=0,...,nlevs-2)
- ColOps::compute_midpoint_delta(team, nlevs-1, u, delta_u);
- ColOps::compute_midpoint_delta(team, nlevs-1, v, delta_v);
- ColOps::compute_midpoint_delta(team, nlevs-1, T, delta_T);
- for (int iq=0; iq(k*Pack::n);
- const auto at_top = range_pack==0;
- const auto not_at_top = not at_top;
- const auto at_bot = range_pack==nlevs-1;
- const auto not_at_bot = not at_bot;
- const bool any_at_top = at_top.any();
- const bool any_at_bot = at_bot.any();
-
- // Get delta(k-1) packs. The range pack should not
- // contain index 0 (so that we don't attempt to access
- // k=-1 index) or index > nlevs-2 (since delta_* views
- // are size nlevs-1).
- auto range_pack_for_m1_shift = range_pack;
- range_pack_for_m1_shift.set(range_pack<1, 1);
- range_pack_for_m1_shift.set(range_pack>nlevs-2, nlevs-2);
- Pack delta_u_k, delta_u_km1,
- delta_v_k, delta_v_km1,
- delta_T_k, delta_T_km1;
- ekat::index_and_shift<-1>(s_delta_u, range_pack_for_m1_shift, delta_u_k, delta_u_km1);
- ekat::index_and_shift<-1>(s_delta_v, range_pack_for_m1_shift, delta_v_k, delta_v_km1);
- ekat::index_and_shift<-1>(s_delta_T, range_pack_for_m1_shift, delta_T_k, delta_T_km1);
-
- // At the top and bottom of the model, set the end points for
- // delta_*_k and delta_*_km1 to be the first and last entries
- // of delta_*, respectively.
- if (any_at_top) {
- delta_u_k.set(at_top, s_delta_u(0));
- delta_v_k.set(at_top, s_delta_v(0));
- delta_T_k.set(at_top, s_delta_T(0));
- }
- if (any_at_bot) {
- delta_u_km1.set(at_bot, s_delta_u(nlevs-2));
- delta_v_km1.set(at_bot, s_delta_v(nlevs-2));
- delta_T_km1.set(at_bot, s_delta_T(nlevs-2));
- }
-
- // Get omega_int(k+1) pack. The range pack should not
- // contain index > nlevs-1 (since omega_int is size nlevs+1).
- auto range_pack_for_p1_shift = range_pack;
- range_pack_for_p1_shift.set(range_pack>nlevs-1, nlevs-1);
- Pack omega_int_k, omega_int_kp1;
- ekat::index_and_shift<1>(s_omega_int, range_pack, omega_int_k, omega_int_kp1);
-
- const auto fac = (dt/2)/pdel(k);
-
- // Update u
- u(k).update(not_at_bot, fac*omega_int_kp1*delta_u_k, -1, 1);
- u(k).update(not_at_top, fac*omega_int_k*delta_u_km1, -1, 1);
-
- // Update v
- v(k).update(not_at_bot, fac*omega_int_kp1*delta_v_k, -1, 1);
- v(k).update(not_at_top, fac*omega_int_k*delta_v_km1, -1, 1);
-
- // Before updating T, first scale using thermal
- // expansion term due to LS vertical advection
- T(k) *= 1 + (dt*Rair/Cpair)*omega(k)/pmid(k);
-
- // Update T
- T(k).update(not_at_bot, fac*omega_int_kp1*delta_T_k, -1, 1);
- T(k).update(not_at_top, fac*omega_int_k*delta_T_km1, -1, 1);
-
- // Update Q
- Pack delta_tracer_k, delta_tracer_km1;
- for (int iq=0; iq(s_delta_tracer, range_pack_for_m1_shift, delta_tracer_k, delta_tracer_km1);
- if (any_at_top) delta_tracer_k.set(at_top, s_delta_tracer(0));
- if (any_at_bot) delta_tracer_km1.set(at_bot, s_delta_tracer(nlevs-2));
-
- Q(iq, k).update(not_at_bot, fac*omega_int_kp1*delta_tracer_k, -1, 1);
- Q(iq, k).update(not_at_top, fac*omega_int_k*delta_tracer_km1, -1, 1);
- }
- });
-
- // Release WS views
- workspace.release_macro_block(delta_Q_slot, n_q_tracers);
- workspace.release_many_contiguous<4>({&omega_int, &delta_u, &delta_v, &delta_T});
-}
-
-// Apply large scale forcing for temperature and water vapor as provided by the IOP file
-KOKKOS_FUNCTION
-void HommeDynamics::
-advance_iop_forcing(const KT::MemberType& team,
- const int nlevs,
- const Real dt,
- const view_1d& divT,
- const view_1d& divq,
- const view_1d& T,
- const view_1d& qv)
-{
- const auto nlev_packs = ekat::npack(nlevs);
- Kokkos::parallel_for(Kokkos::TeamVectorRange(team, nlev_packs), [&] (const int k) {
- T(k).update(divT(k), dt, 1.0);
- qv(k).update(divq(k), dt, 1.0);
- });
-}
-
-// Provide coriolis forcing to u and v winds, using large scale winds specified in IOP forcing file.
-KOKKOS_FUNCTION
-void HommeDynamics::
-iop_apply_coriolis(const KT::MemberType& team,
- const int nlevs,
- const Real dt,
- const Real lat,
- const view_1d& u_ls,
- const view_1d& v_ls,
- const view_1d& u,
- const view_1d& v)
-{
- using C = physics::Constants;
- constexpr Real pi = C::Pi;
- constexpr Real earth_rotation = C::omega;
-
- // Compute coriolis force
- const auto fcor = 2*earth_rotation*std::sin(lat*pi/180);
-
- const auto nlev_packs = ekat::npack(nlevs);
- Kokkos::parallel_for(Kokkos::TeamVectorRange(team, nlev_packs), [&] (const int k) {
- const auto u_cor = v(k) - v_ls(k);
- const auto v_cor = u(k) - u_ls(k);
- u(k).update(u_cor, dt*fcor, 1.0);
- v(k).update(v_cor, -dt*fcor, 1.0);
- });
-}
-
-void HommeDynamics::
-apply_iop_forcing(const Real dt)
-{
- using ESU = ekat::ExeSpaceUtils;
- using PF = PhysicsFunctions;
- using ColOps = ColumnOps;
-
- // Homme objects
- const auto& c = Homme::Context::singleton();
- const auto& hvcoord = c.get();
- const auto& params = c.get();
-
- // Dimensions
- constexpr int NGP = HOMMEXX_NP;
- constexpr int NLEV = HOMMEXX_NUM_LEV;
- constexpr int NLEVI = HOMMEXX_NUM_LEV_P;
- const auto nelem = m_dyn_grid->get_num_local_dofs()/(NGP*NGP);
- const auto total_levels = m_dyn_grid->get_num_vertical_levels();
- const auto qsize = params.qsize;
-
- // Sanity checks since we will be switching between ekat::Pack
- // and Homme::Scalar view types
- EKAT_ASSERT_MSG(NLEV == ekat::npack(total_levels),
- "Error! Dimension for vectorized Homme levels does not match level dimension "
- "of the packed views used here. Check that Pack typedef is using a pack size "
- "consistent with Homme's vector size.\n");
- EKAT_ASSERT_MSG(NLEVI == ekat::npack(total_levels+1),
- "Error! Dimension for vectorized Homme levels does not match level dimension "
- "of the packed views used here. Check that Pack typedef is using a pack size "
- "consistent with Homme's vector size.\n");
-
- // Hybrid coord values
- const auto ps0 = hvcoord.ps0;
- const auto hyam = m_dyn_grid->get_geometry_data("hyam").get_view();
- const auto hybm = m_dyn_grid->get_geometry_data("hybm").get_view();
- const auto hyai = m_dyn_grid->get_geometry_data("hyai").get_view();
- const auto hybi = m_dyn_grid->get_geometry_data("hybi").get_view();
-
- // Homme element states
- auto ps_dyn = get_internal_field("ps_dyn").get_view();
- auto dp3d_dyn = get_internal_field("dp3d_dyn").get_view();
- auto vtheta_dp_dyn = get_internal_field("vtheta_dp_dyn").get_view();
- auto phi_int_dyn = get_internal_field("phi_int_dyn").get_view();
- auto v_dyn = get_internal_field("v_dyn").get_view();
- auto Q_dyn = m_helper_fields.at("Q_dyn").get_view();
- auto Qdp_dyn = get_internal_field("Qdp_dyn").get_view();
-
- // Load data from IOP files, if necessary
- m_iop->read_iop_file_data(timestamp());
-
- // Define local IOP param values
- const auto iop_dosubsidence = m_iop->get_params().get("iop_dosubsidence");
- const auto iop_coriolis = m_iop->get_params().get("iop_coriolis");
- const auto iop_nudge_tq = m_iop->get_params().get("iop_nudge_tq");
- const auto iop_nudge_uv = m_iop->get_params().get("iop_nudge_uv");
- const auto use_large_scale_wind = m_iop->get_params().get("use_large_scale_wind");
- const auto use_3d_forcing = m_iop->get_params().get("use_3d_forcing");
- const auto lat = m_iop->get_params().get("target_latitude");
- const auto iop_nudge_tscale = m_iop->get_params().get("iop_nudge_tscale");
- const auto iop_nudge_tq_low = m_iop->get_params().get("iop_nudge_tq_low");
- const auto iop_nudge_tq_high = m_iop->get_params().get("iop_nudge_tq_high");
-
- // Define local IOP field views
- const Real ps_iop = m_iop->get_iop_field("Ps").get_view()();
- view_1d omega, divT, divq, u_ls, v_ls, qv_iop, t_iop, u_iop, v_iop;
- divT = use_3d_forcing ? m_iop->get_iop_field("divT3d").get_view()
- : m_iop->get_iop_field("divT").get_view();
- divq = use_3d_forcing ? m_iop->get_iop_field("divq3d").get_view()
- : m_iop->get_iop_field("divq").get_view();
- if (iop_dosubsidence) {
- omega = m_iop->get_iop_field("omega").get_view();
- }
- if (iop_coriolis) {
- u_ls = m_iop->get_iop_field("u_ls").get_view();
- v_ls = m_iop->get_iop_field("v_ls").get_view();
- }
- if (iop_nudge_tq) {
- qv_iop = m_iop->get_iop_field("q").get_view();
- t_iop = m_iop->get_iop_field("T").get_view();
- }
- if (iop_nudge_uv) {
- u_iop = use_large_scale_wind ? m_iop->get_iop_field("u_ls").get_view()
- : m_iop->get_iop_field("u").get_view();
- v_iop = use_large_scale_wind ? m_iop->get_iop_field("v_ls").get_view()
- : m_iop->get_iop_field("v").get_view();
- }
-
- // Team policy and workspace manager for eamxx
- const auto policy_iop = ESU::get_default_team_policy(nelem*NGP*NGP, NLEV);
-
- // TODO: Create a memory buffer for this class
- // and add the below WSM and views
- WorkspaceMgr iop_wsm(NLEVI, 7+qsize, policy_iop);
- view_Nd
- temperature("temperature", nelem, NGP, NGP, NLEV);
-
- // Lambda for computing temperature
- auto compute_temperature = [&] () {
- Kokkos::parallel_for("compute_temperature_for_iop", policy_iop, KOKKOS_LAMBDA (const KT::MemberType& team) {
- const int ie = team.league_rank()/(NGP*NGP);
- const int igp = (team.league_rank()/NGP)%NGP;
- const int jgp = team.league_rank()%NGP;
-
- // Get temp views from workspace
- auto ws = iop_wsm.get_workspace(team);
- uview_1d pmid;
- ws.take_many_contiguous_unsafe<1>({"pmid"},{&pmid});
-
- auto ps_i = ps_dyn(ie, igp, jgp);
- auto dp3d_i = ekat::subview(dp3d_dyn, ie, igp, jgp);
- auto vtheta_dp_i = ekat::subview(vtheta_dp_dyn, ie, igp, jgp);
- auto qv_i = ekat::subview(Q_dyn, ie, 0, igp, jgp);
- auto temperature_i = ekat::subview(temperature, ie, igp, jgp);
-
- // Compute reference pressures and layer thickness.
- // TODO: Allow geometry data to allocate packsize
- auto s_pmid = ekat::scalarize(pmid);
- Kokkos::parallel_for(Kokkos::TeamVectorRange(team, total_levels), [&](const int& k) {
- s_pmid(k) = hyam(k)*ps0 + hybm(k)*ps_i;
- });
- team.team_barrier();
-
- // Compute temperature from virtual potential temperature
- Kokkos::parallel_for(Kokkos::TeamVectorRange(team, NLEV), [&] (const int k) {
- auto T_val = vtheta_dp_i(k);
- T_val /= dp3d_i(k);
- T_val = PF::calculate_temperature_from_virtual_temperature(T_val,qv_i(k));
- temperature_i(k) = PF::calculate_T_from_theta(T_val,pmid(k));
- });
-
- // Release WS views
- ws.release_many_contiguous<1>({&pmid});
- });
- };
-
- // Preprocess some homme states to get temperature
- compute_temperature();
- Kokkos::fence();
-
- // Apply IOP forcing
- Kokkos::parallel_for("apply_iop_forcing", policy_iop, KOKKOS_LAMBDA (const KT::MemberType& team) {
- const int ie = team.league_rank()/(NGP*NGP);
- const int igp = (team.league_rank()/NGP)%NGP;
- const int jgp = team.league_rank()%NGP;
-
- // Get temp views from workspace
- auto ws = iop_wsm.get_workspace(team);
- uview_1d pmid, pint, pdel;
- ws.take_many_contiguous_unsafe<3>({"pmid", "pint", "pdel"},
- {&pmid, &pint, &pdel});
-
- auto ps_i = ps_dyn(ie, igp, jgp);
- auto u_i = ekat::subview(v_dyn, ie, 0, igp, jgp);
- auto v_i = ekat::subview(v_dyn, ie, 1, igp, jgp);
- auto temperature_i = ekat::subview(temperature, ie, igp, jgp);
- auto qv_i = ekat::subview(Q_dyn, ie, 0, igp, jgp);
- auto Q_i = Kokkos::subview(Q_dyn, ie, Kokkos::ALL(), igp, jgp, Kokkos::ALL());
-
- // Compute reference pressures and layer thickness.
- // TODO: Allow geometry data to allocate packsize
- auto s_pmid = ekat::scalarize(pmid);
- auto s_pint = ekat::scalarize(pint);
- Kokkos::parallel_for(Kokkos::TeamVectorRange(team, total_levels+1), [&](const int& k) {
- s_pint(k) = hyai(k)*ps0 + hybi(k)*ps_i;
- if (k < total_levels) {
- s_pmid(k) = hyam(k)*ps0 + hybm(k)*ps_i;
- }
- });
- team.team_barrier();
- ColOps::compute_midpoint_delta(team, total_levels, pint, pdel);
- team.team_barrier();
-
- if (iop_dosubsidence) {
- // Compute subsidence due to large-scale forcing
- advance_iop_subsidence(team, total_levels, dt, ps_i, pmid, pint, pdel, omega, ws, u_i, v_i, temperature_i, Q_i);
- }
-
- // Update T and qv according to large scale forcing as specified in IOP file.
- advance_iop_forcing(team, total_levels, dt, divT, divq, temperature_i, qv_i);
-
- if (iop_coriolis) {
- // Apply coriolis forcing to u and v winds
- iop_apply_coriolis(team, total_levels, dt, lat, u_ls, v_ls, u_i, v_i);
- }
-
- // Release WS views
- ws.release_many_contiguous<3>({&pmid, &pint, &pdel});
- });
- Kokkos::fence();
-
- // Postprocess homme states Qdp and vtheta_dp
- Kokkos::parallel_for("compute_qdp_and_vtheta_dp", policy_iop, KOKKOS_LAMBDA (const KT::MemberType& team) {
- const int ie = team.league_rank()/(NGP*NGP);
- const int igp = (team.league_rank()/NGP)%NGP;
- const int jgp = team.league_rank()%NGP;
-
- // Get temp views from workspace
- auto ws = iop_wsm.get_workspace(team);
- uview_1d pmid, pint, pdel;
- ws.take_many_contiguous_unsafe<3>({"pmid", "pint", "pdel"},
- {&pmid, &pint, &pdel});
-
- auto ps_i = ps_dyn(ie, igp, jgp);
- auto dp3d_i = ekat::subview(dp3d_dyn, ie, igp, jgp);
- auto vtheta_dp_i = ekat::subview(vtheta_dp_dyn, ie, igp, jgp);
- auto qv_i = ekat::subview(Q_dyn, ie, 0, igp, jgp);
- auto Q_i = Kokkos::subview(Q_dyn, ie, Kokkos::ALL(), igp, jgp, Kokkos::ALL());
- auto Qdp_i = Kokkos::subview(Qdp_dyn, ie, Kokkos::ALL(), igp, jgp, Kokkos::ALL());
- auto temperature_i = ekat::subview(temperature, ie, igp, jgp);
-
- // Compute reference pressures and layer thickness.
- // TODO: Allow geometry data to allocate packsize
- auto s_pmid = ekat::scalarize(pmid);
- auto s_pint = ekat::scalarize(pint);
- Kokkos::parallel_for(Kokkos::TeamVectorRange(team, total_levels+1), [&](const int& k) {
- s_pint(k) = hyai(k)*ps0 + hybi(k)*ps_i;
- if (k < total_levels) {
- s_pmid(k) = hyam(k)*ps0 + hybm(k)*ps_i;
- }
- });
-
- team.team_barrier();
-
- // Compute Qdp from updated Q
- Kokkos::parallel_for(Kokkos::TeamVectorRange(team, NLEV*qsize), [&] (const int k) {
- const int ilev = k/qsize;
- const int q = k%qsize;
-
- Qdp_i(q, ilev) = Q_i(q, ilev)*dp3d_i(ilev);
- // For BFB on restarts, Q needs to be updated after we compute Qdp
- Q_i(q, ilev) = Qdp_i(q, ilev)/dp3d_i(ilev);
- });
- team.team_barrier();
-
- // Convert updated temperature back to psuedo density virtual potential temperature
- Kokkos::parallel_for(Kokkos::TeamVectorRange(team, NLEV), [&] (const int k) {
- const auto th = PF::calculate_theta_from_T(temperature_i(k),pmid(k));
- vtheta_dp_i(k) = PF::calculate_virtual_temperature(th,qv_i(k))*dp3d_i(k);
- });
-
- // Release WS views
- ws.release_many_contiguous<3>({&pmid, &pint, &pdel});
- });
-
- if (iop_nudge_tq or iop_nudge_uv) {
- // Nudge the domain based on the domain mean
- // and observed quantities of T, Q, u, and
-
- if (iop_nudge_tq) {
- // Compute temperature
- compute_temperature();
- Kokkos::fence();
- }
-
- // Compute domain mean of qv, temperature, u, and v
-
- // TODO: add to local mem buffer
- view_1d qv_mean, t_mean, u_mean, v_mean;
- if (iop_nudge_tq) {
- qv_mean = view_1d("u_mean", NLEV),
- t_mean = view_1d("v_mean", NLEV);
- }
- if (iop_nudge_uv){
- u_mean = view_1d("u_mean", NLEV),
- v_mean = view_1d("v_mean", NLEV);
- }
-
- const auto qv_mean_h = Kokkos::create_mirror_view(qv_mean);
- const auto t_mean_h = Kokkos::create_mirror_view(t_mean);
- const auto u_mean_h = Kokkos::create_mirror_view(u_mean);
- const auto v_mean_h = Kokkos::create_mirror_view(v_mean);
-
- for (int k=0; kget_num_global_dofs();
- t_mean_k /= m_dyn_grid->get_num_global_dofs();
- }
- if (iop_nudge_uv){
- Real& u_mean_k = u_mean_h(k/Pack::n)[k%Pack::n];
- Real& v_mean_k = v_mean_h(k/Pack::n)[k%Pack::n];
- Kokkos::parallel_reduce("compute_domain_means_uv",
- nelem*NGP*NGP,
- KOKKOS_LAMBDA (const int idx, Real& u_sum, Real& v_sum) {
- const int ie = idx/(NGP*NGP);
- const int igp = (idx/NGP)%NGP;
- const int jgp = idx%NGP;
-
- u_sum += v_dyn(ie, 0, igp, jgp, k/Pack::n)[k%Pack::n];
- v_sum += v_dyn(ie, 1, igp, jgp, k/Pack::n)[k%Pack::n];
- },
- u_mean_k,
- v_mean_k);
-
- m_comm.all_reduce(&u_mean_k, 1, MPI_SUM);
- m_comm.all_reduce(&v_mean_k, 1, MPI_SUM);
-
- u_mean_k /= m_dyn_grid->get_num_global_dofs();
- v_mean_k /= m_dyn_grid->get_num_global_dofs();
- }
- }
- Kokkos::deep_copy(qv_mean, qv_mean_h);
- Kokkos::deep_copy(t_mean, t_mean_h);
- Kokkos::deep_copy(u_mean, u_mean_h);
- Kokkos::deep_copy(v_mean, v_mean_h);
-
- // Apply relaxation
- const auto rtau = std::max(dt, iop_nudge_tscale);
- Kokkos::parallel_for("apply_domain_relaxation",
- policy_iop,
- KOKKOS_LAMBDA (const KT::MemberType& team) {
-
- const int ie = team.league_rank()/(NGP*NGP);
- const int igp = (team.league_rank()/NGP)%NGP;
- const int jgp = team.league_rank()%NGP;
-
- // Get temp views from workspace
- auto ws = iop_wsm.get_workspace(team);
- uview_1d pmid;
- ws.take_many_contiguous_unsafe<1>({"pmid"},{&pmid});
-
- auto ps_i = ps_dyn(ie, igp, jgp);
- auto dp3d_i = ekat::subview(dp3d_dyn, ie, igp, jgp);
- auto vtheta_dp_i = ekat::subview(vtheta_dp_dyn, ie, igp, jgp);
- auto qv_i = ekat::subview(Q_dyn, ie, 0, igp, jgp);
- auto temperature_i = ekat::subview(temperature, ie, igp, jgp);
- auto u_i = ekat::subview(v_dyn, ie, 0, igp, jgp);
- auto v_i = ekat::subview(v_dyn, ie, 1, igp, jgp);
-
- // Compute reference pressures and layer thickness.
- // TODO: Allow geometry data to allocate packsize
- auto s_pmid = ekat::scalarize(pmid);
- Kokkos::parallel_for(Kokkos::TeamVectorRange(team, total_levels), [&](const int& k) {
- s_pmid(k) = hyam(k)*ps0 + hybm(k)*ps_i;
- });
- team.team_barrier();
-
- if (iop_nudge_tq or iop_nudge_uv) {
- Kokkos::parallel_for(Kokkos::TeamVectorRange(team, NLEV), [&](const int& k) {
- if (iop_nudge_tq) {
- // Restrict nudging of T and qv to certain levels if requested by user
- // IOP pressure variable is in unitis of [Pa], while iop_nudge_tq_low/high
- // is in units of [hPa], thus convert iop_nudge_tq_low/high
- Mask nudge_level(false);
- int max_size = hyam.size();
- for (int lev=k*Pack::n, p = 0; p < Pack::n && lev < max_size; ++lev, ++p) {
- const auto pressure_from_iop = hyam(lev)*ps0 + hybm(lev)*ps_iop;
- nudge_level.set(p, pressure_from_iop <= iop_nudge_tq_low*100
- and
- pressure_from_iop >= iop_nudge_tq_high*100);
- }
-
- qv_i(k).update(nudge_level, qv_mean(k) - qv_iop(k), -dt/rtau, 1.0);
- temperature_i(k).update(nudge_level, t_mean(k) - t_iop(k), -dt/rtau, 1.0);
-
- // Convert updated temperature back to virtual potential temperature
- const auto th = PF::calculate_theta_from_T(temperature_i(k),pmid(k));
- vtheta_dp_i(k) = PF::calculate_virtual_temperature(th,qv_i(k))*dp3d_i(k);
- }
- if (iop_nudge_uv) {
- u_i(k).update(u_mean(k) - u_iop(k), -dt/rtau, 1.0);
- v_i(k).update(v_mean(k) - v_iop(k), -dt/rtau, 1.0);
- }
- });
- }
-
- // Release WS views
- ws.release_many_contiguous<1>({&pmid});
- });
- }
-}
-
-} // namespace scream
diff --git a/components/eamxx/src/dynamics/homme/eamxx_homme_process_interface.cpp b/components/eamxx/src/dynamics/homme/eamxx_homme_process_interface.cpp
index 8b7495ffd73..a30418c18ee 100644
--- a/components/eamxx/src/dynamics/homme/eamxx_homme_process_interface.cpp
+++ b/components/eamxx/src/dynamics/homme/eamxx_homme_process_interface.cpp
@@ -426,11 +426,6 @@ void HommeDynamics::initialize_impl (const RunType run_type)
if (run_type==RunType::Initial) {
initialize_homme_state ();
} else {
- if (m_iop) {
- // We need to reload IOP data after restarting
- m_iop->read_iop_file_data(timestamp());
- }
-
restart_homme_state ();
}
@@ -669,10 +664,6 @@ void HommeDynamics::homme_post_process (const double dt) {
get_internal_field("w_int_dyn").get_header().get_alloc_properties().reset_subview_idx(tl.n0);
}
- if (m_iop) {
- apply_iop_forcing(dt);
- }
-
if (fv_phys_active()) {
fv_phys_post_process();
// Apply Rayleigh friction to update temperature and horiz_winds
@@ -820,7 +811,7 @@ void HommeDynamics::init_homme_views () {
std::stringstream msg;
msg << "\n************** HOMMEXX SimulationParams **********************\n\n";
msg << " time_step_type: " << Homme::etoi(params.time_step_type) << "\n";
- msg << " moisture: " << (params.moisture==Homme::MoistDry::DRY ? "dry" : "moist") << "\n";
+ msg << " moisture: " << (params.use_moisture ? "moist" : "dry") << "\n";
msg << " remap_alg: " << Homme::etoi(params.remap_alg) << "\n";
msg << " test case: " << Homme::etoi(params.test_case) << "\n";
msg << " ftype: " << Homme::etoi(params.ftype) << "\n";
diff --git a/components/eamxx/src/dynamics/homme/eamxx_homme_process_interface.hpp b/components/eamxx/src/dynamics/homme/eamxx_homme_process_interface.hpp
index 93dff0cd72e..b3e01f8aa30 100644
--- a/components/eamxx/src/dynamics/homme/eamxx_homme_process_interface.hpp
+++ b/components/eamxx/src/dynamics/homme/eamxx_homme_process_interface.hpp
@@ -109,44 +109,6 @@ class HommeDynamics : public AtmosphereProcess
void rayleigh_friction_init ();
void rayleigh_friction_apply (const Real dt) const;
- // IOP functions
- void apply_iop_forcing(const Real dt);
-
- KOKKOS_FUNCTION
- static void advance_iop_subsidence(const KT::MemberType& team,
- const int nlevs,
- const Real dt,
- const Real ps,
- const view_1d& pmid,
- const view_1d& pint,
- const view_1d& pdel,
- const view_1d& omega,
- const Workspace& workspace,
- const view_1d& u,
- const view_1d& v,
- const view_1d& T,
- const view_2d& Q);
-
- KOKKOS_FUNCTION
- static void advance_iop_forcing(const KT::MemberType& team,
- const int nlevs,
- const Real dt,
- const view_1d& divT,
- const view_1d& divq,
- const view_1d& T,
- const view_1d& qv);
-
-
- KOKKOS_FUNCTION
- static void iop_apply_coriolis(const KT::MemberType& team,
- const int nlevs,
- const Real dt,
- const Real lat,
- const view_1d& u_ls,
- const view_1d& v_ls,
- const view_1d& u,
- const view_1d& v);
-
public:
// Fast boolean function returning whether Physics PGN is being used.
bool fv_phys_active() const;
diff --git a/components/eamxx/src/dynamics/homme/homme_grids_manager.cpp b/components/eamxx/src/dynamics/homme/homme_grids_manager.cpp
index df5de6827f6..7376e9af9dd 100644
--- a/components/eamxx/src/dynamics/homme/homme_grids_manager.cpp
+++ b/components/eamxx/src/dynamics/homme/homme_grids_manager.cpp
@@ -188,7 +188,7 @@ void HommeGridsManager::build_dynamics_grid () {
initialize_vertical_coordinates(dyn_grid);
dyn_grid->m_short_name = "dyn";
- add_grid(dyn_grid);
+ add_nonconst_grid(dyn_grid);
}
void HommeGridsManager::
@@ -307,7 +307,7 @@ build_physics_grid (const ci_string& type, const ci_string& rebalance) {
}
phys_grid->m_short_name = type;
- add_grid(phys_grid);
+ add_nonconst_grid(phys_grid);
}
void HommeGridsManager::
diff --git a/components/eamxx/src/dynamics/homme/interface/homme_context_mod.F90 b/components/eamxx/src/dynamics/homme/interface/homme_context_mod.F90
index 5e9f6bd2f9d..377f3c9ed2c 100644
--- a/components/eamxx/src/dynamics/homme/interface/homme_context_mod.F90
+++ b/components/eamxx/src/dynamics/homme/interface/homme_context_mod.F90
@@ -168,37 +168,37 @@ end subroutine init_parallel_f90
function is_parallel_inited_f90 () result(inited) bind(c)
logical (kind=c_bool) :: inited
- inited = is_parallel_inited
+ inited = LOGICAL(is_parallel_inited,kind=c_bool)
end function is_parallel_inited_f90
function is_params_inited_f90 () result(inited) bind(c)
logical (kind=c_bool) :: inited
- inited = is_params_inited
+ inited = LOGICAL(is_params_inited,kind=c_bool)
end function is_params_inited_f90
function is_geometry_inited_f90 () result(inited) bind(c)
logical (kind=c_bool) :: inited
- inited = is_geometry_inited
+ inited = LOGICAL(is_geometry_inited,kind=c_bool)
end function is_geometry_inited_f90
function is_data_structures_inited_f90 () result(inited) bind(c)
logical (kind=c_bool) :: inited
- inited = is_data_structures_inited
+ inited = LOGICAL(is_data_structures_inited,kind=c_bool)
end function is_data_structures_inited_f90
function is_model_inited_f90 () result(inited) bind(c)
logical (kind=c_bool) :: inited
- inited = is_model_inited
+ inited = LOGICAL(is_model_inited,kind=c_bool)
end function is_model_inited_f90
function is_hommexx_functors_inited_f90 () result(inited) bind(c)
logical (kind=c_bool) :: inited
- inited = is_hommexx_functors_inited
+ inited = LOGICAL(is_hommexx_functors_inited,kind=c_bool)
end function is_hommexx_functors_inited_f90
end module homme_context_mod
diff --git a/components/eamxx/src/dynamics/homme/interface/homme_driver_mod.F90 b/components/eamxx/src/dynamics/homme/interface/homme_driver_mod.F90
index eefcd65e8d7..aa6e537baa4 100644
--- a/components/eamxx/src/dynamics/homme/interface/homme_driver_mod.F90
+++ b/components/eamxx/src/dynamics/homme/interface/homme_driver_mod.F90
@@ -192,7 +192,7 @@ subroutine prim_init_model_f90 () bind(c)
elem, hybrid, hvcoord, deriv, tl
! Local variable
- logical(kind=c_bool), parameter :: allocate_buffer = .false.
+ logical, parameter :: allocate_buffer = 0
if (.not. is_data_structures_inited) then
call abortmp ("Error! 'prim_init_data_structures_f90' has not been called yet.\n")
diff --git a/components/eamxx/src/dynamics/homme/physics_dynamics_remapper.cpp b/components/eamxx/src/dynamics/homme/physics_dynamics_remapper.cpp
index 65158fdc390..a1e401dcd17 100644
--- a/components/eamxx/src/dynamics/homme/physics_dynamics_remapper.cpp
+++ b/components/eamxx/src/dynamics/homme/physics_dynamics_remapper.cpp
@@ -426,6 +426,10 @@ do_remap_fwd()
const int team_size = std::min(256, std::min(128*m_num_phys_cols,32*(concurrency/this->m_num_fields+31)/32));
#endif
+#ifdef KOKKOS_ENABLE_SYCL
+ const int team_size = 4;
+#endif
+
//should exclude above cases of CUDA and HIP
#ifndef EAMXX_ENABLE_GPU
const int team_size = (concurrencym_num_fields ? 1 : concurrency/this->m_num_fields);
diff --git a/components/eamxx/src/mct_coupling/CMakeLists.txt b/components/eamxx/src/mct_coupling/CMakeLists.txt
index 308cd177623..39f864e728a 100644
--- a/components/eamxx/src/mct_coupling/CMakeLists.txt
+++ b/components/eamxx/src/mct_coupling/CMakeLists.txt
@@ -38,6 +38,7 @@ set (SCREAM_LIBS
eamxx_cosp
cld_fraction
spa
+ iop_forcing
nudging
diagnostics
tms
diff --git a/components/eamxx/src/physics/CMakeLists.txt b/components/eamxx/src/physics/CMakeLists.txt
index e0e89e60f80..f9beda35a20 100644
--- a/components/eamxx/src/physics/CMakeLists.txt
+++ b/components/eamxx/src/physics/CMakeLists.txt
@@ -8,8 +8,10 @@ add_subdirectory(p3)
if (SCREAM_DOUBLE_PRECISION)
add_subdirectory(rrtmgp)
add_subdirectory(cosp)
+ add_subdirectory(tms)
+ add_subdirectory(iop_forcing)
else()
- message(STATUS "WARNING: RRTMGP and COSP only supported for double precision builds; skipping")
+ message(STATUS "WARNING: RRTMGP, COSP, TMS, and IOPForcing only supported for double precision builds; skipping")
endif()
add_subdirectory(shoc)
add_subdirectory(cld_fraction)
@@ -21,8 +23,4 @@ add_subdirectory(nudging)
if (SCREAM_ENABLE_MAM)
add_subdirectory(mam)
endif()
-if (SCREAM_DOUBLE_PRECISION)
- add_subdirectory(tms)
-else()
- message(STATUS "WARNING: TMS only supported for double precision builds; skipping")
-endif()
+
diff --git a/components/eamxx/src/physics/iop_forcing/CMakeLists.txt b/components/eamxx/src/physics/iop_forcing/CMakeLists.txt
new file mode 100644
index 00000000000..093ceac73c9
--- /dev/null
+++ b/components/eamxx/src/physics/iop_forcing/CMakeLists.txt
@@ -0,0 +1,5 @@
+add_library(iop_forcing eamxx_iop_forcing_process_interface.cpp)
+target_compile_definitions(iop_forcing PUBLIC EAMXX_HAS_IOP_FORCING)
+target_link_libraries(iop_forcing physics_share scream_share)
+
+target_link_libraries(eamxx_physics INTERFACE iop_forcing)
diff --git a/components/eamxx/src/physics/iop_forcing/eamxx_iop_forcing_process_interface.cpp b/components/eamxx/src/physics/iop_forcing/eamxx_iop_forcing_process_interface.cpp
new file mode 100644
index 00000000000..c9a3714e1dc
--- /dev/null
+++ b/components/eamxx/src/physics/iop_forcing/eamxx_iop_forcing_process_interface.cpp
@@ -0,0 +1,520 @@
+#include "physics/iop_forcing/eamxx_iop_forcing_process_interface.hpp"
+
+#include "share/field/field_utils.hpp"
+#include "share/property_checks/field_within_interval_check.hpp"
+
+namespace scream
+{
+// =========================================================================================
+void IOPForcing::set_grids(const std::shared_ptr grids_manager)
+{
+ using namespace ekat::units;
+
+ m_grid = grids_manager->get_grid("Physics");
+ const auto& grid_name = m_grid->name();
+
+ m_num_cols = m_grid->get_num_local_dofs(); // Number of columns on this rank
+ m_num_levs = m_grid->get_num_vertical_levels(); // Number of levels per column
+
+ // Define the different field layouts that will be used for this process
+ FieldLayout scalar2d = m_grid->get_2d_scalar_layout();
+ FieldLayout scalar3d_mid = m_grid->get_3d_scalar_layout(true);
+ FieldLayout vector3d_mid = m_grid->get_3d_vector_layout(true,2);
+
+ constexpr int pack_size = Pack::n;
+
+ add_field("ps", scalar2d, Pa, grid_name);
+
+ add_field("horiz_winds", vector3d_mid, m/s, grid_name, pack_size);
+ add_field("T_mid", scalar3d_mid, K, grid_name, pack_size);
+
+ add_tracer("qv", m_grid, kg/kg, pack_size);
+ add_group("tracers", grid_name, pack_size, Bundling::Required);
+
+ // Sanity check that iop data manager is setup by driver
+ EKAT_REQUIRE_MSG(m_iop_data_manager,
+ "Error! IOPDataManager not setup by driver, but IOPForcing"
+ "being used as an ATM process.\n");
+
+ // Create helper fields for finding horizontal means
+ auto level_only_scalar_layout = scalar3d_mid.clone().strip_dim(0);
+ auto level_only_vector_layout = vector3d_mid.clone().strip_dim(0);
+ const auto iop_nudge_tq = m_iop_data_manager->get_params().get("iop_nudge_tq");
+ const auto iop_nudge_uv = m_iop_data_manager->get_params().get("iop_nudge_uv");
+ if (iop_nudge_tq or iop_nudge_uv) {
+ create_helper_field("horiz_mean_weights", scalar2d, grid_name, pack_size);
+ }
+ if (iop_nudge_tq) {
+ create_helper_field("qv_mean", level_only_scalar_layout, grid_name, pack_size);
+ create_helper_field("t_mean", level_only_scalar_layout, grid_name, pack_size);
+ }
+ if (iop_nudge_uv) {
+ create_helper_field("horiz_winds_mean", level_only_vector_layout, grid_name, pack_size);
+ }
+}
+// =========================================================================================
+void IOPForcing::
+set_computed_group_impl (const FieldGroup& group)
+{
+ EKAT_REQUIRE_MSG(group.m_info->size() >= 1,
+ "Error! IOPForcing requires at least qv as tracer input.\n");
+
+ const auto& name = group.m_info->m_group_name;
+
+ EKAT_REQUIRE_MSG(name=="tracers",
+ "Error! IOPForcing was not expecting a field group called '" << name << "\n");
+
+ EKAT_REQUIRE_MSG(group.m_info->m_bundled,
+ "Error! IOPForcing expects bundled fields for tracers.\n");
+
+ m_num_tracers = group.m_info->size();
+}
+// =========================================================================================
+size_t IOPForcing::requested_buffer_size_in_bytes() const
+{
+ // Number of bytes needed by the WorkspaceManager passed to shoc_main
+ const int nlevi_packs = ekat::npack(m_num_levs+1);
+ const auto policy = ESU::get_default_team_policy(m_num_cols, nlevi_packs);
+ const size_t wsm_bytes = WorkspaceMgr::get_total_bytes_needed(nlevi_packs, 7+m_num_tracers, policy);
+
+ return wsm_bytes;
+}
+// =========================================================================================
+void IOPForcing::init_buffers(const ATMBufferManager &buffer_manager)
+{
+ EKAT_REQUIRE_MSG(buffer_manager.allocated_bytes() >= requested_buffer_size_in_bytes(),
+ "Error! Buffers size not sufficient.\n");
+
+ const int nlevi_packs = ekat::npack(m_num_levs+1);
+ Pack* mem = reinterpret_cast(buffer_manager.get_memory());
+
+ // WSM data
+ m_buffer.wsm_data = mem;
+
+ const auto policy = ESU::get_default_team_policy(m_num_cols, nlevi_packs);
+ const size_t wsm_npacks = WorkspaceMgr::get_total_bytes_needed(nlevi_packs, 7+m_num_tracers, policy)/sizeof(Pack);
+ mem += wsm_npacks;
+
+ size_t used_mem = (reinterpret_cast(mem) - buffer_manager.get_memory())*sizeof(Real);
+ EKAT_REQUIRE_MSG(used_mem==requested_buffer_size_in_bytes(), "Error! Used memory != requested memory for IOPForcing.\n");
+}
+// =========================================================================================
+void IOPForcing::create_helper_field (const std::string& name,
+ const FieldLayout& layout,
+ const std::string& grid_name,
+ const int ps)
+{
+ using namespace ekat::units;
+ FieldIdentifier id(name,layout,Units::nondimensional(),grid_name);
+
+ // Create the field. Init with NaN's, so we spot instances of uninited memory usage
+ Field f(id);
+ f.get_header().get_alloc_properties().request_allocation(ps);
+ f.allocate_view();
+ f.deep_copy(ekat::ScalarTraits::invalid());
+
+ m_helper_fields[name] = f;
+}
+// =========================================================================================
+void IOPForcing::initialize_impl (const RunType run_type)
+{
+ // Set field property checks for the fields in this process
+ using Interval = FieldWithinIntervalCheck;
+ add_postcondition_check(get_field_out("T_mid"),m_grid,100.0,500.0,false);
+ add_postcondition_check(get_field_out("horiz_winds"),m_grid,-400.0,400.0,false);
+ // For qv, ensure it doesn't get negative, by allowing repair of any neg value.
+ // TODO: use a repairable lb that clips only "small" negative values
+ add_postcondition_check