diff --git a/.github/PULL_REQUEST_TEMPLATE b/.github/PULL_REQUEST_TEMPLATE index 2bb5c07fc..7a696e24f 100644 --- a/.github/PULL_REQUEST_TEMPLATE +++ b/.github/PULL_REQUEST_TEMPLATE @@ -2,24 +2,32 @@ - You may delete any sections labeled "optional". -- If you are unclear on what should be written here, see https://github.com/NOAA-EMC/UFS_UTILS/wiki/9.-Creating-a-Pull-Request for some guidance. +- If you are unclear on what should be written here, see https://github.com/ufs-community/UFS_UTILS/wiki/9.-Creating-a-Pull-Request for some guidance. - The title of this pull request should be a brief summary (ideally less than 100 characters) of the changes included in this PR. Please also include the branch to which this PR is being issued. - Use the "Preview" tab to see what your PR will look like when you hit "Create pull request" -# --- Delete this line and those above before hitting "Create pull request" --- +## --- Delete this line and those above before hitting "Create pull request" --- ## DESCRIPTION OF CHANGES: One or more paragraphs describing the problem, solution, and required changes. ## TESTS CONDUCTED: -State whether the contingency tests were run or are pending, and if they were already run, state the result. If contingency test baselines need to be updated as a result of this PR, please specify the machine(s) and path(s) to the new files. Note that running the contigency tests is required for every PR and should be run at least once after all commits or changes have been made after review of the PR. Make note of the compilers used, the platform/machine, and other relevant details as necessary. Please also note whether new unit tests or updates to existing ones were required and their file names. +If there are changes to the build or source code, the tests below must be conducted. Contact a repository manager if you need assistance. + +- [ ] Compile branch on all Tier 1 machines using Intel (Orion, Jet, Hera and WCOSS2). +- [ ] Compile branch on Hera using GNU. +- [ ] Compile branch in 'Debug' mode on WCOSS2. +- [ ] Run unit tests locally on any Tier 1 machine. +- [ ] Run relevant consistency tests locally on all Tier 1 machine. + +Describe any additional tests performed. ## DEPENDENCIES: Add any links to pending PRs that are required prior to merging this PR. For example: -NOAA-EMC/UFS_UTILS/pull/ +ufs-community/UFS_UTILS/pull/ ## DOCUMENTATION: If this PR is contributing new capabilities that need to be documented, please also include updates to the RST files in the docs/source directory as supporting material. diff --git a/.github/workflows/Intel1.yml b/.github/workflows/Intel1.yml new file mode 100644 index 000000000..0cf71f245 --- /dev/null +++ b/.github/workflows/Intel1.yml @@ -0,0 +1,202 @@ +# UFS_UTILS test workflow. +# +# This workflow tests UFS_UTILS with the Intel compiler. +# +# Ed Hartnett 12/14/22 +name: Intel1 +on: + push: + branches: + - develop + paths-ignore: + - README.md + pull_request: + branches: + - develop + paths-ignore: + - README.md + +# Use custom shell with -l so .bash_profile is sourced which loads intel/oneapi/setvars.sh +# without having to do it in manually every step. +defaults: + run: + shell: bash -leo pipefail {0} + +jobs: + Intel: + runs-on: ubuntu-latest + env: + CC: icc + FC: ifort + + steps: + + # See https://software.intel.com/content/www/us/en/develop/articles/oneapi-repo-instructions.html + - name: install-intel + run: | + cd /tmp + wget https://apt.repos.intel.com/intel-gpg-keys/GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB + sudo apt-key add GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB + rm GPG-PUB-KEY-INTEL-SW-PRODUCTS.PUB + echo "deb https://apt.repos.intel.com/oneapi all main" | sudo tee /etc/apt/sources.list.d/oneAPI.list + sudo apt-get update + sudo apt-get install intel-oneapi-dev-utilities intel-oneapi-mpi-devel intel-oneapi-openmp intel-oneapi-compiler-fortran intel-oneapi-compiler-dpcpp-cpp-and-cpp-classic + echo "source /opt/intel/oneapi/setvars.sh" >> ~/.bash_profile + + - name: cache-netcdf + id: cache-netcdf + uses: actions/cache@v2 + with: + path: ~/netcdf + key: Intel-netcdf-c-$4.7.4-{{ runner.os }}-intel3 + + - name: build-hdf5 + if: steps.cache-netcdf.outputs.cache-hit != 'true' + run: | + export CC=mpiicc + wget https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.10/hdf5-1.10.7/src/hdf5-1.10.7.tar.gz &> /dev/null + tar -xzf hdf5-1.10.7.tar.gz + pushd hdf5-1.10.7 + ./configure --prefix=${HOME}/netcdf --enable-parallel --disable-tools --disable-fortran --disable-cxx --enable-parallel-tests --disable-shared --disable-shared --enable-static + make -j2 + make install + + - name: build-netcdf-c + if: steps.cache-netcdf.outputs.cache-hit != 'true' + run: | + export CC=mpiicc + export CPPFLAGS=-I${HOME}/netcdf/include + export LDFLAGS=-L${HOME}/netcdf/lib + wget https://github.com/Unidata/netcdf-c/archive/refs/tags/v4.7.4.tar.gz &> /dev/null + tar -xzf v4.7.4.tar.gz + pushd netcdf-c-4.7.4 + ./configure --prefix=${HOME}/netcdf --disable-dap --disable-utilities --disable-shared + make -j2 + make install + + - name: build-netcdf-fortran + if: steps.cache-netcdf.outputs.cache-hit != 'true' + run: | + export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${HOME}/netcdf/lib" + export PATH="${HOME}/netcdf/bin:$PATH" + export CC=mpiicc + export FC=mpiifort + export CPPFLAGS=-I${HOME}/netcdf/include + export LDFLAGS=-L${HOME}/netcdf/lib + export LIBS=`nc-config --libs` + wget https://github.com/Unidata/netcdf-fortran/archive/v4.5.3.tar.gz &> /dev/null + tar -xzf v4.5.3.tar.gz + pushd netcdf-fortran-4.5.3 + ./configure --prefix=${HOME}/netcdf --disable-shared + make -j2 + make install + + - name: cache-esmf + id: cache-esmf + uses: actions/cache@v2 + with: + path: ~/esmf + key: Intel-esmf-8.2.0-${{ runner.os }}-intel3 + + - name: build-esmf + if: steps.cache-esmf.outputs.cache-hit != 'true' + run: | + pushd ~ + export ESMF_DIR=~/esmf-ESMF_8_2_0 + wget https://github.com/esmf-org/esmf/archive/ESMF_8_2_0.tar.gz &> /dev/null + tar zxf ESMF_8_2_0.tar.gz + cd esmf-ESMF_8_2_0 + export ESMF_COMM=intelmpi + export ESMF_INSTALL_BINDIR=bin + export ESMF_INSTALL_LIBDIR=lib + export ESMF_INSTALL_MODDIR=mod + export ESMF_COMPILER=intel + export ESMF_INSTALL_PREFIX=~/esmf + export ESMF_NETCDF=split + export ESMF_NETCDF_INCLUDE=${HOME}/netcdf/include + export ESMF_NETCDF_LIBPATH=${HOME}/netcdf/lib + export ESMF_NETCDF_LIBS="-lnetcdff -lnetcdf -lhdf5_hl -lhdf5 -lz" + make -j2 + make install + + - name: cache-jasper + id: cache-jasper + uses: actions/cache@v2 + with: + path: ~/jasper + key: Intel-jasper-2.0.25-${{ runner.os }}-intel3 + + - name: build-jasper + if: steps.cache-jasper.outputs.cache-hit != 'true' + run: | + wget https://github.com/jasper-software/jasper/archive/version-2.0.25.tar.gz &> /dev/null + tar zxf version-2.0.25.tar.gz + cd jasper-version-2.0.25 + mkdir build-jasper && cd build-jasper + cmake .. -DCMAKE_INSTALL_PREFIX=~/jasper -DJAS_ENABLE_SHARED=OFF + make -j2 + make install + + - name: checkout-nceplibs + uses: actions/checkout@v2 + with: + repository: NOAA-EMC/NCEPLIBS + path: nceplibs + + - name: cache-nceplibs + id: cache-nceplibs + uses: actions/cache@v2 + with: + path: ~/nceplibs + key: Intel-nceplibs-1.4.0-${{ runner.os }}-intel3 + + - name: build-nceplibs + if: steps.cache-nceplibs.outputs.cache-hit != 'true' + run: | + export ESMFMKFILE=~/esmf/lib/esmf.mk + wget https://github.com/NOAA-EMC/NCEPLIBS/archive/v1.4.0.tar.gz &> /dev/null + tar zxf v1.4.0.tar.gz + cd NCEPLIBS-1.4.0 + mkdir build && cd build + cmake .. -DCMAKE_PREFIX_PATH='~;~/jasper;~/netcdf' -DCMAKE_INSTALL_PREFIX='~/nceplibs' -DFLAT=ON + make -j2 + + - name: checkout-ufs-utils + uses: actions/checkout@v2 + with: + path: ufs_utils + submodules: recursive + + - name: cache-data + id: cache-data + uses: actions/cache@v2 + with: + path: ~/data + key: data-1 + + - name: build + run: | + export ESMFMKFILE=~/esmf/lib/esmf.mk + cd ufs_utils + mkdir build && cd build + export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:~/jasper/lib;~/jasper/lib64" + cmake -DTEST_FILE_DIR=/home/runner/data -DCMAKE_PREFIX_PATH='~;~/jasper;~/nceplibs;~/netcdf' .. + make -j2 + + - name: test + run: | + cd ufs_utils/build + ctest --rerun-failed --output-on-failure + + - name: cache-data + if: steps.cache-data.outputs.cache-hit != 'true' + run: | + mkdir ~/data + cp ufs_utils/build/tests/chgres_cube/data/* ~/data + cp ufs_utils/build/tests/sfc_climo_gen/data/* ~/data + cp ufs_utils/build/tests/cpld_gridgen/data/* ~/data + cp ufs_utils/tests/filter_topo/data/* ~/data + cp ufs_utils/tests/emcsfc_snow2mdl/data/* ~/data + cp ufs_utils/tests/chgres_cube/data/* ~/data + ls -l ~/data + diff --git a/.github/workflows/intel.yml b/.github/workflows/Intel_nceplibs.yml similarity index 67% rename from .github/workflows/intel.yml rename to .github/workflows/Intel_nceplibs.yml index e4266dc6d..e15059809 100644 --- a/.github/workflows/intel.yml +++ b/.github/workflows/Intel_nceplibs.yml @@ -1,22 +1,28 @@ -name: intel -on: [push, pull_request] +name: Intel_nceplibs +on: + push: + branches: + - develop + paths-ignore: + - README.md + pull_request: + branches: + - develop + paths-ignore: + - README.md # Use custom shell with -l so .bash_profile is sourced which loads intel/oneapi/setvars.sh -# without having to do it in manually every step +# without having to do it in manually every step. defaults: run: shell: bash -leo pipefail {0} jobs: - intel-build-and-test: - runs-on: ${{ matrix.os }} + Intel_nceplibs: + runs-on: ubuntu-latest env: CC: icc FC: ifort - CXX: icpc - strategy: - matrix: - os: [ubuntu-20.04] steps: @@ -37,7 +43,7 @@ jobs: uses: actions/cache@v2 with: path: ~/netcdf - key: netcdf-c-$4.7.4-{{ runner.os }}-intel + key: netcdf-c-$4.7.4-{{ runner.os }}-intel3 - name: build-hdf5 if: steps.cache-netcdf.outputs.cache-hit != 'true' @@ -46,7 +52,7 @@ jobs: wget https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.10/hdf5-1.10.7/src/hdf5-1.10.7.tar.gz &> /dev/null tar -xzf hdf5-1.10.7.tar.gz pushd hdf5-1.10.7 - ./configure --prefix=${HOME}/netcdf --enable-parallel --disable-tools --disable-fortran --disable-cxx --enable-parallel-tests + ./configure --prefix=${HOME}/netcdf --enable-parallel --disable-tools --disable-fortran --disable-cxx --enable-parallel-tests --disable-shared --disable-shared --enable-static make -j2 make install @@ -56,10 +62,10 @@ jobs: export CC=mpiicc export CPPFLAGS=-I${HOME}/netcdf/include export LDFLAGS=-L${HOME}/netcdf/lib - wget https://www.unidata.ucar.edu/downloads/netcdf/ftp/netcdf-c-4.7.4.tar.gz &> /dev/null - tar -xzf netcdf-c-4.7.4.tar.gz + wget https://github.com/Unidata/netcdf-c/archive/refs/tags/v4.7.4.tar.gz &> /dev/null + tar -xzf v4.7.4.tar.gz pushd netcdf-c-4.7.4 - ./configure --prefix=${HOME}/netcdf --disable-dap --disable-utilities + ./configure --prefix=${HOME}/netcdf --disable-dap --disable-utilities --disable-shared make -j2 make install @@ -72,10 +78,11 @@ jobs: export FC=mpiifort export CPPFLAGS=-I${HOME}/netcdf/include export LDFLAGS=-L${HOME}/netcdf/lib + export LIBS=`nc-config --libs` wget https://github.com/Unidata/netcdf-fortran/archive/v4.5.3.tar.gz &> /dev/null tar -xzf v4.5.3.tar.gz pushd netcdf-fortran-4.5.3 - ./configure --prefix=${HOME}/netcdf + ./configure --prefix=${HOME}/netcdf --disable-shared make -j2 make install @@ -84,16 +91,16 @@ jobs: uses: actions/cache@v2 with: path: ~/esmf - key: esmf-8.0.1-${{ runner.os }}-intel + key: esmf-8.2.0-${{ runner.os }}-intel3 - name: build-esmf if: steps.cache-esmf.outputs.cache-hit != 'true' run: | pushd ~ - export ESMF_DIR=~/esmf-ESMF_8_0_1 - wget https://github.com/esmf-org/esmf/archive/ESMF_8_0_1.tar.gz &> /dev/null - tar zxf ESMF_8_0_1.tar.gz - cd esmf-ESMF_8_0_1 + export ESMF_DIR=~/esmf-ESMF_8_2_0 + wget https://github.com/esmf-org/esmf/archive/ESMF_8_2_0.tar.gz &> /dev/null + tar zxf ESMF_8_2_0.tar.gz + cd esmf-ESMF_8_2_0 export ESMF_COMM=intelmpi export ESMF_INSTALL_BINDIR=bin export ESMF_INSTALL_LIBDIR=lib @@ -103,6 +110,7 @@ jobs: export ESMF_NETCDF=split export ESMF_NETCDF_INCLUDE=${HOME}/netcdf/include export ESMF_NETCDF_LIBPATH=${HOME}/netcdf/lib + export ESMF_NETCDF_LIBS="-lnetcdff -lnetcdf -lhdf5_hl -lhdf5 -lz" make -j2 make install @@ -111,7 +119,7 @@ jobs: uses: actions/cache@v2 with: path: ~/jasper - key: jasper-2.0.25-${{ runner.os }}-intel + key: jasper-2.0.25-${{ runner.os }}-intel3 - name: build-jasper if: steps.cache-jasper.outputs.cache-hit != 'true' @@ -120,7 +128,7 @@ jobs: tar zxf version-2.0.25.tar.gz cd jasper-version-2.0.25 mkdir build-jasper && cd build-jasper - cmake .. -DCMAKE_INSTALL_PREFIX=~/jasper + cmake .. -DCMAKE_INSTALL_PREFIX=~/jasper -DJAS_ENABLE_SHARED=OFF make -j2 make install @@ -135,15 +143,15 @@ jobs: uses: actions/cache@v2 with: path: ~/nceplibs - key: nceplibs-1.3.0-${{ runner.os }}-intel + key: nceplibs-1.4.0-${{ runner.os }}-intel3 - name: build-nceplibs if: steps.cache-nceplibs.outputs.cache-hit != 'true' run: | export ESMFMKFILE=~/esmf/lib/esmf.mk - wget https://github.com/NOAA-EMC/NCEPLIBS/archive/v1.3.0.tar.gz &> /dev/null - tar zxf v1.3.0.tar.gz - cd NCEPLIBS-1.3.0 + wget https://github.com/NOAA-EMC/NCEPLIBS/archive/v1.4.0.tar.gz &> /dev/null + tar zxf v1.4.0.tar.gz + cd NCEPLIBS-1.4.0 mkdir build && cd build cmake .. -DCMAKE_PREFIX_PATH='~;~/jasper;~/netcdf' -DCMAKE_INSTALL_PREFIX='~/nceplibs' -DFLAT=ON make -j2 @@ -152,19 +160,38 @@ jobs: uses: actions/checkout@v2 with: path: ufs_utils + submodules: recursive + + - name: cache-data + id: cache-data + uses: actions/cache@v2 + with: + path: ~/data + key: data-1 - name: build run: | export ESMFMKFILE=~/esmf/lib/esmf.mk cd ufs_utils mkdir build && cd build - cmake .. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_PREFIX_PATH='~;~/jasper;~/nceplibs;~/netcdf' + export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:~/jasper/lib;~/jasper/lib64" + cmake -DTEST_FILE_DIR=/home/runner/data -DCMAKE_BUILD_TYPE=Debug -DCMAKE_PREFIX_PATH='~;~/jasper;~/nceplibs;~/netcdf' .. make -j2 - name: test run: | - cd ufs_utils/build/tests - wget -i ./chgres_cube/data/files.txt -P ./chgres_cube/data - wget -i ./sfc_climo_gen/data/files.txt -P ./sfc_climo_gen/data - cd ../ + cd ufs_utils/build ctest --rerun-failed --output-on-failure + + - name: cache-data + if: steps.cache-data.outputs.cache-hit != 'true' + run: | + mkdir ~/data + cp ufs_utils/build/tests/chgres_cube/data/* ~/data + cp ufs_utils/build/tests/sfc_climo_gen/data/* ~/data + cp ufs_utils/build/tests/cpld_gridgen/data/* ~/data + cp ufs_utils/tests/filter_topo/data/* ~/data + cp ufs_utils/tests/emcsfc_snow2mdl/data/* ~/data + cp ufs_utils/tests/chgres_cube/data/* ~/data + ls -l ~/data + diff --git a/.github/workflows/debug-docs-test_coverage.yml b/.github/workflows/Linux_nceplibs.yml similarity index 61% rename from .github/workflows/debug-docs-test_coverage.yml rename to .github/workflows/Linux_nceplibs.yml index 6e481a8dc..e1e33af51 100644 --- a/.github/workflows/debug-docs-test_coverage.yml +++ b/.github/workflows/Linux_nceplibs.yml @@ -1,12 +1,27 @@ -name: debug-docs-test_coverage -on: [push, pull_request] +# UFS_UTILS test workflow. +# +# Check UFS_UTILS build based on the NCEPLIBS project (deprecated, but still works). +# +# Ed Hartnett 12/13/22 +name: Linux_nceplibs +on: + push: + branches: + - develop + paths-ignore: + - README.md + pull_request: + branches: + - develop + paths-ignore: + - README.md defaults: run: shell: bash -exo pipefail {0} jobs: - debug-build-and-test: + Linux_nceplibs: runs-on: ubuntu-latest steps: @@ -14,28 +29,24 @@ jobs: - name: install-dependencies run: | sudo apt-get update - sudo apt-get install libmpich-dev - sudo apt-get install doxygen - sudo apt-get install libpng-dev - sudo apt-get install libjpeg-dev + sudo apt-get install libmpich-dev libpng-dev libjpeg-dev sudo apt-get install libnetcdf-dev libnetcdff-dev netcdf-bin pkg-config - python3 -m pip install gcovr - name: cache-esmf id: cache-esmf uses: actions/cache@v2 with: path: ~/esmf - key: esmf-8.0.1-${{ runner.os }} + key: esmf-8.2.0-${{ runner.os }}3 - name: build-esmf if: steps.cache-esmf.outputs.cache-hit != 'true' run: | pushd ~ - export ESMF_DIR=~/esmf-ESMF_8_0_1 - wget https://github.com/esmf-org/esmf/archive/ESMF_8_0_1.tar.gz &> /dev/null - tar zxf ESMF_8_0_1.tar.gz - cd esmf-ESMF_8_0_1 + export ESMF_DIR=~/esmf-ESMF_8_2_0 + wget https://github.com/esmf-org/esmf/archive/ESMF_8_2_0.tar.gz &> /dev/null + tar zxf ESMF_8_2_0.tar.gz + cd esmf-ESMF_8_2_0 export ESMF_COMM=mpich3 export ESMF_INSTALL_BINDIR=bin export ESMF_INSTALL_LIBDIR=lib @@ -53,7 +64,7 @@ jobs: uses: actions/cache@v2 with: path: ~/jasper - key: jasper-2.0.25-${{ runner.os }} + key: jasper-2.0.25-${{ runner.os }}3 - name: build-jasper if: steps.cache-jasper.outputs.cache-hit != 'true' @@ -62,7 +73,7 @@ jobs: tar zxf version-2.0.25.tar.gz cd jasper-version-2.0.25 mkdir build-jasper && cd build-jasper - cmake .. -DCMAKE_INSTALL_PREFIX=~/jasper + cmake .. -DCMAKE_INSTALL_PREFIX=~/jasper -DJAS_ENABLE_SHARED=OFF make -j2 make install @@ -71,14 +82,14 @@ jobs: uses: actions/cache@v2 with: path: ~/nceplibs - key: nceplibs-1.3.0-${{ runner.os }} + key: nceplibs-1.4.0-${{ runner.os }}3 - name: build-nceplibs if: steps.cache-nceplibs.outputs.cache-hit != 'true' run: | - wget https://github.com/NOAA-EMC/NCEPLIBS/archive/v1.3.0.tar.gz &> /dev/null - tar zxf v1.3.0.tar.gz - cd NCEPLIBS-1.3.0 + wget https://github.com/NOAA-EMC/NCEPLIBS/archive/v1.4.0.tar.gz &> /dev/null + tar zxf v1.4.0.tar.gz + cd NCEPLIBS-1.4.0 export ESMFMKFILE=~/esmf/lib/esmf.mk mkdir build && cd build cmake .. -DCMAKE_PREFIX_PATH='~;~/jasper' -DCMAKE_INSTALL_PREFIX='~/nceplibs' -DFLAT=ON @@ -88,6 +99,14 @@ jobs: uses: actions/checkout@v2 with: path: ufs_utils + submodules: recursive + + - name: cache-data + id: cache-data + uses: actions/cache@v2 + with: + path: ~/data + key: data-1 - name: build run: | @@ -97,21 +116,10 @@ jobs: export CC=mpicc export CXX=mpicxx export FC=mpifort - cmake .. -DCMAKE_PREFIX_PATH='~/jasper;~/nceplibs' -DCMAKE_BUILD_TYPE=Debug -DENABLE_DOCS=On -DCMAKE_Fortran_FLAGS="-g -fprofile-arcs -ftest-coverage -O0" + export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:~/jasper/lib;~/jasper/lib64" + cmake -DTEST_FILE_DIR=/home/runner/data -DCMAKE_PREFIX_PATH='~/jasper;~/nceplibs' .. make -j2 - - name: test run: | - cd ufs_utils/build/tests - wget -i ./chgres_cube/data/files.txt -P ./chgres_cube/data - wget -i ./sfc_climo_gen/data/files.txt -P ./sfc_climo_gen/data - cd ../ - export LSAN_OPTIONS=suppressions=LSanSuppress.supp + cd ufs_utils/build ctest --rerun-failed --output-on-failure - export PATH="/home/runner/.local/bin:$PATH" - gcovr -r .. --html-details -o test-coverage.html - - - uses: actions/upload-artifact@v2 - with: - name: test-coverage - path: ufs_utils/build/*.html diff --git a/.github/workflows/Linux_versions.yml b/.github/workflows/Linux_versions.yml new file mode 100644 index 000000000..03baff39d --- /dev/null +++ b/.github/workflows/Linux_versions.yml @@ -0,0 +1,383 @@ +# UFS_UTILS test workflow. +# +# Check different versions of the NCEPLIBS libraries that are used by UFS_UTILS. +# +# Ed Hartnett 12/13/22 +name: Linux_versions +on: + push: + branches: + - develop + paths-ignore: + - README.md + pull_request: + branches: + - develop + paths-ignore: + - README.md + +defaults: + run: + shell: bash -exo pipefail {0} + +jobs: + Linux_versions: + runs-on: ubuntu-latest + env: + FC: mpifort + CC: mpicc + FCFLAGS: -fallow-argument-mismatch + strategy: + fail-fast: true + matrix: + esmf_version: [8_2_0, 8.3.0, 8.4.0] + bacio_version: [2.4.1] + g2_version: [3.4.3] + sp_version: [2.3.3] + ip_version: [3.3.3] + w3emc_version: [2.9.3] + nemsio_version: [2.5.0] + sfcio_version: [1.4.0] + sigio_version: [2.3.0] + + steps: + + - name: install-dependencies + run: | + sudo apt-get update + sudo apt-get install libpng-dev zlib1g-dev libjpeg-dev libmpich-dev + sudo apt-get install libnetcdf-dev libnetcdff-dev netcdf-bin pkg-config + sudo apt-get install autoconf automake libtool + + - name: checkout-esmf + id: cache-esmf + uses: actions/cache@v2 + with: + path: ~/esmf + key: Linux_versions-esmf-${{ matrix.esmf_version }}-${{ runner.os }} + + - name: build-esmf + if: steps.cache-esmf.outputs.cache-hit != 'true' + run: | + pushd ~ + if [[ ${{ matrix.esmf_version }} == "8_2_0" ]]; then + wget https://github.com/esmf-org/esmf/archive/ESMF_${{ matrix.esmf_version }}.tar.gz &> /dev/null + tar zxf ESMF_${{ matrix.esmf_version }}.tar.gz + cd esmf-ESMF_${{ matrix.esmf_version }} + export ESMF_DIR=~/esmf-ESMF_${{ matrix.esmf_version }} + else + wget https://github.com/esmf-org/esmf/archive/refs/tags/v${{ matrix.esmf_version }}.tar.gz &> /dev/null + ls -l + tar zxf v${{ matrix.esmf_version }}.tar.gz + cd esmf-${{ matrix.esmf_version }} + export ESMF_DIR=~/esmf-${{ matrix.esmf_version }} + fi + export ESMF_COMM=mpich3 + export ESMF_INSTALL_BINDIR=bin + export ESMF_INSTALL_LIBDIR=lib + export ESMF_INSTALL_MODDIR=mod + export ESMF_COMPILER=gfortran + export ESMF_INSTALL_PREFIX=~/esmf + export ESMF_NETCDF=split + export ESMF_NETCDF_INCLUDE=/usr/include + export ESMF_NETCDF_LIBPATH=/usr/x86_64-linux-gnu + export ESMF_PIO=OFF + export ESMF_MOAB=OFF + export ESMF_ARRAY_LITE=TRUE + make -j2 + make install + + - name: cache-jasper + id: cache-jasper + uses: actions/cache@v2 + with: + path: ~/jasper + key: Linux_versions-jasper-${{ runner.os }}-2.0.33-1 + + - name: checkout-jasper + if: steps.cache-jasper.outputs.cache-hit != 'true' + uses: actions/checkout@v2 + with: + repository: jasper-software/jasper + path: jasper + ref: version-2.0.33 + + - name: build-jasper + if: steps.cache-jasper.outputs.cache-hit != 'true' + run: | + cd jasper + mkdir build-jasper && cd build-jasper + cmake .. -DCMAKE_INSTALL_PREFIX=~/jasper + make -j2 + make install + + - name: cache-bacio + id: cache-bacio + uses: actions/cache@v2 + with: + path: ~/bacio + key: Linux_versions-bacio-${{ runner.os }}-${{ matrix.bacio_version }} + + - name: checkout-bacio + if: steps.cache-bacio.outputs.cache-hit != 'true' + uses: actions/checkout@v2 + with: + repository: NOAA-EMC/NCEPLIBS-bacio + path: bacio + ref: v${{ matrix.bacio_version }} + + - name: build-bacio + if: steps.cache-bacio.outputs.cache-hit != 'true' + run: | + cd bacio + mkdir build && cd build + cmake .. -DCMAKE_INSTALL_PREFIX=~/bacio + make -j2 + make install + + - name: cache-g2 + id: cache-g2 + uses: actions/cache@v2 + with: + path: ~/g2 + key: Linux_versions-g2-${{ runner.os }}-${{ matrix.g2_version }} + + - name: checkout-g2 + if: steps.cache-g2.outputs.cache-hit != 'true' + uses: actions/checkout@v2 + with: + repository: NOAA-EMC/NCEPLIBS-g2 + path: g2 + ref: v${{ matrix.g2_version }} + + - name: build-g2 + if: steps.cache-g2.outputs.cache-hit != 'true' + run: | + cd g2 + mkdir build + cd build + cmake -DCMAKE_INSTALL_PREFIX=~/g2 -DCMAKE_PREFIX_PATH="~/bacio;~/jasper" .. + make -j2 + make install + + - name: cache-sp + id: cache-sp + uses: actions/cache@v2 + with: + path: ~/sp + key: Linux_versions-sp-${{ runner.os }}-${{ matrix.sp_version }} + + - name: checkout-sp + if: steps.cache-sp.outputs.cache-hit != 'true' + uses: actions/checkout@v2 + with: + repository: NOAA-EMC/NCEPLIBS-sp + path: sp + ref: v${{ matrix.sp_version }} + + - name: build-sp + if: steps.cache-sp.outputs.cache-hit != 'true' + run: | + cd sp + mkdir build + cd build + cmake .. -DCMAKE_INSTALL_PREFIX=~/sp + make -j2 + make install + + - name: cache-ip + id: cache-ip + uses: actions/cache@v2 + with: + path: ~/ip + key: Linux_versions-ip-${{ runner.os }}-${{ matrix.ip_version }} + + - name: checkout-ip + if: steps.cache-ip.outputs.cache-hit != 'true' + uses: actions/checkout@v2 + with: + repository: NOAA-EMC/NCEPLIBS-ip + path: ip + ref: v${{ matrix.ip_version }} + + - name: build-ip + if: steps.cache-ip.outputs.cache-hit != 'true' + run: | + cd ip + mkdir build + cd build + cmake -DCMAKE_INSTALL_PREFIX=~/ip -DCMAKE_PREFIX_PATH=~/sp .. + make -j2 + make install + + # - name: checkout-w3emc + # uses: actions/checkout@v2 + # with: + # repository: NOAA-EMC/NCEPLIBS-w3emc + # path: w3emc + # ref: develop + + # - name: build-w3emc + # run: | + # cd w3emc + # mkdir build + # cd build + # cmake -DCMAKE_PREFIX_PATH=~/bacio -DCMAKE_INSTALL_PREFIX=~/w3emc .. + # make -j2 + # make install + + # - name: checkout-g2c + # uses: actions/checkout@v2 + # with: + # repository: NOAA-EMC/NCEPLIBS-g2c + # path: g2c + # ref: develop + + # - name: build-g2c + # run: | + # cd g2c + # mkdir build + # cd build + # cmake .. -DCMAKE_INSTALL_PREFIX=~/g2c -DJasper_ROOT=~/jasper + # make -j2 + # make install + + - name: cache-sfcio + id: cache-sfcio + uses: actions/cache@v2 + with: + path: ~/sfcio + key: Linux_versions-sfcio-${{ runner.os }}-${{ matrix.sfcio_version }} + + - name: checkout-sfcio + if: steps.cache-sfcio.outputs.cache-hit != 'true' + uses: actions/checkout@v2 + with: + repository: NOAA-EMC/NCEPLIBS-sfcio + path: sfcio + ref: v${{ matrix.sfcio_version }} + + - name: build-sfcio + if: steps.cache-sfcio.outputs.cache-hit != 'true' + run: | + cd sfcio + mkdir build + cd build + cmake .. -DCMAKE_INSTALL_PREFIX=~/sfcio + make -j2 + make install + + - name: cache-w3emc + id: cache-w3emc + uses: actions/cache@v2 + with: + path: ~/w3emc + key: Linux_versions-w3emc-${{ runner.os }}-${{ matrix.w3emc_version }} + + - name: checkout-w3emc + if: steps.cache-w3emc.outputs.cache-hit != 'true' + uses: actions/checkout@v2 + with: + repository: NOAA-EMC/NCEPLIBS-w3emc + path: w3emc + ref: v${{ matrix.w3emc_version }} + + - name: build-w3emc + if: steps.cache-w3emc.outputs.cache-hit != 'true' + run: | + cd w3emc + mkdir build + cd build + cmake .. -DCMAKE_INSTALL_PREFIX=~/w3emc -DCMAKE_PREFIX_PATH=~/bacio + make -j2 + make install + + - name: cache-nemsio + id: cache-nemsio + uses: actions/cache@v2 + with: + path: ~/nemsio + key: Linux_versions-nemsio-${{ runner.os }}-${{ matrix.nemsio_version }} + + - name: checkout-nemsio + if: steps.cache-nemsio.outputs.cache-hit != 'true' + uses: actions/checkout@v2 + with: + repository: NOAA-EMC/NCEPLIBS-nemsio + path: nemsio + ref: v${{ matrix.nemsio_version }} + + - name: build-nemsio + if: steps.cache-nemsio.outputs.cache-hit != 'true' + run: | + cd nemsio + mkdir build + cd build + cmake -DCMAKE_INSTALL_PREFIX=~/nemsio -DCMAKE_PREFIX_PATH="~/bacio;~/w3emc" .. + make -j2 + make install + + - name: cache-sigio + id: cache-sigio + uses: actions/cache@v2 + with: + path: ~/sigio + key: Linux_versions-sigio-${{ runner.os }}-${{ matrix.sigio_version }} + + - name: checkout-sigio + if: steps.cache-sigio.outputs.cache-hit != 'true' + uses: actions/checkout@v2 + with: + repository: NOAA-EMC/NCEPLIBS-sigio + path: sigio + ref: v${{ matrix.sigio_version }} + + - name: build-sigio + if: steps.cache-sigio.outputs.cache-hit != 'true' + run: | + cd sigio + mkdir build + cd build + cmake .. -DCMAKE_INSTALL_PREFIX=~/sigio + make -j2 + make install + + - name: checkout + uses: actions/checkout@v2 + with: + path: ufs_utils + submodules: true + + - name: cache-data + id: cache-data + uses: actions/cache@v2 + with: + path: ~/data + key: data-1 + + - name: build + run: | + set -x + cd ufs_utils + mkdir build + cd build + export ESMFMKFILE=~/esmf/lib/esmf.mk + cmake -DTEST_FILE_DIR=/home/runner/data -DCMAKE_PREFIX_PATH="~/jasper;~/g2c;~/bacio;~/g2;~/w3emc;~/sfcio;~/sigio;~/nemsio;~/sp;~/ip" .. + make -j2 VERBOSE=1 + + - name: test + run: | + cd ufs_utils/build + ctest --verbose --rerun-failed --output-on-failure + + - name: cache-data + if: steps.cache-data.outputs.cache-hit != 'true' + run: | + mkdir ~/data + cp ufs_utils/build/tests/chgres_cube/data/* ~/data + cp ufs_utils/build/tests/sfc_climo_gen/data/* ~/data + cp ufs_utils/build/tests/cpld_gridgen/data/* ~/data + cp ufs_utils/tests/filter_topo/data/* ~/data + cp ufs_utils/tests/emcsfc_snow2mdl/data/* ~/data + cp ufs_utils/tests/chgres_cube/data/* ~/data + ls -l ~/data diff --git a/.github/workflows/Linux_versions_ext.yml b/.github/workflows/Linux_versions_ext.yml new file mode 100644 index 000000000..954458e2a --- /dev/null +++ b/.github/workflows/Linux_versions_ext.yml @@ -0,0 +1,367 @@ +# UFS_UTILS test workflow. +# +# Check different versions of the external libraries that are used by UFS_UTILS. +# +# Ed Hartnett 12/16/22 +name: Linux_versions_ext +on: + push: + branches: + - develop + paths-ignore: + - README.md + pull_request: + branches: + - develop + paths-ignore: + - README.md + +defaults: + run: + shell: bash -exo pipefail {0} + +jobs: + Linux_versions_ext: + runs-on: ubuntu-latest + env: + FC: mpifort + CC: mpicc + FCFLAGS: -fallow-argument-mismatch + strategy: + fail-fast: true + matrix: + esmf_version: [8_2_0, 8.3.1, 8.4.0] + bacio_version: [2.4.1] + g2_version: [3.4.3] + sp_version: [2.3.3] + ip_version: [3.3.3] + w3emc_version: [2.9.3] + nemsio_version: [2.5.0] + sfcio_version: [1.4.0] + sigio_version: [2.3.0] + + steps: + + - name: install-dependencies + run: | + sudo apt-get update + sudo apt-get install libpng-dev zlib1g-dev libjpeg-dev libmpich-dev + sudo apt-get install libnetcdf-dev libnetcdff-dev netcdf-bin pkg-config + sudo apt-get install autoconf automake libtool + + - name: checkout-esmf + id: cache-esmf + uses: actions/cache@v2 + with: + path: ~/esmf + key: Linux_versions-esmf-${{ matrix.esmf_version }}-${{ runner.os }} + + - name: build-esmf + if: steps.cache-esmf.outputs.cache-hit != 'true' + run: | + pushd ~ + if [[ ${{ matrix.esmf_version }} == "8_2_0" ]]; then + wget https://github.com/esmf-org/esmf/archive/ESMF_${{ matrix.esmf_version }}.tar.gz &> /dev/null + tar zxf ESMF_${{ matrix.esmf_version }}.tar.gz + cd esmf-ESMF_${{ matrix.esmf_version }} + export ESMF_DIR=~/esmf-ESMF_${{ matrix.esmf_version }} + else + wget https://github.com/esmf-org/esmf/archive/refs/tags/v${{ matrix.esmf_version }}.tar.gz &> /dev/null + ls -l + tar zxf v${{ matrix.esmf_version }}.tar.gz + cd esmf-${{ matrix.esmf_version }} + export ESMF_DIR=~/esmf-${{ matrix.esmf_version }} + fi + export ESMF_COMM=mpich3 + export ESMF_INSTALL_BINDIR=bin + export ESMF_INSTALL_LIBDIR=lib + export ESMF_INSTALL_MODDIR=mod + export ESMF_COMPILER=gfortran + export ESMF_INSTALL_PREFIX=~/esmf + export ESMF_NETCDF=split + export ESMF_NETCDF_INCLUDE=/usr/include + export ESMF_NETCDF_LIBPATH=/usr/x86_64-linux-gnu + export ESMF_PIO=OFF + export ESMF_MOAB=OFF + export ESMF_ARRAY_LITE=TRUE + make -j2 + make install + + - name: cache-jasper + id: cache-jasper + uses: actions/cache@v2 + with: + path: ~/jasper + key: Linux_versions-jasper-${{ runner.os }}-2.0.33-1 + + - name: checkout-jasper + if: steps.cache-jasper.outputs.cache-hit != 'true' + uses: actions/checkout@v2 + with: + repository: jasper-software/jasper + path: jasper + ref: version-2.0.33 + + - name: build-jasper + if: steps.cache-jasper.outputs.cache-hit != 'true' + run: | + cd jasper + mkdir build-jasper && cd build-jasper + cmake .. -DCMAKE_INSTALL_PREFIX=~/jasper + make -j2 + make install + + - name: cache-bacio + id: cache-bacio + uses: actions/cache@v2 + with: + path: ~/bacio + key: Linux_versions-bacio-${{ runner.os }}-${{ matrix.bacio_version }} + + - name: checkout-bacio + if: steps.cache-bacio.outputs.cache-hit != 'true' + uses: actions/checkout@v2 + with: + repository: NOAA-EMC/NCEPLIBS-bacio + path: bacio + ref: v${{ matrix.bacio_version }} + + - name: build-bacio + if: steps.cache-bacio.outputs.cache-hit != 'true' + run: | + cd bacio + mkdir build && cd build + cmake .. -DCMAKE_INSTALL_PREFIX=~/bacio + make -j2 + make install + + - name: cache-g2 + id: cache-g2 + uses: actions/cache@v2 + with: + path: ~/g2 + key: Linux_versions-g2-${{ runner.os }}-${{ matrix.g2_version }} + + - name: checkout-g2 + if: steps.cache-g2.outputs.cache-hit != 'true' + uses: actions/checkout@v2 + with: + repository: NOAA-EMC/NCEPLIBS-g2 + path: g2 + ref: v${{ matrix.g2_version }} + + - name: build-g2 + if: steps.cache-g2.outputs.cache-hit != 'true' + run: | + cd g2 + mkdir build + cd build + cmake -DCMAKE_INSTALL_PREFIX=~/g2 -DCMAKE_PREFIX_PATH="~/bacio;~/jasper" .. + make -j2 + make install + + - name: cache-sp + id: cache-sp + uses: actions/cache@v2 + with: + path: ~/sp + key: Linux_versions-sp-${{ runner.os }}-${{ matrix.sp_version }} + + - name: checkout-sp + if: steps.cache-sp.outputs.cache-hit != 'true' + uses: actions/checkout@v2 + with: + repository: NOAA-EMC/NCEPLIBS-sp + path: sp + ref: v${{ matrix.sp_version }} + + - name: build-sp + if: steps.cache-sp.outputs.cache-hit != 'true' + run: | + cd sp + mkdir build + cd build + cmake .. -DCMAKE_INSTALL_PREFIX=~/sp + make -j2 + make install + + - name: cache-ip + id: cache-ip + uses: actions/cache@v2 + with: + path: ~/ip + key: Linux_versions-ip-${{ runner.os }}-${{ matrix.ip_version }} + + - name: checkout-ip + if: steps.cache-ip.outputs.cache-hit != 'true' + uses: actions/checkout@v2 + with: + repository: NOAA-EMC/NCEPLIBS-ip + path: ip + ref: v${{ matrix.ip_version }} + + - name: build-ip + if: steps.cache-ip.outputs.cache-hit != 'true' + run: | + cd ip + mkdir build + cd build + cmake -DCMAKE_INSTALL_PREFIX=~/ip -DCMAKE_PREFIX_PATH=~/sp .. + make -j2 + make install + + # - name: checkout-g2c + # uses: actions/checkout@v2 + # with: + # repository: NOAA-EMC/NCEPLIBS-g2c + # path: g2c + # ref: develop + + # - name: build-g2c + # run: | + # cd g2c + # mkdir build + # cd build + # cmake .. -DCMAKE_INSTALL_PREFIX=~/g2c -DJasper_ROOT=~/jasper + # make -j2 + # make install + + - name: cache-sfcio + id: cache-sfcio + uses: actions/cache@v2 + with: + path: ~/sfcio + key: Linux_versions-sfcio-${{ runner.os }}-${{ matrix.sfcio_version }} + + - name: checkout-sfcio + if: steps.cache-sfcio.outputs.cache-hit != 'true' + uses: actions/checkout@v2 + with: + repository: NOAA-EMC/NCEPLIBS-sfcio + path: sfcio + ref: v${{ matrix.sfcio_version }} + + - name: build-sfcio + if: steps.cache-sfcio.outputs.cache-hit != 'true' + run: | + cd sfcio + mkdir build + cd build + cmake .. -DCMAKE_INSTALL_PREFIX=~/sfcio + make -j2 + make install + + - name: cache-w3emc + id: cache-w3emc + uses: actions/cache@v2 + with: + path: ~/w3emc + key: Linux_versions-w3emc-${{ runner.os }}-${{ matrix.w3emc_version }} + + - name: checkout-w3emc + if: steps.cache-w3emc.outputs.cache-hit != 'true' + uses: actions/checkout@v2 + with: + repository: NOAA-EMC/NCEPLIBS-w3emc + path: w3emc + ref: v${{ matrix.w3emc_version }} + + - name: build-w3emc + if: steps.cache-w3emc.outputs.cache-hit != 'true' + run: | + cd w3emc + mkdir build + cd build + cmake .. -DCMAKE_INSTALL_PREFIX=~/w3emc -DCMAKE_PREFIX_PATH=~/bacio + make -j2 + make install + + - name: cache-nemsio + id: cache-nemsio + uses: actions/cache@v2 + with: + path: ~/nemsio + key: Linux_versions-nemsio-${{ runner.os }}-${{ matrix.nemsio_version }} + + - name: checkout-nemsio + if: steps.cache-nemsio.outputs.cache-hit != 'true' + uses: actions/checkout@v2 + with: + repository: NOAA-EMC/NCEPLIBS-nemsio + path: nemsio + ref: v${{ matrix.nemsio_version }} + + - name: build-nemsio + if: steps.cache-nemsio.outputs.cache-hit != 'true' + run: | + cd nemsio + mkdir build + cd build + cmake -DCMAKE_INSTALL_PREFIX=~/nemsio -DCMAKE_PREFIX_PATH="~/bacio;~/w3emc" .. + make -j2 + make install + + - name: cache-sigio + id: cache-sigio + uses: actions/cache@v2 + with: + path: ~/sigio + key: Linux_versions-sigio-${{ runner.os }}-${{ matrix.sigio_version }} + + - name: checkout-sigio + if: steps.cache-sigio.outputs.cache-hit != 'true' + uses: actions/checkout@v2 + with: + repository: NOAA-EMC/NCEPLIBS-sigio + path: sigio + ref: v${{ matrix.sigio_version }} + + - name: build-sigio + if: steps.cache-sigio.outputs.cache-hit != 'true' + run: | + cd sigio + mkdir build + cd build + cmake .. -DCMAKE_INSTALL_PREFIX=~/sigio + make -j2 + make install + + - name: checkout + uses: actions/checkout@v2 + with: + path: ufs_utils + submodules: true + + - name: cache-data + id: cache-data + uses: actions/cache@v2 + with: + path: ~/data + key: data-1 + + - name: build + run: | + set -x + cd ufs_utils + mkdir build + cd build + export ESMFMKFILE=~/esmf/lib/esmf.mk + cmake -DTEST_FILE_DIR=/home/runner/data -DCMAKE_PREFIX_PATH="~/jasper;~/g2c;~/bacio;~/g2;~/w3emc;~/sfcio;~/sigio;~/nemsio;~/sp;~/ip" .. + make -j2 VERBOSE=1 + + - name: test + run: | + cd ufs_utils/build + ctest --verbose --rerun-failed --output-on-failure + + - name: cache-data + if: steps.cache-data.outputs.cache-hit != 'true' + run: | + mkdir ~/data + cp ufs_utils/build/tests/chgres_cube/data/* ~/data + cp ufs_utils/build/tests/sfc_climo_gen/data/* ~/data + cp ufs_utils/build/tests/cpld_gridgen/data/* ~/data + cp ufs_utils/tests/filter_topo/data/* ~/data + cp ufs_utils/tests/emcsfc_snow2mdl/data/* ~/data + cp ufs_utils/tests/chgres_cube/data/* ~/data + ls -l ~/data diff --git a/.github/workflows/developer.yml b/.github/workflows/developer.yml new file mode 100644 index 000000000..14544b08c --- /dev/null +++ b/.github/workflows/developer.yml @@ -0,0 +1,350 @@ +# UFS_UTILS test workflow. +# +# This workflow tests all developer options including +# documentation check, and test code coverage. +# +# +# Ed Hartnett 12/11/22 +name: developer +on: + push: + branches: + - develop + paths-ignore: + - README.md + pull_request: + branches: + - develop + paths-ignore: + - README.md + +defaults: + run: + shell: bash -exo pipefail {0} + +jobs: + developer: + runs-on: ubuntu-latest + env: + FC: mpifort + CC: mpicc + FCFLAGS: -fallow-argument-mismatch + + steps: + + - name: install-dependencies + run: | + sudo apt-get update + sudo apt-get install libpng-dev zlib1g-dev libjpeg-dev doxygen libmpich-dev + sudo apt-get install libnetcdf-dev libnetcdff-dev netcdf-bin pkg-config + # python3 -m pip install gcovr + + - name: cache-esmf + id: cache-esmf + uses: actions/cache@v2 + with: + path: ~/esmf + key: developer-esmf-8.2.0-${{ runner.os }}3 + + - name: build-esmf + if: steps.cache-esmf.outputs.cache-hit != 'true' + run: | + pushd ~ + export ESMF_DIR=~/esmf-ESMF_8_2_0 + wget https://github.com/esmf-org/esmf/archive/ESMF_8_2_0.tar.gz &> /dev/null + tar zxf ESMF_8_2_0.tar.gz + cd esmf-ESMF_8_2_0 + export ESMF_COMM=mpich3 + export ESMF_INSTALL_BINDIR=bin + export ESMF_INSTALL_LIBDIR=lib + export ESMF_INSTALL_MODDIR=mod + export ESMF_COMPILER=gfortran + export ESMF_INSTALL_PREFIX=~/esmf + export ESMF_NETCDF=split + export ESMF_NETCDF_INCLUDE=/usr/include + export ESMF_NETCDF_LIBPATH=/usr/x86_64-linux-gnu + make -j2 + make install + + - name: cache-jasper + id: cache-jasper + uses: actions/cache@v2 + with: + path: ~/jasper + key: developer-jasper-${{ runner.os }}-2.0.33-1 + + - name: checkout-jasper + if: steps.cache-jasper.outputs.cache-hit != 'true' + uses: actions/checkout@v2 + with: + repository: jasper-software/jasper + path: jasper + ref: version-2.0.33 + + - name: build-jasper + if: steps.cache-jasper.outputs.cache-hit != 'true' + run: | + cd jasper + mkdir build-jasper && cd build-jasper + cmake .. -DCMAKE_INSTALL_PREFIX=~/jasper + make -j2 + make install + + - name: cache-bacio + id: cache-bacio + uses: actions/cache@v2 + with: + path: ~/bacio + key: developer-bacio-${{ runner.os }}-v2.4.1 + + - name: checkout-bacio + if: steps.cache-bacio.outputs.cache-hit != 'true' + uses: actions/checkout@v2 + with: + repository: NOAA-EMC/NCEPLIBS-bacio + path: bacio + ref: v2.4.1 + + - name: build-bacio + if: steps.cache-bacio.outputs.cache-hit != 'true' + run: | + cd bacio + mkdir build && cd build + cmake .. -DCMAKE_INSTALL_PREFIX=~/bacio + make -j2 + make install + + - name: cache-g2 + id: cache-g2 + uses: actions/cache@v2 + with: + path: ~/g2 + key: developer-g2-${{ runner.os }}-3.4.5 + + - name: checkout-g2 + if: steps.cache-g2.outputs.cache-hit != 'true' + uses: actions/checkout@v2 + with: + repository: NOAA-EMC/NCEPLIBS-g2 + path: g2 + ref: v3.4.5 + + - name: build-g2 + if: steps.cache-g2.outputs.cache-hit != 'true' + run: | + cd g2 + mkdir build + cd build + cmake -DCMAKE_INSTALL_PREFIX=~/g2 -DCMAKE_PREFIX_PATH="~/bacio;~/jasper" .. + make -j2 + make install + + - name: cache-sp + id: cache-sp + uses: actions/cache@v2 + with: + path: ~/sp + key: developer-sp-${{ runner.os }}-2.3.3-1 + + - name: checkout-sp + if: steps.cache-sp.outputs.cache-hit != 'true' + uses: actions/checkout@v2 + with: + repository: NOAA-EMC/NCEPLIBS-sp + path: sp + ref: v2.3.3 + + - name: build-sp + if: steps.cache-sp.outputs.cache-hit != 'true' + run: | + cd sp + mkdir build + cd build + cmake .. -DCMAKE_INSTALL_PREFIX=~/sp + make -j2 + make install + + - name: cache-ip + id: cache-ip + uses: actions/cache@v2 + with: + path: ~/ip + key: developer-ip-${{ runner.os }}-3.3.3 + + - name: checkout-ip + if: steps.cache-ip.outputs.cache-hit != 'true' + uses: actions/checkout@v2 + with: + repository: NOAA-EMC/NCEPLIBS-ip + path: ip + ref: v3.3.3 + + - name: build-ip + if: steps.cache-ip.outputs.cache-hit != 'true' + run: | + cd ip + mkdir build + cd build + cmake -DCMAKE_INSTALL_PREFIX=~/ip -DCMAKE_PREFIX_PATH=~~/sp .. + make -j2 + make install + + - name: checkout-w3emc + uses: actions/checkout@v2 + with: + repository: NOAA-EMC/NCEPLIBS-w3emc + path: w3emc + ref: v2.9.3 + + - name: build-w3emc + run: | + cd w3emc + mkdir build + cd build + cmake -DCMAKE_PREFIX_PATH=~/bacio -DCMAKE_INSTALL_PREFIX=~/w3emc .. + make -j2 + make install + + # - name: checkout-g2c + # uses: actions/checkout@v2 + # with: + # repository: NOAA-EMC/NCEPLIBS-g2c + # path: g2c + # ref: develop + + # - name: build-g2c + # run: | + # cd g2c + # mkdir build + # cd build + # cmake .. -DCMAKE_INSTALL_PREFIX=~/g2c -DJasper_ROOT=~/jasper + # make -j2 + # make install + + - name: cache-sfcio + id: cache-sfcio + uses: actions/cache@v2 + with: + path: ~/sfcio + key: developer-sfcio-${{ runner.os }}-1.4.1 + + - name: checkout-sfcio + if: steps.cache-sfcio.outputs.cache-hit != 'true' + uses: actions/checkout@v2 + with: + repository: NOAA-EMC/NCEPLIBS-sfcio + path: sfcio + ref: v1.4.1 + + - name: build-sfcio + if: steps.cache-sfcio.outputs.cache-hit != 'true' + run: | + cd sfcio + mkdir build + cd build + cmake .. -DCMAKE_INSTALL_PREFIX=~/sfcio + make -j2 + make install + + - name: cache-nemsio + id: cache-nemsio + uses: actions/cache@v2 + with: + path: ~/nemsio + key: developer-nemsio-${{ runner.os }}-2.5.4 + + - name: checkout-nemsio + if: steps.cache-nemsio.outputs.cache-hit != 'true' + uses: actions/checkout@v2 + with: + repository: NOAA-EMC/NCEPLIBS-nemsio + path: nemsio + ref: v2.5.4 + + - name: build-nemsio + if: steps.cache-nemsio.outputs.cache-hit != 'true' + run: | + cd nemsio + mkdir build + cd build + cmake -DCMAKE_INSTALL_PREFIX=~/nemsio -DCMAKE_PREFIX_PATH="~/bacio;~/w3emc" .. + make -j2 + make install + + - name: cache-sigio + id: cache-sigio + uses: actions/cache@v2 + with: + path: ~/sigio + key: developer-sigio-${{ runner.os }}-2.3.2 + + - name: checkout-sigio + if: steps.cache-sigio.outputs.cache-hit != 'true' + uses: actions/checkout@v2 + with: + repository: NOAA-EMC/NCEPLIBS-sigio + path: sigio + ref: v2.3.2 + + - name: build-sigio + if: steps.cache-sigio.outputs.cache-hit != 'true' + run: | + cd sigio + mkdir build + cd build + cmake .. -DCMAKE_INSTALL_PREFIX=~/sigio + make -j2 + make install + + - name: checkout + uses: actions/checkout@v2 + with: + path: ufs_utils + submodules: true + + - name: cache-data + id: cache-data + uses: actions/cache@v2 + with: + path: ~/data + key: data-1 + + - name: build + run: | + cd ufs_utils + mkdir build + doxygen --version + export ESMFMKFILE=~/esmf/lib/esmf.mk + cd build + cmake -DTEST_FILE_DIR=/home/runner/data -DENABLE_DOCS=On -DCMAKE_PREFIX_PATH="~/jasper;~/g2c;~/bacio;~/g2;~/w3emc;~/sfcio;~/sigio;~/nemsio;~/sp;~/ip" -DCMAKE_Fortran_FLAGS="-g -fprofile-arcs -ftest-coverage -O0" -DCMAKE_C_FLAGS="-g -fprofile-arcs -ftest-coverage -O0" -DCMAKE_BUILD_TYPE=Debug .. + make -j2 VERBOSE=1 + + - name: test + run: | + cd ufs_utils/build + ctest --verbose --rerun-failed --output-on-failure + # gcovr --root .. -v --html-details --exclude ../tests --exclude CMakeFiles --print-summary -o test-coverage.html &> /dev/null + + - name: cache-data + if: steps.cache-data.outputs.cache-hit != 'true' + run: | + mkdir ~/data + cp ufs_utils/build/tests/chgres_cube/data/* ~/data + cp ufs_utils/build/tests/sfc_climo_gen/data/* ~/data + cp ufs_utils/build/tests/cpld_gridgen/data/* ~/data + cp ufs_utils/tests/filter_topo/data/* ~/data + cp ufs_utils/tests/emcsfc_snow2mdl/data/* ~/data + cp ufs_utils/tests/chgres_cube/data/* ~/data + ls -l ~/data + + - name: upload-test-coverage + uses: actions/upload-artifact@v2 + with: + name: ufs_utils-test-coverage + path: | + ufs_utils/build/*.html + ufs_utils/build/*.css + + + + diff --git a/.github/workflows/linux-mac-nceplibs-mpi.yml b/.github/workflows/linux-mac-nceplibs-mpi.yml index e0f29b610..43d611949 100644 --- a/.github/workflows/linux-mac-nceplibs-mpi.yml +++ b/.github/workflows/linux-mac-nceplibs-mpi.yml @@ -1,5 +1,15 @@ name: linux-mac-mpi-nceplibs -on: [push, pull_request] +on: + push: + branches: + - develop + paths-ignore: + - README.md + pull_request: + branches: + - develop + paths-ignore: + - README.md defaults: run: @@ -13,10 +23,11 @@ jobs: FC: gfortran-9 CXX: g++-9 strategy: + fail-fast: true matrix: - os: [macos-10.15, ubuntu-20.04] + os: [macos-11, ubuntu-latest] compiler: [gcc-9] - nceplibs_version: [develop, 1.3.0] + nceplibs_version: [develop, 1.4.0] mpi_type: [mpich, openmpi] netcdf_version: [4.7.4] @@ -25,20 +36,20 @@ jobs: - name: install-dependencies run: | echo "$HOME/mpi/bin" >> $GITHUB_PATH - if [[ ${{ matrix.os }} == "ubuntu-20.04" ]]; then + if [[ ${{ matrix.os }} == "ubuntu-latest" ]]; then sudo apt-get update sudo apt-get install libpng-dev sudo apt-get install libjpeg-dev - elif [[ ${{ matrix.os }} == "macos-10.15" ]]; then - brew update + elif [[ ${{ matrix.os }} == "macos-11" ]]; then + brew update brew install wget + brew install jpeg-turbo if [[ ${{ matrix.compiler }} == "gcc-9" ]]; then sudo ln -sf /usr/local/bin/gfortran-9 /usr/local/bin/gfortran elif [[ ${{ matrix.compiler }} == "gcc-10" ]]; then sudo ln -sf /usr/local/bin/gfortran-10 /usr/local/bin/gfortran fi fi - python3 -m pip install gcovr - name: cache-mpi id: cache-mpi @@ -61,9 +72,9 @@ jobs: wget https://download.open-mpi.org/release/open-mpi/v4.1/openmpi-4.1.1.tar.gz &> /dev/null tar -xzf openmpi-4.1.1.tar.gz cd openmpi-4.1.1 - if [[ ${{ matrix.os }} == "ubuntu-20.04" ]]; then + if [[ ${{ matrix.os }} == "ubuntu-latest" ]]; then ./configure --prefix=$HOME/mpi --enable-mpi-fortran --enable-mpi-cxx - elif [[ ${{ matrix.os }} == "macos-10.15" ]]; then + elif [[ ${{ matrix.os }} == "macos-11" ]]; then ./configure --prefix=$HOME/mpi --enable-mpi-fortran --enable-mpi-cxx --enable-two-level-namespace fi make -j2 @@ -75,7 +86,7 @@ jobs: uses: actions/cache@v2 with: path: ~/netcdf - key: netcdf-c-${{ matrix.netcdf_version }}-${{ runner.os }}-${{ matrix.mpi_type }} + key: netcdf-c-${{ matrix.netcdf_version }}-${{ runner.os }}-${{ matrix.mpi_type }}3 - name: build-hdf5 if: steps.cache-netcdf.outputs.cache-hit != 'true' @@ -84,7 +95,7 @@ jobs: wget https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.10/hdf5-1.10.7/src/hdf5-1.10.7.tar.gz &> /dev/null tar -xzf hdf5-1.10.7.tar.gz pushd hdf5-1.10.7 - ./configure --prefix=${HOME}/netcdf --enable-parallel --disable-tools --disable-fortran --disable-cxx --enable-parallel-tests + ./configure --prefix=${HOME}/netcdf --enable-parallel --disable-tools --disable-fortran --disable-cxx --enable-parallel-tests --disable-shared --enable-static make -j2 make install @@ -94,10 +105,10 @@ jobs: export CC=mpicc export CPPFLAGS=-I${HOME}/netcdf/include export LDFLAGS=-L${HOME}/netcdf/lib - wget https://www.unidata.ucar.edu/downloads/netcdf/ftp/netcdf-c-${{ matrix.netcdf_version }}.tar.gz &> /dev/null - tar -xzf netcdf-c-${{ matrix.netcdf_version }}.tar.gz + wget https://github.com/Unidata/netcdf-c/archive/refs/tags/v${{ matrix.netcdf_version }}.tar.gz &> /dev/null + tar -xzf v${{ matrix.netcdf_version }}.tar.gz cd netcdf-c-${{ matrix.netcdf_version }} - ./configure --prefix=${HOME}/netcdf --disable-dap --disable-utilities + ./configure --prefix=${HOME}/netcdf --disable-dap --disable-utilities --disable-shared make -j2 make install @@ -110,10 +121,11 @@ jobs: export FC=mpifort export CPPFLAGS=-I${HOME}/netcdf/include export LDFLAGS=-L${HOME}/netcdf/lib + export LIBS=`nc-config --libs` wget https://github.com/Unidata/netcdf-fortran/archive/v4.5.3.tar.gz &> /dev/null tar -xzf v4.5.3.tar.gz pushd netcdf-fortran-4.5.3 - ./configure --prefix=${HOME}/netcdf + ./configure --prefix=${HOME}/netcdf --disable-shared make -j2 make install @@ -122,17 +134,17 @@ jobs: uses: actions/cache@v2 with: path: ~/esmf - key: esmf--8.0.1-${{ runner.os }}-${{ matrix.mpi_type }}-netcdf-${{ matrix.netcdf_version }} + key: esmf--8.2.0-${{ runner.os }}-${{ matrix.mpi_type }}-netcdf-${{ matrix.netcdf_version }}3 - name: build-esmf if: steps.cache-esmf.outputs.cache-hit != 'true' run: | set -x pushd ~ - export ESMF_DIR=~/esmf-ESMF_8_0_1 - wget https://github.com/esmf-org/esmf/archive/ESMF_8_0_1.tar.gz &> /dev/null - tar zxf ESMF_8_0_1.tar.gz - cd esmf-ESMF_8_0_1 + export ESMF_DIR=~/esmf-ESMF_8_2_0 + wget https://github.com/esmf-org/esmf/archive/ESMF_8_2_0.tar.gz &> /dev/null + tar zxf ESMF_8_2_0.tar.gz + cd esmf-ESMF_8_2_0 if [[ ${{ matrix.mpi_type}} == "mpich" ]]; then export ESMF_COMM=mpich3 elif [[ ${{ matrix.mpi_type}} == "openmpi" ]]; then @@ -146,6 +158,7 @@ jobs: export ESMF_NETCDF=split export ESMF_NETCDF_INCLUDE=${HOME}/netcdf/include export ESMF_NETCDF_LIBPATH=${HOME}/netcdf/lib + export ESMF_NETCDF_LIBS="-lnetcdff -lnetcdf -lhdf5_hl -lhdf5 -lz" make -j2 make install @@ -154,7 +167,7 @@ jobs: uses: actions/cache@v2 with: path: ~/jasper - key: jasper-2.0.25-${{ runner.os }} + key: jasper-2.0.25-${{ runner.os }}3 - name: build-jasper if: steps.cache-jasper.outputs.cache-hit != 'true' @@ -165,7 +178,7 @@ jobs: tar zxf version-2.0.25.tar.gz cd jasper-version-2.0.25 mkdir build-jasper && cd build-jasper - cmake .. -DCMAKE_INSTALL_PREFIX=~/jasper + cmake .. -DCMAKE_INSTALL_PREFIX=~/jasper -DJAS_ENABLE_SHARED=OFF make -j2 make install @@ -173,8 +186,8 @@ jobs: run: | git clone https://github.com/NOAA-EMC/NCEPLIBS.git nceplibs cd nceplibs - if [[ ${{ matrix.nceplibs_version }} == "1.3.0" ]]; then - git checkout v1.3.0 + if [[ ${{ matrix.nceplibs_version }} == "1.4.0" ]]; then + git checkout v1.4.0 fi - name: get-git-hash @@ -187,7 +200,7 @@ jobs: uses: actions/cache@v2 with: path: ~/nceplibs - key: nceplibs-${{ matrix.nceplibs_version }}-${{ runner.os }}-${{ matrix.mpi_type }}-${{ hashFiles('nceplibs/hash.txt') }} + key: nceplibs-${{ matrix.nceplibs_version }}-${{ runner.os }}-${{ matrix.mpi_type }}-${{ hashFiles('nceplibs/hash.txt') }}3 - name: build-nceplibs if: steps.cache-nceplibs.outputs.cache-hit != 'true' @@ -203,6 +216,14 @@ jobs: uses: actions/checkout@v2 with: path: ufs_utils + submodules: recursive + + - name: cache-data + id: cache-data + uses: actions/cache@v2 + with: + path: ~/data + key: data-2 - name: build run: | @@ -212,15 +233,27 @@ jobs: export CC=mpicc export CXX=mpicxx export FC=mpifort - cmake .. -DCMAKE_PREFIX_PATH='~/jasper;~/nceplibs;~/netcdf' + export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:~/jasper/lib;~/jasper/lib64" + export DYLD_LIBRARY_PATH="${LD_LIBRARY_PATH}:~/jasper/lib;~/jasper/lib64" + cmake -DTEST_FILE_DIR=/home/runner/data -DCMAKE_PREFIX_PATH='~/jasper;~/nceplibs;~/netcdf' .. make -j2 - name: test run: | - cd ufs_utils/build/tests - wget -i ./chgres_cube/data/files.txt -P ./chgres_cube/data - wget -i ./sfc_climo_gen/data/files.txt -P ./sfc_climo_gen/data - cd ../ + cd ufs_utils/build # Oversubscribe for OpenMPI to run more processes than CPUs export OMPI_MCA_rmaps_base_oversubscribe=1 ctest --rerun-failed --output-on-failure + + - name: cache-data + if: steps.cache-data.outputs.cache-hit != 'true' + run: | + mkdir ~/data + cp ufs_utils/build/tests/chgres_cube/data/* ~/data + cp ufs_utils/build/tests/sfc_climo_gen/data/* ~/data + cp ufs_utils/build/tests/cpld_gridgen/data/* ~/data + cp ufs_utils/tests/filter_topo/data/* ~/data + cp ufs_utils/tests/emcsfc_snow2mdl/data/* ~/data + cp ufs_utils/tests/chgres_cube/data/* ~/data + ls -l ~/data + diff --git a/.github/workflows/netcdf-versions.yml b/.github/workflows/netcdf-versions.yml index 53cad1f20..c9a0a6f9c 100644 --- a/.github/workflows/netcdf-versions.yml +++ b/.github/workflows/netcdf-versions.yml @@ -1,5 +1,15 @@ name: netcdf-versions -on: [push, pull_request] +on: + push: + branches: + - develop + paths-ignore: + - README.md + pull_request: + branches: + - develop + paths-ignore: + - README.md defaults: run: @@ -18,17 +28,14 @@ jobs: - name: install-dependencies run: | sudo apt-get update - sudo apt-get install libmpich-dev - sudo apt-get install doxygen - sudo apt-get install libpng-dev - sudo apt-get install libjpeg-dev + sudo apt-get install libmpich-dev libpng-dev libjpeg-dev - name: cache-netcdf id: cache-netcdf uses: actions/cache@v2 with: path: ~/netcdf - key: netcdf-c-${{ matrix.netcdf_version }}-${{ runner.os }} + key: netcdf-c-${{ matrix.netcdf_version }}-${{ runner.os }}4 - name: build-hdf5 if: steps.cache-netcdf.outputs.cache-hit != 'true' @@ -37,7 +44,7 @@ jobs: wget https://support.hdfgroup.org/ftp/HDF5/releases/hdf5-1.10/hdf5-1.10.7/src/hdf5-1.10.7.tar.gz &> /dev/null tar -xzf hdf5-1.10.7.tar.gz pushd hdf5-1.10.7 - ./configure --prefix=${HOME}/netcdf --enable-parallel --disable-tools --disable-fortran --disable-cxx --enable-parallel-tests + ./configure --prefix=${HOME}/netcdf --enable-parallel --disable-tools --disable-fortran --disable-cxx --disable-shared make -j2 make install @@ -47,10 +54,10 @@ jobs: export CC=mpicc export CPPFLAGS=-I${HOME}/netcdf/include export LDFLAGS=-L${HOME}/netcdf/lib - wget https://www.unidata.ucar.edu/downloads/netcdf/ftp/netcdf-c-${{ matrix.netcdf_version }}.tar.gz &> /dev/null - tar -xzf netcdf-c-${{ matrix.netcdf_version }}.tar.gz + wget https://github.com/Unidata/netcdf-c/archive/refs/tags/v${{ matrix.netcdf_version }}.tar.gz &> /dev/null + tar -xzf v${{ matrix.netcdf_version }}.tar.gz cd netcdf-c-${{ matrix.netcdf_version }} - ./configure --prefix=${HOME}/netcdf --disable-dap --disable-utilities + ./configure --prefix=${HOME}/netcdf --disable-dap --disable-utilities --disable-shared make -j2 make install @@ -63,10 +70,11 @@ jobs: export FC=mpifort export CPPFLAGS=-I${HOME}/netcdf/include export LDFLAGS=-L${HOME}/netcdf/lib + export LIBS=`nc-config --libs` wget https://github.com/Unidata/netcdf-fortran/archive/v4.5.3.tar.gz &> /dev/null tar -xzf v4.5.3.tar.gz pushd netcdf-fortran-4.5.3 - ./configure --prefix=${HOME}/netcdf + ./configure --prefix=${HOME}/netcdf --disable-shared make -j2 make install @@ -75,16 +83,16 @@ jobs: uses: actions/cache@v2 with: path: ~/esmf - key: esmf-8.0.1-${{ runner.os }}-netcdf-${{ matrix.netcdf_version }} + key: esmf-8.2.0-${{ runner.os }}-netcdf-${{ matrix.netcdf_version }}3 - name: build-esmf - #if: steps.cache-esmf.outputs.cache-hit != 'true' + if: steps.cache-esmf.outputs.cache-hit != 'true' run: | pushd ~ - export ESMF_DIR=~/esmf-ESMF_8_0_1 - wget https://github.com/esmf-org/esmf/archive/ESMF_8_0_1.tar.gz &> /dev/null - tar zxf ESMF_8_0_1.tar.gz - cd esmf-ESMF_8_0_1 + export ESMF_DIR=~/esmf-ESMF_8_2_0 + wget https://github.com/esmf-org/esmf/archive/ESMF_8_2_0.tar.gz &> /dev/null + tar zxf ESMF_8_2_0.tar.gz + cd esmf-ESMF_8_2_0 export ESMF_COMM=mpich3 export ESMF_INSTALL_BINDIR=bin export ESMF_INSTALL_LIBDIR=lib @@ -94,6 +102,7 @@ jobs: export ESMF_NETCDF=split export ESMF_NETCDF_INCLUDE=${HOME}/netcdf/include export ESMF_NETCDF_LIBPATH=${HOME}/netcdf/lib + export ESMF_NETCDF_LIBS="-lnetcdff -lnetcdf -lhdf5_hl -lhdf5 -lz" make -j2 make install @@ -102,7 +111,7 @@ jobs: uses: actions/cache@v2 with: path: ~/jasper - key: jasper-2.0.25-${{ runner.os }} + key: jasper-2.0.25-${{ runner.os }}3 - name: build-jasper if: steps.cache-jasper.outputs.cache-hit != 'true' @@ -111,7 +120,7 @@ jobs: tar zxf version-2.0.25.tar.gz cd jasper-version-2.0.25 mkdir build-jasper && cd build-jasper - cmake .. -DCMAKE_INSTALL_PREFIX=~/jasper + cmake .. -DCMAKE_INSTALL_PREFIX=~/jasper -DJAS_ENABLE_SHARED=OFF make -j2 make install @@ -120,14 +129,14 @@ jobs: uses: actions/cache@v2 with: path: ~/nceplibs - key: nceplibs-1.3.0-${{ runner.os }}-netcdf-${{ matrix.netcdf_version }} + key: nceplibs-1.4.0-${{ runner.os }}-netcdf-${{ matrix.netcdf_version }}3 - name: build-nceplibs if: steps.cache-nceplibs.outputs.cache-hit != 'true' run: | - wget https://github.com/NOAA-EMC/NCEPLIBS/archive/v1.3.0.tar.gz &> /dev/null - tar zxf v1.3.0.tar.gz - cd NCEPLIBS-1.3.0 + wget https://github.com/NOAA-EMC/NCEPLIBS/archive/v1.4.0.tar.gz &> /dev/null + tar zxf v1.4.0.tar.gz + cd NCEPLIBS-1.4.0 export ESMFMKFILE=~/esmf/lib/esmf.mk mkdir build && cd build cmake .. -DCMAKE_PREFIX_PATH='~;~/jasper;~/netcdf' -DCMAKE_INSTALL_PREFIX='~/nceplibs' -DFLAT=ON @@ -137,6 +146,14 @@ jobs: uses: actions/checkout@v2 with: path: ufs_utils + submodules: recursive + + - name: cache-data + id: cache-data + uses: actions/cache@v2 + with: + path: ~/data + key: data-1 - name: build run: | @@ -146,14 +163,24 @@ jobs: export CC=mpicc export CXX=mpicxx export FC=mpifort - cmake .. -DCMAKE_PREFIX_PATH='~/jasper;~/nceplibs;~/netcdf' -DCMAKE_BUILD_TYPE=Debug + export LD_LIBRARY_PATH="${LD_LIBRARY_PATH}:~/jasper/lib;~/jasper/lib64" + cmake -DTEST_FILE_DIR=/home/runner/work/UFS_UTILS/UFS_UTILS/data -DCMAKE_PREFIX_PATH='~/jasper;~/nceplibs;~/netcdf' .. make -j2 - - name: test run: | - cd ufs_utils/build/tests - wget -i ./chgres_cube/data/files.txt -P ./chgres_cube/data - wget -i ./sfc_climo_gen/data/files.txt -P ./sfc_climo_gen/data - cd ../ - export LSAN_OPTIONS=suppressions=LSanSuppress.supp + cd ufs_utils/build ctest --rerun-failed --output-on-failure + + - name: cache-data + if: steps.cache-data.outputs.cache-hit != 'true' + run: | + mkdir ~/data + cp ufs_utils/build/tests/chgres_cube/data/* ~/data + cp ufs_utils/build/tests/sfc_climo_gen/data/* ~/data + cp ufs_utils/build/tests/cpld_gridgen/data/* ~/data + cp ufs_utils/tests/filter_topo/data/* ~/data + cp ufs_utils/tests/emcsfc_snow2mdl/data/* ~/data + cp ufs_utils/tests/chgres_cube/data/* ~/data + ls -l ~/data + + diff --git a/.gitignore b/.gitignore index 683f653b3..de3cfc8f8 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,11 @@ install/ exec/ lib/ +fix/am +fix/orog +fix/orog_raw +fix/sfc_climo + *.[ao] *.mod *.so diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 000000000..7633c3cf4 --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "ccpp"] + path = ccpp-physics + url = https://github.com/ufs-community/ccpp-physics.git diff --git a/CMakeLists.txt b/CMakeLists.txt index fd4835caa..4278cc9f8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,41 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") option(OPENMP "use OpenMP threading" ON) option(ENABLE_DOCS "Enable generation of doxygen-based documentation." OFF) +# Utilities to be built (Default: ALL) +option(ICEBLEND "Enable building emcsfc_ice_blend.fd" ON) +option(SNOW2MDL "Enable building emcsfc_snow2mdl.fd" ON) +option(GCYCLE "Enable building global_cycle.fd" ON) +option(FRENCTOOLS "Enable building fre-nctools.fd" ON) +option(GRIDTOOLS "Enable building grid_tools.fd" ON) +option(CHGRES "Enable building chgres_cube.fd" ON) +option(OROG_MASK_TOOLS "Enable building orog_mask_tools.fd" ON) +option(SFC_CLIMO_GEN "Enable building sfc_climo_gen.fd" ON) +option(VCOORD_GEN "Enable building vcoord_gen.fd" ON) +option(FVCOMTOOLS "Enable building fvcom_tools.fd" ON) +option(GBLEVENTS "Enable building gblevents.fd" ON) +option(CPLD_GRIDGEN "Enable building cpld_gridgen.fd" ON) +option(WEIGHT_GEN "Enable building weight_gen.fd" ON) + +# Option to build application specific utilities +option(GFS "Enable building GFS-only utilities" OFF) + +# When building the GFS, the following need not be built +if(GFS) + message(STATUS "Building utilities specific to the GFS") + set(FRENCTOOLS OFF CACHE BOOL "Disable building fre-nctools.fd" FORCE) + set(GRIDTOOLS OFF CACHE BOOL "Disable building grid_tools.fd" FORCE) + set(OROG_MASK_TOOLS OFF CACHE BOOL "Disable building orog_mask_tools.fd" FORCE) + set(SFC_CLIMO_GEN OFF CACHE BOOL "Disable building sfc_climo_gen.fd" FORCE) + set(VCOORD_GEN OFF CACHE BOOL "Disable building vcoord_gen.fd" FORCE) + set(FVCOMTOOLS OFF CACHE BOOL "Disable building fvcom_tools.fd" FORCE) + set(GBLEVENTS OFF CACHE BOOL "Disable building gblevents.fd" FORCE) + set(CPLD_GRIDGEN OFF CACHE BOOL "Disable building cpld_gridgen.fd" FORCE) + set(WEIGHT_GEN OFF CACHE BOOL "Disable building weight_gen.fd" FORCE) +endif() + +SET(TEST_FILE_DIR "." CACHE STRING "Check this directory for test files before using FTP.") + +# Set the build type. if(NOT CMAKE_BUILD_TYPE MATCHES "^(Debug|Release|RelWithDebInfo|MinSizeRel)$") message(STATUS "Setting build type to 'Release' as none was specified.") set(CMAKE_BUILD_TYPE @@ -23,19 +58,26 @@ if(NOT CMAKE_BUILD_TYPE MATCHES "^(Debug|Release|RelWithDebInfo|MinSizeRel)$") CACHE STRING "Choose the type of build." FORCE) set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo") - message(STATUS "Set BUILD_TESTING to YES and build unit testing package under tests") - set(BUILD_TESTING "YES") endif() # Set compiler flags. if(CMAKE_Fortran_COMPILER_ID MATCHES "^(Intel)$") set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -g -traceback") set(CMAKE_Fortran_FLAGS_RELEASE "-O3 -fp-model precise") - set(CMAKE_Fortran_FLAGS_DEBUG "-O0 -check -check noarg_temp_created -check nopointer -fp-stack-check -fstack-protector-all -fpe0 -debug -ftrapuv") + set(CMAKE_Fortran_FLAGS_DEBUG "-O0 -check all -ftrapuv") + if(APPLE) + # The linker on macOS does not include `common symbols` by default. + # Passing the -c flag includes them and fixes an error with undefined symbols. + set(CMAKE_Fortran_ARCHIVE_FINISH " -c ") + set(CMAKE_C_ARCHIVE_FINISH " -c ") + endif() elseif(CMAKE_Fortran_COMPILER_ID MATCHES "^(GNU)$") set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -g -fbacktrace") + if(${CMAKE_Fortran_COMPILER_VERSION} VERSION_GREATER_EQUAL 10) + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fallow-argument-mismatch -fallow-invalid-boz") + endif() set(CMAKE_Fortran_FLAGS_RELEASE "-O3") - set(CMAKE_Fortran_FLAGS_DEBUG "-O1 -ggdb -fno-unsafe-math-optimizations -frounding-math -fsignaling-nans -ffpe-trap=invalid,zero,overflow -fbounds-check -fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls") + set(CMAKE_Fortran_FLAGS_DEBUG "-O0 -ggdb -Wall -fcheck=all") endif() if(CMAKE_C_COMPILER_ID MATCHES "^(Intel)$") @@ -54,30 +96,29 @@ if(OPENMP) endif() find_package(sfcio 1.4.0 REQUIRED) -find_package(w3nco 2.4.0 REQUIRED) +find_package(w3emc 2.9.0 REQUIRED) find_package(bacio 2.4.0 REQUIRED) find_package(nemsio 2.5.0 REQUIRED) find_package(sigio 2.3.0 REQUIRED) find_package(sp 2.3.3 REQUIRED) find_package(ip 3.3.3 REQUIRED) -find_package(g2 3.4.0 REQUIRED) -find_package(wgrib2 2.0.8 REQUIRED) +find_package(g2 3.4.3 REQUIRED) find_package(sigio 2.3.0 REQUIRED) -# EMC requires executables in ./exec -set(exec_dir bin) -if(EMC_EXEC_DIR) - set(exec_dir exec) -endif() - # If doxygen documentation we enabled, build it. This must come before # adding the source code directories; the main documentation build # must happen before any of the utility document builds. if(ENABLE_DOCS) find_package(Doxygen REQUIRED) set(abs_top_srcdir "${CMAKE_SOURCE_DIR}") - add_subdirectory(docs) + add_subdirectory(docs) endif() add_subdirectory(sorc) +# Run unit tests. +include(CTest) +if(BUILD_TESTING) + message(STATUS "Set BUILD_TESTING to YES and build unit testing package under tests") + add_subdirectory(tests) +endif() diff --git a/LICENSE.md b/LICENSE.md index b7395d372..d8f627ec6 100644 --- a/LICENSE.md +++ b/LICENSE.md @@ -2,7 +2,7 @@ Copyright 2020 National Oceanic and Atmospheric Administration (by assignment fr The ufs_utils code incorporated in the Unified Forecast System (UFS) was jointly developed by the National Oceanic and Atmospheric Administration and the I. M. Systems Group. The gold standard copy -of the Code will be maintained by NOAA at https://github.com/NOAA-EMC/UFS_UTILS +of the Code will be maintained by NOAA at https://github.com/ufs-community/UFS_UTILS The National Oceanic and Atmospheric Administration is releasing this code under the GNU Lesser General Public License v3.0 (the "License"); you may not use this code except in compliance diff --git a/README.md b/README.md index 05dc5984c..9e64ba59a 100644 --- a/README.md +++ b/README.md @@ -2,45 +2,46 @@ # UFS_UTILS Utilities for the NCEP models. This is part of the -[NCEPLIBS](https://github.com/NOAA-EMC/NCEPLIBS) project. +[Unified Forecast System](https://github.com/ufs-community) project. Documentation for chgres_cube and other utilities can be found at https://noaa-emcufs-utils.readthedocs.io/en/latest/. Complete documentation can be found at -https://noaa-emc.github.io/UFS_UTILS/. +https://ufs-community.github.io/UFS_UTILS/. ## Authors Utility | Programmer(s) --------|---------- chgres_cube | George Gayno, Jeff Beck, Larissa Reames +cpld_gridgen | Denise Worthen emcsfc_ice_blend | George Gayno emcsfc_snow2mdl | George Gayno fre-nctools | GFDL progammer fvcom_tools | David Wright, University of Michigan, Ming Hu, GSD/AMB gblevents | Hang Lei gdas_init | George Gayno -global_cycle | George Gayno, Shrinivas Moorthi, Mark Iredell, Xu Li, Hang Lei -grid_tools | R. J. Purser (regional_esg_grid), Tom Black/Ben Blake (shave.fd), Gerard Ketefian (global_equiv_resol), Tsukasa Fujita, JMA (pmat2), GFDL programmer (topo filtering code). +global_cycle | George Gayno, Shrinivas Moorthi, Xu Li +grid_tools | R. J. Purser (regional_esg_grid), Ben Blake (shave.fd), Gerard Ketefian (global_equiv_resol), Tsukasa Fujita, JMA (pmat2), GFDL programmer (topo filtering code). orog_mask_tools | Ning Wang, Jordan Alpert, Shan Sun and Ning Wang sfc_climo_gen | George Gayno -vcoord_gen | Fanglin Yang, Mark Iredell +vcoord_gen | Fanglin Yang +weight_gen | George Gayno -UFS_UTILS Code managers: George Gayno, Kyle Gerheiser, Jeff Beck, Larissa Reames +UFS_UTILS Code managers: George Gayno, Jeff Beck, Larissa Reames ## Prerequisites This package uses the [hpc-stack](https://github.com/NOAA-EMC/hpc-stack) for the following NCEPLIBS packages: - [NCEPLIBS-sfcio](https://github.com/NOAA-EMC/NCEPLIBS-sfcio) - - [NCEPLIBS-w3nco](https://github.com/NOAA-EMC/NCEPLIBS-w3nco) + - [NCEPLIBS-w3emc](https://github.com/NOAA-EMC/NCEPLIBS-w3emc) - [NCEPLIBS-bacio](https://github.com/NOAA-EMC/NCEPLIBS-bacio) - [NCEPLIBS-nemsio](https://github.com/NOAA-EMC/NCEPLIBS-nemsio) - [NCEPLIBS-sigio](https://github.com/NOAA-EMC/NCEPLIBS-sigio) - [NCEPLIBS-sp](https://github.com/NOAA-EMC/NCEPLIBS-sp) - [NCEPLIBS-ip](https://github.com/NOAA-EMC/NCEPLIBS-ip) - [NCEPLIBS-g2](https://github.com/NOAA-EMC/NCEPLIBS-g2) - - [NCEPLIBS-wgrib2](https://github.com/NOAA-EMC/NCEPLIBS-wgrib2) And for the following third party libraries: @@ -52,62 +53,61 @@ And for the following third party libraries: - [HDF5](https://www.hdfgroup.org/solutions/hdf5/) - [PNG](http://www.libpng.org/pub/png/) +It also uses the following repositories: + + - [Common Community Physics Package](https://github.com/ufs-community/ccpp-physics) + ## Installing +On Orion, Jet, Hera and WCOSS2 do the following: + +1) Set the 'fixed' directories using the `link_fixdirs.sh` +script in `./fix`. Usage: `./link_fixdirs.sh $RUN_ENVIR $machine`, +where `$RUN_ENVIR` is "emc" or "nco" (most developers +should choose "emc") and `$machine` is the platform. Example: + +``` +./link_fixdirs.sh emc hera +``` + +2) Then, invoke the build script: + ``` -mkdir build -cd build -cmake -DCMAKE_INSTALL_PREFIX=/path/to/install .. -make -j2 -make install +./build_all.sh ``` ## Contents -The UFS_UTILS package contains the following utilities (under the sorc -directory): -- chgres_cube -- emcsfc_ice_blend -- emcsfc_snow2mdl -- fre-nctools -- fvcom_tools -- gblevents -- global_cycle -- grid_tools -- orog_mask_tools -- sfc_climo_gen -- vcoord_gen - -The reg_tests directory contains the consistency test code. - -The fix directory is where we set links to directories containing +The `sorc` directory contains the source code. + +The `reg_tests` directory contains the consistency test code. + +The `fix` directory contains links to directories containing large, static data files used by UFS_UTILS programs. -The tests directory contains unit tests. +The `tests` directory contains unit tests. -The ush directory contains scripts to run UFS_UTILS programs. Most +The `ush` directory contains scripts to run UFS_UTILS programs. Most are called from driver scripts. -The util directory contains utility scripts to create coldstart -initial conditions for GFS parallels, and to run the vertical -coordinate generator. +The `util` directory contains utility scripts. -The parm directory contains variable mapping parameter tables used by +The `parm` directory contains parameter files used by the chgres_cube program. -The driver_scripts directory contains high-level driver scripts to +The `driver_scripts` directory contains high-level driver scripts to create a model grid on officially supported HPC platforms. -The modulefiles directory contains modules loaded when building +The `modulefiles` directory contains modules loaded when building UFS_UTILS on supported HPC platforms. They are also loaded at runtime by utility and consistency test scripts. -The docs directory contains the control file for the doxygen +The `docs` directory contains the control file for the doxygen documentation build, as well as some markdown files which are part of the documentation. It also contains (in the source subdirectory) the ReadTheDocs documentation files. -The cmake directory contains CMake package find utilities, and utilities to +The `cmake` directory contains CMake package find utilities, and utilities to run units tests on some supported HPC platforms. ## References diff --git a/VERSION b/VERSION index dc1e644a1..81c871de4 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.6.0 +1.10.0 diff --git a/build_all.sh b/build_all.sh index d67ed5038..75f830326 100755 --- a/build_all.sh +++ b/build_all.sh @@ -3,6 +3,7 @@ # This build script is only used on officially supported machines. All other # users should set module files as needed, and build directly with CMake. # +# # George Gayno set -eux @@ -25,28 +26,31 @@ else set -x fi +# Ensure the submodules have been initialized. + +if [[ ! -d ./ccpp-physics/physics ]]; then + git submodule init + git submodule update +fi + # The unit test data download is part of the build system. Not all machines can # access the EMC ftp site, so turn off the build (-DBUILD_TESTING=OFF) of the units tests accordingly. # Those with access to the EMC ftp site are: Orion and Hera. -if [[ "$target" == "hera" || "$target" == "orion" || "$target" == "wcoss2" ]]; then - CMAKE_FLAGS="-DCMAKE_INSTALL_PREFIX=../ -DEMC_EXEC_DIR=ON -DBUILD_TESTING=OFF" - #CMAKE_FLAGS="-DCMAKE_INSTALL_PREFIX=../ -DEMC_EXEC_DIR=ON -DBUILD_TESTING=ON" - #CMAKE_FLAGS="-DCMAKE_INSTALL_PREFIX=../ -DEMC_EXEC_DIR=ON -DENABLE_DOCS=ON -DBUILD_TESTING=ON" -else - CMAKE_FLAGS="-DCMAKE_INSTALL_PREFIX=../ -DEMC_EXEC_DIR=ON -DBUILD_TESTING=OFF" - #CMAKE_FLAGS="-DCMAKE_INSTALL_PREFIX=../ -DEMC_EXEC_DIR=ON -DENABLE_DOCS=ON -DBUILD_TESTING=OFF" -fi +CMAKE_FLAGS="-DCMAKE_INSTALL_PREFIX=../ -DCMAKE_INSTALL_BINDIR=exec -DBUILD_TESTING=OFF" + +# Allow users of this script to provide CMake options e.g. -DGFS=ON|OFF to build GFS specific utilities only +CMAKE_OPTS=${CMAKE_OPTS:-} rm -fr ./build mkdir ./build && cd ./build -cmake .. ${CMAKE_FLAGS} +cmake .. ${CMAKE_FLAGS} ${CMAKE_OPTS} -make -j 8 VERBOSE=1 +make -j ${BUILD_JOBS:-8} VERBOSE=${BUILD_VERBOSE:-} make install -#make test +#ctest #ctest -I 4,5 exit diff --git a/ccpp-physics b/ccpp-physics new file mode 160000 index 000000000..3a306a493 --- /dev/null +++ b/ccpp-physics @@ -0,0 +1 @@ +Subproject commit 3a306a493a9a0b6c3c39c7b50d356f0ddb7c5c94 diff --git a/cmake/LibMPI.cmake b/cmake/LibMPI.cmake index 68c20dda6..f5a4d5f35 100644 --- a/cmake/LibMPI.cmake +++ b/cmake/LibMPI.cmake @@ -45,43 +45,11 @@ function (platform_name RETURN_VARIABLE) set (${RETURN_VARIABLE} "hera" PARENT_SCOPE) - # wcoss_cray (Luna) - elseif (SITENAME MATCHES "^llogin1" OR - SITENAME MATCHES "^llogin2" OR - SITENAME MATCHES "^llogin3") - - set (${RETURN_VARIABLE} "wcoss_cray" PARENT_SCOPE) - - # wcoss_cray (Surge) - elseif (SITENAME MATCHES "^slogin1" OR - SITENAME MATCHES "^slogin2" OR - SITENAME MATCHES "^slogin3") - - set (${RETURN_VARIABLE} "wcoss_cray" PARENT_SCOPE) - - # wcoss_dell_p3 (Venus) - elseif (SITENAME MATCHES "^v71a1.ncep.noaa.gov" OR - SITENAME MATCHES "^v71a2.ncep.noaa.gov" OR - SITENAME MATCHES "^v71a3.ncep.noaa.gov" OR - SITENAME MATCHES "^v72a1.ncep.noaa.gov" OR - SITENAME MATCHES "^v72a2.ncep.noaa.gov" OR - SITENAME MATCHES "^v72a3.ncep.noaa.gov") - - set (${RETURN_VARIABLE} "wcoss_dell_p3" PARENT_SCOPE) - - # wcoss_dell_p3 (Mars) - elseif (SITENAME MATCHES "^m71a1.ncep.noaa.gov" OR - SITENAME MATCHES "^m71a2.ncep.noaa.gov" OR - SITENAME MATCHES "^m71a3.ncep.noaa.gov" OR - SITENAME MATCHES "^m72a1.ncep.noaa.gov" OR - SITENAME MATCHES "^m72a2.ncep.noaa.gov" OR - SITENAME MATCHES "^m72a3.ncep.noaa.gov") - - set (${RETURN_VARIABLE} "wcoss_dell_p3" PARENT_SCOPE) - # wcoss2 elseif (SITENAME MATCHES "^along01" OR - SITENAME MATCHES "^alogin02") + SITENAME MATCHES "^alogin02" OR + SITENAME MATCHES "^clogin" OR + SITENAME MATCHES "^dlogin") set (${RETURN_VARIABLE} "wcoss2" PARENT_SCOPE) diff --git a/cmake/mpiexec.jet b/cmake/mpiexec.jet index 332b33e29..a59fbcbd9 100755 --- a/cmake/mpiexec.jet +++ b/cmake/mpiexec.jet @@ -6,10 +6,11 @@ # $2+ - Executable and its arguments # -ACCOUNT= +ACCOUNT=nesdis-rdo2 QOS=debug +PARTITION=xjet NP=$1 shift -srun -A $ACCOUNT -q $QOS -n $NP $@ +srun -A $ACCOUNT -p $PARTITION -q $QOS -n $NP $@ diff --git a/cmake/mpiexec.wcoss2 b/cmake/mpiexec.wcoss2 new file mode 100755 index 000000000..1365ad45d --- /dev/null +++ b/cmake/mpiexec.wcoss2 @@ -0,0 +1,15 @@ +#!/bin/bash +# +# Arguments: +# +# $1 - Number of MPI Tasks +# $2+ - Executable and its arguments +# + +ACCOUNT=GFS-DEV +QUEUE=dev + +NP=$1 +shift + +qsub -A $ACCOUNT -q $QUEUE -l select=1:ncpus=$NP:mem=1GB -l place=vscatter -l walltime=00:10:00 $@ diff --git a/docs/source/chgres_cube.rst b/docs/source/chgres_cube.rst index 4cba99841..71f1274c3 100644 --- a/docs/source/chgres_cube.rst +++ b/docs/source/chgres_cube.rst @@ -19,17 +19,21 @@ The program assumes Noah/Noah-MP LSM coefficients for certain soil thresholds. I * Computes required soil parameters * Reads the variable mapping (VARMAP) table. * model_grid.F90 - Sets up the ESMF grid objects for the input data grid and target FV3 grid. - * static_data.F90 - Reads static surface climatological data for the target FV3 grid (such as soil type and vegetation type). Time interpolates time-varying fields, such as monthly plant greenness, to the model run time. Data for each target FV3 resolution resides in the ‘fixed’ directory. Set path via the fix_dir_target_grid namelist variable. + * static_data.F90 - Reads static surface climatological data for the target FV3 grid (such as soil type and vegetation type). Time interpolates time-varying fields, such as monthly plant greenness, to the model run time. Set path to these files via the fix_dir_target_grid namelist variable. * write_data.F90 - Writes the tiled and header files expected by the forecast model. - * input_data.F90 - Contains routines to read atmospheric and surface data from GRIB2, NEMSIO and NetCDF files. - * utils.f90 - Contains utility routines, such as error handling. + * atm_input_data.F90 - Contains routines to read input atmospheric data from GRIB2, NEMSIO and NetCDF files. + * nst_input_data.F90 - Contains routines to read input NSST data from NEMSIO and NetCDF files. + * sfc_input_data.F90 - Contains routines to read input surface data from GRIB2, NEMSIO and NetCDF files. + * utils.F90 - Contains utility routines, such as error handling. * grib2_util.F90 - Routines to (1) convert from RH to specific humidity; (2) convert from omega to dzdt. Required for GRIB2 input data. * atmosphere.F90 - Process atmospheric fields. Horizontally interpolate from input to target FV3 grid using ESMF regridding. Adjust surface pressure according to terrain differences between input and target grid. Vertically interpolate to target FV3 grid vertical levels. Description of main routines: * read_vcoord_info - Reads model vertical coordinate definition file (as specified by namelist variable vcoord_file_target_grid). - * newps - computes adjusted surface pressure given a new terrain height. - * newpr1 - computes 3-D pressure given an adjusted surface pressure. + * newps - Computes adjusted surface pressure given a new terrain height. + * newpr1 - Computes 3-D pressure given an adjusted surface pressure. * vintg - vertically interpolate atmospheric fields to target FV3 grid. + * vintg_wam - vertically interpolate atmospheric fields to the thermosphere. Supports the Whole Atmosphere Model. + * atmosphere_target_data.F90 - Holds the target grid atmospheric ESMF fields. * surface.F90 - process land, sea/lake ice, open water/Near Sea Surface Temperature (NSST) fields. NSST fields are not available when using GRIB2 input data. Description of main routines: * interp - horizontally interpolate fields from input to target FV3 grid. @@ -38,7 +42,10 @@ The program assumes Noah/Noah-MP LSM coefficients for certain soil thresholds. I * rescale_soil_moisture - adjust total soil moisture for differences between soil type on input and target FV3 grids. Required to preserve latent/sensible heat fluxes. * roughness - set roughness length at land and sea/lake ice. At land, a vegetation type-based lookup table is used. * qc_check - some consistency checks. - * search_util.f90 - searches for the nearest valid land/non-land data where the input and target fv3 land-mask differ. Example: when the target FV3 grid depicts an island that is not resolved by the input data. If nearby valid data is not found, a default value is used. + * surface_target_data.F90 - Holds the target grid surface ESMF fields. + * search_util.F90 - searches for the nearest valid land/non-land data where the input and target fv3 land-mask differ. Example: when the target FV3 grid depicts an island that is not resolved by the input data. If nearby valid data is not found, a default value is used. + * thompson_mp_climo_data.F90 - Processes climatological Thompson micro-physics fields. + * wam_climo_data.f90 - Process vertical profile climatological data for the Whole Atmosphere Model. Configuring and using chgres_cube for global applications --------------------------------------------------------- @@ -48,7 +55,7 @@ Program inputs and outputs for global applications **Inputs** -The following four sets of files are located here: https://ftp.emc.ncep.noaa.gov/EIB/UFS/global/fix/fix_fv3_gmted2010.v20191213/ +Users may create their own global grids, or use the pre-defined files are located `here `_. * FV3 mosaic file - (NetCDF format) * CRES_mosaic.nc @@ -69,7 +76,7 @@ The following four sets of files are located here: https://ftp.emc.ncep.noaa.gov * CRES_oro_data.tile5.nc * CRES_oro_data.tile6.nc - * FV3 surface climatological files - Located under the ./fix_sfc sub-directory. One file for each tile. NetCDF format. + * FV3 surface climatological files - Located under the `./fix_sfc `_ sub-directory. One file for each tile. NetCDF format. * CRES.facsf.tileX.nc (fractional coverage for strong/weak zenith angle dependent albedo) * CRES.maximum_snow_albedo.tileX.nc (maximum snow albedo) * CRES.slope_type.tileX.nc (slope type) @@ -79,7 +86,7 @@ The following four sets of files are located here: https://ftp.emc.ncep.noaa.gov * CRES.vegetation_greenness.tileX.nc (vegetation greenness) * CRES.vegetation_type.tileX.nc (vegetation type) - * FV3 vertical coordinate file. Text file. Located here: https://ftp.emc.ncep.noaa.gov/EIB/UFS/global/fix/fix_am.v20191213/ + * FV3 vertical coordinate file. Text file. `Located here `_. * global_hyblev.l$LEVS.txt * Input data files. GRIB2, NEMSIO or NetCDF. See the next section for how to find this data. @@ -103,24 +110,20 @@ The following four sets of files are located here: https://ftp.emc.ncep.noaa.gov * out.sfc.tile1.nc -Where to find GFS GRIB2, NEMSIO and NetCDF data for global applications -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Where to find GFS GRIB2 and NetCDF data for global applications +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ **GRIB2** - * 0.25-degree data (last 10 days only) - Use the **gfs.tHHz.pgrb2.0p25.f000** files in subdirectory gfs.YYYYMMDD/HH `here `_.` + * 0.25-degree data (last 10 days only) - Use the **gfs.tHHz.pgrb2.0p25.f000** files in subdirectory ./gfs.YYYYMMDD/HH/atmos on `NOMADS `_. - * 0.5-degree data - Use the **gfs_4_YYYYMMDD_00HH_000.grb2** file, under **GFS Forecasts 004 (0.5-deg)** here: `NCDC - Global Forecast System `__. Note: *Tests were not done with the AVN, MRF or analysis data*. + * 0.5-degree data - Use the **gfs_4_YYYYMMDD_HHHH_000.grb2** file, under **GFS Forecasts 004 (0.5-deg)** here: `NCEI - Global Forecast System `_. Note: *Tests were not done with the AVN, MRF or analysis data*. - * 1.0-degree data - Use the **gfs_3_YYYYMMDD_00HH_000.grb2 file**, under **GFS Forecasts 003 (1-deg)** here: `NCDC - Global Forecast System `__. Note: *Tests were not done with the AVN, MRF or analysis data*. - -**NEMSIO** - - * T1534 gaussian (last 10 days only) - Use the **gfs.tHHz.atmanl.nemsio** (atmospheric fields) and **gfs.tHHz.sfcanl.nemsio** (surface fields) files in subdirectory gfs.YYYYMMDD/HH `here `_. + * 1.0-degree data - Use the **gfs_3_YYYYMMDD_HHHH_000.grb2 file**, under **GFS Forecasts 003 (1.0-deg)** here: `NCEI - Global Forecast System `_. Note: *Tests were not done with the AVN, MRF or analysis data*. **NetCDF** - * T1534 gaussian (don't have any more details at this time). + * T1534 gaussian (last 10 days only) - Use the **gfs.tHHz.atmanl.nc** (atmospheric fields) and **gfs.tHHz.sfcanl.nc** (surface fields) files in subdirectory ./gfs.YYYYMMDD/HH/atmos on `NOMADS `_. Initializing global domains with GRIB2 data - some caveats ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -138,6 +141,25 @@ Initializing global domains with GRIB2 data - some caveats * Soil moisture in the GRIB2 files is created using bilinear interpolation and, therefore, may be a mixture of values from different soil types. Could result in poor latent/sensible heat fluxes. * Ozone is not available at all isobaric levels. Missing levels are set to a nominal value defined in the variable mapping (VARMAP) file (1E-07). * Only tested with GRIB2 data from GFS v14 and v15 (from 12z July 19, 2017 to current). May not work with older GFS data. Will not work with GRIB2 data from other models. + * Note that when concatenating grib2 files for use in initialization of global simulations, it is possible to inadvertently introduce duplicate variables and levels into the subsequent grib2 files. Chgres_cube will automatically fail with a warning message indicating that the grib2 file used contains these duplicate entries. Prior to continuing it will be necessary to strip out duplicate entries. Users can remove these entries through use of wgrib2, such as in the following command: + * ``wgrib2 IN.grb -submsg 1 | unique.pl | wgrib2 -i IN.grb -GRIB OUT.grb``, where IN.grb is the original concatenated grib2 file, and OUT.grb is the resulting grib2 file, with duplicates removed. The "unique.pl" Perl script is as follows, taken from the `Tricks for wgrib2 `_ website: + + .. code-block:: console + + ----------------------- unique.pl ------------------------ + #!/usr/bin/perl -w + # print only lines where fields 3..N are different + # + while () { + chomp; + $line = $_; + $_ =~ s/^[0-9.]*:[0-9]*://; + if (! defined $inv{$_}) { + $inv{$_} = 1; + print "$line\n"; + } + } + --------------------- end unique.pl ---------------------- Near Sea Surface Temperature (NSST) data and GRIB2 initialization ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -235,7 +257,7 @@ The following four sets of files/directories should all be located in the same d * CRES.vegetation_greenness.tile7.halo4.nc (vegetation greenness) * CRES.vegetation_type.tile7.halo4.nc (vegetation type) - * FV3 vertical coordinate file. Text file. Located in ./fix_am directory. + * FV3 vertical coordinate file. Text file. `Located here `_. * global_hyblev.l$LEVS.txt * Input data files. GRIB2 only. See the next section for how to find this data. @@ -253,23 +275,23 @@ Where to find FV3GFS, NAM, HRRR, and RAP GRIB2 data for regional applications **FV3GFS** - * 0.25-degree data (last 10 days only) - Use the **gfs.tHHz.pgrb2.0p25.f000** files in subdirectory gfs.YYYYMMDD/HH `here `_. + * 0.25-degree data (last 10 days only) - Use the **gfs.tHHz.pgrb2.0p25.f000** files in subdirectory ./gfs.YYYYMMDD/HH/atmos on `NOMADS `_. - * 0.5-degree data - Use the **gfs_4_YYYYMMDD_00HH_000.grb2** file, under **GFS Forecasts 004 (0.5-deg)** here: `NCDC - Global Forecast System `__. Note: *Tests were not done with the AVN, MRF or analysis data*. + * 0.5-degree data - Use the **gfs_4_YYYYMMDD_HHHH_000.grb2** file, under **GFS Forecasts 004 (0.5-deg)** here: `NCEI - Global Forecast System `_. Note: *Tests were not done with the AVN, MRF or analysis data*. - * 1.0-degree data - Use the **gfs_3_YYYYMMDD_00HH_000.grb2 file**, under **GFS Forecasts 003 (1-deg)** here: `NCDC - Global Forecast System `__. Note: *Tests were not done with the AVN, MRF or analysis data*. + * 1.0-degree data - Use the **gfs_3_YYYYMMDD_HHHH_000.grb2 file**, under **GFS Forecasts 003 (1.0-deg)** here: `NCEI - Global Forecast System `_. Note: *Tests were not done with the AVN, MRF or analysis data*. **NAM** - * 12-km data from last few days (NOMADS) - Use the **nam.tHHz.conusnest.hiresfFH.tmHH.grib2** files in subdirectory nam.YYYYMMDD `here `__. + * 12-km data from last few days (NOMADS) - Use the **nam.tHHz.conusnest.hiresfHH.tmHH.grib2** files in subdirectory nam.YYYYMMDD on `NOMADS `_. - * 12-km data from previous 6 months - Use the **nam_218_YYYYMMDD_00HH_000.grb2 file**, under **NAM Forecasts NAM-NMM 218 (12km) Domain** here: `NCDC - North American Mesoscale Forecast System `__. + * 12-km data starting 2020 - Use the **nam_218_YYYYMMDD_HHHH_000.grb2 file**, under **NAM Forecasts NAM-NMM 218 (12km) Domain** here: `NCEI - North American Mesoscale Forecast System `_. - * 12-km archived data older than 6 months can be requested through the Archive Information Request System `here `__. + * 12-km archived data prior to 2020 can be requested through the Archive Information Request System `here `_. **HRRR** - * 3-km operational data from previous few days (NOMADS) - Use the **hrrr.tHHz.wrfnatfFH.grib2** files in the subdirectory hrrr.YYYYMMDD/conus `here `__. + * 3-km operational data from previous few days (NOMADS) - Use the **hrrr.tHHz.wrfnatfHH.grib2** files in the subdirectory ./hrrr.YYYYMMDD/conus `here `_. * 3-km operational data from 2015 to present (AWS S3): Go `here `__ and click “Browse Bucket.” Type "YYYYMMDD" in to the Search bar. Use the **hrrr.t00z.wrfnatf00.grib2** files in the directory hrrr.YYYYMMDD/conus/. @@ -279,13 +301,11 @@ Where to find FV3GFS, NAM, HRRR, and RAP GRIB2 data for regional applications **RAP** + * 13-km operational data for the previous few days (NOMADS): Use the **rap.tHHz.wrfnatfHH.grib2** files in the subdirectory ./rap.YYYYMMDD `here `_. - * 13-km operational data for the previous few days (NOMADS): Use the **rap.tHHz.wrfnatfFH.grib2** files in the subdirectory rap.YYYYMMDD `here `__. - - * 13-km isobaric level data from previous 6 months : Use the **rap_130_YYYYMMDD_00HH_0FF.grb2** files from the HTTPS option under **RAP Forecasts - RAP 130 (13km) - Domain** at NCEI `here `__. - - * 13-km archived isobaric data older than 6 months can be requested through the Archive Information Request System `here `__. + * 13-km isobaric level data from previous 6 months : Use the **rap_130_YYYYMMDD_HHHH_0FF.grb2** files from **RAP Forecasts - RAP 130 (13km) - Domain** at NCEI `here `_. + * 13-km archived isobaric data older than 6 months can be requested through the Archive Information Request System `here `_. Initializing regional domains with GRIB2 data - some caveats @@ -303,6 +323,25 @@ Keep these things in mind when using FV3GFS GRIB2 data for model initialization: * For FV3GFS GRIB2 data, soil moisture is created using bilinear interpolation and, therefore, may be a mixture of values from different soil types. Could result in poor latent/sensible heat fluxes. * Ozone is not available at all isobaric levels. Missing levels are set to a nominal value defined in the variable mapping (VARMAP) file (1E-07). * Only tested with GRIB2 data from FV3GFS, RAP, NAM, and HRRR data. May not work with GRIB2 data from other models. Use these at your own risk. + * Note that when concatenating grib2 files for use in initialization of regional simulations, it is possible to inadvertently introduce duplicate variables and levels into the subsequent grib2 files. Chgres_cube will automatically fail with a warning message indicating that the grib2 file used contains these duplicate entries. Prior to continuing it will be necessary to strip out duplicate entries. Users can remove these entries through use of wgrib2, such as in the following command: + * ``wgrib2 IN.grb -submsg 1 | unique.pl | wgrib2 -i IN.grb -GRIB OUT.grb``, where IN.grb is the original concatenated grib2 file, and OUT.grb is the resulting grib2 file, with duplicates removed. The "unique.pl" Perl script is as follows, taken from the `Tricks for wgrib2 `_ website: + + .. code-block:: console + + ----------------------- unique.pl ------------------------ + #!/usr/bin/perl -w + # print only lines where fields 3..N are different + # + while () { + chomp; + $line = $_; + $_ =~ s/^[0-9.]*:[0-9]*://; + if (! defined $inv{$_}) { + $inv{$_} = 1; + print "$line\n"; + } + } + --------------------- end unique.pl ---------------------- Regional chgres_cube namelist options ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -312,7 +351,6 @@ Namelist variables with “input” in their name refer to data input to chgres_ **Required Entries** * fix_dir_target_grid - Path to the FV3-LAM surface climatological files (such as albedo). - * fix_dir_input_grid - Directory containing RAP lat/lon file. On NOAA HPC machines, typically the “fix/fix_am” directory of the UFS_UTILS directory. * mosaic_file_target_grid - Path and name of the FV3-LAM mosaic file. * orog_dir_target_grid - Directory containing the FV3-LAM orography and grid files (NetCDF). * orog_files_target_grid - Names of the FV3-LAM orography file. @@ -344,6 +382,9 @@ Namelist variables with “input” in their name refer to data input to chgres_ * minmax_vgfrc_from_climo - Use min/max vegetation fraction from climatology. Valid options: .true. or .false. (Default: .true.) * tg3_from_soil - Use tg3 from input soil. Valid options: .true. or .false. . Default: .false. * thomp_mp_climo_file - Location of Thompson aerosol climatology file. Provide only if you wish to use these aerosol variables. + * wam_cold_start - Cold start for the Whole Atmosphere Model. Valid Options: .true. or .false. (Default: .false.) + * use_rh - Use relative humidity instead of specific humidity when reading in external model grib2 files (Default: .false.) + * calrh - Type of relative humidity to specific humidity calculation to use (Default: 0; use existing calculation, or 1; use calculation consistent with GFSv15/v16) Variable Mapping (VARMAP) table ------------------------------- @@ -382,7 +423,7 @@ Column 2: Name of the variable in the output “coldstart” files. Unimplemente Column 3: Behavior when the code can't find the variable in the input file. Options are: * "skip": Don't write to the output file. - * "intrp": LnP interpolation to missing levels. No extrapolation allowd. + * "intrp": Ln(pressure) interpolation to missing levels. Linear interpolation and extrapolation are possible, but require modifying the value of "LINLOG" in input_data.F90 to anything other than 2, or to a negative number, respectively. * "set_to_fill": Set to user-specified field value (see column 4). * "stop": Force an exception and stop code execution. Use this if you absolutely require a field to be present. @@ -407,12 +448,12 @@ Running the program stand alone Making changes to the chgres_cube program ----------------------------------------- -chgres_cube is part of the UFS_UTILS repository (https://github.com/NOAA-EMC/UFS_UTILS). When wanting to contribute to this repository developers shall follow the Gitflow software development process +chgres_cube is part of the UFS_UTILS repository (https://github.com/ufs-community/UFS_UTILS). When wanting to contribute to this repository developers shall follow the Gitflow software development process * Developers shall create their own fork of the UFS_UTILS repository * Developers shall create a ‘feature’ branch off ‘develop’ in their fork for all changes. * Developers shall open an issue and reference it in all commits. -For more details, see the UFS_UTILS wiki page: https://github.com/NOAA-EMC/UFS_UTILS/wiki +For more details, see the UFS_UTILS wiki page: https://github.com/ufs-community/UFS_UTILS/wiki Changes that support current or future NCEP operations will be given priority for inclusion into the authoritative repository. diff --git a/docs/source/ufs_utils.rst b/docs/source/ufs_utils.rst index 6e1193e57..ef50d2838 100644 --- a/docs/source/ufs_utils.rst +++ b/docs/source/ufs_utils.rst @@ -5,7 +5,7 @@ Introduction **************************** -The Unified Forecast Systems (UFS) Utilities repository contains pre-processing programs for the UFS weather model. These programs set up the model grid and create coldstart initial conditions. The repository is hosted on `Github `_. Information on checking out the code and making changes to it is available on the repository `wiki page `_. +The Unified Forecast Systems (UFS) Utilities repository contains pre-processing programs for the UFS weather model. These programs set up the model grid and create coldstart initial conditions. The repository is hosted on `Github `_. Information on checking out the code and making changes to it is available on the repository `wiki page `_. *********************************** Grid Generation @@ -14,9 +14,12 @@ Grid Generation The following programs are used to create a grid. * make_hgrid - * regional_grid_esg + * regional_esg_grid * make_solo_mosaic * orog + * orog_gsl (optional) + * inland (optional) + * lakefrac (optional) * global_equiv_resol * shave * filter_topo @@ -26,7 +29,9 @@ The grid generation process is run by these scripts (located under ./ush) * fv3gfs_grid_driver.sh (driver script) * fv3gfs_make_grid.sh (creates the geo-referencing for the grid) - * fv3gfs_make_orog.sh (creates the land-sea mask and terrain) + * fv3gfs_make_orog.sh (creates the land-sea mask, terrain and EMC gravity wave drag fields) + * fv3gfs_make_orog_gsl.sh (creates GSL gravity wave drag fields) + * fv3gfs_make_lake.sh (adds lakes and lake depth. optional) * fv3gfs_filter_topo.sh (filters the orography) * sfc_climo_gen.sh (creates climatological surface fields, such as soil type) @@ -217,6 +222,8 @@ Land-sea mask and land fraction are created from a global 30-arc second Universi * Kim, Y-J and A. Arakawa, 1995: Improvement of orographic gravity wave parameterization using a mesoscale gravity wave model. J. Atmos. Sci. 52, pp 1875-1902. * Lott, F. and M. J. Miller: 1977: A new sub-grid scale orographic drag parameterization: Its formulation and testing, QJRMS, 123, pp 101-127. +**Caution:** At model grid resolutions of 1 km, the 30-arc-second input data will not be sufficient to properly resolve the land-sea mask, land fraction and orography fields. At model grid resolutions finer than 3 km, the remaining fields (used by the GWD) will not be well resolved. In that case, users should consider not running with GWD. + Code structure -------------- @@ -233,11 +240,11 @@ Program inputs and outputs * The "grid" files (CRES_grid.tile#.nc) containing the geo-reference records for the grid - (NetCDF). Created by the make_hgrid or regional_esg_grid programs. * Global 30-arc-second University of Maryland land cover data. Used to create the land-sea mask. - * ./fix/fix_orog/landcover30.fixed (unformatted binary) + * landcover30.fixed (unformatted binary). Located here `./fix/fix_orog `_. * Global 30-arc-second USGS GMTED2010 orography data. - * ./fix/fix_orog/gmted2010.30sec.int (unformatted binary) + * gmted2010.30sec.int (unformatted binary). Located here `./fix/fix_orog `_. * 30-arc-second RAMP Antarctic terrain data (Radarsat Antarctic Mapping Project) - * ./fix/fix_orog/thirty.second.antarctic.new.bin (unformatted binary) + * thirty.second.antarctic.new.bin (unformatted binary). Located here `./fix/fix_orog `_. **Output data:** @@ -258,6 +265,123 @@ Orography files - one for each tile - oro.CRES.tile#.nc (NetCDF). Contains thes * sigma - slope of orography (unitless) * elvmax - maximum height above mean (meters) +orog_gsl +======== + +Introduction +------------ + +This program computes orographics statistics fields required for the orographic drag suite developed by NOAA's Global Systems Laboratory (GSL). The fields are a subset of the ones calculated by "orog" and are calculated in a different manner. + +Code structure +-------------- + +Location of source code: ./sorc/orog_mask_tools.fd/orog_gsl.fd. + +Program inputs and outputs +-------------------------- + +The program reads the tile number (1-6 for global, 7 for stand-alone regional) and grid resolution (e.g., 768) from standard input. + +**Input data:** + +All in NetCDF. + + * The tiled "grid" files (CRES_grid.tile#.nc) created by the make_hgrid or regional_esg_grid programs. + * geo_em.d01.lat-lon.2.5m.HGT_M.nc - global topographic data on 2.5-minute lat-lon grid (interpolated from GMTED2010 30-second topographic data). `Located here `_. + * HGT.Beljaars_filtered.lat-lon.30s_res.nc - global topographic data on 30-second lat-lon grid (GMTED2010 data smoothed according to Beljaars et al. (QJRMS, 2004)). `Located here `_. + +**Output data:** + +One for each tile. All in NetCDF. + + * CRES_oro_data_ls.tile#.nc - Large-scale file for the gravity wave drag and blocking schemes of `Kim and Doyle (2005) `_ + * CRES_oro_data.ss.tile#.nc - Small-scale file for the gravity wave drag scheme of `Tsiringakis et al. (2017) `_. And the turbulent orographic from drag (TOFD) schemem of Beljaars et al. (QJRMS, 2004). + +Each file contains the following records: + + * geolon - longitude (degrees east) + * geolat - latitude (degrees north) + * stddev - Standard deviation of subgrid topography + * convexity - Convexity of subgrid topography + * oa1 - Orographic asymmetry of subgrid topography - westerly + * oa2 - Orographic asymmetry of subgrid topography - southerly + * oa3 - Orographic asymmetry of subgrid topography - southwesterly + * oa4 - Orographic asymmetry of subgrid topography - northwesterly + * ol1 - Orographic effective length of subgrid topography - westerly + * ol2 - Orographic effective length of subgrid topography - southerly + * ol3 - Orographic effective length of subgrid topography - southwesterly + * ol4 - Orographic effective length of subgrid topography - northwesterly + +inland +====== + +Introduction +------------ + +This program reads an orography file, determines which points are inland from water, then writes out a mask record that identifies these points. + +Code structure +-------------- + +Location of source code: ./sorc/orog_mask_tools.fd/inland.fd. + +Program control options +----------------------- + +The program reads the following parameters from standard input: + * The resolution. Ex: '96' for C96. + * Nonland cutoff fraction. Default is '0.99'. + * Maximum recursive depth. Default is '7'. + * Grid type flag - 'g' for global, 'r' for regional. + +Program inputs and outputs +-------------------------- + +**Input data:** + + * orography file - The orography file from the orog program - oro.CRES.tile#.nc (NetCDF) + +**Output data:** + + * orography file - The input file, but containing an additional 'inland' record - '1' inland, '0' coastal. + +lakefrac +======== + +Introduction +------------ + +This program sets freshwater lake fraction and lake depth on the model grid. + +Code structure +-------------- + +Location of source code: ./sorc/orog_mask_tools.fd/lake.fd. + +Program control options +----------------------- + +The program reads the following parameters from standard input: + * The tile number. + * The resolution. Ex: '96' for C96. + * The path to the global lake data. + * Minimum lake fraction in percent. + +Program inputs and outputs +-------------------------- + +**Input data:** + + * grid file - the "grid" file from the make_hgrid or regional_esg programs - CRES_grid.tile#.nc - (NetCDF) + * orography file - the orography file including the 'inland' flag record from the inland program - oro.CRES.tile#.nc (NetCDF) + * lake status code file - GlobalLakeStatus.dat (located in `./fix/fix_orog `_). See GlobalLakeStatus.txt for the defintion of each code. + * lake depth file - GlobalLakeDepth.dat (located in `./fix/fix_orog `_). See GlobalLakeDepth.txt for a description of this file. + +**Output data:** + + * orography file - the orography file including records of lake fraction and lake depth - oro.CRES.tile#.nc (NetCDF) + filter_topo =========== @@ -362,10 +486,13 @@ Location of the source code: ./sorc/sfc_climo_gen.fd. Brief description of each * driver.F90 - The main driver routine. * interp.F90 - The interpolation driver routine. Reads the input source data and interpolates it to the model grid. + * interp_frac_cats.F90 - Same as interp.F90, but for computing the fraction of each soil and vegetation type category. (When namelist variable 'vegsoilt_frac' is true). * model_grid.F90 - Defines the ESMF grid object for the model grid. * output.f90 - Writes the output surface data to a NetCDF file. For regional grids, will output separate files with and without the halo. + * output_frac_cats.f90 - Same as output.f90, but for writing fractional soil and vegetation type. (When namelist variable 'vegsoilt_frac' is true). * program_setup.f90 - Reads the namelist and sets up program execution. * search.f90 - Replace undefined values on the model grid with a valid value at a nearby neighbor. Undefined values are typically associated with isolated islands where there is no source data. + * search_frac_cats.f90 - Same as search.f90, but for the fractional soil and vegetation type option. (When namelist variable 'vegsoilt_frac' is true). * source_grid.F90 - Reads the grid specifications and land/sea mask for the source data. Sets up the ESMF grid object for the source grid. * utils.f90 - Contains error handling utility routines. @@ -380,6 +507,7 @@ Program execution is controlled via a namelist. The namelist variables are: * input_snowfree_albedo_file - path/name of input snow-free albedo data * input_slope_type_file - path/name of input global slope type data * input_soil_type_file - path/name of input soil type data + * input_soil_color_file - path/name of input soil color data * input_vegetation_type_file - path/name of vegetation type data * input_vegetation_greenness_file - path/name of monthly vegetation greenness data * mosaic_file_mdl - path/name of the model mosaic file @@ -389,25 +517,48 @@ Program execution is controlled via a namelist. The namelist variables are: * maximum_snow_albedo_method - interpolation method for this field. Bilinear or conservative. Default is bilinear. * snowfree_albedo_method - interpolation method for this field. Bilinear or conservative. Default is bilinear. * vegetation_greenness_method - interpolation method for this field. Bilinear or conservative. Default is bilinear. + * vegsoilt_frac - When 'true', outputs the dominate soil and vegetation type, and the fraction of each category. When 'false', only outputs the dominate categories. Default is 'false'. Program inputs and outputs -------------------------- **Input data:** -The global surface climatological data is located in ./fix/fix_sfc_climo. All NetCDF. +The surface climatological data is located here `./fix/fix_sfc_climo `_. All NetCDF. * Global 1-degree fractional coverage strong/weak zenith angle albedo - facsf.1.0.nc * Global 0.05-degree maximum snow albedo - maximum_snow_albedo.0.05.nc * Global 2.6 x 1.5-degree soil substrate temperature - substrate_temperature.2.6x1.5.nc * Global 0.05-degree four component monthly snow-free albedo - snowfree_albedo.4comp.0.05.nc * Global 1.0-degree categorical slope type - slope_type.1.0.nc - * Global 0.05-degree categorical STATSGO soil type - soil_type.statsgo.0.05.nc - * Global 0.05-degree categorical IGBP vegetation type - vegetation_type.igbp.0.05.nc + * Global 0.05-degree CLM soil color (Lawrence and Chase, 2007 JGR) - soil_color.clm.0.05.nc + * Categorical STATSGO soil type + * Global 0.05-degree - soil_type.statsgo.0.05.nc + * Global 0.03-degree - soil_type.statsgo.0.03.nc + * CONUS 30 sec - soil_type.statsgo.conus.30s.nc + * N Hemis 30 sec - soil_type.statsgo.nh.30s.nc + * Global 30 sec - soil_type.statsgo.30s.nc + * Categorical BNU soil type + * Global 30-second - soil_type.bnu.30s.nc + * Categorical IGBP vegetation type + * MODIS-based global 0.05-degree - vegetation_type.modis.igbp.0.05.nc + * MODIS-based global 0.03-degree - vegetation_type.modis.igbp.0.03.nc + * MODIS-based CONUS 30 sec - vegetation_type.modis.igbp.conus.30s.nc + * MODIS-based N Hemis 30 sec - vegetation_type.modis.igbp.nh.30s.nc + * MODIS-based global 30 sec - vegetation_type.modis.igbp.30s.nc + * NESDIS VIIRS-based global 0.10-degree - vegetation_type.viirs.igbp.0.1.nc + * NESDIS VIIRS-based global 0.05-degree - vegetation_type.viirs.igbp.0.05.nc + * NESDIS VIIRS-based global 0.03-degree - vegetation_type.viirs.igbp.0.03.nc + * NESDIS VIIRS-based CONUS 30-second - vegetation_type.viirs.igbp.conus.30s.nc + * NESDIS VIIRS-based N HEMIS 30-second - vegetation_type.viirs.igbp.nh.30s.nc + * NESDIS VIIRS-based global 30-second - vegetation_type.viirs.igbp.30s.nc * Global 0.144-degree monthly vegetation greenness in percent - vegetation_greenness.0.144.nc - * Model mosaic file - CRES_mosaic.nc (NetCDF) - * Model orography files including halo - CRES_oro_data.tile#.halo#.nc (NetCDF) - * Model grid files including halo - CRES_grid.tile#.halo#.nc (NetCDF) + +The files that define the model grid. All NetCDF. + + * Model mosaic file - CRES_mosaic.nc + * Model orography files including halo - CRES_oro_data.tile#.halo#.nc + * Model grid files including halo - CRES_grid.tile#.halo#.nc **Output files:** @@ -419,5 +570,98 @@ All files with and without halo (all NetCDF). * Snow free albedo - CRES_snowfree_albedo.tile#.halo#.nc * Slope type - CRES_slope_type.tile#.halo#.nc * Soil type - CRES_soil_type.tile#.halo#.nc + * Soil color - CRES_soil_color.tile#.halo#.nc * Vegetation type - CRES_vegetation_type.tile#.halo#.nc * Vegetation greenness - CRES_vegetation_greenness.tile#.halo#.nc + + +vcoord_gen +========== + +Introduction +------------ + +This program generates hybrid coordinate parameters from fields such as surface pressure, model top and the number of vertical levels. Outputs the 'ak' and 'bk' parameters used by the forecast model and chgres_cube to define the hybrid levels as follows: + + * pressure = ak + (surface_pressure * bk) + +Code structure +-------------- + +Location of the source code: ./sorc/vcoord_gen.fd. + +Program inputs +-------------- + +The following user-defined parameters are read in from standard input. + + * levs - Integer number of levels + * lupp - Integer number of levels below pupp + * pbot - Real nominal surface pressure (Pa) + * psig - Real nominal pressure where coordinate changes from pure sigma (Pa) + * ppre - Real nominal pressure where coordinate changes from pure pressure (Pa) + * pupp - Real nominal pressure where coordinate changes to upper atmospheric profile (Pa) + * ptop - Real pressure at top (Pa) + * dpbot - Real coordinate thickness at bottom (Pa) + * dpsig - Real thickness of zone within which coordinate changes to pure sigma (Pa) + * dppre - Real thickness of zone within which coordinate changes to pure pressure (Pa) + * dpupp - Real coordinate thickness at pupp (Pa) + * dptop - Real coordinate thickness at top (Pa) + +Program outputs +--------------- + +A text file is output containing the 'ak' and 'bk' values. To use it in chgres_cube, set namelist variable "vcoord_target_grid" to the path/name of this file. + +Run script +---------- + +To run, use script ./util/vcoord_gen/run.sh + +weight_gen +========== + +Introduction +------------ + +Creates ESMF 'scrip' files for gaussian grids. + +Code structure +-------------- + +Location of the source code: ./sorc/weight_gen.fd. + +Program inputs +-------------- + +The global FV3 grid resolution from standard output. Valid choices are: + + * C48 + * C96 + * C128 + * C192 + * C384 + * C768 + * C1152 + * C3072 + +Program outputs +--------------- + +Two gaussian grid 'scrip' files in NetCDF format. One includes two extra rows for the poles. + + * C48 => 192x94 and 192x96 gaussian files + * C96 => 384x192 and 384x194 gaussian files + * C128 => 512x256 and 512x258 gaussian files + * C192 => 768x384 and 768x386 gaussian files + * C384 => 1536x768 and 1536x770 gaussian files + * C768 => 3072x1536 and 3072x1538 gaussian files + * C1152 => 4608x2304 and 4608x2406 gaussian files + * C3072 => 12288x6144 and 12288x6146 gaussian files + +Files contain center and corner point latitude and longitudes. + +Run script +---------- + +To run, use the machine-dependent script under ./util/weight_gen diff --git a/docs/user_guide.md b/docs/user_guide.md index 00ec65b67..924055e72 100644 --- a/docs/user_guide.md +++ b/docs/user_guide.md @@ -2,11 +2,21 @@ # UFS_UTILS -Utilities for the NCEP models. This is part of the -[NCEPLIBS](https://github.com/NOAA-EMC/NCEPLIBS) project. +Utilities for the NCEP Unified Forecast System. The UFS_UTILS code can be found here: -https://github.com/NOAA-EMC/UFS_UTILS. +https://github.com/ufs-community/UFS_UTILS. + +## Documentation for Previous Versions of UFS_UTILS + +* [UFS_UTILS Version 1.10.0](ver-1.10.0/index.html) +* [UFS_UTILS Version 1.9.0](ver-1.9.0/index.html) +* [UFS_UTILS Version 1.8.0](ver-1.8.0/index.html) +* [UFS_UTILS Version 1.7.0](ver-1.7.0/index.html) +* [UFS_UTILS Version 1.6.0](ver-1.6.0/index.html) +* [UFS_UTILS Version 1.5.0](ver-1.5.0/index.html) +* [UFS_UTILS Version 1.4.0](ver-1.4.0/index.html) +* [UFS_UTILS Version 1.3.0](ver-1.3.0/index.html) ## The Utilities @@ -64,4 +74,9 @@ https://github.com/NOAA-EMC/UFS_UTILS. Currently, contains the routines required by global_cycle to perform data assimilation updates to land model states +- cpld_gridgen - Utility to + create the Fix and IC files for the S2SW and S2S applications +- weight_gen - Utility to + create gaussian grid ESMF 'scrip' files for use in creating + ESMF interpolation weight files. diff --git a/driver_scripts/driver_grid.cray.sh b/driver_scripts/driver_grid.cray.sh deleted file mode 100755 index cb8132535..000000000 --- a/driver_scripts/driver_grid.cray.sh +++ /dev/null @@ -1,157 +0,0 @@ -#!/bin/bash - -#BSUB -L /bin/sh -#BSUB -P GFS-DEV -#BSUB -oo log.grid.%J -#BSUB -eo log.grid.%J -#BSUB -J grid_fv3 -#BSUB -q debug -#BSUB -M 2400 -#BSUB -W 00:30 -#BSUB -extsched 'CRAYLINUX[]' - -#----------------------------------------------------------------------- -# Driver script to create a cubic-sphere based model grid on Cray. -# -# Produces the following files (netcdf, each tile in separate file): -# 1) 'mosaic' and 'grid' files containing lat/lon and other -# records that describe the model grid. -# 2) 'oro' files containing land mask, terrain and gravity -# wave drag fields. -# 3) Surface climo fields, such as soil type, vegetation -# greenness and albedo. -# -# Note: The sfc_climo_gen program only runs with an -# mpi task count that is a multiple of six. This is -# an ESMF library requirement. Large grids may require -# tasks spread across multiple nodes. -# -# To run, do the following: -# -# 1) Set "C" resolution, "res" - Example: res=96. -# 2) Set grid type ("gtype"). Valid choices are -# "uniform" - global uniform grid -# "stretch" - global stretched grid -# "nest" - global stretched grid with nest -# "regional_gfdl" - stand-alone gfdl regional grid -# "regional_esg" - stand-alone extended Schmidt gnomonic -# (esg) regional grid -# 3) For "uniform" and "regional_gfdl" grids - to include lake -# fraction and depth, set "add_lake" to true, and the -# "lake_cutoff" value. -# 4) For "stretch" and "nest" grids, set the stretching factor - -# "stretch_fac", and center lat/lon of highest resolution -# tile - "target_lat" and "target_lon". -# 5) For "nest" grids, set the refinement ratio - "refine_ratio", -# the starting/ending i/j index location within the parent -# tile - "istart_nest", "jstart_nest", "iend_nest", "jend_nest" -# 6) For "regional_gfdl" grids, set the "halo". Default is three -# rows/columns. -# 7) For "regional_esg" grids, set center lat/lon of grid, -# - "target_lat/lon" - the i/j dimensions - "i/jdim", the -# x/y grid spacing - "delx/y", and halo. -# 8) Set working directory - TEMP_DIR - and path to the repository -# clone - home_dir. -# 9) Check settings for 'make_gsl_orog' and 'veg_type_src' -# below. -# 10) Submit script: "cat $script | bsub". -# 11) All files will be placed in "out_dir". -# -#----------------------------------------------------------------------- - -source ../sorc/machine-setup.sh > /dev/null 2>&1 -module use ../modulefiles -module load build.$target.intel -module list - -#----------------------------------------------------------------------- -# Set grid specs here. -#----------------------------------------------------------------------- - -export gtype=uniform # 'uniform', 'stretch', 'nest', - # 'regional_gfdl', 'regional_esg' -export make_gsl_orog=false # 'true' if user needs 'oro' files for GSL - # orographic drag suite -export veg_type_src="modis.igbp.0.05" # veg type data. - # For viirs-based vegetation type data, set to: - # 1) "viirs.igbp.0.05" for global 5km data - # 2) "viirs.igbp.0.1" for global 10km data - # 3) "viirs.igbp.0.03" for global 3km data - # 4) "viirs.igbp.conus.0.01" for regional 1km data - # For the modis-based data, set to: - # 1) "modis.igbp.0.05" for global 5km data - # 2) "modis.igbp.0.03" for global 3km data - # 3) "modis.igbp.conus.0.01" for regional 1km data - -if [ $gtype = uniform ]; then - export res=96 - export add_lake=false # Add lake frac and depth to orography data. - export lake_cutoff=0.20 # lake frac < lake_cutoff ignored when add_lake=T -elif [ $gtype = stretch ]; then - export res=96 - export stretch_fac=1.5 # Stretching factor for the grid - export target_lon=-97.5 # Center longitude of the highest resolution tile - export target_lat=35.5 # Center latitude of the highest resolution tile -elif [ $gtype = nest ] || [ $gtype = regional_gfdl ]; then - export add_lake=false # Add lake frac and depth to orography data. - export lake_cutoff=0.20 # lake frac < lake_cutoff ignored when add_lake=T - export res=768 - export stretch_fac=1.5 # Stretching factor for the grid - export target_lon=-97.5 # Center longitude of the highest resolution tile - export target_lat=38.5 # Center latitude of the highest resolution tile - export refine_ratio=3 # The refinement ratio - export istart_nest=123 # Starting i-direction index of nest grid in parent tile supergrid - export jstart_nest=331 # Starting j-direction index of nest grid in parent tile supergrid - export iend_nest=1402 # Ending i-direction index of nest grid in parent tile supergrid - export jend_nest=1194 # Ending j-direction index of nest grid in parent tile supergrid - export halo=3 # Lateral boundary halo -elif [ $gtype = regional_esg ] ; then - export res=-999 # equivalent resolution is computed - export target_lon=-97.5 # Center longitude of grid - export target_lat=35.5 # Center latitude of grid - export idim=301 # Dimension of grid in 'i' direction - export jdim=200 # Dimension of grid in 'j' direction - export delx=0.0585 # Grid spacing (in degrees) in the 'i' direction - # on the SUPERGRID (which has twice the resolution of - # the model grid). The physical grid spacing in the 'i' - # direction is related to delx as follows: - # distance = 2*delx*(circumf_Earth/360 deg) - export dely=0.0585 # Grid spacing (in degrees) in the 'j' direction. - export halo=3 # number of row/cols for halo -fi - -#----------------------------------------------------------------------- -# Check paths. -# home_dir - location of repository. -# TEMP_DIR - working directory. -# out_dir - where files will be placed upon completion. -#----------------------------------------------------------------------- - -export home_dir=$LS_SUBCWD/.. -export TEMP_DIR=/gpfs/hps3/stmp/$LOGNAME/fv3_grid.$gtype -export out_dir=/gpfs/hps3/stmp/$LOGNAME/my_grids - -#----------------------------------------------------------------------- -# Should not need to change anything below here. -#----------------------------------------------------------------------- - -export NODES=1 -export APRUN="aprun -n 1 -N 1 -j 1 -d 1 -cc depth" -export APRUN_SFC="aprun -j 1 -n 24 -N 24" -# The orography code is optimized for six threads. -export OMP_NUM_THREADS=6 -export OMP_STACKSIZE=2048m -export KMP_AFFINITY=disabled -export machine=WCOSS_C -export NCDUMP=/gpfs/hps/usrx/local/prod/NetCDF/4.2/intel/sandybridge/bin/ncdump - -ulimit -a -ulimit -s unlimited - -#----------------------------------------------------------------------- -# Start script. -#----------------------------------------------------------------------- - -$home_dir/ush/fv3gfs_driver_grid.sh - -exit diff --git a/driver_scripts/driver_grid.hera.sh b/driver_scripts/driver_grid.hera.sh index 4674e6e8e..3f10f6095 100755 --- a/driver_scripts/driver_grid.hera.sh +++ b/driver_scripts/driver_grid.hera.sh @@ -6,8 +6,9 @@ #SBATCH -o log.fv3_grid_driver #SBATCH -e log.fv3_grid_driver #SBATCH --nodes=1 --ntasks-per-node=24 +##SBATCH --partition=bigmem #SBATCH -q debug -#SBATCH -t 00:30:00 +#SBATCH -t 00:20:00 #----------------------------------------------------------------------- # Driver script to create a cubic-sphere based model grid on Hera. @@ -23,8 +24,9 @@ # Note: The sfc_climo_gen program only runs with an # mpi task count that is a multiple of six. This is # an ESMF library requirement. Large grids may require -# tasks spread across multiple nodes. The orography code -# benefits from threads. +# tasks spread across multiple nodes or to be run on +# 'bigmem' nodes (#SBATCH --partition=bigmem). The +# orography code benefits from threads. # # To run, do the following: # @@ -52,10 +54,11 @@ # x/y grid spacing - "delx/y", and halo. # 8) Set working directory - TEMP_DIR - and path to the repository # clone - home_dir. -# 9) Check settings for 'make_gsl_orog' and 'veg_type_src' -# below. -# 10) Submit script: "sbatch $script". -# 11) All files will be placed in "out_dir". +# 9) To use the GSL orographic drag suite, set 'make_gsl_orog' to true. +# 10) Set 'soil_veg_src' and 'veg_type_src' to choose the +# soil type and vegetation type data. +# 11) Submit script: "sbatch $script". +# 12) All files will be placed in "out_dir". # #----------------------------------------------------------------------- @@ -72,19 +75,41 @@ module list #----------------------------------------------------------------------- export gtype=uniform # 'uniform', 'stretch', 'nest', - # 'regional_gfdl', 'regional_esg' -export make_gsl_orog=false # 'true' if user needs 'oro' files for GSL - # orographic drag suite -export veg_type_src="modis.igbp.0.05" # veg type data. + # 'regional_gfdl', 'regional_esg'. + +export make_gsl_orog=false # When 'true' will output 'oro' files for + # the GSL orographic drag suite. + +export vegsoilt_frac='.false.' # When .false., output dominant soil and + # vegetation type category. When .true., + # output fraction of each category and + # the dominant category. A Fortran logical, + # so include the dots. + +export veg_type_src="modis.igbp.0.05" # Vegetation type data. # For viirs-based vegetation type data, set to: - # 1) "viirs.igbp.0.05" for global 5km data - # 2) "viirs.igbp.0.1" for global 10km data - # 3) "viirs.igbp.0.03" for global 3km data - # 4) "viirs.igbp.conus.0.01" for regional 1km data + # 1) "viirs.igbp.0.1" for global 0.10-deg data + # 2) "viirs.igbp.0.05" for global 0.05-deg data + # 3) "viirs.igbp.0.03" for global 0.03-deg data + # 4) "viirs.igbp.conus.30s" for CONUS 30s data + # 5) "viirs.igbp.nh.30s" for NH 30s data + # 6) "viirs.igbp.30s" for global 30s data # For the modis-based data, set to: - # 1) "modis.igbp.0.05" for global 5km data - # 2) "modis.igbp.0.03" for global 3km data - # 3) "modis.igbp.conus.0.01" for regional 1km data + # 1) "modis.igbp.0.05" for global 0.05-deg data + # 2) "modis.igbp.0.03" for global 0.03-deg data + # 3) "modis.igbp.conus.30s" for CONUS 30s data + # 4) "modis.igbp.nh.30s" for N Hemis 30s data + # 5) "modis.igbp.30s" for global 30s data + +export soil_type_src="statsgo.0.05" # Soil type data. + # For STATSGO data + # 1) "statsgo.0.05" for global 0.05-deg data + # 2) "statsgo.0.03" for global 0.03-deg data + # 3) "statsgo.conus.30s" for CONUS 30s data + # 4) "statsgo.nh.30s" for NH 30s data + # 5) "statsgo.30s" for global 30s data + # For Beijing Norm. Univ. data + # 1) "bnu.30s" for global 30s data. if [ $gtype = uniform ]; then export res=96 @@ -142,7 +167,6 @@ export APRUN=time export APRUN_SFC=srun export OMP_NUM_THREADS=24 export OMP_STACKSIZE=2048m -export machine=HERA ulimit -a ulimit -s unlimited diff --git a/driver_scripts/driver_grid.jet.sh b/driver_scripts/driver_grid.jet.sh index cf7d08475..2a9ef3e9f 100755 --- a/driver_scripts/driver_grid.jet.sh +++ b/driver_scripts/driver_grid.jet.sh @@ -53,10 +53,11 @@ # x/y grid spacing - "delx/y", and halo. # 8) Set working directory - TEMP_DIR - and path to the repository # clone - home_dir. -# 9) Check settings for 'make_gsl_orog' and 'veg_type_src' -# below. -# 10) Submit script: "sbatch $script". -# 11) All files will be placed in "out_dir". +# 9) To use the GSL orographic drag suite, set 'make_gsl_orog' to true. +# 10) Set 'soil_veg_src' and 'veg_type_src' to choose the +# soil type and vegetation type data. +# 11) Submit script: "sbatch $script". +# 12) All files will be placed in "out_dir". # #----------------------------------------------------------------------- @@ -73,18 +74,40 @@ module list export gtype=uniform # 'uniform', 'stretch', 'nest', # 'regional_gfdl', 'regional_esg' -export make_gsl_orog=false # 'true' if user needs 'oro' files for GSL - # orographic drag suite -export veg_type_src="modis.igbp.0.05" # veg type data. + +export make_gsl_orog=false # When 'true' will output 'oro' files for + # the GSL orographic drag suite. + +export vegsoilt_frac='.false.' # When true, outputs percent of each + # soil and veg type category and a + # dominant category. When false, only + # outputs the dominant category. A + # Fortran logical, so include the dots. + +export veg_type_src="modis.igbp.0.05" # Vegetation type data. # For viirs-based vegetation type data, set to: - # 1) "viirs.igbp.0.05" for global 5km data - # 2) "viirs.igbp.0.1" for global 10km data - # 3) "viirs.igbp.0.03" for global 3km data - # 4) "viirs.igbp.conus.0.01" for regional 1km data + # 1) "viirs.igbp.0.1" for global 0.10-deg data + # 2) "viirs.igbp.0.05" for global 0.05-deg data + # 3) "viirs.igbp.0.03" for global 0.03-deg data + # 4) "viirs.igbp.conus.30s" for CONUS 30s data + # 5) "viirs.igbp.nh.30s" for NH 30s data + # 6) "viirs.igbp.30s" for global 30s data # For the modis-based data, set to: - # 1) "modis.igbp.0.05" for global 5km data - # 2) "modis.igbp.0.03" for global 3km data - # 3) "modis.igbp.conus.0.01" for regional 1km data + # 1) "modis.igbp.0.05" for global 0.05-deg data + # 2) "modis.igbp.0.03" for global 0.03-deg data + # 3) "modis.igbp.conus.30s" for CONUS 30s data + # 4) "modis.igbp.nh.30s" for N Hemis 30s data + # 5) "modis.igbp.30s" for global 30s data + +export soil_type_src="statsgo.0.05" # Soil type data. + # For STATSGO soil type data, set to: + # 1) "statsgo.0.05" for global 0.05-deg data + # 2) "statsgo.0.03" for global 0.03-deg data + # 3) "statsgo.conus.30s" for CONUS 30s data + # 4) "statsgo.nh.30s" for NH 30s data + # 5) "statsgo.30s" for global 30s data + # For Beijing Normal Univ. data, set to: + # 1) "bnu.30s" for global 30s data. if [ $gtype = uniform ]; then export res=96 @@ -142,7 +165,6 @@ export APRUN=time export APRUN_SFC=srun export OMP_NUM_THREADS=24 export OMP_STACKSIZE=2048m -export machine=JET ulimit -a ulimit -s unlimited diff --git a/driver_scripts/driver_grid.orion.sh b/driver_scripts/driver_grid.orion.sh index 3350d21e3..3b56094c3 100755 --- a/driver_scripts/driver_grid.orion.sh +++ b/driver_scripts/driver_grid.orion.sh @@ -52,10 +52,11 @@ # x/y grid spacing - "delx/y", and halo. # 8) Set working directory - TEMP_DIR - and path to the repository # clone - home_dir. -# 9) Check settings for 'make_gsl_orog' and 'veg_type_src' -# below. -# 10) Submit script: "sbatch $script". -# 11) All files will be placed in "out_dir". +# 9) To use the GSL orographic drag suite, set 'make_gsl_orog' to true. +# 10) Set 'soil_veg_src' and 'veg_type_src' to choose the +# soil type and vegetation type data. +# 11) Submit script: "sbatch $script". +# 12) All files will be placed in "out_dir". # #----------------------------------------------------------------------- @@ -73,19 +74,39 @@ module list export gtype=regional_esg # 'uniform', 'stretch', 'nest', # 'regional_gfdl', 'regional_esg' -export make_gsl_orog=false # 'true' if user needs 'oro' files for GSL - # orographic drag suite +export make_gsl_orog=false # When 'true' will output 'oro' files for + # the GSL orographic drag suite. -export veg_type_src="modis.igbp.0.05" # veg type data. +export vegsoilt_frac='.false.' # When true, outputs percent of each + # soil and veg type category and a + # dominant category. When false, only + # outputs the dominant category. A + # Fortran logical, so include the dots. + +export veg_type_src="modis.igbp.0.05" # Vegetation type data. # For viirs-based vegetation type data, set to: - # 1) "viirs.igbp.0.05" for global 5km data - # 2) "viirs.igbp.0.1" for global 10km data - # 3) "viirs.igbp.0.03" for global 3km data - # 4) "viirs.igbp.conus.0.01" for regional 1km data + # 1) "viirs.igbp.0.1" for global 0.10-deg data + # 2) "viirs.igbp.0.05" for global 0.05-deg data + # 3) "viirs.igbp.0.03" for global 0.03-deg data + # 4) "viirs.igbp.conus.30s" for CONUS 30s data + # 5) "viirs.igbp.nh.30s" for NH 30s data + # 6) "viirs.igbp.30s" for global 30s data # For the modis-based data, set to: - # 1) "modis.igbp.0.05" for global 5km data - # 2) "modis.igbp.0.03" for global 3km data - # 3) "modis.igbp.conus.0.01" for regional 1km data + # 1) "modis.igbp.0.05" for global 0.05-deg data + # 2) "modis.igbp.0.03" for global 0.03-deg data + # 3) "modis.igbp.conus.30s" for CONUS 30s data + # 4) "modis.igbp.nh.30s" for N Hemis 30s data + # 5) "modis.igbp.30s" for global 30s data + +export soil_type_src="statsgo.0.05" # Soil type data. + # For STATSGO soil type data, set to: + # 1) "statsgo.0.05" for global 0.05-deg data + # 2) "statsgo.0.03" for global 0.03-deg data + # 3) "statsgo.conus.30s" for CONUS 30s data + # 4) "statsgo.nh.30s" for NH 30s data + # 5) "statsgo.30s" for global 30s data + # For Beijing Normal Univ. data, set to: + # 1) "bnu.30s" for global 30s data. if [ $gtype = uniform ]; then export res=96 @@ -143,7 +164,6 @@ export APRUN=time export APRUN_SFC=srun export OMP_NUM_THREADS=24 export OMP_STACKSIZE=2048m -export machine=ORION ulimit -a ulimit -s 199000000 diff --git a/driver_scripts/driver_grid.dell.sh b/driver_scripts/driver_grid.wcoss2.sh similarity index 67% rename from driver_scripts/driver_grid.dell.sh rename to driver_scripts/driver_grid.wcoss2.sh index c5b7c2c86..1a9c4bfb3 100755 --- a/driver_scripts/driver_grid.dell.sh +++ b/driver_scripts/driver_grid.wcoss2.sh @@ -1,18 +1,15 @@ #!/bin/bash -#BSUB -oo log.grid.%J -#BSUB -eo log.grid.%J -#BSUB -q debug -#BSUB -P GFS-DEV -#BSUB -J grid_fv3 -#BSUB -W 0:30 -#BSUB -x # run not shared -#BSUB -n 24 # total tasks -#BSUB -R span[ptile=24] # tasks per node -#BSUB -R affinity[core(1):distribute=balance] +#PBS -o log +#PBS -e log +#PBS -q debug +#PBS -A GFS-DEV +#PBS -l walltime=00:15:00 +#PBS -N make_grid +#PBS -l select=1:ncpus=24:mem=500GB #----------------------------------------------------------------------- -# Driver script to create a cubic-sphere based model grid on Dell. +# Driver script to create a cubic-sphere based model grid on WCOSS2. # # Produces the following files (netcdf, each tile in separate file): # 1) 'mosaic' and 'grid' files containing lat/lon and other @@ -54,13 +51,16 @@ # x/y grid spacing - "delx/y", and halo. # 8) Set working directory - TEMP_DIR - and path to the repository # clone - home_dir. -# 9) Check settings for 'make_gsl_orog' and 'veg_type_src' -# below. -# 10) Submit script: "cat $script | bsub". -# 11) All files will be placed in "out_dir". +# 9) To use the GSL orographic drag suite, set 'make_gsl_orog' to true. +# 10) Set 'soil_veg_src' and 'veg_type_src' to choose the +# soil type and vegetation type data. +# 11) Submit script: "qsub $script". +# 12) All files will be placed in "out_dir". # #----------------------------------------------------------------------- +cd $PBS_O_WORKDIR + source ../sorc/machine-setup.sh > /dev/null 2>&1 module use ../modulefiles module load build.$target.intel @@ -70,20 +70,42 @@ module list # Set grid specs here. #----------------------------------------------------------------------- -export gtype=uniform # 'uniform', 'stretch', 'nest', +export gtype=regional_esg # 'uniform', 'stretch', 'nest', # 'regional_gfdl', 'regional_esg' -export make_gsl_orog=false # 'true' if user needs 'oro' files for GSL - # orographic drag suite -export veg_type_src="modis.igbp.0.05" # veg type data. + +export make_gsl_orog=false # When 'true' will output 'oro' files for + # the GSL orographic drag suite. + +export vegsoilt_frac='.false.' # When true, outputs percent of each + # soil and veg type category and a + # dominant category. When false, only + # outputs the dominant category. A + # Fortran logical, so include the dots. + +export veg_type_src="modis.igbp.0.05" # Vegetation type data. # For viirs-based vegetation type data, set to: - # 1) "viirs.igbp.0.05" for global 5km data - # 2) "viirs.igbp.0.1" for global 10km data - # 3) "viirs.igbp.0.03" for global 3km data - # 4) "viirs.igbp.conus.0.01" for regional 1km data + # 1) "viirs.igbp.0.1" for global 0.10-deg data + # 2) "viirs.igbp.0.05" for global 0.05-deg data + # 3) "viirs.igbp.0.03" for global 0.03-deg data + # 4) "viirs.igbp.conus.30s" for CONUS 30s data + # 5) "viirs.igbp.nh.30s" for NH 30s data + # 6) "viirs.igbp.30s" for global 30s data # For the modis-based data, set to: - # 1) "modis.igbp.0.05" for global 5km data - # 2) "modis.igbp.0.03" for global 3km data - # 3) "modis.igbp.conus.0.01" for regional 1km data + # 1) "modis.igbp.0.05" for global 0.05-deg data + # 2) "modis.igbp.0.03" for global 0.03-deg data + # 3) "modis.igbp.conus.30s" for CONUS 30s data + # 4) "modis.igbp.nh.30s" for N Hemis 30s data + # 5) "modis.igbp.30s" for global 30s data + +export soil_type_src="statsgo.0.05" # Soil type data + # For STATSGO soil type data, set to: + # 1) "statsgo.0.05" for global 0.05-deg data + # 2) "statsgo.0.03" for global 0.03-deg data + # 3) "statsgo.conus.30s" for CONUS 30s data + # 4) "statsgo.nh.30s" for NH 30s data + # 5) "statsgo.30s" for global 30s data + # For Beijing Normal Univ. data, set to: + # 1) "bnu.30s" for global 30s data. if [ $gtype = uniform ]; then export res=96 @@ -110,7 +132,7 @@ elif [ $gtype = nest ] || [ $gtype = regional_gfdl ]; then elif [ $gtype = regional_esg ] ; then export res=-999 # equivalent resolution is computed export target_lon=-97.5 # Center longitude of grid - export target_lat=35.5 # Center latitude of grid + export target_lat=35.0 # Center latitude of grid export idim=301 # Dimension of grid in 'i' direction export jdim=200 # Dimension of grid in 'j' direction export delx=0.0585 # Grid spacing (in degrees) in the 'i' direction @@ -129,19 +151,23 @@ fi # out_dir - where files will be placed upon completion. #----------------------------------------------------------------------- -export home_dir=$LS_SUBCWD/.. -export TEMP_DIR=/gpfs/dell1/stmp/$LOGNAME/fv3_grid.$gtype -export out_dir=/gpfs/dell1/stmp/$LOGNAME/my_grids +export home_dir=$PBS_O_WORKDIR/.. +export TEMP_DIR=/lfs/h2/emc/stmp/$LOGNAME/fv3_grid.$gtype +export out_dir=/lfs/h2/emc/stmp/$LOGNAME/my_grids #----------------------------------------------------------------------- -# Should not need to change anything below here. +# Should not need to change anything below here unless you want to +# to change the job card for the number of tasks to use. Then, +# you will need to check APRUN_SFC and OMP_NUM_THREADS. #----------------------------------------------------------------------- +set -x + export APRUN=time -export APRUN_SFC="mpirun -l" +export APRUN_SFC="mpiexec -n 24 -ppn 24 -cpu-bind core" export OMP_NUM_THREADS=24 # orog code worked best with 24 threads. +export OMP_PLACES=cores export OMP_STACKSIZE=2048m -export machine=WCOSS_DELL_P3 ulimit -a ulimit -s unlimited diff --git a/fix/link_fixdirs.sh b/fix/link_fixdirs.sh index bc5ea6f41..7fcc370c6 100755 --- a/fix/link_fixdirs.sh +++ b/fix/link_fixdirs.sh @@ -1,7 +1,15 @@ -#!/bin/ksh +#!/bin/bash set -ex -#--Make symbolic links to 'fixed' directories. +# Set up the 'fixed' directories. +# +# This script takes two arguments: +# +# $RUN_ENVIR - Either 'emc' (creates links) or +# 'nco' (copies data). +# +# $machine - is the machine. Choices are: +# 'wcoss2', 'hera', 'jet', 'orion', 's4' RUN_ENVIR=${1} machine=${2} @@ -9,52 +17,60 @@ machine=${2} if [ $# -lt 2 ]; then set +x echo '***ERROR*** must specify two arguements: (1) RUN_ENVIR, (2) machine' - echo ' Syntax: link_fv3gfs.sh ( nco | emc ) ( cray | dell | hera | jet | orion | s4 )' + echo ' Syntax: link_fv3gfs.sh ( nco | emc ) ( wcoss2 | hera | jet | orion | s4 )' exit 1 fi if [ $RUN_ENVIR != emc -a $RUN_ENVIR != nco ]; then set +x echo '***ERROR*** unsupported run environment' - echo 'Syntax: link_fv3gfs.sh ( nco | emc ) ( cray | dell | hera | jet | orion | s4 )' + echo ' Must choose either "nco" or "emc".' exit 1 fi -if [ $machine != cray -a $machine != hera -a $machine != dell -a $machine != jet -a $machine != orion -a $machine != s4 ]; then + +if [ $machine != wcoss2 -a $machine != hera -a $machine != jet -a $machine != orion -a $machine != s4 ]; then set +x echo '***ERROR*** unsupported machine' - echo 'Syntax: link_fv3gfs.sh ( nco | emc ) ( cray | dell | hera | jet | orion | s4 )' + echo 'Syntax: link_fv3gfs.sh ( nco | emc ) ( wcoss2 | hera | jet | orion | s4 )' exit 1 fi LINK="ln -fs" SLINK="ln -fs" -[[ $RUN_ENVIR = nco ]] && LINK="cp -rp" +[[ $RUN_ENVIR = nco ]] && LINK="cp -rpL" pwd=$(pwd -P) #------------------------------ #--model fix fields #------------------------------ -if [ $machine == "cray" ]; then - FIX_DIR="/gpfs/hps3/emc/global/noscrub/emc.glopara/git/fv3gfs/fix" -elif [ $machine = "dell" ]; then - FIX_DIR="/gpfs/dell2/emc/modeling/noscrub/emc.glopara/git/fv3gfs/fix" -elif [ $machine = "hera" ]; then +if [ $machine = "hera" ]; then FIX_DIR="/scratch1/NCEPDEV/global/glopara/fix" elif [ $machine = "jet" ]; then FIX_DIR="/lfs4/HFIP/hfv3gfs/glopara/git/fv3gfs/fix" elif [ $machine = "orion" ]; then FIX_DIR="/work/noaa/global/glopara/fix" +elif [ $machine = "wcoss2" ]; then + FIX_DIR="/lfs/h2/emc/global/noscrub/emc.global/FIX/fix" elif [ $machine = "s4" ]; then FIX_DIR="/data/prod/glopara/fix" fi -for dir in fix_am fix_fv3 fix_orog fix_fv3_gmted2010 fix_sfc_climo; do +am_ver=${am_ver:-20220805} +orog_ver=${orog_ver:-20220805} +sfc_climo_ver=${sfc_climo_ver:-20221017} + +for dir in am orog orog_raw sfc_climo; do if [ -d $dir ]; then [[ $RUN_ENVIR = nco ]] && chmod -R 755 $dir rm -rf $dir fi - $LINK $FIX_DIR/$dir . + if [ $dir = "orog_raw" ]; then + $LINK $FIX_DIR/raw/orog ${dir} + else + fix_ver="${dir}_ver" + $LINK $FIX_DIR/$dir/${!fix_ver} ${dir} + fi done exit 0 diff --git a/modulefiles/build.cheyenne.intel b/modulefiles/build.cheyenne.intel deleted file mode 100644 index 570a424f4..000000000 --- a/modulefiles/build.cheyenne.intel +++ /dev/null @@ -1,29 +0,0 @@ -#%Module##################################################### -## Build and run module for Cheyenne -############################################################# - -module purge -module load ncarenv/1.3 -module load intel/19.1.1 -module load mpt/2.19 -module load ncarcompilers/0.5.0 -module load cmake/3.16.4 - -module use -a /glade/p/ral/jntp/GMTB/tools/NCEPLIBS-ufs-v2.0.0/intel-19.1.1/mpt-2.19/modules - -module load bacio/2.4.1 -module load g2/3.4.1 -module load ip/3.3.3 -module load nemsio/2.5.2 -module load sp/2.3.3 -module load w3nco/2.4.1 -module load sigio/2.3.2 - -module load sfcio/1.4.1 -module load wgrib2/2.0.8 -module load netcdf/4.7.4 - -setenv ESMFMKFILE /glade/p/ral/jntp/GMTB/tools/NCEPLIBS-ufs-v2.0.0/intel-19.1.1/mpt-2.19/lib64/esmf.mk - -setenv CMAKE_C_COMPILER icc -setenv CMAKE_Fortran_COMPILER ifort diff --git a/modulefiles/build.cheyenne.intel.lua b/modulefiles/build.cheyenne.intel.lua new file mode 100644 index 000000000..0c00298d8 --- /dev/null +++ b/modulefiles/build.cheyenne.intel.lua @@ -0,0 +1,85 @@ +help([[ +Load environment to compile UFS_UTILS on Cheyenne using Intel +]]) + +cmake_ver=os.getenv("cmake_ver") or "3.22.0" +load(pathJoin("cmake", cmake_ver)) + +python_ver=os.getenv("python_ver") or "3.7.9" +load(pathJoin("python", python)) + +ncarenv_ver=os.getenv("ncarenv_ver") or "1.3" +load(pathJoin("ncarenv", ncarenv_ver)) + +intel_ver=os.getenv("intel_ver") or "2022.1" +load(pathJoin("intel", intel_ver)) + +mpt_ver=os.getenv("mpt_ver") or "2.25" +load(pathJoin("mpt", mpt_ver)) + +ncarcompilers_ver=os.getenv("ncarcompilers_ver") or "0.5.0" +load(pathJoin("ncarcompilers", ncarcompilers_ver)) + + +unload("netcdf") + + +prepend_path("MODULEPATH", "/glade/work/epicufsrt/GMTB/tools/intel/2022.1/hpc-stack-v1.2.0_6eb6/modulefiles/stack") + +hpc_ver=os.getenv("hpc_ver") or "1.2.0" +load(pathJoin("hpc", hpc_ver)) + +hpc_intel_ver=os.getenv("hpc_intel_ver") or "2022.1" +load(pathJoin("hpc-intel", hpc_intel_ver)) + +hpc_mpt_ver=os.getenv("hpc_mpt_ver") or "2.25" +load(pathJoin("hpc-mpt", hpc_mpt_ver)) + + +-- ??? load("ufs_common") + + +bacio_ver=os.getenv("bacio_ver") or "2.4.1" +load(pathJoin("bacio", bacio_ver)) + +g2_ver=os.getenv("g2_ver") or "3.4.3" +load(pathJoin("g2", g2_ver)) + +ip_ver=os.getenv("ip_ver") or "3.3.3" +load(pathJoin("ip", ip_ver)) + +nemsio_ver=os.getenv("nemsio_ver") or "2.5.2" +load(pathJoin("nemsio", nemsio_ver)) + +sp_ver=os.getenv("sp_ver") or "2.3.3" +load(pathJoin("sp", sp_ver)) + +w3nco_ver=os.getenv("w3nco_ver") or "2.4.1" +load(pathJoin("w3nco", w3nco_ver)) + +sigio_ver=os.getenv("sigio_ver") or "2.3.2" +load(pathJoin("sigio", sigio_ver)) + + + +sfcio_ver=os.getenv("sfcio_ver") or "1.4.1" +load(pathJoin("sfcio", sfcio_ver)) + +netcdf_ver=os.getenv("netcdf_ver") or "4.7.4" +load(pathJoin("netcdf", netcdf_ver)) + +esmf_ver=os.getenv("esmf_ver") or "8.3.0b09" +load(pathJoin("esmf", esmf_ver)) + +setenv("CMAKE_C_COMPILER","icc") +setenv("CMAKE_Fortran_COMPILER","ifort") + +-- From UFS Model build modulefile... +-- setenv("CC", "mpicc") +-- setenv("CXX", "mpicxx") +-- setenv("FC", "mpif90") +-- setenv("CMAKE_Platform", "cheyenne.intel") + + +whatis("Description: UFS_UTILS build environment") + diff --git a/modulefiles/build.hera.gnu b/modulefiles/build.hera.gnu deleted file mode 100644 index 15702b39e..000000000 --- a/modulefiles/build.hera.gnu +++ /dev/null @@ -1,28 +0,0 @@ -#%Module##################################################### -## Build and run module for Hera -############################################################# - -module load hpss -module load cmake/3.16.1 - -module use /scratch2/NCEPDEV/nwprod/hpc-stack/libs/hpc-stack/modulefiles/stack - -module load hpc/1.1.0 -module load hpc-gnu/9.2.0 -module load hpc-mpich/3.3.2 - -module load netcdf/4.7.4 -module load esmf/8_1_0_beta_snapshot_27 -module load bacio/2.4.1 -module load g2/3.4.1 -module load ip/3.3.3 -module load nemsio/2.5.2 -module load sp/2.3.3 -module load w3nco/2.4.1 -module load sfcio/1.4.1 -module load sigio/2.3.2 -module load wgrib2/2.0.8 -module load nccmp/1.8.7.0 -module load png/1.6.35 -module load zlib/1.2.11 -module load jasper/2.0.22 diff --git a/modulefiles/build.hera.gnu.lua b/modulefiles/build.hera.gnu.lua new file mode 100644 index 000000000..33b8e6875 --- /dev/null +++ b/modulefiles/build.hera.gnu.lua @@ -0,0 +1,61 @@ +help([[ +Load environment to compile UFS_UTILS on Hera using Gnu +]]) + +cmake_ver=os.getenv("cmake_ver") or "3.16.1" +load(pathJoin("cmake", cmake_ver)) + +hpss_ver=os.getenv("hpss_ver") or "" +load(pathJoin("hpss", hpss_ver)) + +prepend_path("MODULEPATH", "/scratch2/NCEPDEV/nwprod/hpc-stack/libs/hpc-stack/modulefiles/stack") + +hpc_ver=os.getenv("hpc_ver") or "1.1.0" +load(pathJoin("hpc", hpc_ver)) + +hpc_gnu_ver=os.getenv("hpc_gnu_ver") or "9.2.0" +load(pathJoin("hpc-gnu", hpc_gnu_ver)) + +mpich_ver=os.getenv("mpich_ver") or "3.3.2" +load(pathJoin("hpc-mpich", mpich_ver)) + +netcdf_ver=os.getenv("netcdf_ver") or "4.7.4" +load(pathJoin("netcdf", netcdf_ver)) + +esmf_ver=os.getenv("esmf_ver") or "8.4.0b08" +load(pathJoin("esmf", esmf_ver)) + +bacio_ver=os.getenv("bacio_ver") or "2.4.1" +load(pathJoin("bacio", bacio_ver)) + +g2_ver=os.getenv("g2_ver") or "3.4.3" +load(pathJoin("g2", g2_ver)) + +ip_ver=os.getenv("ip_ver") or "4.0.0" +load(pathJoin("ip", ip_ver)) + +nemsio_ver=os.getenv("nemsio_ver") or "2.5.2" +load(pathJoin("nemsio", nemsio_ver)) + +sp_ver=os.getenv("sp_ver") or "2.3.3" +load(pathJoin("sp", sp_ver)) + +w3emc_ver=os.getenv("w3emc_ver") or "2.9.2" +load(pathJoin("w3emc", w3emc_ver)) + +sfcio_ver=os.getenv("sfcio_ver") or "1.4.1" +load(pathJoin("sfcio", sfcio_ver)) + +sigio_ver=os.getenv("sigio_ver") or "2.3.2" +load(pathJoin("sigio", sigio_ver)) + +nccmp_ver=os.getenv("nccmp_ver") or "1.8.7.0" +load(pathJoin("nccmp", nccmp_ver)) + +zlib_ver=os.getenv("zlib_ver") or "1.2.11" +load(pathJoin("zlib", zlib_ver)) + +png_ver=os.getenv("png_ver") or "1.6.35" +load(pathJoin("png", png_ver)) + +whatis("Description: UFS_UTILS build environment") diff --git a/modulefiles/build.hera.intel b/modulefiles/build.hera.intel deleted file mode 100644 index 7c68b4143..000000000 --- a/modulefiles/build.hera.intel +++ /dev/null @@ -1,31 +0,0 @@ -#%Module##################################################### -## Build and run module for Hera -############################################################# - -module load hpss -module load cmake/3.16.1 - -module use /scratch2/NCEPDEV/nwprod/hpc-stack/libs/hpc-stack/modulefiles/stack - -module load hpc/1.1.0 -module load hpc-intel/18.0.5.274 -module load hpc-impi/2018.0.4 - -module load bacio/2.4.1 -module load g2/3.4.1 -module load ip/3.3.3 -module load nemsio/2.5.2 -module load sp/2.3.3 -module load w3nco/2.4.1 -module load sfcio/1.4.1 -module load sigio/2.3.2 -module load wgrib2/2.0.8 - -module load jasper/2.0.22 -module load zlib/1.2.11 -module load png/1.6.35 - -module load hdf5/1.10.6 -module load netcdf/4.7.4 -module load nccmp/1.8.7.0 -module load esmf/8_1_0_beta_snapshot_27 diff --git a/modulefiles/build.hera.intel.lua b/modulefiles/build.hera.intel.lua new file mode 100644 index 000000000..a3734b6ce --- /dev/null +++ b/modulefiles/build.hera.intel.lua @@ -0,0 +1,67 @@ +help([[ +Load environment to compile UFS_UTILS on Hera using Intel +]]) + +cmake_ver=os.getenv("cmake_ver") or "3.16.1" +load(pathJoin("cmake", cmake_ver)) + +hpss_ver=os.getenv("hpss_ver") or "" +load(pathJoin("hpss", hpss_ver)) + +prepend_path("MODULEPATH", "/scratch2/NCEPDEV/nwprod/hpc-stack/libs/hpc-stack/modulefiles/stack") + +hpc_ver=os.getenv("hpc_ver") or "1.2.0" +load(pathJoin("hpc", hpc_ver)) + +hpc_intel_ver=os.getenv("hpc_intel_ver") or "2022.1.2" +load(pathJoin("hpc-intel", hpc_intel_ver)) + +impi_ver=os.getenv("impi_ver") or "2022.1.2" +load(pathJoin("hpc-impi", impi_ver)) + +bacio_ver=os.getenv("bacio_ver") or "2.4.1" +load(pathJoin("bacio", bacio_ver)) + +g2_ver=os.getenv("g2_ver") or "3.4.5" +load(pathJoin("g2", g2_ver)) + +ip_ver=os.getenv("ip_ver") or "4.0.0" +load(pathJoin("ip", ip_ver)) + +nemsio_ver=os.getenv("nemsio_ver") or "2.5.4" +load(pathJoin("nemsio", nemsio_ver)) + +sp_ver=os.getenv("sp_ver") or "2.3.3" +load(pathJoin("sp", sp_ver)) + +w3emc_ver=os.getenv("w3emc_ver") or "2.9.2" +load(pathJoin("w3emc", w3emc_ver)) + +sfcio_ver=os.getenv("sfcio_ver") or "1.4.1" +load(pathJoin("sfcio", sfcio_ver)) + +sigio_ver=os.getenv("sigio_ver") or "2.3.2" +load(pathJoin("sigio", sigio_ver)) + +zlib_ver=os.getenv("zlib_ver") or "1.2.11" +load(pathJoin("zlib", zlib_ver)) + +png_ver=os.getenv("png_ver") or "1.6.35" +load(pathJoin("libpng", png_ver)) + +hdf5_ver=os.getenv("hdf5_ver") or "1.10.6" +load(pathJoin("hdf5", hdf5_ver)) + +netcdf_ver=os.getenv("netcdf_ver") or "4.7.4" +load(pathJoin("netcdf", netcdf_ver)) + +nccmp_ver=os.getenv("nccmp_ver") or "1.8.9.0" +load(pathJoin("nccmp", nccmp_ver)) + +esmf_ver=os.getenv("esmf_ver") or "8.4.0b08" +load(pathJoin("esmf", esmf_ver)) + +nco_ver=os.getenv("nco_ver") or "4.9.1" +load(pathJoin("nco", nco_ver)) + +whatis("Description: UFS_UTILS build environment") diff --git a/modulefiles/build.jet.intel b/modulefiles/build.jet.intel deleted file mode 100644 index 4161fcff0..000000000 --- a/modulefiles/build.jet.intel +++ /dev/null @@ -1,27 +0,0 @@ -#%Module##################################################### -## Build and run module for Jet -############################################################# -module load cmake/3.16.1 -module load hpss - -module use /lfs4/HFIP/hfv3gfs/nwprod/hpc-stack/libs/modulefiles/stack -module load hpc/1.1.0 -module load hpc-intel/18.0.5.274 -module load hpc-impi/2018.4.274 - -module load hdf5/1.10.6 -module load netcdf/4.7.4 -module load nccmp/1.8.7.0 -module load esmf/8_1_0_beta_snapshot_27 -module load jasper/2.0.22 - -module load w3nco/2.4.1 -module load sp/2.3.3 -module load ip/3.3.3 -module load bacio/2.4.1 -module load sigio/2.3.2 -module load sfcio/1.4.1 -module load nemsio/2.5.2 -module load g2/3.4.1 -module load wgrib2/2.0.8 -module load prod_util/1.2.2 diff --git a/modulefiles/build.jet.intel.lua b/modulefiles/build.jet.intel.lua new file mode 100644 index 000000000..e6ce6a54a --- /dev/null +++ b/modulefiles/build.jet.intel.lua @@ -0,0 +1,64 @@ +help([[ +Load environment to compile UFS_UTILS on Jet +]]) + +cmake_ver=os.getenv("cmake_ver") or "3.16.1" +load(pathJoin("cmake", cmake_ver)) + +hpss_ver=os.getenv("hpss_ver") or "" +load(pathJoin("hpss", hpss_ver)) + +prepend_path("MODULEPATH", "/lfs4/HFIP/hfv3gfs/role.epic/hpc-stack/libs/intel-2022.1.2/modulefiles/stack") + +hpc_ver=os.getenv("hpc_ver") or "1.2.0" +load(pathJoin("hpc", hpc_ver)) + +hpc_intel_ver=os.getenv("hpc_intel_ver") or "2022.1.2" +load(pathJoin("hpc-intel", hpc_intel_ver)) + +impi_ver=os.getenv("impi_ver") or "2022.1.2" +load(pathJoin("hpc-impi", impi_ver)) + +hdf5_ver=os.getenv("hdf5_ver") or "1.10.6" +load(pathJoin("hdf5", hdf5_ver)) + +netcdf_ver=os.getenv("netcdf_ver") or "4.7.4" +load(pathJoin("netcdf", netcdf_ver)) + +nccmp_ver=os.getenv("nccmp_ver") or "1.8.9.0" +load(pathJoin("nccmp", nccmp_ver)) + +esmf_ver=os.getenv("esmf_ver") or "8.4.0b08" +load(pathJoin("esmf", esmf_ver)) + +w3emc_ver=os.getenv("w3emc_ver") or "2.9.2" +load(pathJoin("w3emc", w3emc_ver)) + +sp_ver=os.getenv("sp_ver") or "2.3.3" +load(pathJoin("sp", sp_ver)) + +ip_ver=os.getenv("ip_ver") or "4.0.0" +load(pathJoin("ip", ip_ver)) + +bacio_ver=os.getenv("bacio_ver") or "2.4.1" +load(pathJoin("bacio", bacio_ver)) + +sigio_ver=os.getenv("sigio_ver") or "2.3.2" +load(pathJoin("sigio", sigio_ver)) + +sfcio_ver=os.getenv("sfcio_ver") or "1.4.1" +load(pathJoin("sfcio", sfcio_ver)) + +nemsio_ver=os.getenv("nemsio_ver") or "2.5.4" +load(pathJoin("nemsio", nemsio_ver)) + +g2_ver=os.getenv("g2_ver") or "3.4.5" +load(pathJoin("g2", g2_ver)) + +prod_util_ver=os.getenv("prod_util_ver") or "1.2.2" +load(pathJoin("prod_util", prod_util_ver)) + +nco_ver=os.getenv("nco_ver") or "4.9.3" +load(pathJoin("nco", nco_ver)) + +whatis("Description: UFS_UTILS build environment") diff --git a/modulefiles/build.odin.intel b/modulefiles/build.odin.intel deleted file mode 100644 index 362aa3a84..000000000 --- a/modulefiles/build.odin.intel +++ /dev/null @@ -1,37 +0,0 @@ -#%Module##################################################### -## Build and run module for Odin -############################################################# - -module load craype/2.6.2 -module load craype-ivybridge -module load PrgEnv-intel -module swap intel/19.0.5.281 -module load cray-mpich/7.7.10 -module load cray-libsci -module load cray-netcdf-hdf5parallel -module load cray-parallel-netcdf -module load cray-hdf5-parallel - -setenv NETCDF /opt/cray/pe/netcdf-hdf5parallel/4.6.3.2/INTEL/19.0 - -#module use -a /oldscratch/ywang/external/modulefiles -#module use /oldscratch/ywang/external/NCEPLIBS_SRW/modules -module use /oldscratch/ywang/external/NCEPLIBS_SRWv2.0/modules -module load w3nco -module load sp -module load ip -module load bacio -module load sigio -module load sfcio -module load nemsio -module load g2 -module load wgrib2 - -#module load esmf/8.0.0 -#setenv ESMFMKFILE /oldscratch/ywang/external/NCEPLIBS_SRW/lib64/esmf.mk -setenv ESMFMKFILE /oldscratch/ywang/external/NCEPLIBS_SRWv2.0/lib64/esmf.mk - -setenv CMAKE_Fortran_COMPILER ftn -setenv CMAKE_C_COMPILER cc - -#setenv WGRIB2_ROOT /oldscratch/ywang/external/NCEPLIBS_SRWv2.0/wgrib2-2.0.8 diff --git a/modulefiles/build.orion.intel b/modulefiles/build.orion.intel deleted file mode 100644 index 891623680..000000000 --- a/modulefiles/build.orion.intel +++ /dev/null @@ -1,30 +0,0 @@ -#%Module##################################################### -## Build module for Orion -############################################################# - -module load cmake/3.17.3 - -module use /apps/contrib/NCEP/libs/hpc-stack/modulefiles/stack - -module load hpc/1.1.0 -module load hpc-intel/2018.4 -module load hpc-impi/2018.4 - -module load bacio/2.4.1 -module load g2/3.4.1 -module load ip/3.3.3 -module load nemsio/2.5.2 -module load sp/2.3.3 -module load w3nco/2.4.1 -module load sfcio/1.4.1 -module load sigio/2.3.2 -module load wgrib2/2.0.8 - -module load jasper/2.0.22 -module load zlib/1.2.11 -module load png/1.6.35 - -module load hdf5/1.10.6 -module load netcdf/4.7.4 -module load nccmp/1.8.7.0 -module load esmf/8_1_0_beta_snapshot_27 diff --git a/modulefiles/build.orion.intel.lua b/modulefiles/build.orion.intel.lua new file mode 100644 index 000000000..10ca1a654 --- /dev/null +++ b/modulefiles/build.orion.intel.lua @@ -0,0 +1,64 @@ +help([[ +Load environment to compile UFS_UTILS on Orion +]]) + +cmake_ver=os.getenv("cmake_ver") or "3.17.3" +load(pathJoin("cmake", cmake_ver)) + +prepend_path("MODULEPATH", "/apps/contrib/NCEP/hpc-stack/libs/hpc-stack/modulefiles/stack") + +hpc_ver=os.getenv("hpc_ver") or "1.2.0" +load(pathJoin("hpc", hpc_ver)) + +hpc_intel_ver=os.getenv("hpc_intel_ver") or "2022.1.2" +load(pathJoin("hpc-intel", hpc_intel_ver)) + +impi_ver=os.getenv("impi_ver") or "2022.1.2" +load(pathJoin("hpc-impi", impi_ver)) + +bacio_ver=os.getenv("bacio_ver") or "2.4.1" +load(pathJoin("bacio", bacio_ver)) + +g2_ver=os.getenv("g2_ver") or "3.4.5" +load(pathJoin("g2", g2_ver)) + +ip_ver=os.getenv("ip_ver") or "4.0.0" +load(pathJoin("ip", ip_ver)) + +nemsio_ver=os.getenv("nemsio_ver") or "2.5.4" +load(pathJoin("nemsio", nemsio_ver)) + +sp_ver=os.getenv("sp_ver") or "2.3.3" +load(pathJoin("sp", sp_ver)) + +w3emc_ver=os.getenv("w3emc_ver") or "2.9.2" +load(pathJoin("w3emc", w3emc_ver)) + +sfcio_ver=os.getenv("sfcio_ver") or "1.4.1" +load(pathJoin("sfcio", sfcio_ver)) + +sigio_ver=os.getenv("sigio_ver") or "2.3.2" +load(pathJoin("sigio", sigio_ver)) + +zlib_ver=os.getenv("zlib_ver") or "1.2.11" +load(pathJoin("zlib", zlib_ver)) + +png_ver=os.getenv("png_ver") or "1.6.35" +load(pathJoin("libpng", png_ver)) + +hdf5_ver=os.getenv("hdf5_ver") or "1.10.6" +load(pathJoin("hdf5", hdf5_ver)) + +netcdf_ver=os.getenv("netcdf_ver") or "4.7.4" +load(pathJoin("netcdf", netcdf_ver)) + +nccmp_ver=os.getenv("nccmp_ver") or "1.8.9.0" +load(pathJoin("nccmp", nccmp_ver)) + +esmf_ver=os.getenv("esmf_ver") or "8.4.0b08" +load(pathJoin("esmf", esmf_ver)) + +nco_ver=os.getenv("nco_ver") or "4.9.3" +load(pathJoin("nco", nco_ver)) + +whatis("Description: UFS_UTILS build environment") diff --git a/modulefiles/build.s4.intel b/modulefiles/build.s4.intel deleted file mode 100644 index 8a9a0b0eb..000000000 --- a/modulefiles/build.s4.intel +++ /dev/null @@ -1,28 +0,0 @@ -#%Module##################################################### -## Build and run module for S4 -############################################################# - -module load license_intel/S4 -module use /data/prod/hpc-stack/modulefiles/stack -module load hpc/1.1.0 -module load hpc-intel/18.0.4 -module load hpc-impi/18.0.4 - -module load bacio/2.4.1 -module load g2/3.4.1 -module load ip/3.3.3 -module load nemsio/2.5.2 -module load sp/2.3.3 -module load w3nco/2.4.1 -module load sfcio/1.4.1 -module load sigio/2.3.2 -module load wgrib2/2.0.8 - -module load jasper/2.0.22 -module load zlib/1.2.11 -module load png/1.6.35 - -module load hdf5/1.10.6 -module load netcdf/4.7.4 -module load nccmp/1.8.7.0 -module load esmf/8_1_0_beta_snapshot_27 diff --git a/modulefiles/build.s4.intel.lua b/modulefiles/build.s4.intel.lua new file mode 100644 index 000000000..c9418d420 --- /dev/null +++ b/modulefiles/build.s4.intel.lua @@ -0,0 +1,59 @@ +help([[ +Load environment to compile UFS_UTILS on S4 using Intel +]]) + +load(pathJoin("license_intel","S4")) +prepend_path("MODULEPATH", "/data/prod/hpc-stack/modulefiles/stack") + +hpc_ver=os.getenv("hpc_ver") or "1.2.0" +load(pathJoin("hpc", hpc_ver)) + +hpc_intel_ver=os.getenv("hpc_intel_ver") or "2022.1" +load(pathJoin("hpc-intel", hpc_intel_ver)) + +impi_ver=os.getenv("impi_ver") or "2022.1" +load(pathJoin("hpc-impi", impi_ver)) + +bacio_ver=os.getenv("bacio_ver") or "2.4.1" +load(pathJoin("bacio", bacio_ver)) + +g2_ver=os.getenv("g2_ver") or "3.4.5" +load(pathJoin("g2", g2_ver)) + +ip_ver=os.getenv("ip_ver") or "3.3.3" +load(pathJoin("ip", ip_ver)) + +nemsio_ver=os.getenv("nemsio_ver") or "2.5.4" +load(pathJoin("nemsio", nemsio_ver)) + +sp_ver=os.getenv("sp_ver") or "2.3.3" +load(pathJoin("sp", sp_ver)) + +w3nco_ver=os.getenv("w3nco_ver") or "2.4.1" +load(pathJoin("w3nco", w3nco_ver)) + +sfcio_ver=os.getenv("sfcio_ver") or "1.4.1" +load(pathJoin("sfcio", sfcio_ver)) + +sigio_ver=os.getenv("sigio_ver") or "2.3.2" +load(pathJoin("sigio", sigio_ver)) + +zlib_ver=os.getenv("zlib_ver") or "1.2.11" +load(pathJoin("zlib", zlib_ver)) + +png_ver=os.getenv("png_ver") or "1.6.35" +load(pathJoin("libpng", png_ver)) + +hdf5_ver=os.getenv("hdf5_ver") or "1.10.6" +load(pathJoin("hdf5", hdf5_ver)) + +netcdf_ver=os.getenv("netcdf_ver") or "4.7.4" +load(pathJoin("netcdf", netcdf_ver)) + +nccmp_ver=os.getenv("nccmp_ver") or "1.8.9.0" +load(pathJoin("nccmp", nccmp_ver)) + +esmf_ver=os.getenv("esmf_ver") or "8.2.1b04" +load(pathJoin("esmf", esmf_ver)) + +whatis("Description: UFS_UTILS build environment") diff --git a/modulefiles/build.stampede.intel b/modulefiles/build.stampede.intel index 5d5829507..e91e253ca 100644 --- a/modulefiles/build.stampede.intel +++ b/modulefiles/build.stampede.intel @@ -32,7 +32,6 @@ module load sigio module load sfcio module load nemsio module load g2 -module load wgrib2 #setenv ESMFMKFILE /work/00315/tg455890/stampede2/regional_fv3/NCEPLIBS_SRWv2.0/lib64/esmf.mk diff --git a/modulefiles/build.wcoss2.intel.lua b/modulefiles/build.wcoss2.intel.lua index 48eb0ed46..967e41b48 100644 --- a/modulefiles/build.wcoss2.intel.lua +++ b/modulefiles/build.wcoss2.intel.lua @@ -5,10 +5,10 @@ Load environment to compile UFS_UTILS on WCOSS2 cmake_ver=os.getenv("cmake_ver") or "3.20.2" load(pathJoin("cmake", cmake_ver)) -PrgEnv_intel_ver=os.getenv("PrgEnv_intel_ver") or "8.1.0" +PrgEnv_intel_ver=os.getenv("PrgEnv_intel_ver") or "8.3.3" load(pathJoin("PrgEnv-intel", PrgEnv_intel_ver)) -craype_ver=os.getenv("craype_ver") or "2.7.13" +craype_ver=os.getenv("craype_ver") or "2.7.17" load(pathJoin("craype", craype_ver)) intel_ver=os.getenv("intel_ver") or "19.1.3.304" @@ -17,7 +17,6 @@ load(pathJoin("intel", intel_ver)) cray_mpich_ver=os.getenv("cray_mpich_ver") or "8.1.7" load(pathJoin("cray-mpich", cray_mpich_ver)) - libjpeg_ver=os.getenv("libjpeg_ver") or "9c" load(pathJoin("libjpeg", libjpeg_ver)) @@ -39,8 +38,8 @@ load(pathJoin("bacio", bacio_ver)) sfcio_ver=os.getenv("sfcio_ver") or "1.4.1" load(pathJoin("sfcio", sfcio_ver)) -w3nco_ver=os.getenv("w3nco_ver") or "2.4.1" -load(pathJoin("w3nco", w3nco_ver)) +w3emc_ver=os.getenv("w3emc_ver") or "2.9.2" +load(pathJoin("w3emc", w3emc_ver)) nemsio_ver=os.getenv("nemsio_ver") or "2.5.2" load(pathJoin("nemsio", nemsio_ver)) @@ -51,17 +50,14 @@ load(pathJoin("sigio", sigio_ver)) sp_ver=os.getenv("sp_ver") or "2.3.3" load(pathJoin("sp", sp_ver)) -ip_ver=os.getenv("ip_ver") or "3.3.3" +ip_ver=os.getenv("ip_ver") or "4.0.0" load(pathJoin("ip", ip_ver)) g2_ver=os.getenv("g2_ver") or "3.4.5" load(pathJoin("g2", g2_ver)) -wgrib2_ver=os.getenv("wgrib2_ver") or "2.0.8" -load(pathJoin("wgrib2", wgrib2_ver)) - -- for mpiexec command -cray_pals_ver=os.getenv("cray_pals_ver") or "1.0.12" +cray_pals_ver=os.getenv("cray_pals_ver") or "1.2.2" load(pathJoin("cray-pals", cray_pals_ver)) udunits_ver=os.getenv("udunits_ver") or "2.2.28" @@ -73,10 +69,7 @@ load(pathJoin("gsl", gsl_ver)) nco_ver=os.getenv("nco_ver") or "4.9.7" load(pathJoin("nco", nco_ver)) -setenv("HPC_OPT","/apps/ops/para/libs") -prepend_path("MODULEPATH", "/apps/ops/para/libs/modulefiles/compiler/intel/19.1.3.304") -prepend_path("MODULEPATH", "/apps/ops/para/libs/modulefiles/mpi/intel/19.1.3.304/cray-mpich/8.1.7") -esmf_ver=os.getenv("esmf_ver") or "8.2.1b04" +esmf_ver=os.getenv("esmf_ver") or "8.4.1" load(pathJoin("esmf", esmf_ver)) whatis("Description: UFS_UTILS build environment") diff --git a/modulefiles/build.wcoss_cray.intel b/modulefiles/build.wcoss_cray.intel deleted file mode 100644 index c6e297d28..000000000 --- a/modulefiles/build.wcoss_cray.intel +++ /dev/null @@ -1,39 +0,0 @@ -#%Module##################################################### -## Build and run module for WCOSS-Cray -############################################################# - -module load prod_util/1.1.0 -module load hpss/4.1.0.3 -module load xt-lsfhpc/9.1.3 -module load cfp-intel-sandybridge/1.1.0 -module load cmake/3.16.2 -module load PrgEnv-intel/5.2.56 -module rm intel -module load intel/18.1.163 -module load cray-mpich/7.2.0 -module load craype-haswell -module load alps/5.2.4-2.0502.9822.32.1.ari -module load cray-netcdf/4.3.3.1 -module load cray-hdf5/1.8.14 - -module use /usrx/local/nceplibs/NCEPLIBS/cmake/install/NCEPLIBS-v1.2.0/modules -module load bacio/2.4.1 -module load g2/3.4.1 -module load ip/3.3.3 -module load nemsio/2.5.2 -module load sp/2.3.3 -module load w3nco/2.4.1 -module load sfcio/1.4.1 -module load sigio/2.3.2 -module load wgrib2/2.0.8 - -setenv ZLIB_ROOT /usrx/local/prod/zlib/1.2.7/intel/haswell -setenv PNG_ROOT /usrx/local/prod/png/1.2.49/intel/haswell -setenv Jasper_ROOT /usrx/local/prod/jasper/1.900.1/intel/haswell - -module use /gpfs/hps3/emc/nems/noscrub/emc.nemspara/soft/modulefiles -#module load esmf/8.0.0 -setenv ESMFMKFILE /gpfs/hps3/emc/nems/noscrub/emc.nemspara/soft/esmf/8.0.0/lib/esmf.mk -setenv NETCDF /opt/cray/netcdf/4.3.3.1/INTEL/14.0 -module rm gcc -module load gcc/6.3.0 diff --git a/modulefiles/build.wcoss_dell_p3.intel b/modulefiles/build.wcoss_dell_p3.intel deleted file mode 100644 index 4e44018e8..000000000 --- a/modulefiles/build.wcoss_dell_p3.intel +++ /dev/null @@ -1,35 +0,0 @@ -#%Module##################################################### -## Build and run module for WCOSS-Dell P3 -############################################################# - -module load lsf/10.1 -module load HPSS/5.0.2.5 -module load cmake/3.16.2 - -module use /usrx/local/nceplibs/dev/hpc-stack/libs/hpc-stack/modulefiles/stack - -module load hpc/1.1.0 -module load hpc-ips/18.0.1.163 -module load hpc-impi/18.0.1 - -module load jasper/2.0.22 -module load zlib/1.2.11 -module load png/1.6.35 - -module load hdf5/1.10.6 -module load netcdf/4.7.4 -module load nccmp/1.8.7.0 -module load esmf/8_1_0_beta_snapshot_27 - -module load bacio/2.4.1 -module load g2/3.4.1 -module load ip/3.3.3 -module load nemsio/2.5.2 -module load sp/2.3.3 -module load w3nco/2.4.1 -module load sfcio/1.4.1 -module load sigio/2.3.2 -module load wgrib2/2.0.8 - -module use /usrx/local/dev/modulefiles -module load prod_util/1.1.3 diff --git a/parm/msis_lib/msis21.parm b/parm/msis_lib/msis21.parm new file mode 100644 index 000000000..8809e7b4f Binary files /dev/null and b/parm/msis_lib/msis21.parm differ diff --git a/parm/varmap_tables/README b/parm/varmap_tables/README index 1bfbd10b8..31af3c463 100644 --- a/parm/varmap_tables/README +++ b/parm/varmap_tables/README @@ -14,7 +14,10 @@ Column 2: Name the code will use to save the variable in the output file. Unimpl Comumn 3: Behavior when the code can't find the variable in the input file. Options are: "skip": Don't write to output file. "set_to_fill": Set to user-specified field value (see column 4). - "intrp": LnP interpolation to missing levels. No extrapolation allowd. + "intrp": Ln(pressure) interpolation to missing levels. Linear interpolation and + extrapolation are possible, but require modifying the value of "LINLOG" + in input_data.F90 to anything other than 2, or to a negative number, + respectively. "stop": Force an exception and stop code execution. Use this if you absolutely require a field to be present. Column 4: If column 3 = "set_to_fill", then this value is used to fill in all points diff --git a/reg_tests/chgres_cube/13km.conus.nam.grib2.sh b/reg_tests/chgres_cube/13km.conus.nam.grib2.sh index 7d97800db..16af5e42b 100755 --- a/reg_tests/chgres_cube/13km.conus.nam.grib2.sh +++ b/reg_tests/chgres_cube/13km.conus.nam.grib2.sh @@ -19,7 +19,7 @@ export FIXsfc=${FIXfv3}/fix_sfc export COMIN=${HOMEreg}/input_data/nam.grib2 export GRIB2_FILE_INPUT=nam_218_20200801_0000_000.grb2 -export VCOORD_FILE=${HOMEufs}/fix/fix_am/global_hyblev.l64.txt +export VCOORD_FILE=${HOMEufs}/fix/am/global_hyblev.l64.txt export VARMAP_FILE=${HOMEufs}/parm/varmap_tables/GFSphys_var_map.txt export INPUT_TYPE='grib2' export CONVERT_NST=".false." @@ -82,6 +82,9 @@ done set +x if [ $test_failed -ne 0 ]; then echo "<<< 13-KM CONUS NAM GRIB2 TEST FAILED. >>>" + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + $HOMEufs/reg_tests/update_baseline.sh $HOMEreg "13km_conus_nam_grib2" $commit_num + fi else echo "<<< 13-KM CONUS NAM GRIB2 TEST PASSED. >>>" fi diff --git a/reg_tests/chgres_cube/13km.conus.rap.grib2.sh b/reg_tests/chgres_cube/13km.conus.rap.grib2.sh index 441f953fe..e69bff8b0 100755 --- a/reg_tests/chgres_cube/13km.conus.rap.grib2.sh +++ b/reg_tests/chgres_cube/13km.conus.rap.grib2.sh @@ -19,7 +19,7 @@ export FIXsfc=${FIXfv3}/fix_sfc export COMIN=${HOMEreg}/input_data/rap.grib2 export GRIB2_FILE_INPUT=1921221000900 -export VCOORD_FILE=${HOMEufs}/fix/fix_am/global_hyblev.l64.txt +export VCOORD_FILE=${HOMEufs}/fix/am/global_hyblev.l64.txt export VARMAP_FILE=${HOMEufs}/parm/varmap_tables/GSDphys_var_map.txt export INPUT_TYPE='grib2' export CONVERT_NST=".false." @@ -30,15 +30,15 @@ export HALO_BNDY=4 export CDATE=2019080100 export EXTERNAL_MODEL="RAP" export NSOILL_OUT=9 -export TRACERS_TARGET="NULL" -export TRACERS_INPUT="NULL" +export TRACERS_TARGET='"NULL"' +export TRACERS_INPUT='"NULL"' export SOTYP_FROM_CLIMO=.false. export VGTYP_FROM_CLIMO=.false. export VGFRC_FROM_CLIMO=.true. export MINMAX_VGFRC_FROM_CLIMO=.true. export TG3_FROM_SOIL=.true. export LAI_FROM_CLIMO=.true. -export GEOGRID_FILE_INPUT=${HOMEufs}/fix/fix_am/geo_em.d01.nc_RAPX +export GEOGRID_FILE_INPUT=${HOMEufs}/fix/am/geo_em.d01.nc_RAPX export OMP_NUM_THREADS_CH=${OMP_NUM_THREADS:-1} @@ -90,6 +90,9 @@ done set +x if [ $test_failed -ne 0 ]; then echo "<<< 13-km CONUS RAP W/ GSD PHYSICS AND SFC FROM FILE GRIB2 TEST FAILED. >>>" + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + $HOMEufs/reg_tests/update_baseline.sh $HOMEreg "13km_conus_rap_grib2" $commit_num + fi else echo "<<< 13-km CONUS RAP W/ GSD PHYSICS AND SFC FROM FILE GRIB2 TEST PASSED. >>>" fi diff --git a/reg_tests/chgres_cube/13km.na.gfs.ncei.grib2.sh b/reg_tests/chgres_cube/13km.na.gfs.ncei.grib2.sh index c98df7122..2e48b8095 100755 --- a/reg_tests/chgres_cube/13km.na.gfs.ncei.grib2.sh +++ b/reg_tests/chgres_cube/13km.na.gfs.ncei.grib2.sh @@ -19,7 +19,7 @@ export FIXsfc=${FIXfv3}/fix_sfc export COMIN=${HOMEreg}/input_data/gfs.ncei.grib2 export GRIB2_FILE_INPUT=gfs_4_20190801_0000_000.grb2 -export VCOORD_FILE=${HOMEufs}/fix/fix_am/global_hyblev.l64.txt +export VCOORD_FILE=${HOMEufs}/fix/am/global_hyblev.l64.txt export VARMAP_FILE=${HOMEufs}/parm/varmap_tables/GFSphys_var_map.txt export INPUT_TYPE='grib2' export CONVERT_NST=".false." @@ -79,6 +79,9 @@ done set +x if [ $test_failed -ne 0 ]; then echo "<<< 13-KM NA GFS NCEI GRIB2 TEST FAILED. >>>" + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + $HOMEufs/reg_tests/update_baseline.sh $HOMEreg "13km_na_gfs_ncei_grib2" $commit_num + fi else echo "<<< 13-KM NA GFS NCEI GRIB2 TEST PASSED. >>>" fi diff --git a/reg_tests/chgres_cube/25km.conus.gfs.grib2.sh b/reg_tests/chgres_cube/25km.conus.gfs.grib2.sh index 61bbe7e50..b7cb4129d 100755 --- a/reg_tests/chgres_cube/25km.conus.gfs.grib2.sh +++ b/reg_tests/chgres_cube/25km.conus.gfs.grib2.sh @@ -19,11 +19,11 @@ export FIXsfc=${FIXfv3}/fix_sfc export COMIN=${HOMEreg}/input_data/gfs.grib2 export GRIB2_FILE_INPUT=gfs.t00z.pgrb2.0p50.f000 -export VCOORD_FILE=${HOMEufs}/fix/fix_am/global_hyblev.l64.txt +export VCOORD_FILE=${HOMEufs}/fix/am/global_hyblev.l64.txt export VARMAP_FILE=${HOMEufs}/parm/varmap_tables/GSDphys_noaero_var_map.txt export INPUT_TYPE='grib2' export CONVERT_NST=".false." -export THOMPSON_AEROSOL_FILE=${HOMEufs}/fix/fix_am/Thompson_MP_MONTHLY_CLIMO.nc +export THOMPSON_AEROSOL_FILE=${HOMEufs}/fix/am/Thompson_MP_MONTHLY_CLIMO.nc export OROG_FILES_TARGET_GRID="C403_oro_data.tile7.halo4.nc" export REGIONAL=1 export HALO_BLEND=0 @@ -80,6 +80,9 @@ done set +x if [ $test_failed -ne 0 ]; then echo "<<< 25-KM CONUS GFS GRIB2 TEST FAILED. >>>" + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + $HOMEufs/reg_tests/update_baseline.sh $HOMEreg "25km_conus_gfs_grib2" $commit_num + fi else echo "<<< 25-KM CONUS GFS GRIB2 TEST PASSED. >>>" fi diff --git a/reg_tests/chgres_cube/25km.conus.gfs.pbgrib2.sh b/reg_tests/chgres_cube/25km.conus.gfs.pbgrib2.sh index bb23c3004..b104804a8 100755 --- a/reg_tests/chgres_cube/25km.conus.gfs.pbgrib2.sh +++ b/reg_tests/chgres_cube/25km.conus.gfs.pbgrib2.sh @@ -19,7 +19,7 @@ export FIXsfc=${FIXfv3}/fix_sfc export COMIN=${HOMEreg}/input_data/gfs.pbgrib2 export GRIB2_FILE_INPUT=gfs.t18z.pgrb2.0p25.f006 -export VCOORD_FILE=${HOMEufs}/fix/fix_am/global_hyblev.l64.txt +export VCOORD_FILE=${HOMEufs}/fix/am/global_hyblev.l64.txt export VARMAP_FILE=${HOMEufs}/parm/varmap_tables/GFSphys_var_map.txt export INPUT_TYPE='grib2' export CONVERT_NST=".false." @@ -79,6 +79,9 @@ done set +x if [ $test_failed -ne 0 ]; then echo "<<< 25-KM CONUS GFS PGRIB2+BGRIB2 TEST FAILED. >>>" + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + $HOMEufs/reg_tests/update_baseline.sh $HOMEreg "25km_conus_gfs_pbgrib2" $commit_num + fi else echo "<<< 25-KM CONUS GFS PGRIB2+BGRIB2 TEST PASSED. >>>" fi diff --git a/reg_tests/chgres_cube/3km.conus.hrrr.gfssdf.grib2.sh b/reg_tests/chgres_cube/3km.conus.hrrr.gfssdf.grib2.sh index 67711b8f6..63e7702c5 100755 --- a/reg_tests/chgres_cube/3km.conus.hrrr.gfssdf.grib2.sh +++ b/reg_tests/chgres_cube/3km.conus.hrrr.gfssdf.grib2.sh @@ -19,7 +19,7 @@ export FIXsfc=${FIXfv3}/fix_sfc export COMIN=${HOMEreg}/input_data/hrrr.grib2 export GRIB2_FILE_INPUT=1918200000000 -export VCOORD_FILE=${HOMEufs}/fix/fix_am/global_hyblev.l64.txt +export VCOORD_FILE=${HOMEufs}/fix/am/global_hyblev.l64.txt export VARMAP_FILE=${HOMEufs}/parm/varmap_tables/GFSphys_var_map.txt export INPUT_TYPE='grib2' export CONVERT_NST=".false." @@ -30,9 +30,9 @@ export HALO_BNDY=4 export CDATE=2019080100 export EXTERNAL_MODEL="HRRR" export NSOILL_OUT=4 -export TRACERS_TARGET="NULL" -export TRACERS_INPUT="NULL" -export GEOGRID_FILE_INPUT=${HOMEufs}/fix/fix_am/geo_em.d01.nc_HRRRX +export TRACERS_TARGET='"NULL"' +export TRACERS_INPUT='"NULL"' +export GEOGRID_FILE_INPUT=${HOMEufs}/fix/am/geo_em.d01.nc_HRRRX export OMP_NUM_THREADS_CH=${OMP_NUM_THREADS:-1} @@ -84,6 +84,9 @@ done set +x if [ $test_failed -ne 0 ]; then echo "<<< 3-km CONUS HRRR W/ GFS PHYSICS GRIB2 TEST FAILED. >>>" + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + $HOMEufs/reg_tests/update_baseline.sh $HOMEreg "3km_conus_hrrr_gfssdf_grib2" $commit_num + fi else echo "<<< 3-km CONUS HRRR W/ GFS PHYSICS GRIB2 TEST PASSED. >>>" fi diff --git a/reg_tests/chgres_cube/3km.conus.hrrr.newsfc.grib2.sh b/reg_tests/chgres_cube/3km.conus.hrrr.newsfc.grib2.sh index 30be5e98e..a8dfcea9e 100755 --- a/reg_tests/chgres_cube/3km.conus.hrrr.newsfc.grib2.sh +++ b/reg_tests/chgres_cube/3km.conus.hrrr.newsfc.grib2.sh @@ -19,7 +19,7 @@ export FIXsfc=${FIXfv3}/fix_sfc export COMIN=${HOMEreg}/input_data/hrrr.grib2 export GRIB2_FILE_INPUT=1921300000000 -export VCOORD_FILE=${HOMEufs}/fix/fix_am/global_hyblev.l64.txt +export VCOORD_FILE=${HOMEufs}/fix/am/global_hyblev.l64.txt export VARMAP_FILE=${HOMEufs}/parm/varmap_tables/GSDphys_var_map.txt export INPUT_TYPE='grib2' export CONVERT_NST=".false." @@ -30,15 +30,15 @@ export HALO_BNDY=4 export CDATE=2019080100 export EXTERNAL_MODEL="HRRR" export NSOILL_OUT=9 -export TRACERS_TARGET="NULL" -export TRACERS_INPUT="NULL" +export TRACERS_TARGET='"NULL"' +export TRACERS_INPUT='"NULL"' export SOTYP_FROM_CLIMO=.false. export VGTYP_FROM_CLIMO=.false. export VGFRC_FROM_CLIMO=.false. export MINMAX_VGFRC_FROM_CLIMO=.false. export TG3_FROM_SOIL=.true. export LAI_FROM_CLIMO=.false. -export GEOGRID_FILE_INPUT=${HOMEufs}/fix/fix_am/geo_em.d01.nc_HRRRX +export GEOGRID_FILE_INPUT=${HOMEufs}/fix/am/geo_em.d01.nc_HRRRX export OMP_NUM_THREADS_CH=${OMP_NUM_THREADS:-1} @@ -90,6 +90,9 @@ done set +x if [ $test_failed -ne 0 ]; then echo "<<< 3-km CONUS HRRR W/ GSD PHYSICS AND SFC FROM FILE GRIB2 TEST FAILED. >>>" + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + $HOMEufs/reg_tests/update_baseline.sh $HOMEreg "3km_conus_hrrr_newsfc_grib2" $commit_num + fi else echo "<<< 3-km CONUS HRRR W/ GSD PHYSICS AND SFC FROM FILE GRIB2 TEST PASSED. >>>" fi diff --git a/reg_tests/chgres_cube/README b/reg_tests/chgres_cube/README index 424accd4b..23d03f292 100644 --- a/reg_tests/chgres_cube/README +++ b/reg_tests/chgres_cube/README @@ -7,18 +7,16 @@ To run the consistency tests: 1) Build chgres_cube program. Go to ./sorc and invoke 'build_all.sh' with no arguments. -2) Invoke driver script for your machine. See script - prolog for details. Supported machines are: - - Hera (driver.hera.sh) - - WCOSS-Cray (driver.cray.sh) - - WCOSS-Dell (driver.dell.sh) - - Jet (driver.jet.sh) - - Orion (driver.orion.sh) +2) Set the fixed directories. Go to ./fix and + invoke the script. +3) Invoke driver script for your machine. See script + prolog for details. -A series of daisy-chained tests will run. A test fails -if the output files differ from the baseline set of files -as determined by the 'nccmp' utility. +A series of tests will run. A test fails if the output +files differ from the baseline set of files as determined +by the 'nccmp' utility. -Log output from the tests will be in "regression.log". +Log output from each test will be placed in its own +logfile - "consistency.log??". A summary of results will be in "summary.log". diff --git a/reg_tests/chgres_cube/c192.fv3.history.sh b/reg_tests/chgres_cube/c192.fv3.history.sh index 44fd8ae81..5c63765fd 100755 --- a/reg_tests/chgres_cube/c192.fv3.history.sh +++ b/reg_tests/chgres_cube/c192.fv3.history.sh @@ -19,7 +19,7 @@ export COMIN=${HOMEreg}/input_data/fv3.history # Pay attention to the quotes. Dont start/end with double quote. export ATM_FILES_INPUT='dynf000.tile1.nc","dynf000.tile2.nc","dynf000.tile3.nc","dynf000.tile4.nc","dynf000.tile5.nc","dynf000.tile6.nc' export SFC_FILES_INPUT='phyf000.tile1.nc","phyf000.tile2.nc","phyf000.tile3.nc","phyf000.tile4.nc","phyf000.tile5.nc","phyf000.tile6.nc' -export VCOORD_FILE=${HOMEufs}/fix/fix_am/global_hyblev.l64.txt +export VCOORD_FILE=${HOMEufs}/fix/am/global_hyblev.l64.txt export INPUT_TYPE='history' export MOSAIC_FILE_INPUT_GRID="${HOMEreg}/fix/C96/C96_mosaic.nc" export OROG_DIR_INPUT_GRID=${HOMEreg}/fix/C96 @@ -72,6 +72,9 @@ done set +x if [ $test_failed -ne 0 ]; then echo "<<< C192 FV3 HISTORY TEST FAILED. >>>" + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + $HOMEufs/reg_tests/update_baseline.sh $HOMEreg "c192_fv3_history" $commit_num + fi else echo "<<< C192 FV3 HISTORY TEST PASSED. >>>" fi diff --git a/reg_tests/chgres_cube/c192.gfs.grib2.sh b/reg_tests/chgres_cube/c192.gfs.grib2.sh index 5b8cf2bac..9b7baa99a 100755 --- a/reg_tests/chgres_cube/c192.gfs.grib2.sh +++ b/reg_tests/chgres_cube/c192.gfs.grib2.sh @@ -17,7 +17,7 @@ export FIXfv3=${HOMEreg}/fix/C192 export COMIN=${HOMEreg}/input_data/gfs.grib2 export GRIB2_FILE_INPUT=gfs.t00z.pgrb2.0p50.f000 -export VCOORD_FILE=${HOMEufs}/fix/fix_am/global_hyblev.l65.txt +export VCOORD_FILE=${HOMEufs}/fix/am/global_hyblev.l65.txt export VARMAP_FILE=${HOMEufs}/parm/varmap_tables/GFSphys_var_map.txt export INPUT_TYPE='grib2' export CONVERT_NST=".false." @@ -67,6 +67,9 @@ done set +x if [ $test_failed -ne 0 ]; then echo "<<< C192 GFS GRIB2 TEST FAILED. >>>" + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + $HOMEufs/reg_tests/update_baseline.sh $HOMEreg "c192_gfs_grib2" $commit_num + fi else echo "<<< C192 GFS GRIB2 TEST PASSED. >>>" fi diff --git a/reg_tests/chgres_cube/c96.fv3.nemsio.sh b/reg_tests/chgres_cube/c96.fv3.nemsio.sh index e0271c15b..fe7576206 100755 --- a/reg_tests/chgres_cube/c96.fv3.nemsio.sh +++ b/reg_tests/chgres_cube/c96.fv3.nemsio.sh @@ -16,7 +16,7 @@ export FIXfv3=${HOMEreg}/fix/C96 export COMIN=${HOMEreg}/input_data/fv3.nemsio export ATM_FILES_INPUT=gfs.t12z.atmf000.nemsio export SFC_FILES_INPUT=gfs.t12z.sfcf000.nemsio -export VCOORD_FILE=${HOMEufs}/fix/fix_am/global_hyblev.l64.txt +export VCOORD_FILE=${HOMEufs}/fix/am/global_hyblev.l64.txt export CDATE=2019070412 @@ -63,6 +63,9 @@ done set +x if [ $test_failed -ne 0 ]; then echo "<<< C96 FV3 GAUSSIAN NEMSIO TEST FAILED. >>>" + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + $HOMEufs/reg_tests/update_baseline.sh $HOMEreg "c96_fv3_nemsio" $commit_num + fi else echo "<<< C96 FV3 GAUSSIAN NEMSIO TEST PASSED. >>>" fi diff --git a/reg_tests/chgres_cube/c96.fv3.netcdf.sh b/reg_tests/chgres_cube/c96.fv3.netcdf.sh index 4f5618737..dfdeb6282 100755 --- a/reg_tests/chgres_cube/c96.fv3.netcdf.sh +++ b/reg_tests/chgres_cube/c96.fv3.netcdf.sh @@ -16,7 +16,7 @@ export FIXfv3=${HOMEreg}/fix/C96 export COMIN=${HOMEreg}/input_data/fv3.netcdf export ATM_FILES_INPUT=gfs.t00z.atmf000.nc export SFC_FILES_INPUT=gfs.t00z.sfcf000.nc -export VCOORD_FILE=${HOMEufs}/fix/fix_am/global_hyblev.l64.txt +export VCOORD_FILE=${HOMEufs}/fix/am/global_hyblev.l64.txt export INPUT_TYPE="gaussian_netcdf" export CDATE=2020020200 @@ -64,6 +64,9 @@ done set +x if [ $test_failed -ne 0 ]; then echo "<<< C96 FV3 GAUSSIAN NETCDF TEST FAILED. >>>" + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + $HOMEufs/reg_tests/update_baseline.sh $HOMEreg "c96_fv3_netcdf" $commit_num + fi else echo "<<< C96 FV3 GAUSSIAN NETCDF TEST PASSED. >>>" fi diff --git a/reg_tests/chgres_cube/c96.fv3.netcdf2wam.sh b/reg_tests/chgres_cube/c96.fv3.netcdf2wam.sh index 7adf8f04b..269448759 100755 --- a/reg_tests/chgres_cube/c96.fv3.netcdf2wam.sh +++ b/reg_tests/chgres_cube/c96.fv3.netcdf2wam.sh @@ -15,17 +15,18 @@ rm -fr $DATA export FIXfv3=${HOMEreg}/fix/C96 export COMIN=${HOMEreg}/input_data/fv3.netcdf export ATM_FILES_INPUT=gfs.t00z.atmf000.nc -export VCOORD_FILE=${HOMEufs}/fix/fix_am/global_hyblev.l64.txt +export VCOORD_FILE=${HOMEufs}/fix/am/global_hyblev.l64.txt export INPUT_TYPE="gaussian_netcdf" export CONVERT_SFC=".false." export CONVERT_NST=".false." +export WAM_PARM_FILE=${HOMEufs}/parm/msis_lib/msis21.parm export CDATE=2020020200 # export TRACERS_INPUT='"sphum","liq_wat","o3mr","ice_wat","rainwat","snowwat","graupel"' export TRACERS_TARGET='"sphum","liq_wat","spo3","ice_wat","rainwat","snowwat","graupel","spo","spo2"' -export VCOORD_FILE=${HOMEufs}/fix/fix_am/global_hyblev.l150.txt +export VCOORD_FILE=${HOMEufs}/fix/am/global_hyblev.l150.txt export WAM_COLD_START=.true. export OMP_NUM_THREADS_CH=${OMP_NUM_THREADS:-1} @@ -71,6 +72,9 @@ done set +x if [ $test_failed -ne 0 ]; then echo "<<< C96 FV3 GAUSSIAN NETCDF2WAM TEST FAILED. >>>" + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + $HOMEufs/reg_tests/update_baseline.sh $HOMEreg "c96_fv3_netcdf2wam" $commit_num + fi else echo "<<< C96 FV3 GAUSSIAN NETCDF2WAM TEST PASSED. >>>" fi diff --git a/reg_tests/chgres_cube/c96.fv3.restart.sh b/reg_tests/chgres_cube/c96.fv3.restart.sh index bcc38ea44..9e67bfa96 100755 --- a/reg_tests/chgres_cube/c96.fv3.restart.sh +++ b/reg_tests/chgres_cube/c96.fv3.restart.sh @@ -14,7 +14,7 @@ rm -fr $DATA export FIXfv3=${HOMEreg}/fix/C96 export COMIN=${HOMEreg}/input_data/fv3.restart -export VCOORD_FILE=${HOMEufs}/fix/fix_am/global_hyblev.l64.txt +export VCOORD_FILE=${HOMEufs}/fix/am/global_hyblev.l64.txt export INPUT_TYPE='restart' export MOSAIC_FILE_INPUT_GRID="${HOMEreg}/fix/C384/C384_mosaic.nc" export OROG_DIR_INPUT_GRID=${HOMEreg}/fix/C384 @@ -73,6 +73,9 @@ done set +x if [ $test_failed -ne 0 ]; then echo "<<< C96 FV3 RESTART TEST FAILED. >>>" + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + $HOMEufs/reg_tests/update_baseline.sh $HOMEreg "c96_fv3_restart" $commit_num + fi else echo "<<< C96 FV3 RESTART TEST PASSED. >>>" fi diff --git a/reg_tests/chgres_cube/c96.gefs.grib2.sh b/reg_tests/chgres_cube/c96.gefs.grib2.sh new file mode 100755 index 000000000..6d86a4a1f --- /dev/null +++ b/reg_tests/chgres_cube/c96.gefs.grib2.sh @@ -0,0 +1,79 @@ +#!/bin/bash + +#----------------------------------------------------------------------------- +# Invoke chgres to create C96 coldstart files using GEFS GRIB2 data +# as input. The coldstart files are then compared to baseline files +# using the 'nccmp' utility. This script is run by the machine specific +# driver script. +#----------------------------------------------------------------------------- + +set -x + +export DATA=$OUTDIR/c96_gefs_grib2 +rm -fr $DATA + +export CRES=96 +export FIXfv3=${HOMEreg}/fix/C96 +export COMIN=${HOMEreg}/input_data/gefs.grib2 + +export GRIB2_FILE_INPUT=gec00.t06z.pgrb2abf00 +export VCOORD_FILE=${HOMEufs}/fix/am/global_hyblev.l65.txt +export VARMAP_FILE=${HOMEufs}/parm/varmap_tables/GFSphys_var_map.txt +export INPUT_TYPE='grib2' +export CONVERT_NST=".false." +export TRACERS_TARGET='"sphum","liq_wat","o3mr"' +export TRACERS_INPUT='"spfh","clwmr","o3mr"' + +export CDATE=2020082506 + +export OMP_NUM_THREADS_CH=${OMP_NUM_THREADS:-1} + +NCCMP=${NCCMP:-$(which nccmp)} + +#----------------------------------------------------------------------------- +# Invoke chgres program. +#----------------------------------------------------------------------------- + +echo "Starting at: " `date` + +${HOMEufs}/ush/chgres_cube.sh + +iret=$? +if [ $iret -ne 0 ]; then + set +x + echo "<<< C96 GEFS GRIB2 TEST FAILED. <<<" + exit $iret +fi + +echo "Ending at: " `date` + +#----------------------------------------------------------------------------- +# Compare output from chgres to baseline set of data. +#----------------------------------------------------------------------------- + +cd $DATA + +test_failed=0 +for files in *.nc +do + if [ -f $files ]; then + echo CHECK $files + $NCCMP -dmfqS $files $HOMEreg/baseline_data/c96_gefs_grib2/$files + iret=$? + if [ $iret -ne 0 ]; then + test_failed=1 + fi + fi +done + +set +x +if [ $test_failed -ne 0 ]; then + echo "<<< C96 GEFS GRIB2 TEST FAILED. >>>" + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + $HOMEufs/reg_tests/update_baseline.sh $HOMEreg "c96_gefs_grib2" $commit_num + fi +else + echo "<<< C96 GEFS GRIB2 TEST PASSED. >>>" +fi + +exit 0 diff --git a/reg_tests/chgres_cube/c96.gfs.nemsio.sh b/reg_tests/chgres_cube/c96.gfs.nemsio.sh index 36ea52843..d3714ca3e 100755 --- a/reg_tests/chgres_cube/c96.gfs.nemsio.sh +++ b/reg_tests/chgres_cube/c96.gfs.nemsio.sh @@ -17,7 +17,7 @@ export COMIN=${HOMEreg}/input_data/gfs.nemsio export ATM_FILES_INPUT=gfnanl.gdas.2017071700 export SFC_FILES_INPUT=sfnanl.gdas.2017071700 export NST_FILES_INPUT=nsnanl.gdas.2017071700 -export VCOORD_FILE=${HOMEufs}/fix/fix_am/global_hyblev.l64.txt +export VCOORD_FILE=${HOMEufs}/fix/am/global_hyblev.l64.txt export INPUT_TYPE="gfs_gaussian_nemsio" # dont start/end with double quotes. @@ -67,6 +67,9 @@ done set +x if [ $test_failed -ne 0 ]; then echo "<<< C96 GFS GAUSSIAN NEMSIO TEST FAILED. >>>" + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + $HOMEufs/reg_tests/update_baseline.sh $HOMEreg "c96_gfs_nemsio" $commit_num + fi else echo "<<< C96 GFS GAUSSIAN NEMSIO TEST PASSED. >>>" fi diff --git a/reg_tests/chgres_cube/c96.gfs.sigio.sh b/reg_tests/chgres_cube/c96.gfs.sigio.sh index b04765603..25d0448ea 100755 --- a/reg_tests/chgres_cube/c96.gfs.sigio.sh +++ b/reg_tests/chgres_cube/c96.gfs.sigio.sh @@ -23,7 +23,7 @@ export COMIN=${HOMEreg}/input_data/gfs.sigio export ATM_FILES_INPUT=gdas.t00z.sanl export SFC_FILES_INPUT=gdas.t00z.sfcanl export CONVERT_NST='.false.' -export VCOORD_FILE=${HOMEufs}/fix/fix_am/global_hyblev.l64.txt +export VCOORD_FILE=${HOMEufs}/fix/am/global_hyblev.l64.txt export INPUT_TYPE="gfs_sigio" # dont start/end with double quotes @@ -69,6 +69,9 @@ done set +x if [ $test_failed -ne 0 ]; then echo "<<< C96 GFS SIGIO TEST FAILED. >>>" + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + $HOMEufs/reg_tests/update_baseline.sh $HOMEreg "c96_gfs_sigio" $commit_num + fi else echo "<<< C96 GFS SIGIO TEST PASSED. >>>" fi diff --git a/reg_tests/chgres_cube/c96.regional.sh b/reg_tests/chgres_cube/c96.regional.sh index 8cde6a50a..f96716f3d 100755 --- a/reg_tests/chgres_cube/c96.regional.sh +++ b/reg_tests/chgres_cube/c96.regional.sh @@ -19,7 +19,7 @@ export OROG_FILES_TARGET_GRID="C96_oro_data.tile7.nc" export COMIN=${HOMEreg}/input_data/fv3.nemsio export ATM_FILES_INPUT=gfs.t12z.atmf000.nemsio export SFC_FILES_INPUT=gfs.t12z.sfcf000.nemsio -export VCOORD_FILE=${HOMEufs}/fix/fix_am/global_hyblev.l64.txt +export VCOORD_FILE=${HOMEufs}/fix/am/global_hyblev.l64.txt export REGIONAL=1 export HALO_BLEND=0 export HALO_BNDY=4 @@ -72,6 +72,9 @@ done set +x if [ $test_failed -ne 0 ]; then echo "<<< C96 REGIONAL TEST FAILED. >>>" + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + $HOMEufs/reg_tests/update_baseline.sh $HOMEreg "c96_regional" $commit_num + fi else echo "<<< C96 REGIONAL TEST PASSED. >>>" fi diff --git a/reg_tests/chgres_cube/driver.hera.sh b/reg_tests/chgres_cube/driver.hera.sh index f68e2726b..d7a42a80a 100755 --- a/reg_tests/chgres_cube/driver.hera.sh +++ b/reg_tests/chgres_cube/driver.hera.sh @@ -44,9 +44,16 @@ QUEUE="${QUEUE:-batch}" # and baseline data for each test. #----------------------------------------------------------------------------- +export UPDATE_BASELINE="FALSE" +#export UPDATE_BASELINE="TRUE" + +if [ "$UPDATE_BASELINE" = "TRUE" ]; then + source ../get_hash.sh +fi + export HOMEufs=$PWD/../.. -export HOMEreg=/scratch1/NCEPDEV/da/George.Gayno/noscrub/reg_tests/chgres_cube +export HOMEreg=/scratch1/NCEPDEV/nems/role.ufsutils/ufs_utils/reg_tests/chgres_cube LOG_FILE=consistency.log SUM_FILE=summary.log @@ -202,13 +209,22 @@ export OMP_NUM_THREADS=1 # should match cpus-per-task TEST16=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:05:00 -A $PROJECT_CODE -q $QUEUE -J 25km.conus.gfs.pbgrib2.conus \ -o $LOG_FILE -e $LOG_FILE ./25km.conus.gfs.pbgrib2.sh) +#----------------------------------------------------------------------------- +# Initialize global C96 using GEFS GRIB2 files. +#----------------------------------------------------------------------------- + +LOG_FILE=consistency.log17 +export OMP_NUM_THREADS=1 # should match cpus-per-task +TEST17=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:05:00 -A $PROJECT_CODE -q $QUEUE -J c96.gefs.grib2 \ + -o $LOG_FILE -e $LOG_FILE ./c96.gefs.grib2.sh) + #----------------------------------------------------------------------------- # Create summary log. #----------------------------------------------------------------------------- LOG_FILE=consistency.log sbatch --nodes=1 -t 0:01:00 -A $PROJECT_CODE -J chgres_summary -o $LOG_FILE -e $LOG_FILE \ --open-mode=append -q $QUEUE -d\ - afterok:$TEST1:$TEST2:$TEST3:$TEST4:$TEST5:$TEST6:$TEST7:$TEST8:$TEST9:$TEST10:$TEST11:$TEST12:$TEST13:$TEST14:$TEST15:$TEST16 << EOF + afterok:$TEST1:$TEST2:$TEST3:$TEST4:$TEST5:$TEST6:$TEST7:$TEST8:$TEST9:$TEST10:$TEST11:$TEST12:$TEST13:$TEST14:$TEST15:$TEST16:$TEST17 << EOF #!/bin/bash grep -a '<<<' $LOG_FILE* > $SUM_FILE EOF diff --git a/reg_tests/chgres_cube/driver.jet.sh b/reg_tests/chgres_cube/driver.jet.sh index 155bb6660..813f13cfe 100755 --- a/reg_tests/chgres_cube/driver.jet.sh +++ b/reg_tests/chgres_cube/driver.jet.sh @@ -45,9 +45,16 @@ export HDF5_DISABLE_VERSION_CHECK=2 # and baseline data for each test. #----------------------------------------------------------------------------- +export UPDATE_BASELINE="FALSE" +#export UPDATE_BASELINE="TRUE" + +if [ "$UPDATE_BASELINE" = "TRUE" ]; then + source ../get_hash.sh +fi + export HOMEufs=$PWD/../.. -export HOMEreg=/lfs4/HFIP/emcda/George.Gayno/reg_tests/chgres_cube +export HOMEreg=/lfs4/HFIP/hfv3gfs/emc.nemspara/role.ufsutils/ufs_utils/reg_tests/chgres_cube LOG_FILE=consistency.log SUM_FILE=summary.log @@ -203,6 +210,15 @@ export OMP_NUM_THREADS=1 # should match cpus-per-task TEST16=$(sbatch --parsable --partition=xjet --ntasks-per-node=6 --nodes=1 -t 0:05:00 -A $PROJECT_CODE -q $QUEUE -J 25km.conus.gfs.pbgrib2.conus \ --exclusive -o $LOG_FILE -e $LOG_FILE ./25km.conus.gfs.pbgrib2.sh) +#----------------------------------------------------------------------------- +# Initialize C96 using GEFS GRIB2 data. +#----------------------------------------------------------------------------- + +LOG_FILE=consistency.log17 +export OMP_NUM_THREADS=1 +TEST17=$(sbatch --parsable --partition=xjet --nodes=1 --ntasks-per-node=6 -t 0:05:00 -A $PROJECT_CODE -q $QUEUE -J c96.gefs.grib2 \ + --exclusive -o $LOG_FILE -e $LOG_FILE ./c96.gefs.grib2.sh) + #----------------------------------------------------------------------------- # Create summary log. #----------------------------------------------------------------------------- @@ -210,7 +226,7 @@ TEST16=$(sbatch --parsable --partition=xjet --ntasks-per-node=6 --nodes=1 -t 0:0 LOG_FILE=consistency.log sbatch --partition=xjet --nodes=1 -t 0:01:00 -A $PROJECT_CODE -J chgres_summary -o $LOG_FILE -e $LOG_FILE \ --open-mode=append -q $QUEUE -d\ - afterok:$TEST1:$TEST2:$TEST3:$TEST4:$TEST5:$TEST6:$TEST7:$TEST8:$TEST9:$TEST10:$TEST11:$TEST12:$TEST13:$TEST14:$TEST15:$TEST16 << EOF + afterok:$TEST1:$TEST2:$TEST3:$TEST4:$TEST5:$TEST6:$TEST7:$TEST8:$TEST9:$TEST10:$TEST11:$TEST12:$TEST13:$TEST14:$TEST15:$TEST16:$TEST17 << EOF #!/bin/bash grep -a '<<<' $LOG_FILE* > $SUM_FILE EOF diff --git a/reg_tests/chgres_cube/driver.orion.sh b/reg_tests/chgres_cube/driver.orion.sh index 0c2b72c4a..66de8b85b 100755 --- a/reg_tests/chgres_cube/driver.orion.sh +++ b/reg_tests/chgres_cube/driver.orion.sh @@ -44,9 +44,16 @@ QUEUE="${QUEUE:-batch}" # and baseline data for each test. #----------------------------------------------------------------------------- +export UPDATE_BASELINE="FALSE" +#export UPDATE_BASELINE="TRUE" + +if [ "$UPDATE_BASELINE" = "TRUE" ]; then + source ../get_hash.sh +fi + export HOMEufs=$PWD/../.. -export HOMEreg=/work/noaa/da/ggayno/save/ufs_utils.git/reg_tests/chgres_cube +export HOMEreg=/work/noaa/nems/role-nems/ufs_utils/reg_tests/chgres_cube LOG_FILE=consistency.log SUM_FILE=summary.log @@ -68,7 +75,7 @@ rm -fr $OUTDIR LOG_FILE1=${LOG_FILE}01 export OMP_NUM_THREADS=1 # needs to match cpus-per-task -TEST1=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c96.fv3.restart \ +TEST1=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 --mem=75G -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c96.fv3.restart \ -o $LOG_FILE1 -e $LOG_FILE1 ./c96.fv3.restart.sh) #----------------------------------------------------------------------------- @@ -77,7 +84,7 @@ TEST1=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:15:00 -A $PROJECT_C LOG_FILE2=${LOG_FILE}02 export OMP_NUM_THREADS=1 # needs to match cpus-per-task -TEST2=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c192.fv3.history \ +TEST2=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 --mem=75G -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c192.fv3.history \ --open-mode=append -o $LOG_FILE2 -e $LOG_FILE2 ./c192.fv3.history.sh) #----------------------------------------------------------------------------- @@ -86,7 +93,7 @@ TEST2=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:15:00 -A $PROJECT_C LOG_FILE3=${LOG_FILE}03 export OMP_NUM_THREADS=1 # needs to match cpus-per-task -TEST3=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c96.fv3.nemsio \ +TEST3=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 --mem=75G -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c96.fv3.nemsio \ --open-mode=append -o $LOG_FILE3 -e $LOG_FILE3 ./c96.fv3.nemsio.sh) #----------------------------------------------------------------------------- @@ -95,7 +102,7 @@ TEST3=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:15:00 -A $PROJECT_C LOG_FILE4=${LOG_FILE}04 export OMP_NUM_THREADS=6 # needs to match cpus-per-task -TEST4=$(sbatch --parsable --ntasks-per-node=3 --cpus-per-task=6 --nodes=2 -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c96.gfs.sigio \ +TEST4=$(sbatch --parsable --ntasks-per-node=3 --cpus-per-task=6 --nodes=2 --mem=50G -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c96.gfs.sigio \ --open-mode=append -o $LOG_FILE4 -e $LOG_FILE4 ./c96.gfs.sigio.sh) #----------------------------------------------------------------------------- @@ -104,7 +111,7 @@ TEST4=$(sbatch --parsable --ntasks-per-node=3 --cpus-per-task=6 --nodes=2 -t 0:1 LOG_FILE5=${LOG_FILE}05 export OMP_NUM_THREADS=1 # needs to match cpus-per-task -TEST5=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c96.gfs.nemsio \ +TEST5=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 --mem=75G -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c96.gfs.nemsio \ --open-mode=append -o $LOG_FILE5 -e $LOG_FILE5 ./c96.gfs.nemsio.sh) #----------------------------------------------------------------------------- @@ -113,7 +120,7 @@ TEST5=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:15:00 -A $PROJECT_C LOG_FILE6=${LOG_FILE}06 export OMP_NUM_THREADS=1 # needs to match cpus-per-task -TEST6=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c96.regional \ +TEST6=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 --mem=75G -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c96.regional \ --open-mode=append -o $LOG_FILE6 -e $LOG_FILE6 ./c96.regional.sh) #----------------------------------------------------------------------------- @@ -122,7 +129,7 @@ TEST6=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:15:00 -A $PROJECT_C LOG_FILE7=${LOG_FILE}07 export OMP_NUM_THREADS=1 # needs to match cpus-per-task -TEST7=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:05:00 -A $PROJECT_CODE -q $QUEUE -J c192.gfs.grib2 \ +TEST7=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 --mem=75G -t 0:05:00 -A $PROJECT_CODE -q $QUEUE -J c192.gfs.grib2 \ --open-mode=append -o $LOG_FILE7 -e $LOG_FILE7 ./c192.gfs.grib2.sh) #----------------------------------------------------------------------------- @@ -131,7 +138,7 @@ TEST7=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:05:00 -A $PROJECT_C LOG_FILE8=${LOG_FILE}08 export OMP_NUM_THREADS=1 # needs to match cpus-per-task -TEST8=$(sbatch --parsable --ntasks-per-node=6 --nodes=2 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J c96.fv3.netcdf \ +TEST8=$(sbatch --parsable --ntasks-per-node=6 --nodes=2 --mem=75G -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J c96.fv3.netcdf \ --open-mode=append -o $LOG_FILE8 -e $LOG_FILE8 ./c96.fv3.netcdf.sh) #----------------------------------------------------------------------------- @@ -140,7 +147,7 @@ TEST8=$(sbatch --parsable --ntasks-per-node=6 --nodes=2 -t 0:10:00 -A $PROJECT_C LOG_FILE9=${LOG_FILE}09 export OMP_NUM_THREADS=1 # should match cpus-per-task -TEST9=$(sbatch --parsable --ntasks-per-node=12 --nodes=1 -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c96.fv3.netcdf2wam \ +TEST9=$(sbatch --parsable --ntasks-per-node=12 --nodes=1 --mem=100G -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c96.fv3.netcdf2wam \ --open-mode=append -o $LOG_FILE9 -e $LOG_FILE9 ./c96.fv3.netcdf2wam.sh) #----------------------------------------------------------------------------- @@ -149,7 +156,7 @@ TEST9=$(sbatch --parsable --ntasks-per-node=12 --nodes=1 -t 0:15:00 -A $PROJECT_ LOG_FILE10=${LOG_FILE}10 export OMP_NUM_THREADS=1 # should match cpus-per-task -TEST10=$(sbatch --parsable --ntasks-per-node=12 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J 25km.conus.gfs.grib2 \ +TEST10=$(sbatch --parsable --ntasks-per-node=12 --nodes=1 --mem=75G -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J 25km.conus.gfs.grib2 \ --open-mode=append -o $LOG_FILE10 -e $LOG_FILE10 ./25km.conus.gfs.grib2.sh) #----------------------------------------------------------------------------- @@ -158,7 +165,7 @@ TEST10=$(sbatch --parsable --ntasks-per-node=12 --nodes=1 -t 0:10:00 -A $PROJECT LOG_FILE11=${LOG_FILE}11 export OMP_NUM_THREADS=1 # should match cpus-per-task -TEST11=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J 3km.conus.hrrr.gfssdf.grib2 \ +TEST11=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 --mem=75G -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J 3km.conus.hrrr.gfssdf.grib2 \ --open-mode=append -o $LOG_FILE11 -e $LOG_FILE11 ./3km.conus.hrrr.gfssdf.grib2.sh) #----------------------------------------------------------------------------- @@ -167,7 +174,7 @@ TEST11=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:10:00 -A $PROJECT_ LOG_FILE12=${LOG_FILE}12 export OMP_NUM_THREADS=1 # should match cpus-per-task -TEST12=$(sbatch --parsable --ntasks-per-node=6 --nodes=2 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J 3km.conus.hrrr.newsfc.grib2 \ +TEST12=$(sbatch --parsable --ntasks-per-node=6 --nodes=2 --mem=75G -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J 3km.conus.hrrr.newsfc.grib2 \ --open-mode=append -o $LOG_FILE12 -e $LOG_FILE12 ./3km.conus.hrrr.newsfc.grib2.sh) #----------------------------------------------------------------------------- @@ -176,7 +183,7 @@ TEST12=$(sbatch --parsable --ntasks-per-node=6 --nodes=2 -t 0:10:00 -A $PROJECT_ LOG_FILE13=${LOG_FILE}13 export OMP_NUM_THREADS=1 # should match cpus-per-task -TEST13=$(sbatch --parsable --ntasks-per-node=12 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J 13km.conus.nam.grib2 \ +TEST13=$(sbatch --parsable --ntasks-per-node=12 --nodes=1 --mem=75G -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J 13km.conus.nam.grib2 \ --open-mode=append -o $LOG_FILE13 -e $LOG_FILE13 ./13km.conus.nam.grib2.sh) #----------------------------------------------------------------------------- @@ -185,7 +192,7 @@ TEST13=$(sbatch --parsable --ntasks-per-node=12 --nodes=1 -t 0:10:00 -A $PROJECT LOG_FILE14=${LOG_FILE}14 export OMP_NUM_THREADS=1 # should match cpus-per-task -TEST14=$(sbatch --parsable --ntasks-per-node=12 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J 13km.conus.rap.grib2 \ +TEST14=$(sbatch --parsable --ntasks-per-node=12 --nodes=1 --mem=75G -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J 13km.conus.rap.grib2 \ --open-mode=append -o $LOG_FILE14 -e $LOG_FILE14 ./13km.conus.rap.grib2.sh) #----------------------------------------------------------------------------- @@ -194,7 +201,7 @@ TEST14=$(sbatch --parsable --ntasks-per-node=12 --nodes=1 -t 0:10:00 -A $PROJECT LOG_FILE15=${LOG_FILE}15 export OMP_NUM_THREADS=1 # should match cpus-per-task -TEST15=$(sbatch --parsable --ntasks-per-node=12 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J 13km.na.gfs.ncei.grib2 \ +TEST15=$(sbatch --parsable --ntasks-per-node=12 --nodes=1 --mem=75G -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J 13km.na.gfs.ncei.grib2 \ --open-mode=append -o $LOG_FILE15 -e $LOG_FILE15 ./13km.na.gfs.ncei.grib2.sh) #----------------------------------------------------------------------------- @@ -203,16 +210,25 @@ TEST15=$(sbatch --parsable --ntasks-per-node=12 --nodes=1 -t 0:10:00 -A $PROJECT LOG_FILE16=${LOG_FILE}16 export OMP_NUM_THREADS=1 # should match cpus-per-task -TEST16=$(sbatch --parsable --ntasks-per-node=12 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J 25km.conus.gfs.pbgrib2 \ +TEST16=$(sbatch --parsable --ntasks-per-node=12 --nodes=1 --mem=75G -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J 25km.conus.gfs.pbgrib2 \ --open-mode=append -o $LOG_FILE16 -e $LOG_FILE16 ./25km.conus.gfs.pbgrib2.sh) +#----------------------------------------------------------------------------- +# Initialize C96 using GEFS GRIB2 file. +#----------------------------------------------------------------------------- + +LOG_FILE17=${LOG_FILE}17 +export OMP_NUM_THREADS=1 # needs to match cpus-per-task +TEST17=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 --mem=75G -t 0:05:00 -A $PROJECT_CODE -q $QUEUE -J c96.gefs.grib2 \ + --open-mode=append -o $LOG_FILE17 -e $LOG_FILE17 ./c96.gefs.grib2.sh) + #----------------------------------------------------------------------------- # Create summary log. #----------------------------------------------------------------------------- sbatch --nodes=1 -t 0:01:00 -A $PROJECT_CODE -J chgres_summary -o $LOG_FILE -e $LOG_FILE \ --open-mode=append -q $QUEUE \ - -d afterok:$TEST1:$TEST2:$TEST3:$TEST4:$TEST5:$TEST6:$TEST7:$TEST8:$TEST9:$TEST10:$TEST11:$TEST12:$TEST13:$TEST14:$TEST15:$TEST16 << EOF + -d afterok:$TEST1:$TEST2:$TEST3:$TEST4:$TEST5:$TEST6:$TEST7:$TEST8:$TEST9:$TEST10:$TEST11:$TEST12:$TEST13:$TEST14:$TEST15:$TEST16:$TEST17 << EOF #!/bin/bash grep -a '<<<' ${LOG_FILE}* > $SUM_FILE EOF diff --git a/reg_tests/chgres_cube/driver.wcoss_dell_p3.sh b/reg_tests/chgres_cube/driver.s4.sh similarity index 50% rename from reg_tests/chgres_cube/driver.wcoss_dell_p3.sh rename to reg_tests/chgres_cube/driver.s4.sh index 20cc13003..4e6e60119 100755 --- a/reg_tests/chgres_cube/driver.wcoss_dell_p3.sh +++ b/reg_tests/chgres_cube/driver.s4.sh @@ -2,14 +2,17 @@ #----------------------------------------------------------------------------- # -# Run the chgres_cube consistency tests on WCOSS-Dell. +# Run the chgres_cube consistency tests on S4. # # Set WORK_DIR to a general working location outside the UFS_UTILS directory. -# The exact working directory (OUTDIR) will be WORK_DIR/reg_tests/chgres-cube. -# Set the PROJECT_CODE and QUEUE as appropriate. +# The exact working directory (OUTDIR) will be WORK_DIR/reg_tests/chgres-cube. +# Set the PROJECT_CODE and QUEUE as appropriate. To see which projects you +# are authorized to use, type +# "sacctmgr show assoc Users= format=account,user,qos" # -# Invoke the script as follows with no arguments. A series of daily- -# chained jobs will be submitted. To check the queue, type: "bjobs". +# Invoke the script with no arguments. A series of daisy-chained +# jobs will be submitted. To check the queue, type: +# "squeue -u USERNAME". # # The run output will be stored in OUTDIR. Log output from the suite # will be in LOG_FILE. Once the suite has completed, a summary is @@ -23,16 +26,18 @@ set -x +compiler=${compiler:-"intel"} + source ../../sorc/machine-setup.sh > /dev/null 2>&1 module use ../../modulefiles -module load build.$target.intel +module load build.$target.$compiler module list -export OUTDIR="${WORK_DIR:-/gpfs/dell1/stmp/$LOGNAME}" +export OUTDIR="${WORK_DIR:-/scratch/short/users/$LOGNAME}" export OUTDIR="${OUTDIR}/reg-tests/chgres-cube" -QUEUE="${QUEUE:-dev}" -PROJECT_CODE="${PROJECT_CODE:-GFS-DEV}" +PROJECT_CODE="${PROJECT_CODE:-star}" +QUEUE="${QUEUE:-s4}" #----------------------------------------------------------------------------- # Should not have to change anything below here. HOMEufs is the root @@ -40,170 +45,180 @@ PROJECT_CODE="${PROJECT_CODE:-GFS-DEV}" # and baseline data for each test. #----------------------------------------------------------------------------- +export UPDATE_BASELINE="FALSE" +#export UPDATE_BASELINE="TRUE" + +if [ "$UPDATE_BASELINE" = "TRUE" ]; then + source ../get_hash.sh +fi + export HOMEufs=$PWD/../.. -export HOMEreg=/gpfs/dell2/emc/modeling/noscrub/George.Gayno/ufs_utils.git/reg_tests/chgres_cube +export HOMEreg=/data/users/dhuber/save/nems/role.ufsutils/ufs_utils/reg_tests/chgres_cube +LOG_FILE=consistency.log SUM_FILE=summary.log - -rm -f $SUM_FILE consistency.log?? +rm -f $LOG_FILE* $SUM_FILE export OMP_STACKSIZE=1024M -export APRUN=mpirun - +export APRUN=srun export NCCMP=${NCCMP:-nccmp} +rm -fr $OUTDIR #----------------------------------------------------------------------------- -# Initialize CONUS 25-KM USING GFS GRIB2 files. +# Initialize C96 using FV3 warm restart files. #----------------------------------------------------------------------------- LOG_FILE=consistency.log01 -export OMP_NUM_THREADS=1 -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J chgres01 -W 0:05 -x -n 6 \ - -R "span[ptile=6]" -R "affinity[core(${OMP_NUM_THREADS}):distribute=balance]" "$PWD/25km.conus.gfs.grib2.sh" +export OMP_NUM_THREADS=1 # should match cpus-per-task +TEST1=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c96.fv3.restart \ + -o $LOG_FILE -e $LOG_FILE ./c96.fv3.restart.sh) #----------------------------------------------------------------------------- -# Initialize CONUS 3-KM USING HRRR GRIB2 file WITH GFS PHYSICS. +# Initialize C192 using FV3 tiled history files. #----------------------------------------------------------------------------- LOG_FILE=consistency.log02 -export OMP_NUM_THREADS=1 -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J chgres02 -W 0:07 -x -n 6 \ - -R "span[ptile=6]" -R "affinity[core(${OMP_NUM_THREADS}):distribute=balance]" "$PWD/3km.conus.hrrr.gfssdf.grib2.sh" +export OMP_NUM_THREADS=1 # should match cpus-per-task +TEST2=$(sbatch --parsable --ntasks-per-node=6 --nodes=2 -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c192.fv3.history \ + -o $LOG_FILE -e $LOG_FILE ./c192.fv3.history.sh) #----------------------------------------------------------------------------- -# Initialize CONUS 3-KM USING HRRR GRIB2 file WITH GSD PHYSICS AND SFC VARS FROM FILE. +# Initialize C96 using FV3 gaussian nemsio files. #----------------------------------------------------------------------------- LOG_FILE=consistency.log03 -export OMP_NUM_THREADS=1 -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J chgres03 -W 0:10 -x -n 12 \ - -R "span[ptile=6]" -R "affinity[core(${OMP_NUM_THREADS}):distribute=balance]" "$PWD/3km.conus.hrrr.newsfc.grib2.sh" +export OMP_NUM_THREADS=1 # should match cpus-per-task +TEST3=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c96.fv3.nemsio \ + -o $LOG_FILE -e $LOG_FILE ./c96.fv3.nemsio.sh) #----------------------------------------------------------------------------- -# Initialize CONUS 13-KM USING NAM GRIB2 file WITH GFS PHYSICS . +# Initialize C96 using spectral GFS sigio/sfcio files. #----------------------------------------------------------------------------- LOG_FILE=consistency.log04 -export OMP_NUM_THREADS=1 -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J chgres04 -W 0:05 -x -n 6 \ - -R "span[ptile=6]" -R "affinity[core(${OMP_NUM_THREADS}):distribute=balance]" "$PWD/13km.conus.nam.grib2.sh" +export OMP_NUM_THREADS=6 # should match cpus-per-task +TEST4=$(sbatch --parsable --ntasks-per-node=3 --cpus-per-task=6 --nodes=2 -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c96.gfs.sigio \ + -o $LOG_FILE -e $LOG_FILE ./c96.gfs.sigio.sh) #----------------------------------------------------------------------------- -# Initialize CONUS 13-KM USING RAP GRIB2 file WITH GSD PHYSICS . +# Initialize C96 using spectral GFS gaussian nemsio files. #----------------------------------------------------------------------------- LOG_FILE=consistency.log05 -export OMP_NUM_THREADS=1 -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J chgres05 -W 0:05 -x -n 6 \ - -R "span[ptile=6]" -R "affinity[core(${OMP_NUM_THREADS}):distribute=balance]" "$PWD/13km.conus.rap.grib2.sh" +export OMP_NUM_THREADS=1 # should match cpus-per-task +TEST5=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c96.gfs.nemsio \ + -o $LOG_FILE -e $LOG_FILE ./c96.gfs.nemsio.sh) #----------------------------------------------------------------------------- -# Initialize CONUS 13-KM NA USING NCEI GFS GRIB2 file WITH GFS PHYSICS . +# Initialize regional C96 using FV3 gaussian nemsio files. #----------------------------------------------------------------------------- LOG_FILE=consistency.log06 -export OMP_NUM_THREADS=1 -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J chgres06 -W 0:05 -x -n 6 \ - -R "span[ptile=6]" -R "affinity[core(${OMP_NUM_THREADS}):distribute=balance]" "$PWD/13km.na.gfs.ncei.grib2.sh" +export OMP_NUM_THREADS=1 # should match cpus-per-task +TEST6=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c96.regional \ + -o $LOG_FILE -e $LOG_FILE ./c96.regional.sh) #----------------------------------------------------------------------------- -# Initialize C96 using FV3 warm restart files. +# Initialize C96 using FV3 gaussian netcdf files. #----------------------------------------------------------------------------- LOG_FILE=consistency.log07 -export OMP_NUM_THREADS=1 -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J chgres07 -W 0:15 -x -n 6 \ - -R "span[ptile=6]" -R "affinity[core(${OMP_NUM_THREADS}):distribute=balance]" "$PWD/c96.fv3.restart.sh" +export OMP_NUM_THREADS=1 # should match cpus-per-task +TEST7=$(sbatch --parsable --ntasks-per-node=12 --nodes=1 -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c96.fv3.netcdf \ + -o $LOG_FILE -e $LOG_FILE ./c96.fv3.netcdf.sh) #----------------------------------------------------------------------------- -# Initialize C192 using FV3 tiled history files. +# Initialize global C192 using GFS GRIB2 files. #----------------------------------------------------------------------------- LOG_FILE=consistency.log08 -export OMP_NUM_THREADS=1 -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J chgres08 -W 0:15 -x -n 6 \ - -R "span[ptile=6]" -R "affinity[core(${OMP_NUM_THREADS}):distribute=balance]" "$PWD/c192.fv3.history.sh" +export OMP_NUM_THREADS=1 # should match cpus-per-task +TEST8=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:05:00 -A $PROJECT_CODE -q $QUEUE -J c192.gfs.grib2 \ + -o $LOG_FILE -e $LOG_FILE ./c192.gfs.grib2.sh) #----------------------------------------------------------------------------- -# Initialize C96 using FV3 gaussian nemsio files. +# Initialize CONUS 25-KM USING GFS GRIB2 files. #----------------------------------------------------------------------------- LOG_FILE=consistency.log09 -export OMP_NUM_THREADS=1 -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J chgres09 -W 0:15 -x -n 6 \ - -R "span[ptile=6]" -R "affinity[core(${OMP_NUM_THREADS}):distribute=balance]" "$PWD/c96.fv3.nemsio.sh" +export OMP_NUM_THREADS=1 # should match cpus-per-task +TEST9=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:05:00 -A $PROJECT_CODE -q $QUEUE -J 25km.conus.gfs.grib2.conus \ + -o $LOG_FILE -e $LOG_FILE ./25km.conus.gfs.grib2.sh) #----------------------------------------------------------------------------- -# Initialize C96 using spectral GFS sigio/sfcio files. +# Initialize CONUS 3-KM USING HRRR GRIB2 file WITH GFS PHYSICS. #----------------------------------------------------------------------------- LOG_FILE=consistency.log10 -export OMP_NUM_THREADS=4 -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J chgres10 -W 0:15 -x -n 6 \ - -R "span[ptile=6]" -R "affinity[core(${OMP_NUM_THREADS}):distribute=balance]" "$PWD/c96.gfs.sigio.sh" +export OMP_NUM_THREADS=1 # should match cpus-per-task +TEST10=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J 3km.conus.hrrr.gfssdf.grib2.conus \ + -o $LOG_FILE -e $LOG_FILE ./3km.conus.hrrr.gfssdf.grib2.sh) #----------------------------------------------------------------------------- -# Initialize C96 using spectral GFS gaussian nemsio files. +# Initialize CONUS 3-KM USING HRRR GRIB2 file WITH GSD PHYSICS AND SFC VARS FROM FILE. #----------------------------------------------------------------------------- LOG_FILE=consistency.log11 -export OMP_NUM_THREADS=1 -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J chgres11 -W 0:15 -x -n 6 \ - -R "span[ptile=6]" -R "affinity[core(${OMP_NUM_THREADS}):distribute=balance]" "$PWD/c96.gfs.nemsio.sh" +export OMP_NUM_THREADS=1 # should match cpus-per-task +TEST11=$(sbatch --parsable --ntasks-per-node=6 --nodes=2 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J 3km.conus.hrrr.newsfc.grib2.conus \ + -o $LOG_FILE -e $LOG_FILE ./3km.conus.hrrr.newsfc.grib2.sh) #----------------------------------------------------------------------------- -# Initialize regional C96 using FV3 gaussian nemsio files. +# Initialize CONUS 13-KM USING NAM GRIB2 file WITH GFS PHYSICS . #----------------------------------------------------------------------------- LOG_FILE=consistency.log12 -export OMP_NUM_THREADS=1 -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J chgres12 -W 0:15 -x -n 6 \ - -R "span[ptile=6]" -R "affinity[core(${OMP_NUM_THREADS}):distribute=balance]" "$PWD/c96.regional.sh" +export OMP_NUM_THREADS=1 # should match cpus-per-task +TEST12=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:05:00 -A $PROJECT_CODE -q $QUEUE -J 13km.conus.nam.grib2.conus \ + -o $LOG_FILE -e $LOG_FILE ./13km.conus.nam.grib2.sh) #----------------------------------------------------------------------------- -# Initialize C96 using FV3 gaussian netcdf files. +# Initialize CONUS 13-KM USING RAP GRIB2 file WITH GSD PHYSICS . #----------------------------------------------------------------------------- LOG_FILE=consistency.log13 -export OMP_NUM_THREADS=1 -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J chgres13 -W 0:15 -x -n 12 \ - -R "span[ptile=6]" -R "affinity[core(${OMP_NUM_THREADS}):distribute=balance]" "$PWD/c96.fv3.netcdf.sh" +export OMP_NUM_THREADS=1 # should match cpus-per-task +TEST13=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:05:00 -A $PROJECT_CODE -q $QUEUE -J 13km.conus.rap.grib2.conus \ + -o $LOG_FILE -e $LOG_FILE ./13km.conus.rap.grib2.sh) #----------------------------------------------------------------------------- -# Initialize global C192 using GFS GRIB2 file. +# Initialize CONUS 13-KM NA USING NCEI GFS GRIB2 file WITH GFS PHYSICS . #----------------------------------------------------------------------------- LOG_FILE=consistency.log14 -export OMP_NUM_THREADS=1 -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J chgres14 -W 0:05 -x -n 6 \ - -R "span[ptile=6]" -R "affinity[core(${OMP_NUM_THREADS}):distribute=balance]" "$PWD/c192.gfs.grib2.sh" +export OMP_NUM_THREADS=1 # should match cpus-per-task +TEST14=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:05:00 -A $PROJECT_CODE -q $QUEUE -J 13km.na.gfs.ncei.grib2.conus \ + -o $LOG_FILE -e $LOG_FILE ./13km.na.gfs.ncei.grib2.sh) #----------------------------------------------------------------------------- # Initialize C96 WAM IC using FV3 gaussian netcdf files. #----------------------------------------------------------------------------- LOG_FILE=consistency.log15 -export OMP_NUM_THREADS=1 -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J chgres15 -W 0:15 -x -n 12 \ - -R "span[ptile=6]" -R "affinity[core(${OMP_NUM_THREADS}):distribute=balance]" "$PWD/c96.fv3.netcdf2wam.sh" +export OMP_NUM_THREADS=1 # should match cpus-per-task +TEST15=$(sbatch --parsable --ntasks-per-node=12 --nodes=1 -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c96.fv3.netcdf2wam \ + -o $LOG_FILE -e $LOG_FILE ./c96.fv3.netcdf2wam.sh) #----------------------------------------------------------------------------- -# Initialize CONUS 25-KM USING GFS PGRIB2+BGRIB2 files. +# Initialize CONUS 25-KM USING GFS PGRIB2+BGRIB2 files. #----------------------------------------------------------------------------- LOG_FILE=consistency.log16 -export OMP_NUM_THREADS=1 -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J chgres16 -W 0:05 -x -n 6 \ - -R "span[ptile=6]" -R "affinity[core(${OMP_NUM_THREADS}):distribute=balance]" "$PWD/25km.conus.gfs.pbgrib2.sh" +export OMP_NUM_THREADS=1 # should match cpus-per-task +TEST16=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:05:00 -A $PROJECT_CODE -q $QUEUE -J 25km.conus.gfs.pbgrib2.conus \ + -o $LOG_FILE -e $LOG_FILE ./25km.conus.gfs.pbgrib2.sh) #----------------------------------------------------------------------------- # Create summary log. #----------------------------------------------------------------------------- - LOG_FILE=consistency.log -bsub -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J summary -R "affinity[core(1)]" -R "rusage[mem=100]" -W 0:01 \ - -w 'ended(chgres*)' "grep -a '<<<' "*.log*" >> $SUM_FILE" +sbatch --nodes=1 -t 0:01:00 -A $PROJECT_CODE -J chgres_summary -o $LOG_FILE -e $LOG_FILE \ + --open-mode=append -q $QUEUE -d\ + afterok:$TEST1:$TEST2:$TEST3:$TEST4:$TEST5:$TEST6:$TEST7:$TEST8:$TEST9:$TEST10:$TEST11:$TEST12:$TEST13:$TEST14:$TEST15:$TEST16 << EOF +#!/bin/bash +grep -a '<<<' $LOG_FILE* > $SUM_FILE +EOF -exit +exit 0 diff --git a/reg_tests/chgres_cube/driver.wcoss2.sh b/reg_tests/chgres_cube/driver.wcoss2.sh new file mode 100755 index 000000000..6ae0efb48 --- /dev/null +++ b/reg_tests/chgres_cube/driver.wcoss2.sh @@ -0,0 +1,236 @@ +#!/bin/bash + +#----------------------------------------------------------------------------- +# +# Run the chgres_cube consistency tests on WCOSS2. +# +# Set WORK_DIR to a general working location outside the UFS_UTILS directory. +# The exact working directory (OUTDIR) will be WORK_DIR/reg_tests/chgres-cube. +# +# Set the PROJECT_CODE and QUEUE as appropriate. +# +# Invoke the script with no arguments. To check the queue, type: +# "qstat -u USERNAME". +# +# The run output will be stored in OUTDIR. Log output will be placed +# in LOG_FILE??. Once the suite has completed, a summary is placed +# in SUM_FILE. +# +# A test fails when its output does not match the baseline files as +# determined by the "nccmp" utility. The baseline files are stored in +# HOMEreg. +# +#----------------------------------------------------------------------------- + +set -x + +compiler=${compiler:-"intel"} + +source ../../sorc/machine-setup.sh > /dev/null 2>&1 +module use ../../modulefiles +module load build.$target.$compiler +module list + +export OUTDIR="${WORK_DIR:-/lfs/h2/emc/stmp/$LOGNAME}" +export OUTDIR="${OUTDIR}/reg-tests/chgres-cube" + +PROJECT_CODE="${PROJECT_CODE:-GFS-DEV}" +QUEUE="${QUEUE:-dev}" + +#----------------------------------------------------------------------------- +# Should not have to change anything below here. HOMEufs is the root +# directory of your UFS_UTILS clone. HOMEreg contains the input data +# and baseline data for each test. +#----------------------------------------------------------------------------- + +export UPDATE_BASELINE="FALSE" +#export UPDATE_BASELINE="TRUE" + +if [ "$UPDATE_BASELINE" = "TRUE" ]; then + source ../get_hash.sh +fi + +export HOMEufs=$PWD/../.. + +export HOMEreg=/lfs/h2/emc/nems/noscrub/emc.nems/UFS_UTILS/reg_tests/chgres_cube + +LOG_FILE=consistency.log +SUM_FILE=summary.log +rm -f $LOG_FILE* $SUM_FILE + +export OMP_STACKSIZE=1024M + +export NCCMP=/lfs/h2/emc/global/noscrub/George.Gayno/util/nccmp/nccmp-1.8.5.0/src/nccmp +#export NCCMP=${NCCMP:-nccmp} +rm -fr $OUTDIR + +this_dir=$PWD + +#----------------------------------------------------------------------------- +# Initialize C96 using FV3 warm restart files. +#----------------------------------------------------------------------------- + +LOG_FILE=consistency.log01 +export APRUN="mpiexec -n 6 -ppn 6 --cpu-bind core" +TEST1=$(qsub -V -o $LOG_FILE -e $LOG_FILE -q $QUEUE -A $PROJECT_CODE -l walltime=00:05:00 \ + -N c96.fv3.restart -l select=1:ncpus=6:ompthreads=1:mem=10GB $PWD/c96.fv3.restart.sh) + +#----------------------------------------------------------------------------- +# Initialize C192 using FV3 tiled history files. +#----------------------------------------------------------------------------- + +LOG_FILE=consistency.log02 +export APRUN="mpiexec -n 6 -ppn 6 --cpu-bind core" +TEST2=$(qsub -V -o $LOG_FILE -e $LOG_FILE -q $QUEUE -A $PROJECT_CODE -l walltime=00:05:00 \ + -N c192.fv3.history -l select=1:ncpus=6:ompthreads=1:mem=10GB $PWD/c192.fv3.history.sh) + +#----------------------------------------------------------------------------- +# Initialize C96 using FV3 gaussian nemsio files. +#----------------------------------------------------------------------------- + +LOG_FILE=consistency.log03 +export APRUN="mpiexec -n 6 -ppn 6 --cpu-bind core" +TEST3=$(qsub -V -o $LOG_FILE -e $LOG_FILE -q $QUEUE -A $PROJECT_CODE -l walltime=00:05:00 \ + -N c96.fv3.nemsio -l select=1:ncpus=6:ompthreads=1:mem=45GB $PWD/c96.fv3.nemsio.sh) + +#----------------------------------------------------------------------------- +# Initialize C96 using spectral GFS sigio/sfcio files. +#----------------------------------------------------------------------------- + +LOG_FILE=consistency.log04 +export OMP_PLACES=cores +export APRUN="mpiexec -n 6 -ppn 6 --cpu-bind core --depth 4" +TEST4=$(qsub -V -o $LOG_FILE -e $LOG_FILE -q $QUEUE -A $PROJECT_CODE -l walltime=00:10:00 \ + -N c96.gfs.sigio -l select=1:ncpus=24:ompthreads=4:mem=45GB $PWD/c96.gfs.sigio.sh) + +#----------------------------------------------------------------------------- +# Initialize C96 using spectral GFS gaussian nemsio files. +#----------------------------------------------------------------------------- + +LOG_FILE=consistency.log05 +export APRUN="mpiexec -n 6 -ppn 6 --cpu-bind core" +TEST5=$(qsub -V -o $LOG_FILE -e $LOG_FILE -q $QUEUE -A $PROJECT_CODE -l walltime=00:05:00 \ + -N c96.gfs.nemsio -l select=1:ncpus=6:ompthreads=1:mem=35GB $PWD/c96.gfs.nemsio.sh) + +#----------------------------------------------------------------------------- +# Initialize regional C96 using FV3 gaussian nemsio files. +#----------------------------------------------------------------------------- + +LOG_FILE=consistency.log06 +export APRUN="mpiexec -n 6 -ppn 6 --cpu-bind core" +TEST6=$(qsub -V -o $LOG_FILE -e $LOG_FILE -q $QUEUE -A $PROJECT_CODE -l walltime=00:05:00 \ + -N c96.regional -l select=1:ncpus=6:ompthreads=1:mem=35GB $PWD/c96.regional.sh) + +#----------------------------------------------------------------------------- +# Initialize C96 using FV3 gaussian netcdf files. +#----------------------------------------------------------------------------- + +LOG_FILE=consistency.log07 +export APRUN="mpiexec -n 12 -ppn 12 --cpu-bind core" +TEST7=$(qsub -V -o $LOG_FILE -e $LOG_FILE -q $QUEUE -A $PROJECT_CODE -l walltime=00:05:00 \ + -N c96.fv3.netcdf -l select=1:ncpus=12:ompthreads=1:mem=80GB $PWD/c96.fv3.netcdf.sh) + +#----------------------------------------------------------------------------- +# Initialize global C192 using GFS GRIB2 files. +#----------------------------------------------------------------------------- + +LOG_FILE=consistency.log08 +export APRUN="mpiexec -n 6 -ppn 6 --cpu-bind core" +TEST8=$(qsub -V -o $LOG_FILE -e $LOG_FILE -q $QUEUE -A $PROJECT_CODE -l walltime=00:05:00 \ + -N c192.gfs.grib2 -l select=1:ncpus=6:ompthreads=1:mem=15GB $PWD/c192.gfs.grib2.sh) + +#----------------------------------------------------------------------------- +# Initialize CONUS 25-KM USING GFS GRIB2 files. +#----------------------------------------------------------------------------- + +LOG_FILE=consistency.log09 +export APRUN="mpiexec -n 6 -ppn 6 --cpu-bind core" +TEST9=$(qsub -V -o $LOG_FILE -e $LOG_FILE -q $QUEUE -A $PROJECT_CODE -l walltime=00:05:00 \ + -N 25km.conus.gfs.grib2.conus -l select=1:ncpus=6:ompthreads=1:mem=15GB $PWD/25km.conus.gfs.grib2.sh) + +#----------------------------------------------------------------------------- +# Initialize CONUS 3-KM USING HRRR GRIB2 file WITH GFS PHYSICS. +#----------------------------------------------------------------------------- + +LOG_FILE=consistency.log10 +export APRUN="mpiexec -n 6 -ppn 6 --cpu-bind core" +TEST10=$(qsub -V -o $LOG_FILE -e $LOG_FILE -q $QUEUE -A $PROJECT_CODE -l walltime=00:05:00 \ + -N 3km.conus.hrrr.gfssdf.grib2.conus -l select=1:ncpus=6:ompthreads=1:mem=75GB $PWD/3km.conus.hrrr.gfssdf.grib2.sh) + +#----------------------------------------------------------------------------- +# Initialize CONUS 3-KM USING HRRR GRIB2 file WITH GSD PHYSICS AND SFC VARS FROM FILE. +#----------------------------------------------------------------------------- + +LOG_FILE=consistency.log11 +export APRUN="mpiexec -n 12 -ppn 12 --cpu-bind core" +TEST11=$(qsub -V -o $LOG_FILE -e $LOG_FILE -q $QUEUE -A $PROJECT_CODE -l walltime=00:05:00 \ + -N 3km.conus.hrrr.newsfc.grib2.conus -l select=1:ncpus=12:ompthreads=1:mem=75GB $PWD/3km.conus.hrrr.newsfc.grib2.sh) + +#----------------------------------------------------------------------------- +# Initialize CONUS 13-KM USING NAM GRIB2 file WITH GFS PHYSICS . +#----------------------------------------------------------------------------- + +LOG_FILE=consistency.log12 +export APRUN="mpiexec -n 6 -ppn 6 --cpu-bind core" +TEST12=$(qsub -V -o $LOG_FILE -e $LOG_FILE -q $QUEUE -A $PROJECT_CODE -l walltime=00:05:00 \ + -N 13km.conus.nam.grib2.conus -l select=1:ncpus=6:ompthreads=1:mem=15GB $PWD/13km.conus.nam.grib2.sh) + +#----------------------------------------------------------------------------- +# Initialize CONUS 13-KM USING RAP GRIB2 file WITH GSD PHYSICS . +#----------------------------------------------------------------------------- + +LOG_FILE=consistency.log13 +export APRUN="mpiexec -n 6 -ppn 6 --cpu-bind core" +TEST13=$(qsub -V -o $LOG_FILE -e $LOG_FILE -q $QUEUE -A $PROJECT_CODE -l walltime=00:05:00 \ + -N 13km.conus.rap.grib2.conus -l select=1:ncpus=6:ompthreads=1:mem=15GB $PWD/13km.conus.rap.grib2.sh) + +#----------------------------------------------------------------------------- +# Initialize CONUS 13-KM NA USING NCEI GFS GRIB2 file WITH GFS PHYSICS . +#----------------------------------------------------------------------------- + +LOG_FILE=consistency.log14 +export APRUN="mpiexec -n 6 -ppn 6 --cpu-bind core" +TEST14=$(qsub -V -o $LOG_FILE -e $LOG_FILE -q $QUEUE -A $PROJECT_CODE -l walltime=00:05:00 \ + -N 13km.na.gfs.ncei.grib2.conus -l select=1:ncpus=6:ompthreads=1:mem=25GB $PWD/13km.na.gfs.ncei.grib2.sh) + +#----------------------------------------------------------------------------- +# Initialize C96 WAM IC using FV3 gaussian netcdf files. +#----------------------------------------------------------------------------- + +LOG_FILE=consistency.log15 +export APRUN="mpiexec -n 12 -ppn 12 --cpu-bind core" +TEST15=$(qsub -V -o $LOG_FILE -e $LOG_FILE -q $QUEUE -A $PROJECT_CODE -l walltime=00:05:00 \ + -N c96.fv3.netcdf2wam -l select=1:ncpus=12:ompthreads=1:mem=75GB $PWD/c96.fv3.netcdf2wam.sh) + +#----------------------------------------------------------------------------- +# Initialize CONUS 25-KM USING GFS PGRIB2+BGRIB2 files. +#----------------------------------------------------------------------------- + +LOG_FILE=consistency.log16 +export APRUN="mpiexec -n 6 -ppn 6 --cpu-bind core" +TEST16=$(qsub -V -o $LOG_FILE -e $LOG_FILE -q $QUEUE -A $PROJECT_CODE -l walltime=00:05:00 \ + -N 25km.conus.gfs.pbgrib2.conus -l select=1:ncpus=6:ompthreads=1:mem=15GB $PWD/25km.conus.gfs.pbgrib2.sh) + +#----------------------------------------------------------------------------- +# Initialize global C96 using GEFS GRIB2 files. +#----------------------------------------------------------------------------- + +LOG_FILE=consistency.log17 +export APRUN="mpiexec -n 6 -ppn 6 --cpu-bind core" +TEST17=$(qsub -V -o $LOG_FILE -e $LOG_FILE -q $QUEUE -A $PROJECT_CODE -l walltime=00:05:00 \ + -N c96.gefs.grib2 -l select=1:ncpus=6:ompthreads=1:mem=15GB $PWD/c96.gefs.grib2.sh) + +#----------------------------------------------------------------------------- +# Create summary log. +#----------------------------------------------------------------------------- + +LOG_FILE=consistency.log +qsub -V -o ${LOG_FILE} -e ${LOG_FILE} -q $QUEUE -A $PROJECT_CODE -l walltime=00:01:00 \ + -N chgres_summary -l select=1:ncpus=1:mem=100MB \ + -W depend=afterok:$TEST1:$TEST2:$TEST3:$TEST4:$TEST5:$TEST6:$TEST7:$TEST8:$TEST9:$TEST10:$TEST11:$TEST12:$TEST13:$TEST14:$TEST15:$TEST16:$TEST17 << EOF +#!/bin/bash +cd ${this_dir} +grep -a '<<<' ${LOG_FILE}?? | grep -v echo > $SUM_FILE +EOF + +exit 0 diff --git a/reg_tests/chgres_cube/driver.wcoss_cray.sh b/reg_tests/chgres_cube/driver.wcoss_cray.sh deleted file mode 100755 index d08b9cdb9..000000000 --- a/reg_tests/chgres_cube/driver.wcoss_cray.sh +++ /dev/null @@ -1,223 +0,0 @@ -#!/bin/bash - -#----------------------------------------------------------------------------- -# -# Run the chgres_cube consistency tests on WCOSS-Cray. -# -# Set WORK_DIR to a general working location outside the UFS_UTILS directory. -# The exact working directory (OUTDIR) will be WORK_DIR/reg_tests/chgres-cube. -# Set the PROJECT_CODE and QUEUE as appropriate. -# -# Invoke the script with no arguments. A series of daily- -# chained jobs will be submitted. To check the queue, type: "bjobs". -# -# The run output will be stored in OUTDIR. Log output from the suite -# will be in LOG_FILE. Once the suite has completed, a summary is -# placed in SUM_FILE. -# -# A test fails when its output does not match the baseline files as -# determined by the "nccmp" utility. The baseline files are stored in -# HOMEreg. -# -#----------------------------------------------------------------------------- - -set -x - -source ../../sorc/machine-setup.sh > /dev/null 2>&1 -module use ../../modulefiles -module load build.$target.intel -module list - -export OUTDIR="${WORK_DIR:-/gpfs/hps3/stmp/$LOGNAME}" -export OUTDIR="${OUTDIR}/reg-tests/chgres-cube" - -QUEUE="${QUEUE:-dev}" -PROJECT_CODE="${PROJECT_CODE:-GFS-DEV}" - -#----------------------------------------------------------------------------- -# Should not have to change anything below here. HOMEufs is the root -# directory of your UFS_UTILS clone. HOMEreg contains the input data -# and baseline data for each test. -#----------------------------------------------------------------------------- - -export HOMEufs=$PWD/../.. - -export HOMEreg=/gpfs/hps3/emc/global/noscrub/George.Gayno/ufs_utils.git/reg_tests/chgres_cube - -LOG_FILE=consistency.log -SUM_FILE=summary.log -rm -f ${LOG_FILE}* $SUM_FILE - -export NCCMP=/gpfs/hps3/emc/global/noscrub/George.Gayno/util/netcdf/nccmp - -export OMP_STACKSIZE=1024M - -export KMP_AFFINITY=disabled - -#----------------------------------------------------------------------------- -# Initialize CONUS 25-KM USING GFS GRIB2 files. -#----------------------------------------------------------------------------- - -LOG_FILE1=${LOG_FILE}01 -export OMP_NUM_THREADS=1 -export APRUN="aprun -j 1 -n 6 -N 6 -d ${OMP_NUM_THREADS} -cc depth" -bsub -e $LOG_FILE1 -o $LOG_FILE1 -q $QUEUE -P $PROJECT_CODE -J chgres01 -M 1000 -W 0:05 -extsched 'CRAYLINUX[]' \ - "export NODES=1; $PWD/25km.conus.gfs.grib2.sh" - -#----------------------------------------------------------------------------- -# Initialize CONUS 3-KM USING HRRR GRIB2 file WITH GFS PHYSICS. -#----------------------------------------------------------------------------- - -LOG_FILE2=${LOG_FILE}02 -export OMP_NUM_THREADS=1 -export APRUN="aprun -j 1 -n 6 -N 6 -d ${OMP_NUM_THREADS} -cc depth" -bsub -e $LOG_FILE2 -o $LOG_FILE2 -q $QUEUE -P $PROJECT_CODE -J chgres02 -M 1000 -W 0:07 -extsched 'CRAYLINUX[]' \ - "export NODES=1; $PWD/3km.conus.hrrr.gfssdf.grib2.sh" - -#----------------------------------------------------------------------------- -# Initialize CONUS 3-KM USING HRRR GRIB2 file WITH GSD PHYSICS AND SFC VARS FROM FILE. -#----------------------------------------------------------------------------- - -LOG_FILE3=${LOG_FILE}03 -export OMP_NUM_THREADS=1 -export APRUN="aprun -j 1 -n 12 -N 6 -d ${OMP_NUM_THREADS} -cc depth" -bsub -e $LOG_FILE3 -o $LOG_FILE3 -q $QUEUE -P $PROJECT_CODE -J chgres03 -M 1000 -W 0:07 -extsched 'CRAYLINUX[]' \ - "export NODES=2; $PWD/3km.conus.hrrr.newsfc.grib2.sh" - -#----------------------------------------------------------------------------- -# Initialize CONUS 13-KM USING NAM GRIB2 file WITH GFS PHYSICS . -#----------------------------------------------------------------------------- - -LOG_FILE4=${LOG_FILE}04 -export OMP_NUM_THREADS=1 -export APRUN="aprun -j 1 -n 6 -N 6 -d ${OMP_NUM_THREADS} -cc depth" -bsub -e $LOG_FILE4 -o $LOG_FILE4 -q $QUEUE -P $PROJECT_CODE -J chgres04 -M 1000 -W 0:07 -extsched 'CRAYLINUX[]' \ - "export NODES=1; $PWD/13km.conus.nam.grib2.sh" - -#----------------------------------------------------------------------------- -# Initialize CONUS 13-KM USING RAP GRIB2 file WITH GSD PHYSICS . -#----------------------------------------------------------------------------- - -LOG_FILE5=${LOG_FILE}05 -export OMP_NUM_THREADS=1 -export APRUN="aprun -j 1 -n 6 -N 6 -d ${OMP_NUM_THREADS} -cc depth" -bsub -e $LOG_FILE5 -o $LOG_FILE5 -q $QUEUE -P $PROJECT_CODE -J chgres05 -M 1000 -W 0:07 -extsched 'CRAYLINUX[]' \ - "export NODES=1; $PWD/13km.conus.rap.grib2.sh" - -#----------------------------------------------------------------------------- -# Initialize CONUS 13-KM NA USING NCEI GFS GRIB2 file WITH GFS PHYSICS . -#----------------------------------------------------------------------------- - -LOG_FILE6=${LOG_FILE}06 -export OMP_NUM_THREADS=1 -export APRUN="aprun -j 1 -n 6 -N 6 -d ${OMP_NUM_THREADS} -cc depth" -bsub -e $LOG_FILE6 -o $LOG_FILE6 -q $QUEUE -P $PROJECT_CODE -J chgres06 -M 1000 -W 0:07 -extsched 'CRAYLINUX[]' \ - "export NODES=1; $PWD/13km.na.gfs.ncei.grib2.sh" - -#----------------------------------------------------------------------------- -# Initialize C96 using FV3 warm restart files. -#----------------------------------------------------------------------------- - -LOG_FILE7=${LOG_FILE}07 -export OMP_NUM_THREADS=1 -export APRUN="aprun -j 1 -n 6 -N 6 -d ${OMP_NUM_THREADS} -cc depth" -bsub -e $LOG_FILE7 -o $LOG_FILE7 -q $QUEUE -P $PROJECT_CODE -J chgres07 -M 1000 -W 0:15 -extsched 'CRAYLINUX[]' \ - "export NODES=1; $PWD/c96.fv3.restart.sh" - -#----------------------------------------------------------------------------- -# Initialize C192 using FV3 tiled history files. -#----------------------------------------------------------------------------- - -LOG_FILE8=${LOG_FILE}08 -export OMP_NUM_THREADS=1 -export APRUN="aprun -j 1 -n 6 -N 6 -d ${OMP_NUM_THREADS} -cc depth" -bsub -e $LOG_FILE8 -o $LOG_FILE8 -q $QUEUE -P $PROJECT_CODE -J chgres08 -M 1000 -W 0:15 -extsched 'CRAYLINUX[]' \ - "export NODES=1; $PWD/c192.fv3.history.sh" - -#----------------------------------------------------------------------------- -# Initialize C96 using FV3 gaussian nemsio files. -#----------------------------------------------------------------------------- - -LOG_FILE9=${LOG_FILE}09 -export OMP_NUM_THREADS=1 -export APRUN="aprun -j 1 -n 6 -N 6 -d ${OMP_NUM_THREADS} -cc depth" -bsub -e $LOG_FILE9 -o $LOG_FILE9 -q $QUEUE -P $PROJECT_CODE -J chgres09 -M 1000 -W 0:15 -extsched 'CRAYLINUX[]' \ - "export NODES=1; $PWD/c96.fv3.nemsio.sh" - -#----------------------------------------------------------------------------- -# Initialize C96 using spectral GFS sigio/sfcio files. -#----------------------------------------------------------------------------- - -LOG_FILE10=${LOG_FILE}10 -export OMP_NUM_THREADS=4 -export APRUN="aprun -j 1 -n 6 -N 6 -d ${OMP_NUM_THREADS} -cc depth" -bsub -e $LOG_FILE10 -o $LOG_FILE10 -q $QUEUE -P $PROJECT_CODE -J chgres10 -M 1000 -W 0:15 -extsched 'CRAYLINUX[]' \ - "export NODES=1; $PWD/c96.gfs.sigio.sh" - -#----------------------------------------------------------------------------- -# Initialize C96 using spectral GFS gaussian nemsio files. -#----------------------------------------------------------------------------- - -LOG_FILE11=${LOG_FILE}11 -export OMP_NUM_THREADS=1 -export APRUN="aprun -j 1 -n 6 -N 6 -d ${OMP_NUM_THREADS} -cc depth" -bsub -e $LOG_FILE11 -o $LOG_FILE11 -q $QUEUE -P $PROJECT_CODE -J chgres11 -M 1000 -W 0:15 -extsched 'CRAYLINUX[]' \ - "export NODES=1; $PWD/c96.gfs.nemsio.sh" - -#----------------------------------------------------------------------------- -# Initialize regional C96 using FV3 gaussian nemsio files. -#----------------------------------------------------------------------------- - -LOG_FILE12=${LOG_FILE}12 -export OMP_NUM_THREADS=1 -export APRUN="aprun -j 1 -n 6 -N 6 -d ${OMP_NUM_THREADS} -cc depth" -bsub -e $LOG_FILE12 -o $LOG_FILE12 -q $QUEUE -P $PROJECT_CODE -J chgres12 -M 1000 -W 0:15 -extsched 'CRAYLINUX[]' \ - "export NODES=1; $PWD/c96.regional.sh" - -#----------------------------------------------------------------------------- -# Initialize C96 using FV3 gaussian netcdf files. -#----------------------------------------------------------------------------- - -LOG_FILE13=${LOG_FILE}13 -export OMP_NUM_THREADS=1 -export APRUN="aprun -j 1 -n 12 -N 6 -d ${OMP_NUM_THREADS} -cc depth" -bsub -e $LOG_FILE13 -o $LOG_FILE13 -q $QUEUE -P $PROJECT_CODE -J chgres13 -M 1000 -W 0:15 -extsched 'CRAYLINUX[]' \ - "export NODES=2; $PWD/c96.fv3.netcdf.sh" - -#----------------------------------------------------------------------------- -# Initialize global C192 using GFS GRIB2 data. -#----------------------------------------------------------------------------- - -LOG_FILE14=${LOG_FILE}14 -export OMP_NUM_THREADS=1 -export APRUN="aprun -j 1 -n 6 -N 6 -d ${OMP_NUM_THREADS} -cc depth" -bsub -e $LOG_FILE14 -o $LOG_FILE14 -q $QUEUE -P $PROJECT_CODE -J chgres14 -M 1000 -W 0:05 -extsched 'CRAYLINUX[]' \ - "export NODES=1; $PWD/c192.gfs.grib2.sh" - -#----------------------------------------------------------------------------- -# Initialize C96 WAM IC using FV3 gaussian netcdf files. -#----------------------------------------------------------------------------- - -LOG_FILE15=${LOG_FILE}15 -export OMP_NUM_THREADS=1 -export APRUN="aprun -j 1 -n 12 -N 6 -d ${OMP_NUM_THREADS} -cc depth" -bsub -e $LOG_FILE15 -o $LOG_FILE15 -q $QUEUE -P $PROJECT_CODE -J chgres15 -M 1000 -W 0:15 -extsched 'CRAYLINUX[]' \ - "export NODES=2; $PWD/c96.fv3.netcdf2wam.sh" - -#----------------------------------------------------------------------------- -# Initialize CONUS 25-KM USING GFS PGRIB2+BGRIB2 files. -#----------------------------------------------------------------------------- - -LOG_FILE16=${LOG_FILE}16 -export OMP_NUM_THREADS=1 -export APRUN="aprun -j 1 -n 6 -N 6 -d ${OMP_NUM_THREADS} -cc depth" -bsub -e $LOG_FILE16 -o $LOG_FILE16 -q $QUEUE -P $PROJECT_CODE -J chgres16 -M 1000 -W 0:05 -extsched 'CRAYLINUX[]' \ - "export NODES=1; $PWD/25km.conus.gfs.pbgrib2.sh" - -#----------------------------------------------------------------------------- -# Create summary log. -#----------------------------------------------------------------------------- - -bsub -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J summary -R "rusage[mem=100]" -W 0:01 -w 'ended(chgres*)' "grep -a '<<<' "*.log*" >> $SUM_FILE" - -exit diff --git a/reg_tests/cpld_gridgen/RegressionTests_hera.intel.log b/reg_tests/cpld_gridgen/RegressionTests_hera.intel.log new file mode 100644 index 000000000..6e9632d61 --- /dev/null +++ b/reg_tests/cpld_gridgen/RegressionTests_hera.intel.log @@ -0,0 +1,76 @@ +Sat Apr 23 17:52:41 UTC 2022 +Start Regression test + +Working dir = /scratch1/NCEPDEV/stmp4/Minsuk.Ji/CPLD_GRIDGEN/rt_142841/025 +Baseline dir = /scratch1/NCEPDEV/nems/role.ufsutils/ufs_utils/reg_tests/cpld_gridgen/baseline_data/025 + +Checking test 025 results .... +Comparing Bu.mx025_SCRIP.nc........OK +Comparing C384.mx025.tile1.nc........OK +Comparing C384.mx025.tile2.nc........OK +Comparing C384.mx025.tile3.nc........OK +Comparing C384.mx025.tile4.nc........OK +Comparing C384.mx025.tile5.nc........OK +Comparing C384.mx025.tile6.nc........OK +Comparing Ct.mx025_SCRIP_land.nc........OK +Comparing Ct.mx025_SCRIP.nc........OK +Comparing Ct.mx025.to.C384.nc........OK +Comparing Cu.mx025_SCRIP.nc........OK +Comparing Cv.mx025_SCRIP.nc........OK +Comparing grid_cice_NEMS_mx025.nc........OK +Comparing kmtu_cice_NEMS_mx025.nc........OK +Comparing mesh.mx025.nc........OK +Comparing tripole.mx025.nc........OK + + +Working dir = /scratch1/NCEPDEV/stmp4/Minsuk.Ji/CPLD_GRIDGEN/rt_142841/050 +Baseline dir = /scratch1/NCEPDEV/nems/role.ufsutils/ufs_utils/reg_tests/cpld_gridgen/baseline_data/050 + +Checking test 050 results .... +Comparing Bu.mx050_SCRIP.nc........OK +Comparing C192.mx050.tile1.nc........OK +Comparing C192.mx050.tile2.nc........OK +Comparing C192.mx050.tile3.nc........OK +Comparing C192.mx050.tile4.nc........OK +Comparing C192.mx050.tile5.nc........OK +Comparing C192.mx050.tile6.nc........OK +Comparing Ct.mx025_SCRIP.nc........OK +Comparing Ct.mx050_SCRIP_land.nc........OK +Comparing Ct.mx050_SCRIP.nc........OK +Comparing Ct.mx050.to.C192.nc........OK +Comparing Cu.mx050_SCRIP.nc........OK +Comparing Cv.mx050_SCRIP.nc........OK +Comparing grid_cice_NEMS_mx050.nc........OK +Comparing kmtu_cice_NEMS_mx050.nc........OK +Comparing mesh.mx050.nc........OK +Comparing tripole.mx025.Ct.to.mx050.Ct.neareststod.nc........OK +Comparing tripole.mx050.nc........OK + + +Working dir = /scratch1/NCEPDEV/stmp4/Minsuk.Ji/CPLD_GRIDGEN/rt_142841/100 +Baseline dir = /scratch1/NCEPDEV/nems/role.ufsutils/ufs_utils/reg_tests/cpld_gridgen/baseline_data/100 + +Checking test 100 results .... +Comparing Bu.mx100_SCRIP.nc........OK +Comparing C96.mx100.tile1.nc........OK +Comparing C96.mx100.tile2.nc........OK +Comparing C96.mx100.tile3.nc........OK +Comparing C96.mx100.tile4.nc........OK +Comparing C96.mx100.tile5.nc........OK +Comparing C96.mx100.tile6.nc........OK +Comparing Ct.mx025_SCRIP.nc........OK +Comparing Ct.mx100_SCRIP_land.nc........OK +Comparing Ct.mx100_SCRIP.nc........OK +Comparing Ct.mx100.to.C96.nc........OK +Comparing Cu.mx100_SCRIP.nc........OK +Comparing Cv.mx100_SCRIP.nc........OK +Comparing grid_cice_NEMS_mx100.nc........OK +Comparing kmtu_cice_NEMS_mx100.nc........OK +Comparing mesh.mx100.nc........OK +Comparing tripole.mx025.Ct.to.mx100.Ct.neareststod.nc........OK +Comparing tripole.mx100.nc........OK +Comparing ufs.topo_edits_011818.nc........OK + + +REGRESSION TEST WAS SUCCESSFUL +Sat Apr 23 17:57:15 UTC 2022 diff --git a/reg_tests/cpld_gridgen/RegressionTests_jet.intel.log b/reg_tests/cpld_gridgen/RegressionTests_jet.intel.log new file mode 100644 index 000000000..88b074661 --- /dev/null +++ b/reg_tests/cpld_gridgen/RegressionTests_jet.intel.log @@ -0,0 +1,76 @@ +Mon Apr 25 14:59:30 GMT 2022 +Start Regression test + +Working dir = /lfs4/HFIP/h-nems//Minsuk.Ji/CPLD_GRIDGEN/rt_25376/025 +Baseline dir = /lfs4/HFIP/hfv3gfs/emc.nemspara/role.ufsutils/ufs_utils/reg_tests/cpld_gridgen/baseline_data/025 + +Checking test 025 results .... +Comparing Bu.mx025_SCRIP.nc........OK +Comparing C384.mx025.tile1.nc........OK +Comparing C384.mx025.tile2.nc........OK +Comparing C384.mx025.tile3.nc........OK +Comparing C384.mx025.tile4.nc........OK +Comparing C384.mx025.tile5.nc........OK +Comparing C384.mx025.tile6.nc........OK +Comparing Ct.mx025.to.C384.nc........OK +Comparing Ct.mx025_SCRIP.nc........OK +Comparing Ct.mx025_SCRIP_land.nc........OK +Comparing Cu.mx025_SCRIP.nc........OK +Comparing Cv.mx025_SCRIP.nc........OK +Comparing grid_cice_NEMS_mx025.nc........OK +Comparing kmtu_cice_NEMS_mx025.nc........OK +Comparing mesh.mx025.nc........OK +Comparing tripole.mx025.nc........OK + + +Working dir = /lfs4/HFIP/h-nems//Minsuk.Ji/CPLD_GRIDGEN/rt_25376/050 +Baseline dir = /lfs4/HFIP/hfv3gfs/emc.nemspara/role.ufsutils/ufs_utils/reg_tests/cpld_gridgen/baseline_data/050 + +Checking test 050 results .... +Comparing Bu.mx050_SCRIP.nc........OK +Comparing C192.mx050.tile1.nc........OK +Comparing C192.mx050.tile2.nc........OK +Comparing C192.mx050.tile3.nc........OK +Comparing C192.mx050.tile4.nc........OK +Comparing C192.mx050.tile5.nc........OK +Comparing C192.mx050.tile6.nc........OK +Comparing Ct.mx025_SCRIP.nc........OK +Comparing Ct.mx050.to.C192.nc........OK +Comparing Ct.mx050_SCRIP.nc........OK +Comparing Ct.mx050_SCRIP_land.nc........OK +Comparing Cu.mx050_SCRIP.nc........OK +Comparing Cv.mx050_SCRIP.nc........OK +Comparing grid_cice_NEMS_mx050.nc........OK +Comparing kmtu_cice_NEMS_mx050.nc........OK +Comparing mesh.mx050.nc........OK +Comparing tripole.mx025.Ct.to.mx050.Ct.neareststod.nc........OK +Comparing tripole.mx050.nc........OK + + +Working dir = /lfs4/HFIP/h-nems//Minsuk.Ji/CPLD_GRIDGEN/rt_25376/100 +Baseline dir = /lfs4/HFIP/hfv3gfs/emc.nemspara/role.ufsutils/ufs_utils/reg_tests/cpld_gridgen/baseline_data/100 + +Checking test 100 results .... +Comparing Bu.mx100_SCRIP.nc........OK +Comparing C96.mx100.tile1.nc........OK +Comparing C96.mx100.tile2.nc........OK +Comparing C96.mx100.tile3.nc........OK +Comparing C96.mx100.tile4.nc........OK +Comparing C96.mx100.tile5.nc........OK +Comparing C96.mx100.tile6.nc........OK +Comparing Ct.mx025_SCRIP.nc........OK +Comparing Ct.mx100.to.C96.nc........OK +Comparing Ct.mx100_SCRIP.nc........OK +Comparing Ct.mx100_SCRIP_land.nc........OK +Comparing Cu.mx100_SCRIP.nc........OK +Comparing Cv.mx100_SCRIP.nc........OK +Comparing grid_cice_NEMS_mx100.nc........OK +Comparing kmtu_cice_NEMS_mx100.nc........OK +Comparing mesh.mx100.nc........OK +Comparing tripole.mx025.Ct.to.mx100.Ct.neareststod.nc........OK +Comparing tripole.mx100.nc........OK +Comparing ufs.topo_edits_011818.nc........OK + + +REGRESSION TEST WAS SUCCESSFUL +Mon Apr 25 15:07:31 GMT 2022 diff --git a/reg_tests/cpld_gridgen/RegressionTests_orion.intel.log b/reg_tests/cpld_gridgen/RegressionTests_orion.intel.log new file mode 100644 index 000000000..2a7e3b8e0 --- /dev/null +++ b/reg_tests/cpld_gridgen/RegressionTests_orion.intel.log @@ -0,0 +1,76 @@ +Sat Apr 23 12:52:18 CDT 2022 +Start Regression test + +Working dir = /work/noaa/stmp/jminsuk/CPLD_GRIDGEN/rt_614/025 +Baseline dir = /work/noaa/nems/role-nems/ufs_utils/reg_tests/cpld_gridgen/baseline_data/025 + +Checking test 025 results .... +Comparing Bu.mx025_SCRIP.nc........OK +Comparing C384.mx025.tile1.nc........OK +Comparing C384.mx025.tile2.nc........OK +Comparing C384.mx025.tile3.nc........OK +Comparing C384.mx025.tile4.nc........OK +Comparing C384.mx025.tile5.nc........OK +Comparing C384.mx025.tile6.nc........OK +Comparing Ct.mx025_SCRIP_land.nc........OK +Comparing Ct.mx025_SCRIP.nc........OK +Comparing Ct.mx025.to.C384.nc........OK +Comparing Cu.mx025_SCRIP.nc........OK +Comparing Cv.mx025_SCRIP.nc........OK +Comparing grid_cice_NEMS_mx025.nc........OK +Comparing kmtu_cice_NEMS_mx025.nc........OK +Comparing mesh.mx025.nc........OK +Comparing tripole.mx025.nc........OK + + +Working dir = /work/noaa/stmp/jminsuk/CPLD_GRIDGEN/rt_614/050 +Baseline dir = /work/noaa/nems/role-nems/ufs_utils/reg_tests/cpld_gridgen/baseline_data/050 + +Checking test 050 results .... +Comparing Bu.mx050_SCRIP.nc........OK +Comparing C192.mx050.tile1.nc........OK +Comparing C192.mx050.tile2.nc........OK +Comparing C192.mx050.tile3.nc........OK +Comparing C192.mx050.tile4.nc........OK +Comparing C192.mx050.tile5.nc........OK +Comparing C192.mx050.tile6.nc........OK +Comparing Ct.mx025_SCRIP.nc........OK +Comparing Ct.mx050_SCRIP_land.nc........OK +Comparing Ct.mx050_SCRIP.nc........OK +Comparing Ct.mx050.to.C192.nc........OK +Comparing Cu.mx050_SCRIP.nc........OK +Comparing Cv.mx050_SCRIP.nc........OK +Comparing grid_cice_NEMS_mx050.nc........OK +Comparing kmtu_cice_NEMS_mx050.nc........OK +Comparing mesh.mx050.nc........OK +Comparing tripole.mx025.Ct.to.mx050.Ct.neareststod.nc........OK +Comparing tripole.mx050.nc........OK + + +Working dir = /work/noaa/stmp/jminsuk/CPLD_GRIDGEN/rt_614/100 +Baseline dir = /work/noaa/nems/role-nems/ufs_utils/reg_tests/cpld_gridgen/baseline_data/100 + +Checking test 100 results .... +Comparing Bu.mx100_SCRIP.nc........OK +Comparing C96.mx100.tile1.nc........OK +Comparing C96.mx100.tile2.nc........OK +Comparing C96.mx100.tile3.nc........OK +Comparing C96.mx100.tile4.nc........OK +Comparing C96.mx100.tile5.nc........OK +Comparing C96.mx100.tile6.nc........OK +Comparing Ct.mx025_SCRIP.nc........OK +Comparing Ct.mx100_SCRIP_land.nc........OK +Comparing Ct.mx100_SCRIP.nc........OK +Comparing Ct.mx100.to.C96.nc........OK +Comparing Cu.mx100_SCRIP.nc........OK +Comparing Cv.mx100_SCRIP.nc........OK +Comparing grid_cice_NEMS_mx100.nc........OK +Comparing kmtu_cice_NEMS_mx100.nc........OK +Comparing mesh.mx100.nc........OK +Comparing tripole.mx025.Ct.to.mx100.Ct.neareststod.nc........OK +Comparing tripole.mx100.nc........OK +Comparing ufs.topo_edits_011818.nc........OK + + +REGRESSION TEST WAS SUCCESSFUL +Sat Apr 23 12:56:51 CDT 2022 diff --git a/reg_tests/cpld_gridgen/parm/grid.nml.IN b/reg_tests/cpld_gridgen/parm/grid.nml.IN new file mode 100644 index 000000000..8776b58c8 --- /dev/null +++ b/reg_tests/cpld_gridgen/parm/grid.nml.IN @@ -0,0 +1,15 @@ +& grid_nml +ni=NI_GLB +nj=NJ_GLB +dirsrc='FIXDIR' +dirout='OUTDIR' +fv3dir='MOSAICDIR' +topofile=TOPOGFILE +editsfile=EDITSFILE +res=RESNAME +atmres=MOSAICRES +npx=NPX +editmask=DO_MASKEDIT +debug=DO_DEBUG +do_postwgts=DO_POSTWGTS +/ diff --git a/reg_tests/cpld_gridgen/rt.conf b/reg_tests/cpld_gridgen/rt.conf new file mode 100644 index 000000000..64b2a617f --- /dev/null +++ b/reg_tests/cpld_gridgen/rt.conf @@ -0,0 +1,32 @@ +################################################################# +# Baseline configurations +# C384_025 needs to be the first test due to dependency of +# the weight-generation from 1/4deg ocean to lower resolution +################################################################# + +# TEST_NAME | DEP_NAME +# + C384_025 | + C192_050 | C384_025 + C096_100 | C384_025 + +################################################################# +# Non-baseline configurations. +# These configurations have been tested on hera. For hera, the +# memory use for the C3072 config is approx 60% of the full node, +# C1152 is 12% of the full node and C768 is 8% of the full node. +# The default is set as 12g on RDHPCS platforms and should be +# sufficient for all but C3072. On hera C3072 requires approx 50min +# of wall clock and using --exclusive. See C3072 settings in rt.sh +# +# Note that the 5deg ocean cases are currently only supported on +# hera +################################################################# + + #C3072_025 | + #C1152_025 | + #C768_025 | + + #C192_025 | + #C048_500 | C384_025 + #C096_500 | C384_025 diff --git a/reg_tests/cpld_gridgen/rt.sh b/reg_tests/cpld_gridgen/rt.sh new file mode 100755 index 000000000..b08cbac7c --- /dev/null +++ b/reg_tests/cpld_gridgen/rt.sh @@ -0,0 +1,317 @@ +#!/bin/bash +set -eu + +SECONDS=0 + +error() { + echo + echo "$@" 1>&2 + exit 1 +} + +usage() { + echo + echo "Usage: $program [-c] [-m] [-h] [-b]" + echo + echo " -b build the executable" + echo + echo " -c create a new baseline" + echo + echo " -m compare against the new baseline" + echo + echo " -h display this help and exit" + echo + echo " Examples" + echo + echo " './rt.sh -b' build exe file. compare against the existing baseline" + echo " './rt.sh -bc' build exe file. create a new baseline" + echo " './rt.sh -m' do not build exe file. compare against the new baseline" + echo +} + +usage_and_exit() { + usage + exit $1 +} + +check_results() { + + [ -o xtrace ] && set_x='set -x' || set_x='set +x' + set +x + + local test_status=PASS + # verification run + if [[ $CREATE_BASELINE = false ]]; then + + echo | tee -a $PATHRT/$REGRESSIONTEST_LOG + echo "Working dir = $RUNDIR" | tee -a $PATHRT/$REGRESSIONTEST_LOG + echo "Baseline dir = $BASELINE" | tee -a $PATHRT/$REGRESSIONTEST_LOG + echo | tee -a $PATHRT/$REGRESSIONTEST_LOG + echo "Checking test $TEST_NAME results ...." | tee -a $PATHRT/$REGRESSIONTEST_LOG + + for file in $BASELINE/*.nc; do + printf %s "Comparing " $(basename ${file}) "...." | tee -a $PATHRT/$REGRESSIONTEST_LOG + + if [[ ! -f $RUNDIR/$(basename ${file}) ]]; then + echo "....MISSING file" | tee -a $PATHRT/$REGRESSIONTEST_LOG + test_status=FAIL + else + $NCCMP -dmfqS -w format $(basename ${file}) $file >>${PATHRT}/nccmp_${TEST_NAME}.log 2>&1 && d=$? || d=$? + if [[ $d -ne 0 ]]; then + echo "....NOT OK" | tee -a $PATHRT/$REGRESSIONTEST_LOG + test_status=FAIL + else + echo "....OK" | tee -a $PATHRT/$REGRESSIONTEST_LOG + fi + fi + done + echo | tee -a $PATHRT/$REGRESSIONTEST_LOG + + # baseline creation run + else + + echo | tee -a $PATHRT/$REGRESSIONTEST_LOG + echo "Working dir = $RUNDIR" | tee -a $PATHRT/$REGRESSIONTEST_LOG + echo "Moving baseline files to $NEW_BASELINE ...." | tee -a $PATHRT/$REGRESSIONTEST_LOG + echo | tee -a $PATHRT/$REGRESSIONTEST_LOG + + mkdir -p $NEW_BASELINE + + for file in *.nc; do + printf %s "Moving " $file "...." | tee -a $PATHRT/$REGRESSIONTEST_LOG + + cp $file $NEW_BASELINE/$file && d=$? || d=$? + if [[ $d -ne 0 ]]; then + echo "....NOT OK" | tee -a $PATHRT/$REGRESSIONTEST_LOG + test_status=FAIL + else + echo "....OK" | tee -a $PATHRT/$REGRESSIONTEST_LOG + fi + done + echo | tee -a $PATHRT/$REGRESSIONTEST_LOG + + fi + + if [[ $test_status == FAIL ]]; then + echo "$TEST_NAME failed" >> $PATHRT/fail_test_$TEST_NAME + fi +} + +readonly program=$(basename $0) +# PATHRT - Path to regression tests directory +readonly PATHRT="$(cd $(dirname $0) && pwd -P)" +export PATHRT +# PATHTR - Path to the UFS UTILS directory +readonly PATHTR="$(cd $PATHRT/../.. && pwd)" +export PATHTR +TESTS_FILE="$PATHRT/rt.conf" +export TEST_NAME= + +# for C3072 on hera, use WLCLK=60 and MEM="--exclusive" +WLCLK_dflt=10 +export WLCLK=$WLCLK_dflt +MEM_dflt="--mem=12g" +export MEM=$MEM_dflt + +cd $PATHRT +export compiler=${compiler:-intel} +source $PATHTR/sorc/machine-setup.sh >/dev/null 2>&1 +echo "Machine: $target" +echo "Compiler: $compiler" + +COMPILE_LOG=compile.log +REGRESSIONTEST_LOG=RegressionTests_$target.$compiler.log +rm -f fail_test* $COMPILE_LOG run_*.log nccmp_*.log summary.log + +if [[ $target = wcoss2 ]]; then + STMP=${STMP:-/lfs/h2/emc/stmp/$USER} + export MOM6_FIXDIR=/lfs/h2/emc/nems/noscrub/emc.nems/UFS_UTILS/reg_tests/cpld_gridgen/fix_mom6 + BASELINE_ROOT=/lfs/h2/emc/nems/noscrub/emc.nems/UFS_UTILS/reg_tests/cpld_gridgen/baseline_data + ACCOUNT=${ACCOUNT:-GFS-DEV} + export APRUN="mpiexec -n 1 -ppn 1 --cpu-bind core" + QUEUE=${QUEUE:-dev} + SBATCH_COMMAND="./cpld_gridgen.sh" + NCCMP=/lfs/h2/emc/global/noscrub/George.Gayno/util/nccmp/nccmp-1.8.5.0/src/nccmp +elif [[ $target = hera ]]; then + STMP=${STMP:-/scratch1/NCEPDEV/stmp4/$USER} + export MOM6_FIXDIR=/scratch1/NCEPDEV/nems/role.ufsutils/ufs_utils/reg_tests/cpld_gridgen/fix_mom6 + BASELINE_ROOT=/scratch1/NCEPDEV/nems/role.ufsutils/ufs_utils/reg_tests/cpld_gridgen/baseline_data + ACCOUNT=${ACCOUNT:-nems} + QUEUE=${QUEUE:-batch} + NCCMP=nccmp + PARTITION=hera + SBATCH_COMMAND="./cpld_gridgen.sh" +elif [[ $target = orion ]]; then + STMP=${STMP:-/work/noaa/stmp/$USER} + export MOM6_FIXDIR=/work/noaa/nems/role-nems/ufs_utils/reg_tests/cpld_gridgen/fix_mom6 + BASELINE_ROOT=/work/noaa/nems/role-nems/ufs_utils/reg_tests/cpld_gridgen/baseline_data + ACCOUNT=${ACCOUNT:-nems} + QUEUE=${QUEUE:-batch} + NCCMP=nccmp + PARTITION=orion + ulimit -s unlimited + SBATCH_COMMAND="./cpld_gridgen.sh" +elif [[ $target = jet ]]; then + STMP=${STMP:-/lfs4/HFIP/h-nems/$USER} + export MOM6_FIXDIR=/lfs4/HFIP/hfv3gfs/emc.nemspara/role.ufsutils/ufs_utils/reg_tests/cpld_gridgen/fix_mom6 + BASELINE_ROOT=/lfs4/HFIP/hfv3gfs/emc.nemspara/role.ufsutils/ufs_utils/reg_tests/cpld_gridgen/baseline_data + ACCOUNT=${ACCOUNT:-h-nems} + QUEUE=${QUEUE:-batch} + NCCMP=nccmp + PARTITION=xjet + ulimit -s unlimited + SBATCH_COMMAND="./cpld_gridgen.sh" +fi +NEW_BASELINE_ROOT=$STMP/CPLD_GRIDGEN/BASELINE +RUNDIR_ROOT=$STMP/CPLD_GRIDGEN/rt_$$ + +BUILD_EXE=false +CREATE_BASELINE=false +while getopts :bcmh opt; do + case $opt in + b) + BUILD_EXE=true + ;; + c) + CREATE_BASELINE=true + ;; + m) + BASELINE_ROOT=$NEW_BASELINE_ROOT + ;; + h) + usage_and_exit 0 + ;; + '?') + error "$program: invalid option" + ;; + esac +done + +# Build the executable file +if [[ $BUILD_EXE = true ]]; then + cd $PATHTR + rm -rf $PATHTR/build $PATHTR/exec $PATHTR/lib + ./build_all.sh >$PATHRT/$COMPILE_LOG 2>&1 && d=$? || d=$? + if [[ d -ne 0 ]]; then + error "Build did not finish successfully. Check $COMPILE_LOG" + else + echo "Build was successful" + fi +fi + +if [[ ! -f $PATHTR/exec/cpld_gridgen ]]; then + error "cpld_gridgen exe file is not found in $PATHTR/exe/. Try -b to build or -h for help." +else + echo "cpld_gridgen exe file is found in $PATHTR/exec/" +fi + +module use $PATHTR/modulefiles +module load build.$target.$compiler +module list + +if [[ $CREATE_BASELINE = true ]]; then + rm -rf $NEW_BASELINE_ROOT + mkdir -p $NEW_BASELINE_ROOT +fi + +date > $PATHRT/$REGRESSIONTEST_LOG +echo "Start Regression test" | tee -a $PATHRT/$REGRESSIONTEST_LOG + +# Run tests specified in $TESTS_FILE +while read -r line || [ "$line" ]; do + + line="${line#"${line%%[![:space:]]*}"}" + [[ ${#line} == 0 ]] && continue + [[ $line =~ \# ]] && continue + + TEST_NAME=$(echo $line | cut -d'|' -f1 | sed -e 's/^ *//' -e 's/ *$//') + DEP_NAME=$(echo $line | cut -d'|' -f2 | sed -e 's/^ *//' -e 's/ *$//') + MOSAICRES=${TEST_NAME%_*} + TEST_NAME=${TEST_NAME##*_} + DEP_NAME=${DEP_NAME##*_} + + cd $PATHRT + RUNDIR=$RUNDIR_ROOT/$TEST_NAME + BASELINE=$BASELINE_ROOT/$TEST_NAME + NEW_BASELINE=$NEW_BASELINE_ROOT/$TEST_NAME + DEPDIR=$RUNDIR_ROOT/$DEP_NAME + mkdir -p $RUNDIR + + # OUTDIR_PATH is passed down to $PATHTR/ush/cpld_gridgen.sh + # It MUST be set + export OUTDIR_PATH=$RUNDIR + export MOSAICRES=$MOSAICRES + + if [[ -n $DEP_NAME ]]; then + cp $DEPDIR/Ct.mx025_SCRIP.nc $RUNDIR >/dev/null 2>&1 && d=$? || d=$? + if [[ $d -eq 1 ]]; then + error "DEPDIR $DEPDIR does not exist. Dependency not met" + fi + fi + + cp $PATHTR/exec/cpld_gridgen $RUNDIR + cp $PATHTR/ush/cpld_gridgen.sh $RUNDIR + cp $PATHRT/parm/grid.nml.IN $RUNDIR + cd $RUNDIR + + if [[ $target = wcoss2 ]]; then + + # rm -f $RUNDIR/bad.${TEST_NAME} + + TEST=$(qsub -V -o $PATHRT/run_${TEST_NAME}.log -e $PATHRT/run_${TEST_NAME}.log -q $QUEUE -A $ACCOUNT \ + -Wblock=true -l walltime=00:${WLCLK}:00 -N $TEST_NAME -l select=1:ncpus=1:mem=12GB -v RESNAME=$TEST_NAME $SBATCH_COMMAND) + + # qsub -o $PATHRT/run_${TEST_NAME}.log -e $PATHRT/run_${TEST_NAME}.log -q $QUEUE -A $ACCOUNT \ + # -Wblock=true -l walltime=00:01:00 -N chgres_summary -l select=1:ncpus=1:mem=100MB -W depend=afternotok:$TEST << EOF + #!/bin/bash + # touch $RUNDIR/bad.${TEST_NAME} + #EOF + # if [[ -f $RUNDIR/bad.${TEST_NAME} ]]; then + # error "Batch job for test $TEST_NAME did not finish successfully. Refer to run_${TEST_NAME}.log" + # fi + + else + sbatch --wait --ntasks-per-node=1 --nodes=1 ${MEM} -t 00:${WLCLK}:00 -A $ACCOUNT -q $QUEUE -J $TEST_NAME \ + --partition=$PARTITION -o $PATHRT/run_${TEST_NAME}.log -e $PATHRT/run_${TEST_NAME}.log \ + --wrap "time $SBATCH_COMMAND $TEST_NAME" && d=$? || d=$? + + if [[ d -ne 0 ]]; then + error "Batch job for test $TEST_NAME did not finish successfully. Refer to run_${TEST_NAME}.log" + fi + + fi + + check_results + +done <$TESTS_FILE +if [[ $? -ne 0 ]]; then + error "Run test while loop did not finish properly" +fi + +cd $PATHRT +FAIL_FILES="fail_test_*" +for file in $FAIL_FILES; do + if [[ -f "$file" ]]; then + cat "$file" >> fail_test + fi +done + +if [[ -e fail_test ]]; then + echo | tee -a $REGRESSIONTEST_LOG + for file in fail_test_*; do + cat $file >>$REGRESSIONTEST_LOG + cat $file >>summary.log + done + + echo | tee -a $REGRESSIONTEST_LOG + echo "REGRESSION TEST FAILED" | tee -a $REGRESSIONTEST_LOG +else + echo | tee -a $REGRESSIONTEST_LOG + echo "REGRESSION TEST WAS SUCCESSFUL" | tee -a $REGRESSIONTEST_LOG + echo "All tests passed" >>summary.log +fi +date >> $REGRESSIONTEST_LOG + +elapsed_time=$( printf '%02dh:%02dm:%02ds\n' $((SECONDS%86400/3600)) $((SECONDS%3600/60)) $((SECONDS%60)) ) +echo "Elapsed time: ${elapsed_time}. Have a nice day!" >> ${REGRESSIONTEST_LOG} +echo "Elapsed time: ${elapsed_time}. Have a nice day!" diff --git a/reg_tests/get_hash.sh b/reg_tests/get_hash.sh new file mode 100755 index 000000000..443c62098 --- /dev/null +++ b/reg_tests/get_hash.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +#set -x + +commit_string=$(git log -1 --oneline) + +commit_num=$(echo $commit_string | cut -c1-7) + +echo ${commit_num} + +export commit_num diff --git a/reg_tests/global_cycle/C768.fv3gfs.sh b/reg_tests/global_cycle/C768.fv3gfs.sh index 5bb326c42..268c18f44 100755 --- a/reg_tests/global_cycle/C768.fv3gfs.sh +++ b/reg_tests/global_cycle/C768.fv3gfs.sh @@ -32,7 +32,8 @@ export JCAP=1534 export LONB=3072 export LATB=1536 -export FIXgsm=$BASE_GSM/fix/fix_am +export FIXgsm=$BASE_GSM/fix/am +export FNAISC=$FIXgsm/CFSR.SEAICE.1982.2012.monthly.clim.grb export DONST="YES" export use_ufo=.true. @@ -70,6 +71,9 @@ if [ $test_failed -ne 0 ]; then echo "*********************************" echo "<<< C768 GLOBAL CYCLE TEST FAILED. >>>" echo "*********************************" + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + $BASE_GSM/reg_tests/update_baseline.sh $HOMEreg "c768.fv3gfs" $commit_num + fi else echo echo "*********************************" diff --git a/reg_tests/global_cycle/C768.lndincsnow.sh b/reg_tests/global_cycle/C768.lndincsnow.sh index 62a91fa7a..b0fe41a46 100755 --- a/reg_tests/global_cycle/C768.lndincsnow.sh +++ b/reg_tests/global_cycle/C768.lndincsnow.sh @@ -34,7 +34,7 @@ export JCAP=1534 export LONB=3072 export LATB=1536 -export FIXgsm=$BASE_GSM/fix/fix_am +export FIXgsm=$BASE_GSM/fix/am export DONST="NO" export use_ufo=.true. @@ -75,6 +75,9 @@ if [ $test_failed -ne 0 ]; then echo "****************************************" echo "<<< C768 LANDINC SNOW CYCLE TEST FAILED. >>>" echo "****************************************" + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + $BASE_GSM/reg_tests/update_baseline.sh $HOMEreg "c768.lndincsnow" $commit_num + fi else echo echo "***************************************" diff --git a/reg_tests/global_cycle/C768.lndincsoil.sh b/reg_tests/global_cycle/C768.lndincsoil.sh index 5d50c4221..a344785e6 100755 --- a/reg_tests/global_cycle/C768.lndincsoil.sh +++ b/reg_tests/global_cycle/C768.lndincsoil.sh @@ -36,7 +36,7 @@ export JCAP=1534 export LONB=3072 export LATB=1536 -export FIXgsm=$BASE_GSM/fix/fix_am +export FIXgsm=$BASE_GSM/fix/am export DONST="NO" export use_ufo=.true. @@ -77,6 +77,9 @@ if [ $test_failed -ne 0 ]; then echo "*****************************************" echo "<<< C768 LANDINC SOILT CYCLE TEST FAILED. >>>" echo "*****************************************" + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + $BASE_GSM/reg_tests/update_baseline.sh $HOMEreg "c768.lndincsoil" $commit_num + fi else echo echo "*****************************************" diff --git a/reg_tests/global_cycle/driver.hera.sh b/reg_tests/global_cycle/driver.hera.sh index a7058347a..c049f51fd 100755 --- a/reg_tests/global_cycle/driver.hera.sh +++ b/reg_tests/global_cycle/driver.hera.sh @@ -36,9 +36,16 @@ QUEUE="${QUEUE:-batch}" # Should not have to change anything below. #----------------------------------------------------------------------------- +export UPDATE_BASELINE="FALSE" +#export UPDATE_BASELINE="TRUE" + +if [ "$UPDATE_BASELINE" = "TRUE" ]; then + source ../get_hash.sh +fi + DATA_DIR="${WORK_DIR}/reg-tests/global-cycle" -export HOMEreg=/scratch1/NCEPDEV/da/George.Gayno/noscrub/reg_tests/global_cycle +export HOMEreg=/scratch1/NCEPDEV/nems/role.ufsutils/ufs_utils/reg_tests/global_cycle export OMP_NUM_THREADS_CY=2 diff --git a/reg_tests/global_cycle/driver.jet.sh b/reg_tests/global_cycle/driver.jet.sh index f5f488415..0f0ab0c4d 100755 --- a/reg_tests/global_cycle/driver.jet.sh +++ b/reg_tests/global_cycle/driver.jet.sh @@ -34,9 +34,16 @@ QUEUE="${QUEUE:-batch}" # Should not have to change anything below. #----------------------------------------------------------------------------- +export UPDATE_BASELINE="FALSE" +#export UPDATE_BASELINE="TRUE" + +if [ "$UPDATE_BASELINE" = "TRUE" ]; then + source ../get_hash.sh +fi + export DATA_DIR="${WORK_DIR}/reg-tests/global-cycle" -export HOMEreg=/lfs4/HFIP/emcda/George.Gayno/reg_tests/global_cycle +export HOMEreg=/lfs4/HFIP/hfv3gfs/emc.nemspara/role.ufsutils/ufs_utils/reg_tests/global_cycle export OMP_NUM_THREADS_CY=2 diff --git a/reg_tests/global_cycle/driver.orion.sh b/reg_tests/global_cycle/driver.orion.sh index 27d138c8d..3bd5d6dc0 100755 --- a/reg_tests/global_cycle/driver.orion.sh +++ b/reg_tests/global_cycle/driver.orion.sh @@ -34,9 +34,16 @@ QUEUE="${QUEUE:-batch}" # Should not have to change anything below. #----------------------------------------------------------------------------- +export UPDATE_BASELINE="FALSE" +#export UPDATE_BASELINE="TRUE" + +if [ "$UPDATE_BASELINE" = "TRUE" ]; then + source ../get_hash.sh +fi + export DATA_DIR="${WORK_DIR}/reg-tests/global-cycle" -export HOMEreg=/work/noaa/da/ggayno/save/ufs_utils.git/reg_tests/global_cycle +export HOMEreg=/work/noaa/nems/role-nems/ufs_utils/reg_tests/global_cycle export OMP_NUM_THREADS_CY=2 diff --git a/reg_tests/global_cycle/driver.s4.sh b/reg_tests/global_cycle/driver.s4.sh new file mode 100755 index 000000000..439925c7e --- /dev/null +++ b/reg_tests/global_cycle/driver.s4.sh @@ -0,0 +1,84 @@ +#!/bin/bash + +#----------------------------------------------------------------------------- +# +# Run global_cycle consistency test on S4. +# +# Set $WORK_DIR to your working directory. Set the project code +# and queue as appropriate. +# +# Invoke the script from the command line as follows: ./$script +# +# Log output is placed in consistency.log??. A summary is +# placed in summary.log +# +# A test fails when its output does not match the baseline files +# as determined by the 'nccmp' utility. This baseline files are +# stored in HOMEreg. +# +#----------------------------------------------------------------------------- + +set -x + +compiler=${compiler:-"intel"} + +source ../../sorc/machine-setup.sh > /dev/null 2>&1 +module use ../../modulefiles +module load build.$target.$compiler +module list + +WORK_DIR="${WORK_DIR:-/scratch/short/users/$LOGNAME}" + +PROJECT_CODE="${PROJECT_CODE:-star}" +QUEUE="${QUEUE:-batch}" + +#----------------------------------------------------------------------------- +# Should not have to change anything below. +#----------------------------------------------------------------------------- + +export UPDATE_BASELINE="FALSE" +#export UPDATE_BASELINE="TRUE" + +if [ "$UPDATE_BASELINE" = "TRUE" ]; then + source ../get_hash.sh +fi + +DATA_DIR="${WORK_DIR}/reg-tests/global-cycle" + +export HOMEreg=/data/users/dhuber/save/nems/role.ufsutils/ufs_utils/reg_tests/global_cycle + +export OMP_NUM_THREADS_CY=2 + +export APRUNCY="srun" + +export NWPROD=$PWD/../.. + +reg_dir=$PWD + +LOG_FILE=consistency.log01 +export DATA="${DATA_DIR}/test1" +export COMOUT=$DATA +TEST1=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:05:00 -A $PROJECT_CODE -q $QUEUE -J c768.fv3gfs \ + -o $LOG_FILE -e $LOG_FILE ./C768.fv3gfs.sh) + +LOG_FILE=consistency.log02 +export DATA="${DATA_DIR}/test2" +export COMOUT=$DATA +TEST2=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:05:00 -A $PROJECT_CODE -q $QUEUE -J c768.lndincsoil \ + -o $LOG_FILE -e $LOG_FILE ./C768.lndincsoil.sh) + +LOG_FILE=consistency.log03 +export DATA="${DATA_DIR}/test3" +export COMOUT=$DATA +TEST3=$(sbatch --parsable --ntasks-per-node=6 --nodes=1 -t 0:05:00 -A $PROJECT_CODE -q $QUEUE -J c768.lndincsnow \ + -o $LOG_FILE -e $LOG_FILE ./C768.lndincsnow.sh) + +LOG_FILE=consistency.log +sbatch --nodes=1 -t 0:01:00 -A $PROJECT_CODE -J summary -o $LOG_FILE -e $LOG_FILE \ + --open-mode=append -q $QUEUE -d\ + afterok:$TEST1:$TEST2:$TEST3 << EOF +#!/bin/bash +grep -a '<<<' ${LOG_FILE}* > summary.log +EOF + +exit diff --git a/reg_tests/global_cycle/driver.wcoss2.sh b/reg_tests/global_cycle/driver.wcoss2.sh new file mode 100755 index 000000000..7889e7a1e --- /dev/null +++ b/reg_tests/global_cycle/driver.wcoss2.sh @@ -0,0 +1,86 @@ +#!/bin/bash + +#----------------------------------------------------------------------------- +# +# Run global_cycle consistency test on WCOSS2. +# +# Set $WORK_DIR to your working directory. Set the project code +# and queue as appropriate. +# +# Invoke the script from the command line as follows: ./$script +# +# Log output is placed in consistency.log??. A summary is +# placed in summary.log +# +# A test fails when its output does not match the baseline files +# as determined by the 'nccmp' utility. This baseline files are +# stored in HOMEreg. +# +#----------------------------------------------------------------------------- + +set -x + +compiler=${compiler:-"intel"} + +source ../../sorc/machine-setup.sh > /dev/null 2>&1 +module use ../../modulefiles +module load build.$target.$compiler +module list + +WORK_DIR="${WORK_DIR:-/lfs/h2/emc/stmp/$LOGNAME}" + +PROJECT_CODE="${PROJECT_CODE:-GFS-DEV}" +QUEUE="${QUEUE:-dev}" + +#----------------------------------------------------------------------------- +# Should not have to change anything below. +#----------------------------------------------------------------------------- + +export UPDATE_BASELINE="FALSE" +#export UPDATE_BASELINE="TRUE" + +if [ "$UPDATE_BASELINE" = "TRUE" ]; then + source ../get_hash.sh +fi + +DATA_DIR="${WORK_DIR}/reg-tests/global-cycle" + +export HOMEreg=/lfs/h2/emc/nems/noscrub/emc.nems/UFS_UTILS/reg_tests/global_cycle + +export OMP_NUM_THREADS_CY=2 +export OMP_PLACES=cores + +export APRUNCY="mpiexec -n 6 -ppn 6 --cpu-bind core --depth ${OMP_NUM_THREADS_CY}" + +export NWPROD=$PWD/../.. + +reg_dir=$PWD + +export NCCMP=/lfs/h2/emc/global/noscrub/George.Gayno/util/nccmp/nccmp-1.8.5.0/src/nccmp + +LOG_FILE=consistency.log +rm -f ${LOG_FILE}* + +export DATA="${DATA_DIR}/test1" +export COMOUT=$DATA +TEST1=$(qsub -V -o ${LOG_FILE}01 -e ${LOG_FILE}01 -q $QUEUE -A $PROJECT_CODE -l walltime=00:05:00 \ + -N c768.fv3gfs -l select=1:ncpus=12:mem=12GB $PWD/C768.fv3gfs.sh) + +export DATA="${DATA_DIR}/test2" +export COMOUT=$DATA +TEST2=$(qsub -V -o ${LOG_FILE}02 -e ${LOG_FILE}02 -q $QUEUE -A $PROJECT_CODE -l walltime=00:05:00 \ + -N c768.lndincsoil -l select=1:ncpus=12:mem=8GB $PWD/C768.lndincsoil.sh) + +export DATA="${DATA_DIR}/test3" +export COMOUT=$DATA +TEST3=$(qsub -V -o ${LOG_FILE}03 -e ${LOG_FILE}03 -q $QUEUE -A $PROJECT_CODE -l walltime=00:05:00 \ + -N c768.lndincsnow -l select=1:ncpus=12:mem=8GB $PWD/C768.lndincsnow.sh) + +qsub -V -o ${LOG_FILE} -e ${LOG_FILE} -q $QUEUE -A $PROJECT_CODE -l walltime=00:01:00 \ + -N cycle_summary -l select=1:ncpus=1:mem=100MB -W depend=afterok:$TEST1:$TEST2:$TEST3 << EOF +#!/bin/bash +cd $reg_dir +grep -a '<<<' ${LOG_FILE}?? | grep -v echo > summary.log +EOF + +exit diff --git a/reg_tests/global_cycle/driver.wcoss_cray.sh b/reg_tests/global_cycle/driver.wcoss_cray.sh deleted file mode 100755 index f18242917..000000000 --- a/reg_tests/global_cycle/driver.wcoss_cray.sh +++ /dev/null @@ -1,75 +0,0 @@ -#!/bin/bash - -#----------------------------------------------------------------------------- -# -# Run global_cycle consistency tests on WCOSS-Cray. -# -# Set $WORK_DIR to your working directory. Set the project code nd -# and queue as appropriate. -# -# Invoke the script as follows: ./$script -# -# Log output is placed in consistency.log??. A summary is -# placed in summary.log -# -# A test fails when its output does not match the baseline files -# as determined by the 'nccmp' utility. This baseline files are -# stored in HOMEreg. -# -#----------------------------------------------------------------------------- - -source ../../sorc/machine-setup.sh > /dev/null 2>&1 -module use ../../modulefiles -module load build.$target.intel -module list - -WORK_DIR="${WORK_DIR:-/gpfs/hps3/stmp/$LOGNAME}" - -PROJECT_CODE="${PROJECT_CODE:-GDAS-T2O}" -QUEUE="${QUEUE:-dev}" - -#----------------------------------------------------------------------------- -# Should not have to change anything below. -#----------------------------------------------------------------------------- - -DATA_DIR="${WORK_DIR}/reg-tests/global-cycle" - -export HOMEreg=/gpfs/hps3/emc/global/noscrub/George.Gayno/ufs_utils.git/reg_tests/global_cycle - -export OMP_NUM_THREADS_CY=4 - -export KMP_AFFINITY=disabled - -export APRUNCY="aprun -n 6 -N 6 -j 1 -d $OMP_NUM_THREADS_CY -cc depth" - -export NWPROD=$PWD/../.. - -export COMOUT=$DATA - -export NCCMP=/gpfs/hps3/emc/global/noscrub/George.Gayno/util/netcdf/nccmp - -reg_dir=$PWD - -LOG_FILE=consistency.log01 -export DATA="${DATA_DIR}/test1" -export COMOUT=$DATA -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J c768.fv3gfs -M 2400 -W 0:05 \ - -extsched 'CRAYLINUX[]' "export NODES=1; $PWD/C768.fv3gfs.sh" - -LOG_FILE=consistency.log02 -export DATA="${DATA_DIR}/test2" -export COMOUT=$DATA -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J c768.lndincsoil -M 2400 -W 0:05 \ - -extsched 'CRAYLINUX[]' "export NODES=1; $PWD/C768.lndincsoil.sh" - -LOG_FILE=consistency.log03 -export DATA="${DATA_DIR}/test3" -export COMOUT=$DATA -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J c768.lndincsnow -M 2400 -W 0:05 \ - -extsched 'CRAYLINUX[]' "export NODES=1; $PWD/C768.lndincsnow.sh" - -LOG_FILE=consistency.log -bsub -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J summary -R "rusage[mem=100]" -W 0:01 \ - -w 'ended(c768.*)' "grep -a '<<<' "${LOG_FILE}*" >> summary.log" - -exit diff --git a/reg_tests/global_cycle/driver.wcoss_dell_p3.sh b/reg_tests/global_cycle/driver.wcoss_dell_p3.sh deleted file mode 100755 index 13896deb0..000000000 --- a/reg_tests/global_cycle/driver.wcoss_dell_p3.sh +++ /dev/null @@ -1,71 +0,0 @@ -#!/bin/bash - -#----------------------------------------------------------------------------- -# -# Run global_cycle consistency tests on WCOSS-Dell. -# -# Set $WORK_DIR to your working directory. Set the project code -# and queue as appropriate. -# -# Invoke the script from the command line as follows: ./$script -# -# Log output is placed in consistency.log??. A summary is -# placed in summary.log. -# -# A test fails when its output does not match the baseline files -# as determined by the 'nccmp' utility. This baseline files are -# stored in HOMEreg. -# -#----------------------------------------------------------------------------- - -set -x - -source ../../sorc/machine-setup.sh > /dev/null 2>&1 -module use ../../modulefiles -module load build.$target.intel -module list - -WORK_DIR="${WORK_DIR:-/gpfs/dell1/stmp/$LOGNAME}" - -PROJECT_CODE="${PROJECT_CODE:-GFS-DEV}" -QUEUE="${QUEUE:-dev}" - -#----------------------------------------------------------------------------- -# Should not have to change anything below. -#----------------------------------------------------------------------------- - -DATA_DIR="${WORK_DIR}/reg-tests/global-cycle" - -export HOMEreg=/gpfs/dell2/emc/modeling/noscrub/George.Gayno/ufs_utils.git/reg_tests/global_cycle - -export OMP_NUM_THREADS_CY=2 - -export APRUNCY="mpirun -l" - -export NWPROD=$PWD/../.. - -reg_dir=$PWD - -LOG_FILE=consistency.log01 -export DATA="${DATA_DIR}/test1" -export COMOUT=$DATA -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J c768.fv3gfs -W 0:05 -x -n 6 \ - -M 2400 -R "span[ptile=6]" -R "affinity[core(1)]" "$PWD/C768.fv3gfs.sh" - -LOG_FILE=consistency.log02 -export DATA="${DATA_DIR}/test2" -export COMOUT=$DATA -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J c768.lndincsoil -W 0:05 -x -n 6 \ - -M 2400 -R "span[ptile=6]" -R "affinity[core(1)]" "$PWD/C768.lndincsoil.sh" - -LOG_FILE=consistency.log03 -export DATA="${DATA_DIR}/test3" -export COMOUT=$DATA -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J c768.lndincsnow -W 0:05 -x -n 6 \ - -M 2400 -R "span[ptile=6]" -R "affinity[core(1)]" "$PWD/C768.lndincsnow.sh" - -LOG_FILE=consistency.log -bsub -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J summary -R "affinity[core(1)]" -R "rusage[mem=100]" -W 0:01 \ - -w 'ended(c768.*)' "grep -a '<<<' "${LOG_FILE}*" >> summary.log" - -exit diff --git a/reg_tests/grid_gen/c96.uniform.sh b/reg_tests/grid_gen/c96.uniform.sh index 72e4f90f9..6811c71af 100755 --- a/reg_tests/grid_gen/c96.uniform.sh +++ b/reg_tests/grid_gen/c96.uniform.sh @@ -55,6 +55,9 @@ done set +x if [ $test_failed -ne 0 ]; then echo "<<< C96 UNIFORM TEST FAILED. >>>" + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + $home_dir/reg_tests/update_baseline.sh "${HOMEreg}/.." "c96.uniform" $commit_num + fi else echo "<<< C96 UNIFORM TEST PASSED. >>>" fi diff --git a/reg_tests/grid_gen/c96.viirs.vegt.sh b/reg_tests/grid_gen/c96.viirs.vegt.sh index dd593680d..d0db44538 100755 --- a/reg_tests/grid_gen/c96.viirs.vegt.sh +++ b/reg_tests/grid_gen/c96.viirs.vegt.sh @@ -57,6 +57,9 @@ done set +x if [ $test_failed -ne 0 ]; then echo "<<< C96 VIIRS VEGT TEST FAILED. >>>" + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + $home_dir/reg_tests/update_baseline.sh "${HOMEreg}/.." "c96.viirs.vegt" $commit_num + fi else echo "<<< C96 VIIRS VEGT TEST PASSED. >>>" fi diff --git a/reg_tests/grid_gen/driver.hera.sh b/reg_tests/grid_gen/driver.hera.sh index 11ebb7c76..ef3b37b1c 100755 --- a/reg_tests/grid_gen/driver.hera.sh +++ b/reg_tests/grid_gen/driver.hera.sh @@ -8,16 +8,16 @@ # as appropriate. To see which projects you are authorized to use, # type "account_params". # -# Invoke the script with no arguments. A series of daily- -# chained jobs will be submitted. To check the queue, type: +# Invoke the script with no arguments. A set of tests will +# be submitted to run in parallel. To check the queue, type: # "squeue -u USERNAME". # -# Log output from the suite will be in LOG_FILE. Once the suite -# has completed, a summary is placed in SUM_FILE. +# Log output from each tests will be in its own LOG_FILE. Once +# the tests have completed, a summary is placed in SUM_FILE. # # A test fails when its output does not match the baseline files as # determined by the "nccmp" utility. The baseline files are stored in -# HOMEreg +# HOMEreg. # #----------------------------------------------------------------------------- @@ -39,14 +39,20 @@ PROJECT_CODE="${PROJECT_CODE:-fv3-cpu}" # Should not have to change anything below here. #----------------------------------------------------------------------------- +export UPDATE_BASELINE="FALSE" +#export UPDATE_BASELINE="TRUE" + +if [ "$UPDATE_BASELINE" = "TRUE" ]; then + source ../get_hash.sh +fi + LOG_FILE=consistency.log SUM_FILE=summary.log export home_dir=$PWD/../.. export APRUN=time export APRUN_SFC=srun export OMP_STACKSIZE=2048m -export machine=HERA -export HOMEreg=/scratch1/NCEPDEV/da/George.Gayno/noscrub/reg_tests/grid_gen/baseline_data +export HOMEreg=/scratch1/NCEPDEV/nems/role.ufsutils/ufs_utils/reg_tests/grid_gen/baseline_data ulimit -a #ulimit -s unlimited @@ -59,43 +65,57 @@ export OMP_NUM_THREADS=24 # C96 uniform grid #----------------------------------------------------------------------------- -TEST1=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c96.uniform \ - -o $LOG_FILE -e $LOG_FILE ./c96.uniform.sh) +LOG_FILE1=${LOG_FILE}01 +TEST1=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J c96.uniform \ + -o $LOG_FILE1 -e $LOG_FILE1 ./c96.uniform.sh) #----------------------------------------------------------------------------- # C96 uniform grid using viirs vegetation data. #----------------------------------------------------------------------------- -TEST2=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c96.viirs.vegt \ - -o $LOG_FILE -e $LOG_FILE -d afterok:$TEST1 ./c96.viirs.vegt.sh) +LOG_FILE2=${LOG_FILE}02 +TEST2=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J c96.viirs.vegt \ + -o $LOG_FILE2 -e $LOG_FILE2 ./c96.viirs.vegt.sh) #----------------------------------------------------------------------------- # gfdl regional grid #----------------------------------------------------------------------------- -TEST3=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J gfdl.regional \ - -o $LOG_FILE -e $LOG_FILE -d afterok:$TEST2 ./gfdl.regional.sh) +LOG_FILE3=${LOG_FILE}03 +TEST3=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:07:00 -A $PROJECT_CODE -q $QUEUE -J gfdl.regional \ + -o $LOG_FILE3 -e $LOG_FILE3 ./gfdl.regional.sh) + +#----------------------------------------------------------------------------- +# ESG regional grid (output dominant soil/vegetation type). +#----------------------------------------------------------------------------- + +LOG_FILE4=${LOG_FILE}04 +TEST4=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:07:00 -A $PROJECT_CODE -q $QUEUE -J esg.regional \ + -o $LOG_FILE4 -e $LOG_FILE4 ./esg.regional.sh) #----------------------------------------------------------------------------- -# esg regional grid +# ESG regional grid (output percent of each soil and vegetation type and +# the dominant category). #----------------------------------------------------------------------------- -TEST4=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J esg.regional \ - -o $LOG_FILE -e $LOG_FILE -d afterok:$TEST3 ./esg.regional.sh) +LOG_FILE5=${LOG_FILE}05 +TEST5=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:07:00 -A $PROJECT_CODE -q $QUEUE -J esg.regional.pct.cat \ + -o $LOG_FILE5 -e $LOG_FILE5 ./esg.regional.pct.cat.sh) #----------------------------------------------------------------------------- # Regional GSL gravity wave drag test. #----------------------------------------------------------------------------- -TEST5=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J reg.gsl.gwd \ - -o $LOG_FILE -e $LOG_FILE -d afterok:$TEST4 ./regional.gsl.gwd.sh) +LOG_FILE6=${LOG_FILE}06 +TEST6=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:07:00 -A $PROJECT_CODE -q $QUEUE -J reg.gsl.gwd \ + -o $LOG_FILE6 -e $LOG_FILE6 ./regional.gsl.gwd.sh) #----------------------------------------------------------------------------- # Create summary log. #----------------------------------------------------------------------------- sbatch --nodes=1 -t 0:01:00 -A $PROJECT_CODE -J grid_summary -o $LOG_FILE -e $LOG_FILE \ - --open-mode=append -q $QUEUE -d afterok:$TEST5 << EOF + --open-mode=append -q $QUEUE -d afterok:$TEST1:$TEST2:$TEST3:$TEST4:$TEST5:$TEST6 << EOF #!/bin/bash -grep -a '<<<' $LOG_FILE > $SUM_FILE +grep -a '<<<' ${LOG_FILE}* > $SUM_FILE EOF diff --git a/reg_tests/grid_gen/driver.jet.sh b/reg_tests/grid_gen/driver.jet.sh index 3674f0c2f..2d3f5fcfc 100755 --- a/reg_tests/grid_gen/driver.jet.sh +++ b/reg_tests/grid_gen/driver.jet.sh @@ -8,12 +8,12 @@ # as appropriate. To see which projects you are authorized to use, # type "account_params". # -# Invoke the script with no arguments. A series of daily- -# chained jobs will be submitted. To check the queue, type: +# Invoke the script with no arguments. Several tests will +# be submitted to run in parallel. To check the queue, type: # "squeue -u USERNAME". # -# Log output from the suite will be in LOG_FILE. Once the suite -# has completed, a summary is placed in SUM_FILE. +# Log output from each test will be placed in its own LOG_FILE. +# Once the suite has completed, a summary is placed in SUM_FILE. # # A test fails when its output does not match the baseline files as # determined by the "nccmp" utility. The baseline files are stored in @@ -28,8 +28,8 @@ module list set -x -QUEUE="${QUEUE:-windfall}" -PROJECT_CODE="${PROJECT_CODE:-emcda}" +QUEUE="${QUEUE:-batch}" +PROJECT_CODE="${PROJECT_CODE:-hfv3gfs}" export WORK_DIR="${WORK_DIR:-/lfs4/HFIP/emcda/$LOGNAME/stmp}" export WORK_DIR="${WORK_DIR}/reg-tests/grid-gen" @@ -37,14 +37,20 @@ export WORK_DIR="${WORK_DIR}/reg-tests/grid-gen" # Should not have to change anything below here. #----------------------------------------------------------------------------- +export UPDATE_BASELINE="FALSE" +#export UPDATE_BASELINE="TRUE" + +if [ "$UPDATE_BASELINE" = "TRUE" ]; then + source ../get_hash.sh +fi + LOG_FILE=consistency.log SUM_FILE=summary.log export home_dir=$PWD/../.. export APRUN=time export APRUN_SFC=srun export OMP_STACKSIZE=2048m -export machine=JET -export HOMEreg=/lfs4/HFIP/emcda/George.Gayno/reg_tests/grid_gen/baseline_data +export HOMEreg=/lfs4/HFIP/hfv3gfs/emc.nemspara/role.ufsutils/ufs_utils/reg_tests/grid_gen/baseline_data ulimit -a ulimit -s unlimited @@ -57,43 +63,57 @@ export OMP_NUM_THREADS=24 # C96 uniform grid #----------------------------------------------------------------------------- -TEST1=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c96.uniform \ - --partition=xjet -o $LOG_FILE -e $LOG_FILE ./c96.uniform.sh) +LOG_FILE1=${LOG_FILE}01 +TEST1=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J c96.uniform \ + --partition=xjet -o $LOG_FILE1 -e $LOG_FILE1 ./c96.uniform.sh) #----------------------------------------------------------------------------- # C96 uniform grid using viirs vegetation type data. #----------------------------------------------------------------------------- -TEST2=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c96.viirs.vegt \ - --partition=xjet -o $LOG_FILE -e $LOG_FILE -d afterok:$TEST1 ./c96.viirs.vegt.sh) +LOG_FILE2=${LOG_FILE}02 +TEST2=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J c96.viirs.vegt \ + --partition=xjet -o $LOG_FILE2 -e $LOG_FILE2 ./c96.viirs.vegt.sh) #----------------------------------------------------------------------------- # gfdl regional grid #----------------------------------------------------------------------------- -TEST3=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J gfdl.regional \ - --partition=xjet -o $LOG_FILE -e $LOG_FILE -d afterok:$TEST2 ./gfdl.regional.sh) +LOG_FILE3=${LOG_FILE}03 +TEST3=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:07:00 -A $PROJECT_CODE -q $QUEUE -J gfdl.regional \ + --partition=xjet -o $LOG_FILE3 -e $LOG_FILE3 ./gfdl.regional.sh) + +#----------------------------------------------------------------------------- +# ESG regional grid (output dominant soil/vegetation type). +#----------------------------------------------------------------------------- + +LOG_FILE4=${LOG_FILE}04 +TEST4=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:07:00 -A $PROJECT_CODE -q $QUEUE -J esg.regional \ + --partition=xjet -o $LOG_FILE4 -e $LOG_FILE4 ./esg.regional.sh) #----------------------------------------------------------------------------- -# ESG regional grid +# ESG regional grid (output percent of each soil and vegetation type and +# the dominant category). #----------------------------------------------------------------------------- -TEST4=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J esg.regional \ - --partition=xjet -o $LOG_FILE -e $LOG_FILE -d afterok:$TEST3 ./esg.regional.sh) +LOG_FILE5=${LOG_FILE}05 +TEST5=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:07:00 -A $PROJECT_CODE -q $QUEUE -J esg.regional.pct.cat \ + --partition=xjet -o $LOG_FILE5 -e $LOG_FILE5 ./esg.regional.pct.cat.sh) #----------------------------------------------------------------------------- # Regional GSL gravity wave drag. #----------------------------------------------------------------------------- -TEST5=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J reg.gsl.gwd \ - --partition=xjet -o $LOG_FILE -e $LOG_FILE -d afterok:$TEST4 ./regional.gsl.gwd.sh) +LOG_FILE6=${LOG_FILE}06 +TEST6=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:07:00 -A $PROJECT_CODE -q $QUEUE -J reg.gsl.gwd \ + --partition=xjet -o $LOG_FILE6 -e $LOG_FILE6 ./regional.gsl.gwd.sh) #----------------------------------------------------------------------------- # Create summary log. #----------------------------------------------------------------------------- sbatch --partition=xjet --nodes=1 -t 0:01:00 -A $PROJECT_CODE -J grid_summary -o $LOG_FILE -e $LOG_FILE \ - --open-mode=append -q $QUEUE -d afterok:$TEST5 << EOF + -q $QUEUE -d afterok:$TEST1:$TEST2:$TEST3:$TEST4:$TEST5:$TEST6 << EOF #!/bin/bash -grep -a '<<<' $LOG_FILE > $SUM_FILE +grep -a '<<<' ${LOG_FILE}* > $SUM_FILE EOF diff --git a/reg_tests/grid_gen/driver.orion.sh b/reg_tests/grid_gen/driver.orion.sh index f5902cf15..a3a60e678 100755 --- a/reg_tests/grid_gen/driver.orion.sh +++ b/reg_tests/grid_gen/driver.orion.sh @@ -6,14 +6,14 @@ # # Set WORK_DIR to your working directory. Set the PROJECT_CODE and QUEUE # as appropriate. To see which projects you are authorized to use, -# type "saccount_params". +# type "saccount_params" (after a 'module load contrib noaatools'). # -# Invoke the script with no arguments. A series of daily- -# chained jobs will be submitted. To check the queue, type: +# Invoke the script with no arguments. A set of tests will +# be submitted to run in parallel. To check the queue, type: # "squeue -u $LOGNAME". # -# Log output from the suite will be in LOG_FILE. Once the suite -# has completed, a summary is placed in SUM_FILE. +# Log output from each test will be placed in its own LOG_FILE. +# Once the suite has completed, a summary is placed in SUM_FILE. # # A test fails when its output does not match the baseline files as # determined by the "nccmp" utility. The baseline files are stored in @@ -45,8 +45,15 @@ export APRUN=time export APRUN_SFC=srun export OMP_STACKSIZE=2048m export OMP_NUM_THREADS=24 -export machine=ORION -export HOMEreg=/work/noaa/da/ggayno/save/ufs_utils.git/reg_tests/grid_gen/baseline_data + +export UPDATE_BASELINE="FALSE" +#export UPDATE_BASELINE="TRUE" + +if [ "$UPDATE_BASELINE" = "TRUE" ]; then + source ../get_hash.sh +fi + +export HOMEreg=/work/noaa/nems/role-nems/ufs_utils/reg_tests/grid_gen/baseline_data rm -fr $WORK_DIR @@ -54,43 +61,57 @@ rm -fr $WORK_DIR # C96 uniform grid #----------------------------------------------------------------------------- +LOG_FILE1=${LOG_FILE}01 TEST1=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c96.uniform \ - -o $LOG_FILE -e $LOG_FILE ./c96.uniform.sh) + -o $LOG_FILE1 -e $LOG_FILE1 ./c96.uniform.sh) #----------------------------------------------------------------------------- # C96 uniform grid using viirs vegetation type data. #----------------------------------------------------------------------------- +LOG_FILE2=${LOG_FILE}02 TEST2=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c96.viirs.vegt \ - --open-mode=append -o $LOG_FILE -e $LOG_FILE -d afterok:$TEST1 ./c96.viirs.vegt.sh) + -o $LOG_FILE2 -e $LOG_FILE2 ./c96.viirs.vegt.sh) #----------------------------------------------------------------------------- # GFDL regional grid #----------------------------------------------------------------------------- +LOG_FILE3=${LOG_FILE}03 TEST3=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J gfdl.regional \ - --open-mode=append -o $LOG_FILE -e $LOG_FILE -d afterok:$TEST2 ./gfdl.regional.sh) + -o $LOG_FILE3 -e $LOG_FILE3 ./gfdl.regional.sh) #----------------------------------------------------------------------------- -# ESG regional grid +# ESG regional grid (output dominant soil/vegetation type). #----------------------------------------------------------------------------- +LOG_FILE4=${LOG_FILE}04 TEST4=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J esg.regional \ - --open-mode=append -o $LOG_FILE -e $LOG_FILE -d afterok:$TEST3 ./esg.regional.sh) + -o $LOG_FILE4 -e $LOG_FILE4 ./esg.regional.sh) + +#----------------------------------------------------------------------------- +# ESG regional grid (output percent of each soil and vegetation type and +# the dominant category). +#----------------------------------------------------------------------------- + +LOG_FILE5=${LOG_FILE}05 +TEST5=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J esg.regional.pct.cat \ + -o $LOG_FILE5 -e $LOG_FILE5 ./esg.regional.pct.cat.sh) #----------------------------------------------------------------------------- # Regional grid with GSL gravity wave drag fields. #----------------------------------------------------------------------------- -TEST5=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J reg.gsl.gwd \ - --open-mode=append -o $LOG_FILE -e $LOG_FILE -d afterok:$TEST4 ./regional.gsl.gwd.sh) +LOG_FILE6=${LOG_FILE}06 +TEST6=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J reg.gsl.gwd \ + -o $LOG_FILE6 -e $LOG_FILE6 ./regional.gsl.gwd.sh) #----------------------------------------------------------------------------- # Create summary log. #----------------------------------------------------------------------------- sbatch --nodes=1 -t 0:01:00 -A $PROJECT_CODE -J grid_summary -o $LOG_FILE -e $LOG_FILE \ - --open-mode=append -q $QUEUE -d afterok:$TEST5 << EOF + -q $QUEUE -d afterok:$TEST1:$TEST2:$TEST3:$TEST4:$TEST5:$TEST6 << EOF #!/bin/bash -grep -a '<<<' $LOG_FILE > $SUM_FILE +grep -a '<<<' ${LOG_FILE}* > $SUM_FILE EOF diff --git a/reg_tests/grid_gen/driver.wcoss_dell_p3.sh b/reg_tests/grid_gen/driver.s4.sh similarity index 51% rename from reg_tests/grid_gen/driver.wcoss_dell_p3.sh rename to reg_tests/grid_gen/driver.s4.sh index 3def7e696..190c22c9c 100755 --- a/reg_tests/grid_gen/driver.wcoss_dell_p3.sh +++ b/reg_tests/grid_gen/driver.s4.sh @@ -2,13 +2,16 @@ #----------------------------------------------------------------------------- # -# Run grid generation consistency tests on WCOSS-Dell. +# Run grid generation consistency tests on S4. # # Set WORK_DIR to your working directory. Set the PROJECT_CODE and QUEUE -# as appropriate. +# as appropriate. To see which projects you are authorized to use, +# type +# "sacctmgr show assoc Users= format=account,user,qos" # # Invoke the script with no arguments. A series of daily- -# chained jobs will be submitted. To check the queue, type: "bjobs". +# chained jobs will be submitted. To check the queue, type: +# "squeue -u USERNAME". # # Log output from the suite will be in LOG_FILE. Once the suite # has completed, a summary is placed in SUM_FILE. @@ -19,75 +22,88 @@ # #----------------------------------------------------------------------------- +compiler=${compiler:-"intel"} + source ../../sorc/machine-setup.sh > /dev/null 2>&1 module use ../../modulefiles -module load build.$target.intel +module load build.$target.$compiler module list set -x -QUEUE="${QUEUE:-debug}" -PROJECT_CODE="${PROJECT_CODE:-GFS-DEV}" -export WORK_DIR="${WORK_DIR:-/gpfs/dell1/stmp/$LOGNAME}" +export WORK_DIR="${WORK_DIR:-/scratch/short/users/$LOGNAME}" export WORK_DIR="${WORK_DIR}/reg-tests/grid-gen" +QUEUE="${QUEUE:-s4}" +PROJECT_CODE="${PROJECT_CODE:-star}" #----------------------------------------------------------------------------- # Should not have to change anything below here. #----------------------------------------------------------------------------- +export UPDATE_BASELINE="FALSE" +#export UPDATE_BASELINE="TRUE" + +if [ "$UPDATE_BASELINE" = "TRUE" ]; then + source ../get_hash.sh +fi + LOG_FILE=consistency.log SUM_FILE=summary.log export home_dir=$PWD/../.. export APRUN=time -export APRUN_SFC="mpirun -l" +export APRUN_SFC=srun export OMP_STACKSIZE=2048m -export machine=WCOSS_DELL_P3 -export HOMEreg=/gpfs/dell2/emc/modeling/noscrub/George.Gayno/ufs_utils.git/reg_tests/grid_gen/baseline_data -export OMP_NUM_THREADS=24 +export machine=S4 +export HOMEreg=/data/users/dhuber/save/nems/role.ufsutils/ufs_utils/reg_tests/grid_gen/baseline_data + +ulimit -a +#ulimit -s unlimited rm -fr $WORK_DIR -ulimit -a -ulimit -s unlimited +export OMP_NUM_THREADS=24 #----------------------------------------------------------------------------- # C96 uniform grid #----------------------------------------------------------------------------- -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J c96.uniform -W 0:15 -x -n 24 \ - -R "span[ptile=24]" -R "affinity[core(1):distribute=balance]" "$PWD/c96.uniform.sh" +TEST1=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c96.uniform \ + -o $LOG_FILE -e $LOG_FILE ./c96.uniform.sh) #----------------------------------------------------------------------------- -# C96 uniform grid using viirs vegetation type data. +# C96 uniform grid using viirs vegetation data. #----------------------------------------------------------------------------- -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J c96.viirs.vegt -W 0:15 -x -n 24 -w 'ended(c96.uniform)' \ - -R "span[ptile=24]" -R "affinity[core(1):distribute=balance]" "$PWD/c96.viirs.vegt.sh" +TEST2=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:15:00 -A $PROJECT_CODE -q $QUEUE -J c96.viirs.vegt \ + -o $LOG_FILE -e $LOG_FILE -d afterok:$TEST1 ./c96.viirs.vegt.sh) #----------------------------------------------------------------------------- -# GFDL regional grid +# gfdl regional grid #----------------------------------------------------------------------------- -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J gfdl.regional -W 0:10 -x -n 24 -w 'ended(c96.viirs.vegt)' \ - -R "span[ptile=24]" -R "affinity[core(1):distribute=balance]" "$PWD/gfdl.regional.sh" +TEST3=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J gfdl.regional \ + -o $LOG_FILE -e $LOG_FILE -d afterok:$TEST2 ./gfdl.regional.sh) #----------------------------------------------------------------------------- -# ESG regional grid +# esg regional grid #----------------------------------------------------------------------------- -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J esg.regional -W 0:10 -x -n 24 -w 'ended(gfdl.regional)' \ - -R "span[ptile=24]" -R "affinity[core(1):distribute=balance]" "$PWD/esg.regional.sh" +TEST4=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J esg.regional \ + -o $LOG_FILE -e $LOG_FILE -d afterok:$TEST3 ./esg.regional.sh) #----------------------------------------------------------------------------- -# Regional GSL gravity wave drag. +# Regional GSL gravity wave drag test. #----------------------------------------------------------------------------- -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J reg.gsl.gwd -W 0:08 -x -n 24 -w 'ended(esg.regional)' \ - -R "span[ptile=24]" -R "affinity[core(1):distribute=balance]" "$PWD/regional.gsl.gwd.sh" +TEST5=$(sbatch --parsable --ntasks-per-node=24 --nodes=1 -t 0:10:00 -A $PROJECT_CODE -q $QUEUE -J reg.gsl.gwd \ + -o $LOG_FILE -e $LOG_FILE -d afterok:$TEST4 ./regional.gsl.gwd.sh) #----------------------------------------------------------------------------- # Create summary log. #----------------------------------------------------------------------------- -bsub -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J summary -R "affinity[core(1)]" -R "rusage[mem=100]" -W 0:01 \ - -w 'ended(reg.gsl.gwd)' "grep -a '<<<' $LOG_FILE >> $SUM_FILE" +sbatch --nodes=1 -t 0:01:00 -A $PROJECT_CODE -J grid_summary -o $LOG_FILE -e $LOG_FILE \ + --open-mode=append -q $QUEUE -d afterok:$TEST5 << EOF +#!/bin/bash +grep -a '<<<' $LOG_FILE > $SUM_FILE +EOF diff --git a/reg_tests/grid_gen/driver.wcoss2.sh b/reg_tests/grid_gen/driver.wcoss2.sh new file mode 100755 index 000000000..da8b9d0ed --- /dev/null +++ b/reg_tests/grid_gen/driver.wcoss2.sh @@ -0,0 +1,123 @@ +#!/bin/bash + +#----------------------------------------------------------------------------- +# +# Run grid generation consistency tests on WCOSS2. +# +# Set WORK_DIR to your working directory. Set the PROJECT_CODE and QUEUE +# as appropriate. +# +# Invoke the script with no arguments. Several tests will be started +# in parallel. To check the queue, type: "qstat -u USERNAME". +# +# Log output from the tests will be stored in their own LOG_FILE. +# Once the tests have completed, a summary is placed in SUM_FILE. +# +# A test fails when its output does not match the baseline files as +# determined by the "nccmp" utility. The baseline files are stored in +# $HOMEreg. +# +#----------------------------------------------------------------------------- + +compiler=${compiler:-"intel"} + +source ../../sorc/machine-setup.sh > /dev/null 2>&1 +module use ../../modulefiles +module load build.$target.$compiler +module list + +set -x + +export WORK_DIR="${WORK_DIR:-/lfs/h2/emc/stmp/$LOGNAME}" +export WORK_DIR="${WORK_DIR}/reg-tests/grid-gen" +QUEUE="${QUEUE:-dev}" +PROJECT_CODE="${PROJECT_CODE:-GFS-DEV}" + +#----------------------------------------------------------------------------- +# Should not have to change anything below here. +#----------------------------------------------------------------------------- + +export UPDATE_BASELINE="FALSE" +#export UPDATE_BASELINE="TRUE" + +if [ "$UPDATE_BASELINE" = "TRUE" ]; then + source ../get_hash.sh +fi + +export NCCMP=/lfs/h2/emc/global/noscrub/George.Gayno/util/nccmp/nccmp-1.8.5.0/src/nccmp + +LOG_FILE=consistency.log +rm -f ${LOG_FILE} +SUM_FILE=summary.log +export home_dir=$PWD/../.. +export APRUN=time +export APRUN_SFC="mpiexec -n 30 -ppn 30 -cpu-bind core" +export OMP_STACKSIZE=2048m +export OMP_NUM_THREADS=30 # orog code uses threads +export OMP_PLACES=cores +export HOMEreg=/lfs/h2/emc/nems/noscrub/emc.nems/UFS_UTILS/reg_tests/grid_gen/baseline_data +this_dir=$PWD + +ulimit -a + +rm -fr $WORK_DIR + +#----------------------------------------------------------------------------- +# C96 uniform grid +#----------------------------------------------------------------------------- + +LOG_FILE1=${LOG_FILE}01 +TEST1=$(qsub -V -o $LOG_FILE1 -e $LOG_FILE1 -q $QUEUE -A $PROJECT_CODE -l walltime=00:10:00 \ + -N c96.uniform -l select=1:ncpus=30:mem=40GB $PWD/c96.uniform.sh) + +#----------------------------------------------------------------------------- +# C96 uniform grid using viirs vegetation data. +#----------------------------------------------------------------------------- + +LOG_FILE2=${LOG_FILE}02 +TEST2=$(qsub -V -o $LOG_FILE2 -e $LOG_FILE2 -q $QUEUE -A $PROJECT_CODE -l walltime=00:10:00 \ + -N c96.viirs.vegt -l select=1:ncpus=30:mem=40GB $PWD/c96.viirs.vegt.sh) + +#----------------------------------------------------------------------------- +# gfdl regional grid +#----------------------------------------------------------------------------- + +LOG_FILE3=${LOG_FILE}03 +TEST3=$(qsub -V -o $LOG_FILE3 -e $LOG_FILE3 -q $QUEUE -A $PROJECT_CODE -l walltime=00:07:00 \ + -N gfdl.regional -l select=1:ncpus=30:mem=40GB $PWD/gfdl.regional.sh) + +#----------------------------------------------------------------------------- +# ESG regional grid (output dominant soil/vegetation type). +#----------------------------------------------------------------------------- + +LOG_FILE4=${LOG_FILE}04 +TEST4=$(qsub -V -o $LOG_FILE4 -e $LOG_FILE4 -q $QUEUE -A $PROJECT_CODE -l walltime=00:07:00 \ + -N esg.regional -l select=1:ncpus=30:mem=40GB $PWD/esg.regional.sh) + +#----------------------------------------------------------------------------- +# ESG regional grid (output percent of each soil and vegetation type and +# the dominant category). +#----------------------------------------------------------------------------- + +LOG_FILE5=${LOG_FILE}05 +TEST5=$(qsub -V -o $LOG_FILE5 -e $LOG_FILE5 -q $QUEUE -A $PROJECT_CODE -l walltime=00:07:00 \ + -N esg.regional.pct.cat -l select=1:ncpus=30:mem=40GB $PWD/esg.regional.pct.cat.sh) + +#----------------------------------------------------------------------------- +# Regional GSL gravity wave drag test. +#----------------------------------------------------------------------------- + +LOG_FILE6=${LOG_FILE}06 +TEST6=$(qsub -V -o $LOG_FILE6 -e $LOG_FILE6 -q $QUEUE -A $PROJECT_CODE -l walltime=00:07:00 \ + -N rsg.gsl.gwd -l select=1:ncpus=30:mem=40GB $PWD/regional.gsl.gwd.sh) + +#----------------------------------------------------------------------------- +# Create summary log. +#----------------------------------------------------------------------------- + +qsub -V -o ${LOG_FILE} -e ${LOG_FILE} -q $QUEUE -A $PROJECT_CODE -l walltime=00:02:00 \ + -N grid_summary -l select=1:ncpus=1:mem=100MB -W depend=afterok:$TEST1:$TEST2:$TEST3:$TEST4:$TEST5:$TEST6 << EOF +#!/bin/bash +cd ${this_dir} +grep -a '<<<' ${LOG_FILE}* | grep -v echo > $SUM_FILE +EOF diff --git a/reg_tests/grid_gen/driver.wcoss_cray.sh b/reg_tests/grid_gen/driver.wcoss_cray.sh deleted file mode 100755 index 5887676ff..000000000 --- a/reg_tests/grid_gen/driver.wcoss_cray.sh +++ /dev/null @@ -1,97 +0,0 @@ -#!/bin/bash - -#----------------------------------------------------------------------------- -# -# Run grid generation consistency tests on WCOSS-Cray. -# -# Set WORK_DIR to your working directory. Set the PROJECT_CODE and QUEUE -# as appropriate. -# -# Invoke the script with no arguments. A series of daily- -# chained jobs will be submitted. To check the queue, type: "bjobs". -# -# Log output from the suite will be in LOG_FILE. Once the suite -# has completed, a summary is placed in SUM_FILE. -# -# A test fails when its output does not match the baseline files as -# determined by the "nccmp" utility. The baseline files are stored in -# HOMEreg -# -#----------------------------------------------------------------------------- - -source ../../sorc/machine-setup.sh > /dev/null 2>&1 -module use ../../modulefiles -module load build.$target.intel -module list - -set -x - -QUEUE="${QUEUE:-debug}" -PROJECT_CODE="${PROJECT_CODE:-GFS-DEV}" -export WORK_DIR="${WORK_DIR:-/gpfs/hps3/stmp/$LOGNAME}" -export WORK_DIR="${WORK_DIR}/reg-tests/grid-gen" - -#----------------------------------------------------------------------------- -# Should not have to change anything below here. -#----------------------------------------------------------------------------- - -export home_dir=$PWD/../.. -LOG_FILE=consistency.log -SUM_FILE=summary.log -export APRUN="aprun -n 1 -N 1 -j 1 -d 1 -cc depth" -export APRUN_SFC="aprun -j 1 -n 24 -N 24" -export OMP_STACKSIZE=2048m -export OMP_NUM_THREADS=6 -export machine=WCOSS_C -export KMP_AFFINITY=disabled -export NCCMP=/gpfs/hps3/emc/global/noscrub/George.Gayno/util/netcdf/nccmp -export HOMEreg=/gpfs/hps3/emc/global/noscrub/George.Gayno/ufs_utils.git/reg_tests/grid_gen/baseline_data -export NCDUMP=/gpfs/hps/usrx/local/prod/NetCDF/4.2/intel/sandybridge/bin/ncdump - -rm -fr $WORK_DIR - -ulimit -a -ulimit -s unlimited - -#----------------------------------------------------------------------------- -# C96 uniform grid -#----------------------------------------------------------------------------- - -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J c96.uniform -W 0:15 -M 2400 \ - -extsched 'CRAYLINUX[]' "export NODES=1; $PWD/c96.uniform.sh" - -#----------------------------------------------------------------------------- -# C96 uniform grid using viirs vegetation type data. -#----------------------------------------------------------------------------- - -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J c96.viirs.vegt -W 0:15 -M 2400 \ - -w 'ended(c96.uniform)' -extsched 'CRAYLINUX[]' "export NODES=1; $PWD/c96.viirs.vegt.sh" - -#----------------------------------------------------------------------------- -# gfdl regional grid -#----------------------------------------------------------------------------- - -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J gfdl.regional -W 0:10 -M 2400 \ - -w 'ended(c96.viirs.vegt)' -extsched 'CRAYLINUX[]' "export NODES=1; $PWD/gfdl.regional.sh" - -#----------------------------------------------------------------------------- -# ESG regional grid -#----------------------------------------------------------------------------- - -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J esg.regional -W 0:10 -M 2400 \ - -w 'ended(gfdl.regional)' -extsched 'CRAYLINUX[]' "export NODES=1; $PWD/esg.regional.sh" - -#----------------------------------------------------------------------------- -# Regional GSL gravity wave drag. -#----------------------------------------------------------------------------- - -bsub -e $LOG_FILE -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J reg.gsl.gwd -W 0:08 -M 2400 \ - -w 'ended(esg.regional)' -extsched 'CRAYLINUX[]' "export NODES=1; $PWD/regional.gsl.gwd.sh" - -#----------------------------------------------------------------------------- -# Create summary log. -#----------------------------------------------------------------------------- - -bsub -o $LOG_FILE -q $QUEUE -P $PROJECT_CODE -J summary -R "rusage[mem=100]" -W 0:01 -w 'ended(reg.gsl.gwd)' "grep -a '<<<' $LOG_FILE >> $SUM_FILE" - -exit diff --git a/reg_tests/grid_gen/esg.regional.pct.cat.sh b/reg_tests/grid_gen/esg.regional.pct.cat.sh new file mode 100755 index 000000000..2afbed9e1 --- /dev/null +++ b/reg_tests/grid_gen/esg.regional.pct.cat.sh @@ -0,0 +1,75 @@ +#!/bin/bash + +#----------------------------------------------------------------------- +# Create a regional esg grid. Output dominant soil and vegetation +# categories and well as the percentage of each category. +# Compare output to a set of baseline files using the 'nccmp' +# utility. This script is run by the machine specific driver script. +#----------------------------------------------------------------------- + +set -x + +TEST_NAME="esg.regional.pct.cat" +export TEMP_DIR=${WORK_DIR}/${TEST_NAME}.work +export out_dir=${WORK_DIR}/${TEST_NAME} + +export gtype=regional_esg +export target_lon=-97.5 # Center longitude of the highest resolution tile +export target_lat=35.5 # Center latitude of the highest resolution tile +export idim=1301 # Dimension of grid in 'i' direction +export jdim=600 # Dimension of grid in 'j' direction +export delx=0.0145 # Grid spacing in degrees in 'i' direction +export dely=0.0145 # Grid spacing in degrees in 'j' direction +export halo=3 +export vegsoilt_frac=.true. # Output dominant soil/veg categories as well + # as the percentage of each category. + +NCCMP=${NCCMP:-$(which nccmp)} + +#----------------------------------------------------------------------- +# Start script. +#----------------------------------------------------------------------- + +echo "Starting at: " `date` + +$home_dir/ush/fv3gfs_driver_grid.sh + +iret=$? +if [ $iret -ne 0 ]; then + set +x + echo "<<< ESG REGIONAL PERCENT CATEGORY TEST FAILED. <<<" + exit $iret +fi + +echo "Ending at: " `date` + +#----------------------------------------------------------------------------- +# Compare output to baseline set of data. +#----------------------------------------------------------------------------- + +cd $out_dir/C3113 + +test_failed=0 +for files in *tile*.nc ./fix_sfc/*tile*.nc +do + if [ -f $files ]; then + echo CHECK $files + $NCCMP -dmfqS $files $HOMEreg/${TEST_NAME}/$files + iret=$? + if [ $iret -ne 0 ]; then + test_failed=1 + fi + fi +done + +set +x +if [ $test_failed -ne 0 ]; then + echo "<<< ESG REGIONAL PERCENT CATEGORY TEST FAILED. >>>" + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + $home_dir/reg_tests/update_baseline.sh "${HOMEreg}/.." "${TEST_NAME}" $commit_num + fi +else + echo "<<< ESG REGIONAL PERCENT CATEGORY TEST PASSED. >>>" +fi + +exit 0 diff --git a/reg_tests/grid_gen/esg.regional.sh b/reg_tests/grid_gen/esg.regional.sh index d88a260dc..55963531f 100755 --- a/reg_tests/grid_gen/esg.regional.sh +++ b/reg_tests/grid_gen/esg.regional.sh @@ -61,6 +61,9 @@ done set +x if [ $test_failed -ne 0 ]; then echo "<<< ESG REGIONAL TEST FAILED. >>>" + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + $home_dir/reg_tests/update_baseline.sh "${HOMEreg}/.." "esg.regional" $commit_num + fi else echo "<<< ESG REGIONAL TEST PASSED. >>>" fi diff --git a/reg_tests/grid_gen/gfdl.regional.sh b/reg_tests/grid_gen/gfdl.regional.sh index 985b498d2..76f94a4f4 100755 --- a/reg_tests/grid_gen/gfdl.regional.sh +++ b/reg_tests/grid_gen/gfdl.regional.sh @@ -64,6 +64,9 @@ done set +x if [ $test_failed -ne 0 ]; then echo "<<< GFDL REGIONAL TEST FAILED. >>>" + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + $home_dir/reg_tests/update_baseline.sh "${HOMEreg}/.." "gfdl.regional" $commit_num + fi else echo "<<< GFDL REGIONAL TEST PASSED. >>>" fi diff --git a/reg_tests/grid_gen/regional.gsl.gwd.sh b/reg_tests/grid_gen/regional.gsl.gwd.sh index 0a66daeeb..415ca3813 100755 --- a/reg_tests/grid_gen/regional.gsl.gwd.sh +++ b/reg_tests/grid_gen/regional.gsl.gwd.sh @@ -62,6 +62,9 @@ done set +x if [ $test_failed -ne 0 ]; then echo "<<< REGIONAL GSL GWD TEST FAILED. >>>" + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + $home_dir/reg_tests/update_baseline.sh "${HOMEreg}/.." "regional.gsl.gwd" $commit_num + fi else echo "<<< REGIONAL GSL GWD TEST PASSED. >>>" fi diff --git a/reg_tests/ice_blend/driver.hera.sh b/reg_tests/ice_blend/driver.hera.sh index 3b7d9c4da..b86f370d1 100755 --- a/reg_tests/ice_blend/driver.hera.sh +++ b/reg_tests/ice_blend/driver.hera.sh @@ -43,13 +43,20 @@ export DATA="${DATA}/reg-tests/ice-blend" # Should not have to change anything below. #----------------------------------------------------------------------------- +export UPDATE_BASELINE="FALSE" +#export UPDATE_BASELINE="TRUE" + +if [ "$UPDATE_BASELINE" = "TRUE" ]; then + source ../get_hash.sh +fi + export WGRIB=/scratch2/NCEPDEV/nwprod/NCEPLIBS/utils/grib_util.v1.1.1/exec/wgrib export WGRIB2=/scratch2/NCEPDEV/nwprod/NCEPLIBS/utils/grib_util.v1.1.1/exec/wgrib2 export COPYGB=/scratch2/NCEPDEV/nwprod/NCEPLIBS/utils/grib_util.v1.1.1/exec/copygb export COPYGB2=/scratch2/NCEPDEV/nwprod/NCEPLIBS/utils/grib_util.v1.1.1/exec/copygb2 export CNVGRIB=/scratch2/NCEPDEV/nwprod/NCEPLIBS/utils/grib_util.v1.1.1/exec/cnvgrib -export HOMEreg=/scratch1/NCEPDEV/da/George.Gayno/noscrub/reg_tests/ice_blend +export HOMEreg=/scratch1/NCEPDEV/nems/role.ufsutils/ufs_utils/reg_tests/ice_blend export HOMEgfs=$PWD/../.. rm -fr $DATA diff --git a/reg_tests/ice_blend/driver.jet.sh b/reg_tests/ice_blend/driver.jet.sh index f11191bfb..6c5498aa9 100755 --- a/reg_tests/ice_blend/driver.jet.sh +++ b/reg_tests/ice_blend/driver.jet.sh @@ -31,7 +31,11 @@ set -x source ../../sorc/machine-setup.sh > /dev/null 2>&1 module use ../../modulefiles module load build.$target.intel +module load gnu/9.2.0 +module load wgrib2/3.1.1_ncep +set +x module list +set -x export DATA="${WORK_DIR:-/lfs4/HFIP/emcda/$LOGNAME/stmp}" export DATA="${DATA}/reg-tests/ice-blend" @@ -40,13 +44,21 @@ export DATA="${DATA}/reg-tests/ice-blend" # Should not have to change anything below. #----------------------------------------------------------------------------- +export UPDATE_BASELINE="FALSE" +#export UPDATE_BASELINE="TRUE" + +if [ "$UPDATE_BASELINE" = "TRUE" ]; then + source ../get_hash.sh +fi + export WGRIB=/apps/wgrib/1.8.1.0b/bin/wgrib -export WGRIB2=/apps/wgrib2/0.1.9.6a/bin/wgrib2 -export COPYGB=/lfs4/HFIP/emcda/George.Gayno/ufs_utils.git/jet_port/grib_util/copygb -export COPYGB2=/lfs4/HFIP/emcda/George.Gayno/ufs_utils.git/jet_port/grib_util/copygb2 +export WGRIB2=${WGRIB2_ROOT}/bin/wgrib2 +export COPYGB=/lfs4/HFIP/hfv3gfs/emc.nemspara/role.ufsutils/ufs_utils/grib_util/NCEPLIBS-grib_util/exec/bin/copygb +export COPYGB2=/lfs4/HFIP/hfv3gfs/emc.nemspara/role.ufsutils/ufs_utils/grib_util/NCEPLIBS-grib_util/exec/bin/copygb2 export CNVGRIB=/apps/cnvgrib/1.4.0/bin/cnvgrib -export HOMEreg=/lfs4/HFIP/emcda/George.Gayno/reg_tests/ice_blend +export HOMEreg=/lfs4/HFIP/hfv3gfs/emc.nemspara/role.ufsutils/ufs_utils/reg_tests/ice_blend + export HOMEgfs=$PWD/../.. rm -fr $DATA diff --git a/reg_tests/ice_blend/driver.orion.sh b/reg_tests/ice_blend/driver.orion.sh index 73d917ea2..cf8d559b7 100755 --- a/reg_tests/ice_blend/driver.orion.sh +++ b/reg_tests/ice_blend/driver.orion.sh @@ -43,13 +43,20 @@ export DATA="${DATA}/reg-tests/ice-blend" # Should not have to change anything below. #----------------------------------------------------------------------------- +export UPDATE_BASELINE="FALSE" +#export UPDATE_BASELINE="TRUE" + +if [ "$UPDATE_BASELINE" = "TRUE" ]; then + source ../get_hash.sh +fi + export WGRIB=/apps/contrib/NCEPLIBS/orion/utils/grib_util.v1.2.0/exec/wgrib export WGRIB2=/apps/contrib/NCEPLIBS/orion/utils/grib_util.v1.2.0/exec/wgrib2 export COPYGB=/apps/contrib/NCEPLIBS/lib/NCEPLIBS-grib_util/v1.1.1/exec/copygb export COPYGB2=/apps/contrib/NCEPLIBS/orion/utils/grib_util.v1.2.0/exec/copygb2 export CNVGRIB=/apps/contrib/NCEPLIBS/orion/utils/grib_util.v1.2.0/exec/cnvgrib -export HOMEreg=/work/noaa/da/ggayno/save/ufs_utils.git/reg_tests/ice_blend +export HOMEreg=/work/noaa/nems/role-nems/ufs_utils/reg_tests/ice_blend export HOMEgfs=$PWD/../.. rm -fr $DATA diff --git a/reg_tests/ice_blend/driver.s4.sh b/reg_tests/ice_blend/driver.s4.sh new file mode 100755 index 000000000..7aee14a02 --- /dev/null +++ b/reg_tests/ice_blend/driver.s4.sh @@ -0,0 +1,66 @@ +#!/bin/bash + +#----------------------------------------------------------------------------- +# +# Run ice_blend consistency test on S4. +# +# Set $DATA to your working directory. Set the project code (SBATCH -A) +# and queue (SBATCH -q) as appropriate. +# +# Invoke the script as follows: sbatch $script +# +# Log output is placed in consistency.log. A summary is +# placed in summary.log +# +# The test fails when its output does not match the baseline file +# as determined by the 'cmp' command. The baseline file is +# stored in HOMEreg. +# +#----------------------------------------------------------------------------- + +#SBATCH -J ice_blend +#SBATCH -A s4 +#SBATCH --open-mode=truncate +#SBATCH -o consistency.log +#SBATCH -e consistency.log +#SBATCH --ntasks=1 +#SBATCH -q s4 +#SBATCH -t 00:03:00 + +set -x + +compiler=${compiler:-"intel"} + +source ../../sorc/machine-setup.sh > /dev/null 2>&1 +module use ../../modulefiles +module load build.$target.$compiler +module list + +export DATA="${WORK_DIR:-/scratch/short/users/$LOGNAME}" +export DATA="${DATA}/reg-tests/ice-blend" + +#----------------------------------------------------------------------------- +# Should not have to change anything below. +#----------------------------------------------------------------------------- + +export UPDATE_BASELINE="FALSE" +#export UPDATE_BASELINE="TRUE" + +if [ "$UPDATE_BASELINE" = "TRUE" ]; then + source ../get_hash.sh +fi + +export WGRIB=/data/prod/hpc-stack/intel-2022.1/grib_util/1.2.2/bin/wgrib +export WGRIB2=/data/prod/hpc-stack/intel-2022.1/wgrib2/2.0.8/bin/wgrib2 +export COPYGB=/data/prod/hpc-stack/intel-2022.1/grib_util/1.2.2/bin/copygb +export COPYGB2=/data/prod/hpc-stack/intel-2022.1/grib_util/1.2.2/bin/copygb2 +export CNVGRIB=/data/prod/hpc-stack/intel-2022.1/grib_util/1.2.2/bin/cnvgrib + +export HOMEreg=/data/users/dhuber/save/nems/role.ufsutils/ufs_utils/reg_tests/ice_blend +export HOMEgfs=$PWD/../.. + +rm -fr $DATA + +./ice_blend.sh + +exit 0 diff --git a/reg_tests/ice_blend/driver.wcoss2.sh b/reg_tests/ice_blend/driver.wcoss2.sh new file mode 100755 index 000000000..3131dda72 --- /dev/null +++ b/reg_tests/ice_blend/driver.wcoss2.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +#----------------------------------------------------------------------------- +# +# Run ice_blend consistency test on WCOSS2. +# +# Set $DATA to your working directory. Set the project code (PBS -A) +# and queue (PBS -q) as appropriate. +# +# Invoke the script as follows: qsub $script +# +# Log output is placed in consistency.log. A summary is +# placed in summary.log +# +# The test fails when its output does not match the baseline file +# as determined by the 'cmp' command. The baseline file is +# stored in HOMEreg. +# +#----------------------------------------------------------------------------- + +#PBS -l walltime=00:02:00 +#PBS -o consistency.log +#PBS -e consistency.log +#PBS -N iceb_regt +#PBS -q dev +#PBS -A GFS-DEV +#PBS -l select=1:ncpus=1:mem=2500MB + +cd $PBS_O_WORKDIR + +source ../../sorc/machine-setup.sh > /dev/null 2>&1 +module use ../../modulefiles +module load build.$target.intel +module load grib_util/1.2.3 +module load wgrib2/2.0.8 +module list + +set -x + +export DATA="${WORK_DIR:-/lfs/h2/emc/stmp/$LOGNAME}" +export DATA="${DATA}/reg-tests/ice-blend" + +#----------------------------------------------------------------------------- +# Should not have to change anything below. +#----------------------------------------------------------------------------- + +export UPDATE_BASELINE="FALSE" +#export UPDATE_BASELINE="TRUE" + +if [ "$UPDATE_BASELINE" = "TRUE" ]; then + source ../get_hash.sh +fi + +export HOMEreg=/lfs/h2/emc/nems/noscrub/emc.nems/UFS_UTILS/reg_tests/ice_blend +export HOMEgfs=$PBS_O_WORKDIR/../.. + +rm -fr $DATA + +./ice_blend.sh + +exit 0 diff --git a/reg_tests/ice_blend/driver.wcoss_cray.sh b/reg_tests/ice_blend/driver.wcoss_cray.sh deleted file mode 100755 index 7556b9b55..000000000 --- a/reg_tests/ice_blend/driver.wcoss_cray.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash - -#----------------------------------------------------------------------------- -# -# Run ice_blend consistency test on WCOSS-Cray. -# -# Set $DATA to your working directory. Set the project code (BSUB -P) -# and queue (BSUB -q) as appropriate. -# -# Invoke the script as follows: cat $script | bsub -# -# Log output is placed in consistency.log. A summary is -# placed in summary.log. -# -# The test fails when its output does not match the baseline file -# as determined by the 'cmp' command. The baseline file is -# stored in HOMEreg. -# -#----------------------------------------------------------------------------- - -#BSUB -W 0:02 -#BSUB -o consistency.log -#BSUB -e consistency.log -#BSUB -J iceb_regt -#BSUB -q debug -#BSUB -R "rusage[mem=2000]" -#BSUB -P GFS-DEV - -set -x - -source ../../sorc/machine-setup.sh > /dev/null 2>&1 -module use ../../modulefiles -module load build.$target.intel -module list - -export DATA="${WORK_DIR:-/gpfs/hps3/stmp/$LOGNAME}" -export DATA="${DATA}/reg-tests/ice-blend" - -#----------------------------------------------------------------------------- -# Should not have to change anything below. -#----------------------------------------------------------------------------- - -export WGRIB=/gpfs/hps/nco/ops/nwprod/grib_util.v1.0.5/exec/wgrib -export WGRIB2=/gpfs/hps/nco/ops/nwprod/grib_util.v1.0.5/exec/wgrib2 -export COPYGB2=/gpfs/hps/nco/ops/nwprod/grib_util.v1.0.5/exec/copygb2 -export COPYGB=/gpfs/hps/nco/ops/nwprod/grib_util.v1.0.5/exec/copygb -export CNVGRIB=/gpfs/hps/nco/ops/nwprod/grib_util.v1.0.5/exec/cnvgrib - -export HOMEreg=/gpfs/hps3/emc/global/noscrub/George.Gayno/ufs_utils.git/reg_tests/ice_blend -export HOMEgfs=$PWD/../.. - -rm -fr $DATA - -./ice_blend.sh - -exit 0 diff --git a/reg_tests/ice_blend/driver.wcoss_dell_p3.sh b/reg_tests/ice_blend/driver.wcoss_dell_p3.sh deleted file mode 100755 index 2d91a3417..000000000 --- a/reg_tests/ice_blend/driver.wcoss_dell_p3.sh +++ /dev/null @@ -1,56 +0,0 @@ -#!/bin/bash - -#----------------------------------------------------------------------------- -# -# Run ice_blend consistency test on WCOSS-Dell. -# -# Set $DATA to your working directory. Set the project code (BSUB -P) -# and queue (BSUB -q) as appropriate. -# -# Invoke the script as follows: cat $script | bsub -# -# Log output is placed in consistency.log. A summary is -# placed in summary.log -# -# The test fails when its output does not match the baseline file -# as determined by the 'cmp' command. The baseline file is -# stored in HOMEreg. -# -#----------------------------------------------------------------------------- - -#BSUB -W 0:02 -#BSUB -o consistency.log -#BSUB -e consistency.log -#BSUB -J iceb_regt -#BSUB -q debug -#BSUB -R "affinity[core(1)]" -#BSUB -P GFS-DEV - -source ../../sorc/machine-setup.sh > /dev/null 2>&1 -module use ../../modulefiles -module load build.$target.intel -module list - -set -x - -export DATA="${WORK_DIR:-/gpfs/dell1/stmp/$LOGNAME}" -export DATA="${DATA}/reg-tests/ice-blend" - -#----------------------------------------------------------------------------- -# Should not have to change anything below. -#----------------------------------------------------------------------------- - -export WGRIB="/gpfs/dell1/nco/ops/nwprod/grib_util.v1.1.1/exec/wgrib" -export WGRIB2="/gpfs/dell1/nco/ops/nwprod/grib_util.v1.1.1/exec/wgrib2" -export COPYGB2="/gpfs/dell1/nco/ops/nwprod/grib_util.v1.1.1/exec/copygb2" -export COPYGB="/gpfs/dell1/nco/ops/nwprod/grib_util.v1.1.1/exec/copygb" -export CNVGRIB="/gpfs/dell1/nco/ops/nwprod/grib_util.v1.1.1/exec/cnvgrib" - -export HOMEreg=/gpfs/dell2/emc/modeling/noscrub/George.Gayno/ufs_utils.git/reg_tests/ice_blend -export HOMEgfs=$PWD/../.. - -rm -fr $DATA - -./ice_blend.sh - -exit 0 diff --git a/reg_tests/ice_blend/ice_blend.sh b/reg_tests/ice_blend/ice_blend.sh index b1c193ca3..fcd90fa35 100755 --- a/reg_tests/ice_blend/ice_blend.sh +++ b/reg_tests/ice_blend/ice_blend.sh @@ -18,7 +18,7 @@ if [ $iret -ne 0 ]; then exit $iret fi -cmp ${DATA}/seaice.5min.blend $HOMEreg/baseline_data/seaice.5min.blend +cmp ${DATA}/seaice.5min.blend $HOMEreg/baseline_data/t1534/seaice.5min.blend iret=$? test_failed=0 if [ $iret -ne 0 ]; then @@ -32,6 +32,10 @@ if [ $test_failed -ne 0 ]; then echo "<<< ICE BLEND TEST FAILED. >>>" echo "*********************************" echo "<<< ICE BLEND TEST FAILED. >>>" > ./summary.log + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + cd $DATA + $HOMEgfs/reg_tests/update_baseline.sh $HOMEreg "t1534" $commit_num + fi else echo echo "*********************************" diff --git a/reg_tests/rt.sh b/reg_tests/rt.sh index 9630f178d..1bf12f987 100755 --- a/reg_tests/rt.sh +++ b/reg_tests/rt.sh @@ -1,4 +1,4 @@ -#!/bin/bash -l +#!/bin/bash ulimit -s unlimited @@ -16,7 +16,26 @@ cd ${WORK_DIR} rm -f reg_test_results.txt rm -rf UFS_UTILS -git clone --recursive https://github.com/NOAA-EMC/UFS_UTILS.git +git clone https://github.com/ufs-community/UFS_UTILS.git +rc=$? + +# Check to see if the clone was successful. Previously, it has +# failed due to lack of disk space. + +if [[ $rc == 0 ]] && [[ -d UFS_UTILS ]];then + echo "Clone Successful" +else + target=`hostname -s` + if [[ -d /lfs3 ]] ; then + target=Jet + elif [[ -d /lfs/h1 ]] ; then + target=WCOSS2 + elif [[ -d /scratch1 ]] ; then + target=Hera + fi + echo "Clone Failed" | mail -s "UFS_UTILS Consistency Tests failed on ${target}" ${MAILTO} +fi + cd UFS_UTILS source sorc/machine-setup.sh @@ -38,37 +57,49 @@ echo "Started on " `hostname -s` >> ${WORK_DIR}/reg_test_results.txt ./build_all.sh -if [[ $target == "wcoss_dell_p3" ]] || [[ $target == "wcoss_cray" ]]; then - prod_machine=`cat /etc/prod` - prod_letter=${prod_machine:0:1} - - this_machine=`hostname -s` - this_letter=${this_machine:0:1} - - # Mars (m), Venus (v) - if [[ "${this_letter}" == "${prod_letter}" ]]; then +if [[ $target == "wcoss2" ]]; then + this_machine=`cat /etc/cluster_name` + prod_machine=`grep primary /lfs/h1/ops/prod/config/prodmachinefile` + prod_machine=`echo ${prod_machine/primary:}` + if [[ "${this_machine}" == "${prod_machine}" ]]; then exit 0 fi fi -# Set machine_id variable for running link_fixdirs -if [[ $target == "wcoss_dell_p3" ]]; then - machine_id=dell - module load lsf/10.1 -elif [[ $target == "wcoss_cray" ]]; then - machine_id=cray - module load xt-lsfhpc/9.1.3 -else - machine_id=$target -fi +machine_id=$target cd fix ./link_fixdirs.sh emc $machine_id cd ../reg_tests +#if [[ $target == "orion" ]] || [[ $target == "jet" ]] || [[ $target == "hera" ]] || [[ $target == "wcoss2" ]] ; then +if [[ $target == "orion" ]] || [[ $target == "jet" ]] || [[ $target == "hera" ]] ; then + + cd cpld_gridgen + export ACCOUNT=$PROJECT_CODE + export STMP=$WORK_DIR/reg-tests + + ./rt.sh 2>/dev/null & + + set -x + + sleep_time=0 + while [ ! -f "summary.log" ]; do + sleep 10 + sleep_time=$((sleep_time+10)) + if (( sleep_time > TIMEOUT_LIMIT )); then + kill -9 %1 + mail -s "UFS_UTILS Consistency Tests timed out on ${target}" ${MAILTO} < ${WORK_DIR}/reg_test_results.txt + exit 1 + fi + done + cd .. + +fi + sleep_time=0 -for dir in global_cycle chgres_cube grid_gen; do +for dir in snow2mdl global_cycle chgres_cube grid_gen; do cd $dir ./driver.$target.sh # Wait for job to complete @@ -83,19 +114,12 @@ for dir in global_cycle chgres_cube grid_gen; do cd .. done -if [[ $target == "wcoss_dell_p3" ]]; then - module load lsf/10.1 -elif [[ $target == "wcoss_cray" ]]; then - module load xt-lsfhpc/9.1.3 -fi - - -for dir in snow2mdl ice_blend; do +for dir in weight_gen ice_blend; do cd $dir - if [[ $target == "hera" ]] || [[ $target == "jet" ]] || [[ $target == "orion" ]]; then + if [[ $target == "hera" ]] || [[ $target == "jet" ]] || [[ $target == "orion" ]] || [[ $target == "s4" ]] ; then sbatch -A ${PROJECT_CODE} ./driver.$target.sh - elif [[ $target == "wcoss_dell_p3" ]] || [[ $target == "wcoss_cray" ]]; then - cat ./driver.$target.sh | bsub -P ${PROJECT_CODE} + elif [[ $target == "wcoss2" ]] ; then + qsub -v WORK_DIR ./driver.$target.sh fi # Wait for job to complete @@ -115,8 +139,8 @@ done echo "Commit hash: ${current_hash}" >> ${WORK_DIR}/reg_test_results.txt echo "" >> ${WORK_DIR}/reg_test_results.txt -for dir in chgres_cube grid_gen global_cycle ice_blend snow2mdl; do - success=true +success=true +for dir in weight_gen cpld_gridgen chgres_cube grid_gen global_cycle ice_blend snow2mdl; do if grep -qi "FAILED" ${dir}/summary.log; then success=false echo "${dir} consistency tests FAILED" >> ${WORK_DIR}/reg_test_results.txt diff --git a/reg_tests/snow2mdl/driver.hera.sh b/reg_tests/snow2mdl/driver.hera.sh index 9885f0ac9..bc80942d8 100755 --- a/reg_tests/snow2mdl/driver.hera.sh +++ b/reg_tests/snow2mdl/driver.hera.sh @@ -2,12 +2,12 @@ #----------------------------------------------------------------------------- # -# Run snow2mdl consistency test on Hera. +# Run snow2mdl consistency tests on Hera. # -# Set $DATA to your working directory. Set the project code (SBATCH -A) +# Set $DATA_ROOT to your working directory. Set the project code (SBATCH -A) # and queue (SBATCH -q) as appropriate. # -# Invoke the script as follows: sbatch $script +# Invoke the script from the command line as follows: ./$script # # Log output is placed in consistency.log. A summary is # placed in summary.log @@ -18,15 +18,6 @@ # #----------------------------------------------------------------------------- -#SBATCH -J snow -#SBATCH -A fv3-cpu -#SBATCH --open-mode=truncate -#SBATCH -o consistency.log -#SBATCH -e consistency.log -#SBATCH --ntasks=1 -#SBATCH -q debug -#SBATCH -t 00:03:00 - set -x compiler=${compiler:-"intel"} @@ -36,20 +27,48 @@ module use ../../modulefiles module load build.$target.$compiler module list -export DATA="${WORK_DIR:-/scratch2/NCEPDEV/stmp1/$LOGNAME}" -export DATA="${DATA}/reg-tests/snow2mdl" +DATA_ROOT="${WORK_DIR:-/scratch2/NCEPDEV/stmp1/$LOGNAME}" +DATA_ROOT="${DATA_ROOT}/reg-tests/snow2mdl" + +rm -fr $DATA_ROOT + +PROJECT_CODE="${PROJECT_CODE:-fv3-cpu}" +QUEUE="${QUEUE:-batch}" #----------------------------------------------------------------------------- # Should not have to change anything below. #----------------------------------------------------------------------------- -rm -fr $DATA +export UPDATE_BASELINE="FALSE" +#export UPDATE_BASELINE="TRUE" -export HOMEreg=/scratch1/NCEPDEV/da/George.Gayno/noscrub/reg_tests/snow2mdl +if [ "$UPDATE_BASELINE" = "TRUE" ]; then + source ../get_hash.sh +fi + +export HOMEreg=/scratch1/NCEPDEV/nems/role.ufsutils/ufs_utils/reg_tests/snow2mdl export HOMEgfs=$PWD/../.. export WGRIB=/scratch2/NCEPDEV/nwprod/NCEPLIBS/utils/grib_util.v1.1.1/exec/wgrib export WGRIB2=/scratch2/NCEPDEV/nwprod/NCEPLIBS/utils/grib_util.v1.1.1/exec/wgrib2 -./snow2mdl.sh +# The first test mimics GFS OPS. + +export DATA="${DATA_ROOT}/test.ops" +TEST1=$(sbatch --parsable -J snow.ops -A ${PROJECT_CODE} -o consistency.log -e consistency.log \ + --ntasks=1 -q ${QUEUE} -t 00:03:00 ./snow2mdl.ops.sh) + +# The second test is for the new AFWA global GRIB2 data. + +export DATA="${DATA_ROOT}/test.global" +TEST2=$(sbatch --parsable -J snow.global -A ${PROJECT_CODE} -o consistency.log -e consistency.log \ + --ntasks=1 -q ${QUEUE} -t 00:03:00 -d afterok:$TEST1 ./snow2mdl.global.sh) + +# Create summary file. + +sbatch --nodes=1 -t 0:01:00 -A ${PROJECT_CODE} -J snow_summary -o consistency.log -e consistency.log \ + --open-mode=append -q ${QUEUE} -d afterok:$TEST2 << EOF +#!/bin/bash +grep -a '<<<' consistency.log > summary.log +EOF exit 0 diff --git a/reg_tests/snow2mdl/driver.jet.sh b/reg_tests/snow2mdl/driver.jet.sh index 2b8345b97..62bd63664 100755 --- a/reg_tests/snow2mdl/driver.jet.sh +++ b/reg_tests/snow2mdl/driver.jet.sh @@ -2,12 +2,12 @@ #----------------------------------------------------------------------------- # -# Run snow2mdl consistency test on Jet. +# Run snow2mdl consistency tests on Jet. # -# Set $DATA to your working directory. Set the project code (SBATCH -A) -# and queue (SBATCH -q) as appropriate. +# Set $DATA_ROOT to your working directory. Set the project code and +# and queue as appropriate. # -# Invoke the script as follows: sbatch $script +# Invoke the script as follows: ./$script # # Log output is placed in consistency.log. A summary is # placed in summary.log @@ -18,35 +18,59 @@ # #----------------------------------------------------------------------------- -#SBATCH --nodes=1 -#SBATCH --partition=sjet -#SBATCH --time 0:01 -#SBATCH --account=emcda -#SBATCH --job-name=snow2mdl -#SBATCH -o consistency.log -#SBATCH -e consistency.log set -x source ../../sorc/machine-setup.sh > /dev/null 2>&1 module use ../../modulefiles module load build.$target.intel +module load gnu/9.2.0 +module load wgrib2/3.1.1_ncep +set +x module list +set -x + +DATA_ROOT="${WORK_DIR:-/lfs4/HFIP/emcda/$LOGNAME/stmp}" +DATA_ROOT="${DATA_ROOT}/reg-tests/snow2mdl" -export DATA="${WORK_DIR:-/lfs4/HFIP/emcda/$LOGNAME/stmp}" -export DATA="${DATA}/reg-tests/snow2mdl" +PROJECT_CODE="${PROJECT_CODE:-hfv3gfs}" +QUEUE="${QUEUE:-batch}" #----------------------------------------------------------------------------- # Should not have to change anything below. #----------------------------------------------------------------------------- -export HOMEreg=/lfs4/HFIP/emcda/George.Gayno/reg_tests/snow2mdl +export UPDATE_BASELINE="FALSE" +#export UPDATE_BASELINE="TRUE" + +if [ "$UPDATE_BASELINE" = "TRUE" ]; then + source ../get_hash.sh +fi + +export HOMEreg=/lfs4/HFIP/hfv3gfs/emc.nemspara/role.ufsutils/ufs_utils/reg_tests/snow2mdl export HOMEgfs=$PWD/../.. export WGRIB=/apps/wgrib/1.8.1.0b/bin/wgrib -export WGRIB2=/apps/wgrib2/0.1.9.6a/bin/wgrib2 +export WGRIB2=${WGRIB2_ROOT}/bin/wgrib2 + +rm -fr $DATA_ROOT -rm -fr $DATA +# This tests the OPS GFS snow processing. -./snow2mdl.sh +export DATA="${DATA_ROOT}/test.ops" +TEST1=$(sbatch --parsable --nodes=1 --partition=xjet --time 0:02 -J snow.ops -o consistency.log \ + -e consistency.log -A $PROJECT_CODE -q $QUEUE ./snow2mdl.ops.sh) +# Test the new global afwa grib2 data. + +export DATA="${DATA_ROOT}/test.global" +TEST2=$(sbatch --parsable --nodes=1 --partition=xjet --time 0:02 -J snow.global -o consistency.log \ + -e consistency.log -A $PROJECT_CODE -q $QUEUE -d afterok:$TEST1 ./snow2mdl.global.sh) + +# Create summary file. + +sbatch --nodes=1 --partition=xjet -t 0:01:00 -A $PROJECT_CODE -J snow.summary -o consistency.log \ + -e consistency.log --open-mode=append -q $QUEUE -d afterok:$TEST2 << EOF +#!/bin/bash +grep -a '<<<' consistency.log > summary.log +EOF exit 0 diff --git a/reg_tests/snow2mdl/driver.orion.sh b/reg_tests/snow2mdl/driver.orion.sh index e4c707eaa..4715557cb 100755 --- a/reg_tests/snow2mdl/driver.orion.sh +++ b/reg_tests/snow2mdl/driver.orion.sh @@ -2,31 +2,22 @@ #----------------------------------------------------------------------------- # -# Run snow2mdl consistency test on Orion. +# Run snow2mdl consistency tests on Orion. # -# Set $DATA to your working directory. Set the project code (SBATCH -A) -# and queue (SBATCH -q) as appropriate. +# Set $DATA_ROOT to your working directory. Set the project code +# and queue as appropriate. # -# Invoke the script as follows: sbatch $script +# Invoke the script as follows: ./$script # # Log output is placed in consistency.log. A summary is # placed in summary.log # # The test fails when its output does not match the baseline file -# as determined by the 'cmp' command. The baseline file is +# as determined by the 'cmp' command. The baseline files are # stored in HOMEreg. # #----------------------------------------------------------------------------- -#SBATCH -J snow -#SBATCH -A fv3-cpu -#SBATCH --open-mode=truncate -#SBATCH -o consistency.log -#SBATCH -e consistency.log -#SBATCH --ntasks=1 -#SBATCH -q debug -#SBATCH -t 00:03:00 - set -x source ../../sorc/machine-setup.sh > /dev/null 2>&1 @@ -36,20 +27,49 @@ module list ulimit -s unlimited -export DATA="${WORK_DIR:-/work/noaa/stmp/$LOGNAME}" -export DATA="${DATA}/reg-tests/snow2mdl" +export DATA_ROOT="${WORK_DIR:-/work/noaa/stmp/$LOGNAME}" +export DATA_ROOT="${DATA_ROOT}/reg-tests/snow2mdl" + +PROJECT_CODE="${PROJECT_CODE:-fv3-cpu}" +QUEUE="${QUEUE:-batch}" #----------------------------------------------------------------------------- # Should not have to change anything below. #----------------------------------------------------------------------------- -rm -fr $DATA +export UPDATE_BASELINE="FALSE" +#export UPDATE_BASELINE="TRUE" + +if [ "$UPDATE_BASELINE" = "TRUE" ]; then + source ../get_hash.sh +fi -export HOMEreg=/work/noaa/da/ggayno/save/ufs_utils.git/reg_tests/snow2mdl +rm -fr $DATA_ROOT + +export HOMEreg=/work/noaa/nems/role-nems/ufs_utils/reg_tests/snow2mdl export HOMEgfs=$PWD/../.. export WGRIB=/apps/contrib/NCEPLIBS/orion/utils/grib_util.v1.2.0/exec/wgrib export WGRIB2=/apps/contrib/NCEPLIBS/orion/utils/grib_util.v1.2.0/exec/wgrib2 -./snow2mdl.sh +# The first test mimics GFS OPS. + +export DATA="${DATA_ROOT}/test.ops" +TEST1=$(sbatch --parsable -J snow.ops -A $PROJECT_CODE -o consistency.log \ + -e consistency.log --ntasks=1 -q $QUEUE -t 00:03:00 ./snow2mdl.ops.sh) + +# This tests the afwa global grib2 data. + +export DATA="${DATA_ROOT}/test.global" +TEST2=$(sbatch --parsable -J snow.global -A $PROJECT_CODE -o consistency.log \ + -e consistency.log --ntasks=1 -q $QUEUE -t 00:03:00 --open-mode=append \ + -d afterok:$TEST1 ./snow2mdl.global.sh) + +# Create the summary file. + +sbatch --ntasks=1 -t 0:01:00 -A $PROJECT_CODE -J snow_summary -o consistency.log -e consistency.log \ + --open-mode=append -q $QUEUE -d afterok:$TEST2 << EOF +#!/bin/bash +grep -a '<<<' consistency.log > summary.log +EOF exit 0 diff --git a/reg_tests/snow2mdl/driver.s4.sh b/reg_tests/snow2mdl/driver.s4.sh new file mode 100755 index 000000000..608a19584 --- /dev/null +++ b/reg_tests/snow2mdl/driver.s4.sh @@ -0,0 +1,72 @@ +#!/bin/bash + +#----------------------------------------------------------------------------- +# +# Run snow2mdl consistency test on S4. +# +# Set $DATA_ROOT to your working directory. Set the project code +# and queue as appropriate. +# +# Invoke the script as follows: ./$script +# +# Log output is placed in consistency.log. A summary is +# placed in summary.log +# +# The test fails when its output does not match the baseline file +# as determined by the 'cmp' command. The baseline file is +# stored in HOMEreg. +# +#----------------------------------------------------------------------------- + +set -x + +compiler=${compiler:-"intel"} + +source ../../sorc/machine-setup.sh > /dev/null 2>&1 +module use ../../modulefiles +module load build.$target.$compiler +module list + +DATA_ROOT="${WORK_DIR:-/scratch/short/users/$LOGNAME}" +DATA_ROOT="${DATA_ROOT}/reg-tests/snow2mdl" + +PROJECT_CODE="${PROJECT_CODE:-star}" +QUEUE="${QUEUE:-s4}" + +#----------------------------------------------------------------------------- +# Should not have to change anything below. +#----------------------------------------------------------------------------- + +export UPDATE_BASELINE="FALSE" +#export UPDATE_BASELINE="TRUE" + +if [ "$UPDATE_BASELINE" = "TRUE" ]; then + source ../get_hash.sh +fi + +export HOMEreg=/data/users/dhuber/save/nems/role.ufsutils/ufs_utils/reg_tests/snow2mdl +export HOMEgfs=$PWD/../.. +export WGRIB=/data/prod/hpc-stack/intel-2022.1/grib_util/1.2.2/bin/wgrib +export WGRIB2=/data/prod/hpc-stack/intel-2022.1/wgrib2/2.0.8/bin/wgrib2 + +# The first test mimics GFS OPS. + +export DATA="${DATA_ROOT}/test.ops" +TEST1=$(sbatch --parsable -J snow.ops -A ${PROJECT_CODE} -o consistency.log -e consistency.log \ + --ntasks=1 -q ${QUEUE} -t 00:03:00 ./snow2mdl.ops.sh) + +# The second test is for the new AFWA global GRIB2 data. + +export DATA="${DATA_ROOT}/test.global" +TEST2=$(sbatch --parsable -J snow.global -A ${PROJECT_CODE} -o consistency.log -e consistency.log \ + --ntasks=1 -q ${QUEUE} -t 00:03:00 -d afterok:$TEST1 ./snow2mdl.global.sh) + +# Create summary file. + +sbatch --nodes=1 -t 0:01:00 -A ${PROJECT_CODE} -J snow_summary -o consistency.log -e consistency.log \ + --open-mode=append -q ${QUEUE} -d afterok:$TEST2 << EOF +#!/bin/bash +grep -a '<<<' consistency.log > summary.log +EOF + +exit 0 diff --git a/reg_tests/snow2mdl/driver.wcoss2.sh b/reg_tests/snow2mdl/driver.wcoss2.sh new file mode 100755 index 000000000..2a1cf4f3e --- /dev/null +++ b/reg_tests/snow2mdl/driver.wcoss2.sh @@ -0,0 +1,82 @@ +#!/bin/bash + +#----------------------------------------------------------------------------- +# +# Run snow2mdl consistency tests on WCOSS2. +# +# Set $DATA_ROOT to your working directory. Set the project code +# and queue as appropriate. +# +# Invoke the script as follows: ./$script +# +# Log output is placed in consistency.log. A summary is +# placed in summary.log +# +# The test fails when its output does not match the baseline file +# as determined by the 'cmp' command. The baseline files are +# stored in HOMEreg. +# +#----------------------------------------------------------------------------- + +source ../../sorc/machine-setup.sh > /dev/null 2>&1 +module use ../../modulefiles +module load build.$target.intel +module load grib_util/1.2.2 +module load wgrib2/2.0.8 +module list + +set -x + +export DATA_ROOT="${WORK_DIR:-/lfs/h2/emc/stmp/$LOGNAME}" +export DATA_ROOT="${DATA_ROOT}/reg-tests/snow2mdl" + +PROJECT_CODE=${PROJECT_CODE:-"GFS-DEV"} +QUEUE=${QUEUE:-"dev"} + +#----------------------------------------------------------------------------- +# Should not have to change anything below. +#----------------------------------------------------------------------------- + +export UPDATE_BASELINE="FALSE" +#export UPDATE_BASELINE="TRUE" + +if [ "$UPDATE_BASELINE" = "TRUE" ]; then + source ../get_hash.sh +fi + +export HOMEreg=/lfs/h2/emc/nems/noscrub/emc.nems/UFS_UTILS/reg_tests/snow2mdl +export HOMEgfs=$PWD/../.. + +LOG_FILE=consistency.log +SUM_FILE=summary.log + +rm -fr $DATA_ROOT + +#----------------------------------------------------------------------------- +# Test GFS ops snow. +#----------------------------------------------------------------------------- + +export DATA=$DATA_ROOT/test.ops +TEST1=$(qsub -V -o $LOG_FILE -e $LOG_FILE -q $QUEUE -A $PROJECT_CODE -l select=1:ncpus=1:mem=2500MB \ + -N snow.ops -l walltime=00:03:00 $PWD/snow2mdl.ops.sh) + +#----------------------------------------------------------------------------- +# Test afwa global snow. +#----------------------------------------------------------------------------- + +export DATA=$DATA_ROOT/test.global +TEST2=$(qsub -V -o $LOG_FILE -e $LOG_FILE -q $QUEUE -A $PROJECT_CODE -l select=1:ncpus=1:mem=2500MB \ + -N snow.global -l walltime=00:03:00 -W depend=afterok:$TEST1 $PWD/snow2mdl.global.sh) + +#----------------------------------------------------------------------------- +# Create summary log. +#----------------------------------------------------------------------------- + +this_dir=$PWD +qsub -V -o ${LOG_FILE} -e ${LOG_FILE} -q $QUEUE -A $PROJECT_CODE -l walltime=00:01:00 \ + -N snow_summary -l select=1:ncpus=1:mem=100MB -W depend=afterok:$TEST2 << EOF +#!/bin/bash +cd ${this_dir} +grep -a '<<<' $LOG_FILE | grep -v echo > $SUM_FILE +EOF +exit 0 diff --git a/reg_tests/snow2mdl/driver.wcoss_cray.sh b/reg_tests/snow2mdl/driver.wcoss_cray.sh deleted file mode 100755 index 197ecb161..000000000 --- a/reg_tests/snow2mdl/driver.wcoss_cray.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/bin/bash - -#----------------------------------------------------------------------------- -# -# Run snow2mdl consistency test on WCOSS-Cray. -# -# Set $DATA to your working directory. Set the project code (BSUB -P) -# and queue (BSUB -q) as appropriate. -# -# Invoke the script as follows: cat $script | bsub -# -# Log output is placed in consistency.log. A summary is -# placed in summary.log -# -# The test fails when its output does not match the baseline file -# as determined by the 'cmp' command. The baseline file is -# stored in HOMEreg. -# -#----------------------------------------------------------------------------- - -#BSUB -W 0:02 -#BSUB -o consistency.log -#BSUB -e consistency.log -#BSUB -J s2m_regt -#BSUB -q debug -#BSUB -R "rusage[mem=2000]" -#BSUB -P GFS-DEV - -set -x - -source ../../sorc/machine-setup.sh > /dev/null 2>&1 -module use ../../modulefiles -module load build.$target.intel -module list - -export DATA="${WORK_DIR:-/gpfs/hps3/stmp/$LOGNAME}" -export DATA="${DATA}/reg-tests/snow2mdl" - -#----------------------------------------------------------------------------- -# Should not have to change anything below. -#----------------------------------------------------------------------------- - -export HOMEreg=/gpfs/hps3/emc/global/noscrub/George.Gayno/ufs_utils.git/reg_tests/snow2mdl -export HOMEgfs=$PWD/../.. -export WGRIB=/gpfs/hps/nco/ops/nwprod/grib_util.v1.0.2/exec/wgrib -export WGRIB2=/gpfs/hps/nco/ops/nwprod/grib_util.v1.0.2/exec/wgrib2 - -rm -fr $DATA - -./snow2mdl.sh - -exit 0 diff --git a/reg_tests/snow2mdl/driver.wcoss_dell_p3.sh b/reg_tests/snow2mdl/driver.wcoss_dell_p3.sh deleted file mode 100755 index 0f315d391..000000000 --- a/reg_tests/snow2mdl/driver.wcoss_dell_p3.sh +++ /dev/null @@ -1,52 +0,0 @@ -#!/bin/bash - -#----------------------------------------------------------------------------- -# -# Run snow2mdl consistency test on WCOSS-Dell. -# -# Set $DATA to your working directory. Set the project code (BSUB -P) -# and queue (BSUB -q) as appropriate. -# -# Invoke the script as follows: cat $script | bsub -# -# Log output is placed in consistency.log. A summary is -# placed in summary.log -# -# The test fails when its output does not match the baseline file -# as determined by the 'cmp' command. The baseline file is -# stored in HOMEreg. -# -#----------------------------------------------------------------------------- - -#BSUB -W 0:02 -#BSUB -o consistency.log -#BSUB -e consistency.log -#BSUB -J s2m_regt -#BSUB -q debug -#BSUB -R "affinity[core(1)]" -#BSUB -P GFS-DEV - -source ../../sorc/machine-setup.sh > /dev/null 2>&1 -module use ../../modulefiles -module load build.$target.intel -module list - -set -x - -export DATA="${WORK_DIR:-/gpfs/dell1/stmp/$LOGNAME}" -export DATA="${DATA}/reg-tests/snow2mdl" - -#----------------------------------------------------------------------------- -# Should not have to change anything below. -#----------------------------------------------------------------------------- - -export HOMEreg=/gpfs/dell2/emc/modeling/noscrub/George.Gayno/ufs_utils.git/reg_tests/snow2mdl -export HOMEgfs=$PWD/../.. -export WGRIB=/gpfs/dell1/nco/ops/nwprod/grib_util.v1.0.6/exec/wgrib -export WGRIB2=/gpfs/dell1/nco/ops/nwprod/grib_util.v1.0.6/exec/wgrib2 - -rm -fr $DATA - -./snow2mdl.sh - -exit 0 diff --git a/reg_tests/snow2mdl/snow2mdl.global.sh b/reg_tests/snow2mdl/snow2mdl.global.sh new file mode 100755 index 000000000..c31c0a476 --- /dev/null +++ b/reg_tests/snow2mdl/snow2mdl.global.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +#-------------------------------------------------------------------------- +# Create a snow file from afwa global data. This script is run from +# its machine-specific driver. +#-------------------------------------------------------------------------- + +set -x + +export IMS_FILE=$HOMEreg/input_data/imssnow96.afwa.global.grb +export AFWA_NH_FILE="" +export AFWA_SH_FILE="" +export AFWA_GLOBAL_FILE="$HOMEreg/input_data/afwa.global.grb2" + +export MODEL_LATITUDE_FILE=$HOMEgfs/fix/am/global_latitudes.t1534.3072.1536.grb +export MODEL_LONGITUDE_FILE=$HOMEgfs/fix/am/global_longitudes.t1534.3072.1536.grb +export MODEL_SLMASK_FILE=$HOMEgfs/fix/am/global_slmask.t1534.3072.1536.grb +export GFS_LONSPERLAT_FILE=$HOMEgfs/fix/am/global_lonsperlat.t1534.3072.1536.txt + +export OMP_NUM_THREADS=1 +export OUTPUT_GRIB2=.false. + +${HOMEgfs}/ush/emcsfc_snow.sh + +iret=$? +if [ $iret -ne 0 ]; then + set +x + echo "<<< SNOW2MDL GLOBAL TEST FAILED. <<<" + exit $iret +fi + +test_failed=0 + +cmp ${DATA}/snogrb_model $HOMEreg/baseline_data/t1534.global/snogrb_model +iret=$? +if [ $iret -ne 0 ]; then + test_failed=1 +fi + +set +x +if [ $test_failed -ne 0 ]; then + echo + echo "*********************************" + echo "<<< SNOW2MDL GLOBAL TEST FAILED. >>>" + echo "*********************************" + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + cd $DATA + $HOMEgfs/reg_tests/update_baseline.sh $HOMEreg "t1534.global" $commit_num + fi +else + echo + echo "*********************************" + echo "<<< SNOW2MDL GLOBAL TEST PASSED. >>>" + echo "*********************************" +fi + +exit diff --git a/reg_tests/snow2mdl/snow2mdl.sh b/reg_tests/snow2mdl/snow2mdl.ops.sh similarity index 52% rename from reg_tests/snow2mdl/snow2mdl.sh rename to reg_tests/snow2mdl/snow2mdl.ops.sh index 4acec05b8..8024b3215 100755 --- a/reg_tests/snow2mdl/snow2mdl.sh +++ b/reg_tests/snow2mdl/snow2mdl.ops.sh @@ -1,7 +1,7 @@ #!/bin/bash #-------------------------------------------------------------------------- -# Create a T1534 snow file. This script is run from its machine-specific +# Mimic GFS OPS. This script is run from its machine-specific # driver. #-------------------------------------------------------------------------- @@ -11,10 +11,10 @@ export IMS_FILE=$HOMEreg/input_data/imssnow96.grb export AFWA_NH_FILE=$HOMEreg/input_data/NPR.SNWN.SP.S1200.MESH16 export AFWA_SH_FILE=$HOMEreg/input_data/NPR.SNWS.SP.S1200.MESH16 -export MODEL_LATITUDE_FILE=$HOMEgfs/fix/fix_am/global_latitudes.t1534.3072.1536.grb -export MODEL_LONGITUDE_FILE=$HOMEgfs/fix/fix_am/global_longitudes.t1534.3072.1536.grb -export MODEL_SLMASK_FILE=$HOMEgfs/fix/fix_am/global_slmask.t1534.3072.1536.grb -export GFS_LONSPERLAT_FILE=$HOMEgfs/fix/fix_am/global_lonsperlat.t1534.3072.1536.txt +export MODEL_LATITUDE_FILE=$HOMEgfs/fix/am/global_latitudes.t1534.3072.1536.grb +export MODEL_LONGITUDE_FILE=$HOMEgfs/fix/am/global_longitudes.t1534.3072.1536.grb +export MODEL_SLMASK_FILE=$HOMEgfs/fix/am/global_slmask.t1534.3072.1536.grb +export GFS_LONSPERLAT_FILE=$HOMEgfs/fix/am/global_lonsperlat.t1534.3072.1536.txt export OMP_NUM_THREADS=1 export OUTPUT_GRIB2=.false. @@ -24,14 +24,13 @@ ${HOMEgfs}/ush/emcsfc_snow.sh iret=$? if [ $iret -ne 0 ]; then set +x - echo "<<< SNOW2MDL TEST FAILED. <<<" - echo "<<< SNOW2MDL TEST FAILED. <<<" > ./summary.log + echo "<<< SNOW2MDL OPS TEST FAILED. <<<" exit $iret fi test_failed=0 -cmp ${DATA}/snogrb_model $HOMEreg/baseline_data/snogrb_model +cmp ${DATA}/snogrb_model $HOMEreg/baseline_data/t1534.ops/snogrb_model iret=$? if [ $iret -ne 0 ]; then test_failed=1 @@ -41,15 +40,17 @@ set +x if [ $test_failed -ne 0 ]; then echo echo "*********************************" - echo "<<< SNOW2MDL TEST FAILED. >>>" + echo "<<< SNOW2MDL OPS TEST FAILED. >>>" echo "*********************************" - echo "<<< SNOW2MDL TEST FAILED. >>>" > ./summary.log + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + cd $DATA + $HOMEgfs/reg_tests/update_baseline.sh $HOMEreg "t1534.ops" $commit_num + fi else echo echo "*********************************" - echo "<<< SNOW2MDL TEST PASSED. >>>" + echo "<<< SNOW2MDL OPS TEST PASSED. >>>" echo "*********************************" - echo "<<< SNOW2MDL TEST PASSED. >>>" > ./summary.log fi exit diff --git a/reg_tests/update_baseline.sh b/reg_tests/update_baseline.sh new file mode 100755 index 000000000..d0cb329f6 --- /dev/null +++ b/reg_tests/update_baseline.sh @@ -0,0 +1,56 @@ +#!/bin/bash + +set -x + +HOMEreg=$1 +test_name=$2 +commit_num=$3 + +base_dir=$HOMEreg/baseline_data +base_dir_commit=${base_dir}/$test_name.$commit_num + +chmod 755 $base_dir + +if [ -d $base_dir_commit ];then + chmod 777 $base_dir_commit + if [ -d $base_dir_commit/fix_sfc ]; then + chmod 777 $base_dir_commit/fix_sfc + fi + rm -fr $base_dir_commit +fi + +mkdir -p $base_dir_commit + +for files in *.nc snogrb_model seaice.5min.blend +do + if [ -f $files ]; then + cp $files $base_dir_commit + chmod 444 $base_dir_commit/$files + fi +done + +# The grid_gen tests have a subdirectory for +# the surface climo fields. + +if [ -d ./fix_sfc ]; then + mkdir -p $base_dir_commit/fix_sfc + cd fix_sfc + for files in *.nc + do + if [ -f $files ]; then + cp $files $base_dir_commit/fix_sfc + chmod 444 $base_dir_commit/fix_sfc/$files + fi + done + chmod 555 $base_dir_commit/fix_sfc +fi + +chmod 555 $base_dir_commit +rm -f $base_dir/$test_name +cd $base_dir +ln -fs $test_name.$commit_num $test_name + +# move this to driver? +###chmod 555 $base_dir + +exit diff --git a/reg_tests/weight_gen/driver.hera.sh b/reg_tests/weight_gen/driver.hera.sh new file mode 100755 index 000000000..ae8131f38 --- /dev/null +++ b/reg_tests/weight_gen/driver.hera.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +#----------------------------------------------------------------------------- +# +# Run weight_gen consistency test on Hera. +# +# Set $DATA to your working directory. Set the project code (SBATCH -A) +# and queue (SBATCH -q) as appropriate. +# +# Invoke the script as follows: sbatch $script +# +# Log output is placed in consistency.log. A summary is +# placed in summary.log +# +# The test fails when its output does not match the baseline files +# as determined by the 'nccmp' command. The baseline file is +# stored in HOMEreg. +# +#----------------------------------------------------------------------------- + +#SBATCH -J weight_gen +#SBATCH -A fv3-cpu +#SBATCH --open-mode=truncate +#SBATCH -o consistency.log +#SBATCH -e consistency.log +#SBATCH --ntasks=1 +#SBATCH -q debug +#SBATCH -t 00:03:00 + +set -x + +compiler=${compiler:-"intel"} + +source ../../sorc/machine-setup.sh > /dev/null 2>&1 +module use ../../modulefiles +module load build.$target.$compiler +module list + +export DATA="${WORK_DIR:-/scratch2/NCEPDEV/stmp1/$LOGNAME}" +export DATA="${DATA}/reg-tests/weight_gen" + +#----------------------------------------------------------------------------- +# Should not have to change anything below. +#----------------------------------------------------------------------------- + +export UPDATE_BASELINE="FALSE" +#export UPDATE_BASELINE="TRUE" + +if [ "$UPDATE_BASELINE" = "TRUE" ]; then + source ../get_hash.sh +fi + +export HOMEreg=/scratch1/NCEPDEV/nems/role.ufsutils/ufs_utils/reg_tests/weight_gen +export HOMEufs=$PWD/../.. + +./weight_gen.sh + +exit 0 diff --git a/reg_tests/weight_gen/driver.jet.sh b/reg_tests/weight_gen/driver.jet.sh new file mode 100755 index 000000000..9fdee3eb8 --- /dev/null +++ b/reg_tests/weight_gen/driver.jet.sh @@ -0,0 +1,57 @@ +#!/bin/bash + +#----------------------------------------------------------------------------- +# +# Run weight_gen consistency test on Jet. +# +# Set $DATA to your working directory. Set the project code +# (SBATCH --account) as appropriate. +# +# Invoke the script as follows: sbatch $script +# +# Log output is placed in consistency.log. A summary is +# placed in summary.log +# +# The test fails when its output does not match the baseline files +# as determined by the 'nccmp' command. The baseline file is +# stored in HOMEreg. +# +#----------------------------------------------------------------------------- + +#SBATCH --nodes=1 +#SBATCH --partition=sjet +#SBATCH --time 0:01 +#SBATCH --account=emcda +#SBATCH --job-name=weight_gen +#SBATCH -o consistency.log +#SBATCH -e consistency.log + +set -x + +compiler=${compiler:-"intel"} + +source ../../sorc/machine-setup.sh > /dev/null 2>&1 +module use ../../modulefiles +module load build.$target.$compiler +module list + +export DATA="${WORK_DIR:-/lfs4/HFIP/emcda/$LOGNAME/stmp}" +export DATA="${DATA}/reg-tests/weight_gen" + +#----------------------------------------------------------------------------- +# Should not have to change anything below. +#----------------------------------------------------------------------------- + +export UPDATE_BASELINE="FALSE" +#export UPDATE_BASELINE="TRUE" + +if [ "$UPDATE_BASELINE" = "TRUE" ]; then + source ../get_hash.sh +fi + +export HOMEreg=/lfs4/HFIP/hfv3gfs/emc.nemspara/role.ufsutils/ufs_utils/reg_tests/weight_gen +export HOMEufs=$PWD/../.. + +./weight_gen.sh + +exit 0 diff --git a/reg_tests/weight_gen/driver.orion.sh b/reg_tests/weight_gen/driver.orion.sh new file mode 100755 index 000000000..43b6f0b92 --- /dev/null +++ b/reg_tests/weight_gen/driver.orion.sh @@ -0,0 +1,58 @@ +#!/bin/bash + +#----------------------------------------------------------------------------- +# +# Run weight_gen consistency test on Orion. +# +# Set $DATA to your working directory. Set the project code (SBATCH -A) +# and queue (SBATCH -q) as appropriate. +# +# Invoke the script as follows: sbatch $script +# +# Log output is placed in consistency.log. A summary is +# placed in summary.log +# +# The test fails when its output does not match the baseline files +# as determined by the 'nccmp' command. The baseline file is +# stored in HOMEreg. +# +#----------------------------------------------------------------------------- + +#SBATCH -J weight_gen +#SBATCH -A fv3-cpu +#SBATCH --open-mode=truncate +#SBATCH -o consistency.log +#SBATCH -e consistency.log +#SBATCH --ntasks=1 +#SBATCH -q debug +#SBATCH -t 00:03:00 + +set -x + +compiler=${compiler:-"intel"} + +source ../../sorc/machine-setup.sh > /dev/null 2>&1 +module use ../../modulefiles +module load build.$target.$compiler +module list + +export DATA="${WORK_DIR:-/work/noaa/stmp/$LOGNAME}" +export DATA="${DATA}/reg-tests/weight_gen" + +#----------------------------------------------------------------------------- +# Should not have to change anything below. +#----------------------------------------------------------------------------- + +export UPDATE_BASELINE="FALSE" +#export UPDATE_BASELINE="TRUE" + +if [ "$UPDATE_BASELINE" = "TRUE" ]; then + source ../get_hash.sh +fi + +export HOMEreg=/work/noaa/nems/role-nems/ufs_utils/reg_tests/weight_gen +export HOMEufs=$PWD/../.. + +./weight_gen.sh + +exit 0 diff --git a/reg_tests/weight_gen/driver.wcoss2.sh b/reg_tests/weight_gen/driver.wcoss2.sh new file mode 100755 index 000000000..584c0fea1 --- /dev/null +++ b/reg_tests/weight_gen/driver.wcoss2.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +#----------------------------------------------------------------------------- +# +# Run weight_gen consistency test on WCOSS2. +# +# Set $DATA to your working directory. Set the project code (PBS -A) +# and queue (PBS -q) as appropriate. +# +# Invoke the script as follows: qsub $script +# +# Log output is placed in consistency.log. A summary is +# placed in summary.log +# +# The test fails when its output does not match the baseline files +# as determined by the 'nccmp' command. The baseline file is +# stored in HOMEreg. +# +#----------------------------------------------------------------------------- + +#PBS -l walltime=00:02:00 +#PBS -o consistency.log +#PBS -e consistency.log +#PBS -N wgt_regt +#PBS -q debug +#PBS -A GFS-DEV +#PBS -l select=1:ncpus=1:mem=250MB + +set -x + +cd $PBS_O_WORKDIR + +compiler=${compiler:-"intel"} + +source ../../sorc/machine-setup.sh > /dev/null 2>&1 +module use ../../modulefiles +module load build.$target.$compiler +module list + +export DATA="${WORK_DIR:-/lfs/h2/emc/stmp/$LOGNAME}" +export DATA="${DATA}/reg-tests/weight_gen" + +#----------------------------------------------------------------------------- +# Should not have to change anything below. +#----------------------------------------------------------------------------- + +export UPDATE_BASELINE="FALSE" +#export UPDATE_BASELINE="TRUE" + +if [ "$UPDATE_BASELINE" = "TRUE" ]; then + source ../get_hash.sh +fi + +export HOMEreg=/lfs/h2/emc/nems/noscrub/emc.nems/UFS_UTILS/reg_tests/weight_gen +export HOMEufs=$PBS_O_WORKDIR/../.. + +export NCCMP=/lfs/h2/emc/global/noscrub/George.Gayno/util/nccmp/nccmp-1.8.5.0/src/nccmp + +./weight_gen.sh + +exit 0 diff --git a/reg_tests/weight_gen/weight_gen.sh b/reg_tests/weight_gen/weight_gen.sh new file mode 100755 index 000000000..8609e5845 --- /dev/null +++ b/reg_tests/weight_gen/weight_gen.sh @@ -0,0 +1,63 @@ +#!/bin/bash + +set -x + +#----------------------------------------------------------------------------- +# Run weight consistency test. This script called from its machine-specific +# driver script. +#----------------------------------------------------------------------------- + +rm -fr $DATA +mkdir -p $DATA +cd $DATA + +HOMEexec=$HOMEufs/exec +HOMEtest=$HOMEufs/reg_tests +HOMEtest_wg=$HOMEtest/weight_gen + +# Run executable +${HOMEexec}/weight_gen "C48" + +iret=$? +if [ $iret -ne 0 ]; then + set +x + echo "<<< WEIGHT_GEN TEST FAILED. >>>" + echo "<<< WEIGHT_GEN TEST FAILED. >>>" > $HOMEtest_wg/summary.log + exit $iret +fi + +NCCMP=${NCCMP:-$(which nccmp)} + +test_failed=0 +for files in *.nc +do + if [ -f $files ]; then + echo CHECK $files + $NCCMP -dmfqS $files $HOMEreg/baseline_data/C48/$files + iret=$? + if [ $iret -ne 0 ]; then + test_failed=1 + fi + fi +done + +set +x +if [ $test_failed -ne 0 ]; then + echo + echo "*********************************" + echo "<<< WEIGHT_GEN TEST FAILED. >>>" + echo "*********************************" + echo "<<< WEIGHT_GEN TEST FAILED. >>>" > $HOMEtest_wg/summary.log + if [ "$UPDATE_BASELINE" = "TRUE" ]; then + cd $DATA + $HOMEtest/update_baseline.sh $HOMEreg "C48" $commit_num + fi +else + echo + echo "*********************************" + echo "<<< WEIGHT_GEN TEST PASSED. >>>" + echo "*********************************" + echo "<<< WEIGHT_GEN TEST PASSED. >>>" > $HOMEtest_wg/summary.log +fi + +exit 0 diff --git a/scripts/exemcsfc_global_sfc_prep.sh b/scripts/exemcsfc_global_sfc_prep.sh index 7662402a9..bea65decb 100755 --- a/scripts/exemcsfc_global_sfc_prep.sh +++ b/scripts/exemcsfc_global_sfc_prep.sh @@ -72,7 +72,7 @@ RUN=${RUN:-"gfs"} export HOMEgfs=${HOMEgfs:-$NWROOT/gfs.${gfs_ver:?}} export USHgfs=${USHgfs:-$HOMEgfs/ush} export FIXgfs=${FIXgfs:-$HOMEgfs/fix} -FIXgfs_am=${FIXgfs_am:-$HOMEgfs/fix/fix_am} +FIXgfs_am=${FIXgfs_am:-$HOMEgfs/fix/am} export EXECgfs=${EXECgfs:-$HOMEgfs/exec} # output com directory. @@ -90,7 +90,7 @@ cd $DATA export SENDCOM=${SENDCOM:-"NO"} #----------------------------------------------------------------------- -# the "postmsg" and "err_exit" utilities are only used in ncep ops +# The "err_exit" utility is only used in ncep ops # when the "prod_util" module is loaded. #----------------------------------------------------------------------- @@ -134,10 +134,7 @@ export pgmout=${pgmout:-OUTPUT} # call utility script to create global ice blend data. #----------------------------------------------------------------------- -if test "$use_prod_util" = "true" ; then - msg="create blended ice data." - postmsg "$jlogfile" "$msg" -fi +echo "Create blended ice data." ${USHgfs}/emcsfc_ice_blend.sh rc=$? @@ -157,16 +154,10 @@ if ((rc != 0));then if test "$SENDCOM" = "YES" then if [ -s $BLENDED_ICE_FILE_m6hrs ]; then - msg="copy old ice blend file to current directory" - if test "$use_prod_util" = "true" ; then - postmsg "$jlogfile" "$msg" - fi + echo "Copy old ice blend file to current directory" cp $BLENDED_ICE_FILE_m6hrs $COMOUT/$BLENDED_ICE_FILE else - msg="FATAL ERROR: CURRENT AND 6-HR OLD ICE FILE MISSING" - if test "$use_prod_util" = "true" ; then - postmsg "$jlogfile" "$msg" - fi + echo "FATAL ERROR: CURRENT AND 6-HR OLD ICE FILE MISSING" if test "$use_prod_util" = "true" ; then err_exit else @@ -198,10 +189,7 @@ export GFS_LONSPERLAT_FILE=${LONSPERLAT:-$FIXgfs_am/global_lonsperlat.t${resolut export MODEL_SNOW_FILE=${FNSNOAJCAP:-${RUN}.${cycle}.snogrb_t${resolution}} export MODEL_SNOW_FILE_m6hrs=${FNSNOGJCAP:-${COMINgfs_m6hrs}/${RUN}.${cycle_m6hrs}.snogrb_t${resolution}} -if test "$use_prod_util" = "true" ; then - msg="create ${JCAP} snow data." - postmsg "$jlogfile" "$msg" -fi +echo "Create ${JCAP} snow data." ${USHgfs}/emcsfc_snow.sh rc=$? @@ -221,16 +209,10 @@ if ((rc != 0)); then if test "$SENDCOM" = "YES" then if [ -s $MODEL_SNOW_FILE_m6hrs ]; then - msg="COPY OLD ${JCAP} SNOW FILE TO CURRENT DIRECTORY" - if test "$use_prod_util" = "true" ; then - postmsg "$jlogfile" "$msg" - fi + echo "COPY OLD ${JCAP} SNOW FILE TO CURRENT DIRECTORY" cp $MODEL_SNOW_FILE_m6hrs $COMOUT/$MODEL_SNOW_FILE else - msg="FATAL ERROR: CURRENT AND 6-HR OLD ${JCAP} SNOW MISSING" - if test "$use_prod_util" = "true" ; then - postmsg "$jlogfile" "$msg" - fi + echo "FATAL ERROR: CURRENT AND 6-HR OLD ${JCAP} SNOW MISSING" if test "$use_prod_util" = "true" ; then err_exit else @@ -265,10 +247,7 @@ export GFS_LONSPERLAT_FILE=${LONSPERLAT_ENKF:-$FIXgfs_am/global_lonsperlat.t${re export MODEL_SNOW_FILE=${FNSNOAJCAP_ENKF:-${RUN}.${cycle}.snogrb_t${resolution}} export MODEL_SNOW_FILE_m6hrs=${FNSNOGJCAP_ENKF:-${COMINgfs_m6hrs}/${RUN}.${cycle_m6hrs}.snogrb_t${resolution}} -if test "$use_prod_util" = "true" ; then - msg="create enkf snow data." - postmsg "$jlogfile" "$msg" -fi +echo "Create enkf snow data." ${USHgfs}/emcsfc_snow.sh rc=$? @@ -282,16 +261,10 @@ if ((rc != 0)); then if test "$SENDCOM" = "YES" then if [ -s $MODEL_SNOW_FILE_m6hrs ]; then - msg="COPY OLD ENKF SNOW FILE TO CURRENT DIRECTORY" - if test "$use_prod_util" = "true" ; then - postmsg "$jlogfile" "$msg" - fi + echo "COPY OLD ENKF SNOW FILE TO CURRENT DIRECTORY" cp $MODEL_SNOW_FILE_m6hrs $COMOUT/$MODEL_SNOW_FILE else - msg="FATAL ERROR: CURRENT AND 6-HR OLD ENKF SNOW MISSING" - if test "$use_prod_util" = "true" ; then - postmsg "$jlogfile" "$msg" - fi + echo "FATAL ERROR: CURRENT AND 6-HR OLD ENKF SNOW MISSING" if test "$use_prod_util" = "true" ; then err_exit else diff --git a/sorc/CMakeLists.txt b/sorc/CMakeLists.txt index 282878ff5..f238e2f76 100644 --- a/sorc/CMakeLists.txt +++ b/sorc/CMakeLists.txt @@ -2,19 +2,47 @@ # UFS_UTILS project. # # George Gayno -add_subdirectory(emcsfc_ice_blend.fd) -add_subdirectory(emcsfc_snow2mdl.fd) -if (OpenMP_FOUND) - add_subdirectory(global_cycle.fd) - add_subdirectory(lsm_routines.fd) -else() - message(STATUS "OpenMP is required for global_cycle.fd and was NOT found, skipping ...") -endif() -add_subdirectory(fre-nctools.fd) -add_subdirectory(grid_tools.fd) -add_subdirectory(chgres_cube.fd) -add_subdirectory(orog_mask_tools.fd) -add_subdirectory(sfc_climo_gen.fd) -add_subdirectory(vcoord_gen.fd) -add_subdirectory(fvcom_tools.fd) -add_subdirectory(gblevents.fd) +if(ICEBLEND) + add_subdirectory(emcsfc_ice_blend.fd) +endif() +if(SNOW2MDL) + add_subdirectory(emcsfc_snow2mdl.fd) +endif() +if(GCYCLE) + if (OpenMP_Fortran_FOUND) + add_subdirectory(global_cycle.fd) + add_subdirectory(lsm_routines.fd) + else() + message(STATUS "OpenMP is required for global_cycle.fd and was NOT found, skipping ...") + endif() +endif() +if(FRENCTOOLS) + add_subdirectory(fre-nctools.fd) +endif() +if(GRIDTOOLS) + add_subdirectory(grid_tools.fd) +endif() +if(CHGRES) + add_subdirectory(chgres_cube.fd) +endif() +if(OROG_MASK_TOOLS) + add_subdirectory(orog_mask_tools.fd) +endif() +if(SFC_CLIMO_GEN) + add_subdirectory(sfc_climo_gen.fd) +endif() +if(VCOORD_GEN) + add_subdirectory(vcoord_gen.fd) +endif() +if(FVCOMTOOLS) + add_subdirectory(fvcom_tools.fd) +endif() +if(GBLEVENTS) + add_subdirectory(gblevents.fd) +endif() +if(CPLD_GRIDGEN) +add_subdirectory(cpld_gridgen.fd) +endif() +if(WEIGHT_GEN) + add_subdirectory(weight_gen.fd) +endif() diff --git a/sorc/chgres_cube.fd/CMakeLists.txt b/sorc/chgres_cube.fd/CMakeLists.txt index 6f66f1352..91124c1cc 100644 --- a/sorc/chgres_cube.fd/CMakeLists.txt +++ b/sorc/chgres_cube.fd/CMakeLists.txt @@ -1,16 +1,20 @@ # This is the CMake build file for the chgres_cube utility in the # UFS_UTILS package. # -# George Gayno, Mark Potts, Kyle Gerheiser +# George Gayno, Mark Potts, Kyle Gerheiser, Larissa Reames set(lib_src atmosphere.F90 + atmosphere_target_data.F90 grib2_util.F90 - input_data.F90 + atm_input_data.F90 + sfc_input_data.F90 + nst_input_data.F90 model_grid.F90 program_setup.F90 search_util.F90 static_data.F90 + surface_target_data.F90 surface.F90 thompson_mp_climo_data.F90 wam_climo_data.f90 @@ -20,11 +24,13 @@ set(lib_src set(exe_src chgres.F90) +add_subdirectory(msis2.1.fd) + if(CMAKE_Fortran_COMPILER_ID MATCHES "^(Intel)$") set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -r8 -assume byterecl") elseif(CMAKE_Fortran_COMPILER_ID MATCHES "^(GNU)$") set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -ffree-line-length-0 -fdefault-real-8") - + # Turn on this argument mismatch flag for gfortran10. if(CMAKE_Fortran_COMPILER_VERSION VERSION_GREATER_EQUAL 10) set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fallow-argument-mismatch") @@ -43,14 +49,16 @@ target_include_directories(chgres_cube_lib INTERFACE ${mod_dir}) target_link_libraries( chgres_cube_lib PUBLIC + g2::g2_d nemsio::nemsio sfcio::sfcio sigio::sigio bacio::bacio_4 + ip::ip_d sp::sp_d - w3nco::w3nco_d + w3emc::w3emc_d esmf - wgrib2::wgrib2 + msis2 MPI::MPI_Fortran NetCDF::NetCDF_Fortran) @@ -60,7 +68,7 @@ endif() target_link_libraries(${exe_name} PRIVATE chgres_cube_lib) -install(TARGETS ${exe_name} RUNTIME DESTINATION ${exec_dir}) +install(TARGETS ${exe_name}) # If doxygen documentation we enabled, build it. if(ENABLE_DOCS) diff --git a/sorc/chgres_cube.fd/atm_input_data.F90 b/sorc/chgres_cube.fd/atm_input_data.F90 new file mode 100644 index 000000000..50ccbef86 --- /dev/null +++ b/sorc/chgres_cube.fd/atm_input_data.F90 @@ -0,0 +1,3307 @@ +!> @file +!! @brief Read atmospheric data from GRIB2, NEMSIO and NetCDF files. +!! @author George Gayno NCEP/EMC + +!> Read atmospheric data on the input grid. +!! Supported formats include fv3 tiled 'restart' files, fv3 tiled +!! 'history' files, fv3 gaussian history files, spectral gfs +!! gaussian nemsio files, and spectral gfs sigio/sfcio files. +!! +!! Public variables are defined below: "input" indicates field +!! associated with the input grid. +!! +!! @author George Gayno NCEP/EMC + +module atm_input_data + use esmf + use netcdf + use nemsio_module + + use program_setup, only : data_dir_input_grid, & + atm_files_input_grid, & + grib2_file_input_grid, & + atm_core_files_input_grid, & + atm_tracer_files_input_grid, & + tracers_input, num_tracers_input, & + tracers, & + get_var_cond, & + external_model, & + read_from_input, & + input_type + use model_grid, only : input_grid, & + i_input, j_input, & + ip1_input, jp1_input, & + num_tiles_input_grid, & + latitude_input_grid, & + longitude_input_grid + use utilities, only : error_handler, & + netcdf_err, & + handle_grib_error, & + quicksort, & + dint2p +implicit none + + private + +! Fields associated with the atmospheric model. + + type(esmf_field), public :: dzdt_input_grid !< vert velocity + type(esmf_field) :: dpres_input_grid !< pressure thickness + type(esmf_field), public :: pres_input_grid !< 3-d pressure + type(esmf_field), public :: ps_input_grid !< surface pressure + type(esmf_field), public :: terrain_input_grid !< terrain height + type(esmf_field), public :: temp_input_grid !< temperature + + type(esmf_field), public :: u_input_grid !< u/v wind at grid + type(esmf_field), public :: v_input_grid !< box center + type(esmf_field), public :: xwind_input_grid !< x-component wind + type(esmf_field), public :: ywind_input_grid !< y-component wind + type(esmf_field), public :: zwind_input_grid !< z-component wind + type(esmf_field), allocatable, public :: tracers_input_grid(:) !< tracers + + integer, public :: lev_input !< number of atmospheric layers + integer, public :: levp1_input !< number of atmos layer interfaces + + character(len=50), private, allocatable :: slevs(:) !< The atmospheric levels in the GRIB2 input file. + + public :: read_input_atm_data + public :: cleanup_input_atm_data + public :: convert_winds_to_xyz + + contains + + !> Read input grid atmospheric data driver. +!! +!! @param[in] localpet ESMF local persistent execution thread +!! @author George Gayno NCEP/EMC + subroutine read_input_atm_data(localpet) + + implicit none + + integer, intent(in) :: localpet + +!------------------------------------------------------------------------------- +! Read the tiled 'warm' restart files. +!------------------------------------------------------------------------------- + + if (trim(input_type) == "restart") then + + call read_input_atm_restart_file(localpet) + +!------------------------------------------------------------------------------- +! Read the gaussian history files in netcdf format. +!------------------------------------------------------------------------------- + + elseif (trim(input_type) == "gaussian_netcdf") then + + call read_input_atm_gaussian_netcdf_file(localpet) + +!------------------------------------------------------------------------------- +! Read the tiled history files in netcdf format. +!------------------------------------------------------------------------------- + + elseif (trim(input_type) == "history") then + + call read_input_atm_tiled_history_file(localpet) + +!------------------------------------------------------------------------------- +! Read the gaussian history files in nemsio format. +!------------------------------------------------------------------------------- + + elseif (trim(input_type) == "gaussian_nemsio") then ! fv3gfs gaussian nemsio + + call read_input_atm_gaussian_nemsio_file(localpet) + +!------------------------------------------------------------------------------- +! Read the spectral gfs gaussian history files in nemsio format. +!------------------------------------------------------------------------------- + + elseif (trim(input_type) == "gfs_gaussian_nemsio") then ! spectral gfs gaussian + ! nemsio. + call read_input_atm_gfs_gaussian_nemsio_file(localpet) + +!------------------------------------------------------------------------------- +! Read the spectral gfs gaussian history files in sigio format. +!------------------------------------------------------------------------------- + + elseif (trim(input_type) == "gfs_sigio") then ! spectral gfs sigio format. + + call read_input_atm_gfs_sigio_file(localpet) + +!------------------------------------------------------------------------------- +! Read fv3gfs data in grib2 format. +!------------------------------------------------------------------------------- + + elseif (trim(input_type) == "grib2") then + + call read_input_atm_grib2_file(localpet) + + endif + + end subroutine read_input_atm_data + + +!> Create atmospheric esmf fields. +!! +!! @author George Gayno NCEP/EMC + subroutine init_atm_esmf_fields + + implicit none + + integer :: i, rc + + print*,"- INITIALIZE ATMOSPHERIC ESMF FIELDS." + + print*,"- CALL FieldCreate FOR INPUT GRID SURFACE PRESSURE." + ps_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID TERRAIN." + terrain_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID xwind." + xwind_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + ungriddedLBound=(/1/), & + ungriddedUBound=(/lev_input/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID ywind." + ywind_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + ungriddedLBound=(/1/), & + ungriddedUBound=(/lev_input/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID zwind." + zwind_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + ungriddedLBound=(/1/), & + ungriddedUBound=(/lev_input/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID TEMPERATURE." + temp_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + ungriddedLBound=(/1/), & + ungriddedUBound=(/lev_input/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + allocate(tracers_input_grid(num_tracers_input)) + + do i = 1, num_tracers_input + print*,"- CALL FieldCreate FOR INPUT GRID TRACER ", trim(tracers_input(i)) + tracers_input_grid(i) = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + ungriddedLBound=(/1/), & + ungriddedUBound=(/lev_input/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + enddo + + print*,"- CALL FieldCreate FOR INPUT GRID DZDT." + dzdt_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + ungriddedLBound=(/1/), & + ungriddedUBound=(/lev_input/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID U." + u_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + ungriddedLBound=(/1/), & + ungriddedUBound=(/lev_input/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID V." + v_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + ungriddedLBound=(/1/), & + ungriddedUBound=(/lev_input/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID PRESSURE." + pres_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + ungriddedLBound=(/1/), & + ungriddedUBound=(/lev_input/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + end subroutine init_atm_esmf_fields + +!> Read input atmospheric data from spectral gfs (old sigio format). +!! +!! @note Format used prior to July 19, 2017. +!! @param[in] localpet ESMF local persistent execution thread +!! @author George Gayno NCEP/EMC + subroutine read_input_atm_gfs_sigio_file(localpet) + + use sigio_module + + implicit none + + integer, intent(in) :: localpet + + character(len=300) :: the_file + + integer(sigio_intkind) :: iret + integer :: rc, i, j, k + integer :: clb(3), cub(3) + + real(esmf_kind_r8) :: ak, bk + real(esmf_kind_r8), allocatable :: dummy2d(:,:) + real(esmf_kind_r8), allocatable :: dummy3d(:,:,:) + real(esmf_kind_r8), allocatable :: dummy3d2(:,:,:) + real(esmf_kind_r8), pointer :: pptr(:,:,:), psptr(:,:) + real(esmf_kind_r8), allocatable :: pi(:,:,:) + + type(sigio_head) :: sighead + type(sigio_dbta) :: sigdata + + the_file = trim(data_dir_input_grid) // "/" // trim(atm_files_input_grid(1)) + + print*,"- ATMOSPHERIC DATA IN SIGIO FORMAT." + print*,"- OPEN AND READ: ", trim(the_file) + + call sigio_sropen(21, trim(the_file), iret) + if (iret /= 0) then + rc = iret + call error_handler("OPENING SPECTRAL GFS SIGIO FILE.", rc) + endif + call sigio_srhead(21, sighead, iret) + if (iret /= 0) then + rc = iret + call error_handler("READING SPECTRAL GFS SIGIO FILE.", rc) + endif + + lev_input = sighead%levs + levp1_input = lev_input + 1 + + if (num_tracers_input /= sighead%ntrac) then + call error_handler("WRONG NUMBER OF TRACERS EXPECTED.", 99) + endif + + if (sighead%idvt == 0 .or. sighead%idvt == 21) then + if (trim(tracers_input(1)) /= 'spfh' .or. & + trim(tracers_input(2)) /= 'o3mr' .or. & + trim(tracers_input(3)) /= 'clwmr') then + call error_handler("TRACERS SELECTED DO NOT MATCH FILE CONTENTS.", 99) + endif + else + print*,'- UNRECOGNIZED IDVT: ', sighead%idvt + call error_handler("UNRECOGNIZED IDVT", 99) + endif + +!--------------------------------------------------------------------------- +! Initialize esmf atmospheric fields. +!--------------------------------------------------------------------------- + + call init_atm_esmf_fields + + if (localpet == 0) then + allocate(dummy2d(i_input,j_input)) + allocate(dummy3d(i_input,j_input,lev_input)) + allocate(dummy3d2(i_input,j_input,lev_input)) + else + allocate(dummy2d(0,0)) + allocate(dummy3d(0,0,0)) + allocate(dummy3d2(0,0,0)) + endif + + if (localpet == 0) then + call sigio_aldbta(sighead, sigdata, iret) + if (iret /= 0) then + rc = iret + call error_handler("ALLOCATING SIGDATA.", rc) + endif + call sigio_srdbta(21, sighead, sigdata, iret) + if (iret /= 0) then + rc = iret + call error_handler("READING SIGDATA.", rc) + endif + call sptez(0,sighead%jcap,4,i_input, j_input, sigdata%ps, dummy2d, 1) + dummy2d = exp(dummy2d) * 1000.0 + print*,'surface pres ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR SURFACE PRESSURE." + call ESMF_FieldScatter(ps_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + call sptez(0,sighead%jcap,4,i_input, j_input, sigdata%hs, dummy2d, 1) + print*,'terrain ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR TERRAIN." + call ESMF_FieldScatter(terrain_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + do k = 1, num_tracers_input + + if (localpet == 0) then + call sptezm(0,sighead%jcap,4,i_input, j_input, lev_input, sigdata%q(:,:,k), dummy3d, 1) + print*,trim(tracers_input(k)),maxval(dummy3d),minval(dummy3d) + endif + + print*,"- CALL FieldScatter FOR INPUT ", trim(tracers_input(k)) + call ESMF_FieldScatter(tracers_input_grid(k), dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + enddo + + if (localpet == 0) then + call sptezm(0,sighead%jcap,4,i_input, j_input, lev_input, sigdata%t, dummy3d, 1) + print*,'temp ',maxval(dummy3d),minval(dummy3d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID TEMPERATURE." + call ESMF_FieldScatter(temp_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +!--------------------------------------------------------------------------- +! The spectral gfs files have omega, not vertical velocity. Set to +! zero for now. Convert from omega to vv in the future? +!--------------------------------------------------------------------------- + + if (localpet == 0) then + print*,"- NO VERTICAL VELOCITY RECORD. SET TO ZERO." + dummy3d = 0.0 + endif + + print*,"- CALL FieldScatter FOR INPUT DZDT." + call ESMF_FieldScatter(dzdt_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + call sptezmv(0, sighead%jcap, 4, i_input, j_input, lev_input, sigdata%d, sigdata%z, dummy3d, dummy3d2, 1) + print*,'u ',maxval(dummy3d),minval(dummy3d) + print*,'v ',maxval(dummy3d2),minval(dummy3d2) + endif + + print*,"- CALL FieldScatter FOR INPUT U-WIND." + call ESMF_FieldScatter(u_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + print*,"- CALL FieldScatter FOR INPUT V-WIND." + call ESMF_FieldScatter(v_input_grid, dummy3d2, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + deallocate(dummy2d, dummy3d, dummy3d2) + + if (localpet == 0) call sigio_axdbta(sigdata, iret) + + call sigio_sclose(21, iret) + +!--------------------------------------------------------------------------- +! Convert from 2-d to 3-d component winds. +!--------------------------------------------------------------------------- + + call convert_winds_to_xyz + +!--------------------------------------------------------------------------- +! Compute 3-d pressure from 'ak' and 'bk'. +!--------------------------------------------------------------------------- + + print*,"- COMPUTE 3-D PRESSURE." + + print*,"- CALL FieldGet FOR 3-D PRES." + nullify(pptr) + call ESMF_FieldGet(pres_input_grid, & + computationalLBound=clb, & + computationalUBound=cub, & + farrayPtr=pptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + print*,"- CALL FieldGet FOR SURFACE PRESSURE." + nullify(psptr) + call ESMF_FieldGet(ps_input_grid, & + farrayPtr=psptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + +!--------------------------------------------------------------------------- +! First, compute interface pressure. +!--------------------------------------------------------------------------- + + allocate(pi(clb(1):cub(1),clb(2):cub(2),1:levp1_input),stat=rc) + + do k=1,levp1_input + ak = sighead%vcoord(k,1) + bk = sighead%vcoord(k,2) + do i= clb(1), cub(1) + do j= clb(2), cub(2) + pi(i,j,k) = ak + bk*psptr(i,j) + enddo + enddo + enddo + + if (localpet == 0) then + print*,'pres int ',psptr(clb(1),clb(2)),pi(clb(1),clb(2),:) + endif + +!--------------------------------------------------------------------------- +! Now comput mid-layer pressure from interface pressure. +!--------------------------------------------------------------------------- + + do k=1,lev_input + do i= clb(1), cub(1) + do j= clb(2), cub(2) + pptr(i,j,k) = (pi(i,j,k)+pi(i,j,k+1))/2.0_esmf_kind_r8 + enddo + enddo + enddo + + deallocate(pi) + + if (localpet == 0) then + print*,'pres ',psptr(clb(1),clb(2)),pptr(clb(1),clb(2),:) + endif + + end subroutine read_input_atm_gfs_sigio_file + +!> Read input atmospheric data from spectral gfs (global gaussian in +!! nemsio format. Starting July 19, 2017). +!! +!! @param[in] localpet ESMF local persistent execution thread +!! @author George Gayno NCEP/EMC + subroutine read_input_atm_gfs_gaussian_nemsio_file(localpet) + + implicit none + + integer, intent(in) :: localpet + + character(len=300) :: the_file + character(len=20) :: vlevtyp, vname + + integer(nemsio_intkind) :: vlev, iret + integer :: i, j, k, n, rc + integer :: clb(3), cub(3) + + real(nemsio_realkind), allocatable :: vcoord(:,:,:) + real(nemsio_realkind), allocatable :: dummy(:) + real(esmf_kind_r8), allocatable :: dummy2d(:,:) + real(esmf_kind_r8), allocatable :: dummy3d(:,:,:) + real(esmf_kind_r8) :: ak, bk + real(esmf_kind_r8), allocatable :: pi(:,:,:) + real(esmf_kind_r8), pointer :: pptr(:,:,:), psptr(:,:) + + type(nemsio_gfile) :: gfile + + the_file = trim(data_dir_input_grid) // "/" // trim(atm_files_input_grid(1)) + + print*,"- READ ATMOS DATA FROM SPECTRAL GFS NEMSIO FILE: ", trim(the_file) + + print*,"- OPEN FILE." + call nemsio_open(gfile, the_file, "read", iret=iret) + if (iret /= 0) call error_handler("OPENING SPECTRAL GFS NEMSIO ATM FILE.", iret) + + print*,"- READ NUMBER OF VERTICAL LEVELS." + call nemsio_getfilehead(gfile, iret=iret, dimz=lev_input) + if (iret /= 0) call error_handler("READING NUMBER OF VERTICAL LEVLES.", iret) + + levp1_input = lev_input + 1 + + allocate(vcoord(levp1_input,3,2)) + + print*,"- READ VERTICAL COORDINATE INFO." + call nemsio_getfilehead(gfile, iret=iret, vcoord=vcoord) + if (iret /= 0) call error_handler("READING VERTICAL COORDINATE INFO.", iret) + +!--------------------------------------------------------------------------- +! Initialize esmf atmospheric fields. +!--------------------------------------------------------------------------- + + call init_atm_esmf_fields + + if (localpet == 0) then + allocate(dummy(i_input*j_input)) + allocate(dummy2d(i_input,j_input)) + allocate(dummy3d(i_input,j_input,lev_input)) + else + allocate(dummy(0)) + allocate(dummy2d(0,0)) + allocate(dummy3d(0,0,0)) + endif + +!----------------------------------------------------------------------- +! 3-d fields in gaussian files increment from bottom to model top. +! That is what is expected by this program, so no need to flip indices. +!----------------------------------------------------------------------- + + if (localpet == 0) then + print*,"- READ TEMPERATURE." + vname = "tmp" + vlevtyp = "mid layer" + do vlev = 1, lev_input + call nemsio_readrecv(gfile, vname, vlevtyp, vlev, dummy, 0, iret) + if (iret /= 0) call error_handler("READING TEMPERATURE RECORD.", iret) + dummy3d(:,:,vlev) = reshape(dummy, (/i_input,j_input/)) +! print*,'temp check after read ',vlev, dummy3d(1,1,vlev) + enddo + endif + + print*,"- CALL FieldScatter FOR INPUT GRID TEMPERATURE." + call ESMF_FieldScatter(temp_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + do n = 1, num_tracers_input + + if (localpet == 0) then + print*,"- READ ", trim(tracers_input(n)) + vname = trim(tracers_input(n)) + vlevtyp = "mid layer" + do vlev = 1, lev_input + call nemsio_readrecv(gfile, vname, vlevtyp, vlev, dummy, 0, iret) + if (iret /= 0) call error_handler("READING TRACER RECORD.", iret) +! print*,'tracer ',vlev, maxval(dummy),minval(dummy) + dummy3d(:,:,vlev) = reshape(dummy, (/i_input,j_input/)) + enddo + endif + + print*,"- CALL FieldScatter FOR INPUT ", trim(tracers_input(n)) + call ESMF_FieldScatter(tracers_input_grid(n), dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + enddo + + if (localpet == 0) then + print*,"- READ U-WINDS." + vname = "ugrd" + vlevtyp = "mid layer" + do vlev = 1, lev_input + call nemsio_readrecv(gfile, vname, vlevtyp, vlev, dummy, 0, iret) + if (iret /= 0) call error_handler("READING U-WIND RECORD.", iret) +! print*,'ugrd ',vlev, maxval(dummy),minval(dummy) + dummy3d(:,:,vlev) = reshape(dummy, (/i_input,j_input/)) + enddo + endif + + print*,"- CALL FieldScatter FOR INPUT U-WIND." + call ESMF_FieldScatter(u_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ V-WINDS." + vname = "vgrd" + vlevtyp = "mid layer" + do vlev = 1, lev_input + call nemsio_readrecv(gfile, vname, vlevtyp, vlev, dummy, 0, iret) + if (iret /= 0) call error_handler("READING V-WIND RECORD.", iret) +! print*,'vgrd ',vlev, maxval(dummy),minval(dummy) + dummy3d(:,:,vlev) = reshape(dummy, (/i_input,j_input/)) + enddo + endif + + print*,"- CALL FieldScatter FOR INPUT V-WIND." + call ESMF_FieldScatter(v_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +!--------------------------------------------------------------------------- +! The spectral gfs nemsio files do not have a vertical velocity or +! omega record. So set to zero for now. +!--------------------------------------------------------------------------- + + if (localpet == 0) then + print*,"- NO VERTICAL VELOCITY RECORD. SET TO ZERO." + dummy3d = 0.0 + endif + + print*,"- CALL FieldScatter FOR INPUT DZDT." + call ESMF_FieldScatter(dzdt_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ HGT." + vname = "hgt" + vlevtyp = "sfc" + vlev = 1 + call nemsio_readrecv(gfile, vname, vlevtyp, vlev, dummy, 0, iret) + if (iret /= 0) call error_handler("READING HGT RECORD.", iret) +! print*,'hgt ',vlev, maxval(dummy),minval(dummy) + dummy2d = reshape(dummy, (/i_input,j_input/)) + endif + + print*,"- CALL FieldScatter FOR TERRAIN." + call ESMF_FieldScatter(terrain_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ PRES." + vname = "pres" + vlevtyp = "sfc" + vlev = 1 + call nemsio_readrecv(gfile, vname, vlevtyp, vlev, dummy, 0, iret) + if (iret /= 0) call error_handler("READING PRES RECORD.", iret) +! print*,'pres ',vlev, maxval(dummy),minval(dummy) + dummy2d = reshape(dummy, (/i_input,j_input/)) + endif + + print*,"- CALL FieldScatter FOR SURFACE PRESSURE." + call ESMF_FieldScatter(ps_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + call nemsio_close(gfile) + + deallocate(dummy, dummy2d, dummy3d) + +!--------------------------------------------------------------------------- +! Convert from 2-d to 3-d component winds. +!--------------------------------------------------------------------------- + + call convert_winds_to_xyz + +!--------------------------------------------------------------------------- +! Compute 3-d pressure from 'ak' and 'bk'. +!--------------------------------------------------------------------------- + + print*,"- COMPUTE 3-D PRESSURE." + + print*,"- CALL FieldGet FOR 3-D PRES." + nullify(pptr) + call ESMF_FieldGet(pres_input_grid, & + computationalLBound=clb, & + computationalUBound=cub, & + farrayPtr=pptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + print*,"- CALL FieldGet FOR SURFACE PRESSURE." + nullify(psptr) + call ESMF_FieldGet(ps_input_grid, & + farrayPtr=psptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + +!--------------------------------------------------------------------------- +! First, compute interface pressure. +!--------------------------------------------------------------------------- + + allocate(pi(clb(1):cub(1),clb(2):cub(2),1:levp1_input)) + + do k=1,levp1_input + ak = vcoord(k,1,1) + bk = vcoord(k,2,1) + do i= clb(1), cub(1) + do j= clb(2), cub(2) + pi(i,j,k) = ak + bk*psptr(i,j) + enddo + enddo + enddo + + deallocate(vcoord) + +!--------------------------------------------------------------------------- +! Now comput mid-layer pressure from interface pressure. +!--------------------------------------------------------------------------- + + do k=1,lev_input + do i= clb(1), cub(1) + do j= clb(2), cub(2) + pptr(i,j,k) = (pi(i,j,k)+pi(i,j,k+1))/2.0 + enddo + enddo + enddo + + deallocate(pi) + + end subroutine read_input_atm_gfs_gaussian_nemsio_file + +!> Read input grid atmospheric fv3 gaussian nemsio files. +!! +!! @param[in] localpet ESMF local persistent execution thread +!! @author George Gayno NCEP/EMC + subroutine read_input_atm_gaussian_nemsio_file(localpet) + + implicit none + + integer, intent(in) :: localpet + + character(len=300) :: the_file + character(len=20) :: vlevtyp, vname + + integer :: i, j, k, n + integer :: rc, clb(3), cub(3) + integer(nemsio_intkind) :: vlev, iret + + real(nemsio_realkind), allocatable :: vcoord(:,:,:) + real(nemsio_realkind), allocatable :: dummy(:) + real(esmf_kind_r8), allocatable :: dummy2d(:,:) + real(esmf_kind_r8), allocatable :: dummy3d(:,:,:) + real(esmf_kind_r8), pointer :: presptr(:,:,:), psptr(:,:) + real(esmf_kind_r8), pointer :: dpresptr(:,:,:) + real(esmf_kind_r8), allocatable :: pres_interface(:) + + type(nemsio_gfile) :: gfile + + the_file = trim(data_dir_input_grid) // "/" // trim(atm_files_input_grid(1)) + + print*,"- READ ATMOS DATA FROM GAUSSIAN NEMSIO FILE: ", trim(the_file) + + print*,"- OPEN FILE." + call nemsio_open(gfile, the_file, "read", iret=iret) + if (iret /= 0) call error_handler("OPENING GAUSSIAN NEMSIO ATM FILE.", iret) + + print*,"- READ NUMBER OF VERTICAL LEVELS." + call nemsio_getfilehead(gfile, iret=iret, dimz=lev_input) + if (iret /= 0) call error_handler("READING NUMBER OF VERTICAL LEVLES.", iret) + + levp1_input = lev_input + 1 + + allocate(vcoord(levp1_input,3,2)) + + print*,"- READ VERTICAL COORDINATE INFO." + call nemsio_getfilehead(gfile, iret=iret, vcoord=vcoord) + if (iret /= 0) call error_handler("READING VERTICAL COORDINATE INFO.", iret) + +!--------------------------------------------------------------------------- +! Initialize esmf atmospheric fields. +!--------------------------------------------------------------------------- + + call init_atm_esmf_fields + + print*,"- CALL FieldCreate FOR INPUT DPRES." + dpres_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + ungriddedLBound=(/1/), & + ungriddedUBound=(/lev_input/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + if (localpet == 0) then + allocate(dummy(i_input*j_input)) + allocate(dummy2d(i_input,j_input)) + allocate(dummy3d(i_input,j_input,lev_input)) + else + allocate(dummy(0)) + allocate(dummy2d(0,0)) + allocate(dummy3d(0,0,0)) + endif + +!----------------------------------------------------------------------- +! 3-d fields in gaussian files increment from bottom to model top. +! That is what is expected by this program, so no need to flip indices. +!----------------------------------------------------------------------- + + if (localpet == 0) then + print*,"- READ TEMPERATURE." + vname = "tmp" + vlevtyp = "mid layer" + do vlev = 1, lev_input + call nemsio_readrecv(gfile, vname, vlevtyp, vlev, dummy, 0, iret) + if (iret /= 0) call error_handler("READING TEMPERATURE RECORD.", iret) + dummy3d(:,:,vlev) = reshape(dummy, (/i_input,j_input/)) + print*,'temp check after read ',vlev, dummy3d(1,1,vlev) + enddo + endif + + print*,"- CALL FieldScatter FOR INPUT GRID TEMPERATURE." + call ESMF_FieldScatter(temp_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + do n = 1, num_tracers_input + + if (localpet == 0) then + print*,"- READ ", trim(tracers_input(n)) + vname = trim(tracers_input(n)) + vlevtyp = "mid layer" + do vlev = 1, lev_input + call nemsio_readrecv(gfile, vname, vlevtyp, vlev, dummy, 0, iret) + if (iret /= 0) call error_handler("READING TRACER RECORD.", iret) + print*,'tracer ',vlev, maxval(dummy),minval(dummy) + dummy3d(:,:,vlev) = reshape(dummy, (/i_input,j_input/)) + enddo + endif + + print*,"- CALL FieldScatter FOR INPUT ", trim(tracers_input(n)) + call ESMF_FieldScatter(tracers_input_grid(n), dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + enddo + + if (localpet == 0) then + print*,"- READ U-WINDS." + vname = "ugrd" + vlevtyp = "mid layer" + do vlev = 1, lev_input + call nemsio_readrecv(gfile, vname, vlevtyp, vlev, dummy, 0, iret) + if (iret /= 0) call error_handler("READING U-WIND RECORD.", iret) + print*,'ugrd ',vlev, maxval(dummy),minval(dummy) + dummy3d(:,:,vlev) = reshape(dummy, (/i_input,j_input/)) + enddo + endif + + print*,"- CALL FieldScatter FOR INPUT U-WIND." + call ESMF_FieldScatter(u_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ V-WINDS." + vname = "vgrd" + vlevtyp = "mid layer" + do vlev = 1, lev_input + call nemsio_readrecv(gfile, vname, vlevtyp, vlev, dummy, 0, iret) + if (iret /= 0) call error_handler("READING V-WIND RECORD.", iret) + print*,'vgrd ',vlev, maxval(dummy),minval(dummy) + dummy3d(:,:,vlev) = reshape(dummy, (/i_input,j_input/)) + enddo + endif + + print*,"- CALL FieldScatter FOR INPUT V-WIND." + call ESMF_FieldScatter(v_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ DPRES." + vname = "dpres" + vlevtyp = "mid layer" + do vlev = 1, lev_input + call nemsio_readrecv(gfile, vname, vlevtyp, vlev, dummy, 0, iret) + if (iret /= 0) call error_handler("READING DPRES RECORD.", iret) + print*,'dpres ',vlev, maxval(dummy),minval(dummy) + dummy3d(:,:,vlev) = reshape(dummy, (/i_input,j_input/)) + enddo + endif + + print*,"- CALL FieldScatter FOR INPUT DPRES." + call ESMF_FieldScatter(dpres_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ DZDT." + vname = "dzdt" + vlevtyp = "mid layer" + do vlev = 1, lev_input + call nemsio_readrecv(gfile, vname, vlevtyp, vlev, dummy, 0, iret) + if (iret /= 0) call error_handler("READING DZDT RECORD.", iret) + print*,'dzdt ',vlev, maxval(dummy),minval(dummy) + dummy3d(:,:,vlev) = reshape(dummy, (/i_input,j_input/)) + enddo + endif + + print*,"- CALL FieldScatter FOR INPUT DZDT." + call ESMF_FieldScatter(dzdt_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ HGT." + vname = "hgt" + vlevtyp = "sfc" + vlev = 1 + call nemsio_readrecv(gfile, vname, vlevtyp, vlev, dummy, 0, iret) + if (iret /= 0) call error_handler("READING HGT RECORD.", iret) + print*,'hgt ',vlev, maxval(dummy),minval(dummy) + dummy2d = reshape(dummy, (/i_input,j_input/)) + endif + + print*,"- CALL FieldScatter FOR TERRAIN." + call ESMF_FieldScatter(terrain_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + call nemsio_close(gfile) + + deallocate(dummy, dummy2d, dummy3d) + +!--------------------------------------------------------------------------- +! Convert from 2-d to 3-d component winds. +!--------------------------------------------------------------------------- + + call convert_winds_to_xyz + +!--------------------------------------------------------------------------- +! Compute 3-d pressure. Mid-layer and surface pressure are computed +! from delta p. The surface pressure in the file is not used. After +! the model's write component interpolates from the cubed-sphere grid +! to the gaussian grid, the surface pressure is no longer consistent +! with the delta p (per Jun Wang). +!--------------------------------------------------------------------------- + + print*,"- COMPUTE 3-D PRESSURE." + + print*,"- CALL FieldGet FOR DELTA PRESSURE." + nullify(dpresptr) + call ESMF_FieldGet(dpres_input_grid, & + computationalLBound=clb, & + computationalUBound=cub, & + farrayPtr=dpresptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + print*,"- CALL FieldGet FOR 3-D PRESSURE." + nullify(presptr) + call ESMF_FieldGet(pres_input_grid, & + farrayPtr=presptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + print*,"- CALL FieldGet FOR SURFACE PRESSURE." + nullify(psptr) + call ESMF_FieldGet(ps_input_grid, & + farrayPtr=psptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + allocate(pres_interface(levp1_input)) + + if (localpet == 0) then + do k = clb(3), cub(3) + print*,'dpres is ',cub(1),cub(2),k, dpresptr(cub(1),cub(2),k) + enddo + endif + + do i = clb(1), cub(1) + do j = clb(2), cub(2) + pres_interface(levp1_input) = vcoord(levp1_input,1,1) + do k = lev_input, 1, -1 + pres_interface(k) = pres_interface(k+1) + dpresptr(i,j,k) + enddo + psptr(i,j) = pres_interface(1) + do k = 1, lev_input + presptr(i,j,k) = (pres_interface(k) + pres_interface(k+1)) / 2.0_8 + enddo + enddo + enddo + + deallocate(vcoord) + + if (localpet == 0) then + print*,'psfc is ',clb(1),clb(2),psptr(clb(1),clb(2)) + print*,'pres is ',clb(1),clb(2),presptr(clb(1),clb(2),:) + endif + + print*,'pres check 1',localpet,maxval(presptr(:,:,1)),minval(presptr(:,:,1)) + print*,'pres check lev',localpet,maxval(presptr(:,:,lev_input)),minval(presptr(:,:,lev_input)) + + deallocate(pres_interface) + + call ESMF_FieldDestroy(dpres_input_grid, rc=rc) + + end subroutine read_input_atm_gaussian_nemsio_file + +!> Read input grid fv3 atmospheric data 'warm' restart files. +!! +!! @note Routine reads tiled files in parallel. Tile 1 is read by +!! localpet 0; tile 2 by localpet 1, etc. The number of pets +!! must be equal to or greater than the number of tiled files. +!! Logic only tested with global input data of six tiles. +!! @param[in] localpet ESMF local persistent execution thread +!! @author George Gayno NCEP/EMC + subroutine read_input_atm_restart_file(localpet) + + implicit none + + integer, intent(in) :: localpet + + character(len=500) :: tilefile + + integer :: i, j, k + integer :: clb(3), cub(3) + integer :: rc, tile, ncid, id_var + integer :: error, id_dim + + real(esmf_kind_r8), allocatable :: ak(:) + real(esmf_kind_r8), pointer :: presptr(:,:,:), psptr(:,:) + real(esmf_kind_r8), pointer :: dpresptr(:,:,:) + real(esmf_kind_r8), allocatable :: data_one_tile(:,:) + real(esmf_kind_r8), allocatable :: data_one_tile_3d(:,:,:) + real(esmf_kind_r8), allocatable :: pres_interface(:) + +!--------------------------------------------------------------------------- +! Get number of vertical levels and model top pressure. +!--------------------------------------------------------------------------- + + tilefile = trim(data_dir_input_grid) // "/" // trim(atm_core_files_input_grid(7)) + print*,"- READ ATM VERTICAL LEVELS FROM: ", trim(tilefile) + error=nf90_open(trim(tilefile),nf90_nowrite,ncid) + call netcdf_err(error, 'opening: '//trim(tilefile) ) + + error=nf90_inq_dimid(ncid, 'xaxis_1', id_dim) + call netcdf_err(error, 'reading xaxis_1 id' ) + error=nf90_inquire_dimension(ncid,id_dim,len=levp1_input) + call netcdf_err(error, 'reading xaxis_1 value' ) + + lev_input = levp1_input - 1 + + allocate(ak(levp1_input)) + + error=nf90_inq_varid(ncid, 'ak', id_var) + call netcdf_err(error, 'reading field id' ) + error=nf90_get_var(ncid, id_var, ak) + call netcdf_err(error, 'reading ak' ) + + error = nf90_close(ncid) + +!--------------------------------------------------------------------------- +! Initialize esmf atmospheric fields. +!--------------------------------------------------------------------------- + + call init_atm_esmf_fields + + print*,"- CALL FieldCreate FOR INPUT GRID DELTA PRESSURE." + dpres_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + ungriddedLBound=(/1/), & + ungriddedUBound=(/lev_input/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + if (localpet < num_tiles_input_grid) then + allocate(data_one_tile_3d(i_input,j_input,lev_input)) + allocate(data_one_tile(i_input,j_input)) + else + allocate(data_one_tile_3d(0,0,0)) + allocate(data_one_tile(0,0)) + endif + + if (localpet < num_tiles_input_grid) then + tile = localpet+1 + tilefile= trim(data_dir_input_grid) // "/" // trim(atm_core_files_input_grid(tile)) + print*,"- READ ATMOSPHERIC CORE FILE: ", trim(tilefile) + error=nf90_open(trim(tilefile),nf90_nowrite,ncid) + call netcdf_err(error, 'opening: '//trim(tilefile) ) + endif + + if (localpet < num_tiles_input_grid) then + error=nf90_inq_varid(ncid, 'phis', id_var) + call netcdf_err(error, 'reading field id' ) + error=nf90_get_var(ncid, id_var, data_one_tile) + call netcdf_err(error, 'reading field' ) + data_one_tile = data_one_tile / 9.806_8 ! geopotential height + endif + + do tile = 1, num_tiles_input_grid + print*,"- CALL FieldScatter FOR INPUT GRID TERRAIN for tile ",tile + call ESMF_FieldScatter(terrain_input_grid, data_one_tile, rootpet=tile-1, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + enddo + + if (localpet < num_tiles_input_grid) then +!cggg when outputting warm restart files, use w. + error=nf90_inq_varid(ncid, 'W', id_var) + call netcdf_err(error, 'reading field id' ) + error=nf90_get_var(ncid, id_var, data_one_tile_3d) + call netcdf_err(error, 'reading field' ) + data_one_tile_3d(:,:,1:lev_input) = data_one_tile_3d(:,:,lev_input:1:-1) + +! Using 'w' from restart files has caused problems. Set to zero. +! data_one_tile_3d = 0.0_8 + endif + + do tile = 1, num_tiles_input_grid + print*,"- CALL FieldScatter FOR INPUT GRID VERTICAL VELOCITY for tile ",tile + call ESMF_FieldScatter(dzdt_input_grid, data_one_tile_3d, rootpet=tile-1, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + enddo + + if (localpet < num_tiles_input_grid) then + error=nf90_inq_varid(ncid, 'T', id_var) + call netcdf_err(error, 'reading field id' ) + error=nf90_get_var(ncid, id_var, data_one_tile_3d) + call netcdf_err(error, 'reading field' ) + data_one_tile_3d(:,:,1:lev_input) = data_one_tile_3d(:,:,lev_input:1:-1) + endif + + do tile = 1, num_tiles_input_grid + print*,"- CALL FieldScatter FOR INPUT GRID TEMPERATURE." + call ESMF_FieldScatter(temp_input_grid, data_one_tile_3d, rootpet=tile-1, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + enddo + + if (localpet < num_tiles_input_grid) then + error=nf90_inq_varid(ncid, 'delp', id_var) + call netcdf_err(error, 'reading field id' ) + error=nf90_get_var(ncid, id_var, data_one_tile_3d) + call netcdf_err(error, 'reading field' ) + data_one_tile_3d(:,:,1:lev_input) = data_one_tile_3d(:,:,lev_input:1:-1) + endif + + do tile = 1, num_tiles_input_grid + print*,"- CALL FieldScatter FOR INPUT DELTA PRESSURE." + call ESMF_FieldScatter(dpres_input_grid, data_one_tile_3d, rootpet=tile-1, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + enddo + + if (localpet < num_tiles_input_grid) then + error=nf90_inq_varid(ncid, 'ua', id_var) + call netcdf_err(error, 'reading field id' ) + error=nf90_get_var(ncid, id_var, data_one_tile_3d) + call netcdf_err(error, 'reading field' ) + data_one_tile_3d(:,:,1:lev_input) = data_one_tile_3d(:,:,lev_input:1:-1) + endif + + do tile = 1, num_tiles_input_grid + print*,"- CALL FieldScatter FOR INPUT GRID U." + call ESMF_FieldScatter(u_input_grid, data_one_tile_3d, rootpet=tile-1, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + enddo + + if (localpet < num_tiles_input_grid) then + error=nf90_inq_varid(ncid, 'va', id_var) + call netcdf_err(error, 'reading field id' ) + error=nf90_get_var(ncid, id_var, data_one_tile_3d) + call netcdf_err(error, 'reading field' ) + data_one_tile_3d(:,:,1:lev_input) = data_one_tile_3d(:,:,lev_input:1:-1) + endif + + do tile = 1, num_tiles_input_grid + print*,"- CALL FieldScatter FOR INPUT GRID V." + call ESMF_FieldScatter(v_input_grid, data_one_tile_3d, rootpet=tile-1, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + enddo + + if (localpet < num_tiles_input_grid) error = nf90_close(ncid) + + if (localpet < num_tiles_input_grid) then + tile = localpet+1 + tilefile= trim(data_dir_input_grid) // "/" // trim(atm_tracer_files_input_grid(tile)) + print*,"- READ ATMOSPHERIC TRACER FILE: ", trim(tilefile) + error=nf90_open(trim(tilefile),nf90_nowrite,ncid) + call netcdf_err(error, 'opening: '//trim(tilefile) ) + endif + + do i = 1, num_tracers_input + + if (localpet < num_tiles_input_grid) then + error=nf90_inq_varid(ncid, tracers_input(i), id_var) + call netcdf_err(error, 'reading field id' ) + error=nf90_get_var(ncid, id_var, data_one_tile_3d) + call netcdf_err(error, 'reading field' ) + data_one_tile_3d(:,:,1:lev_input) = data_one_tile_3d(:,:,lev_input:1:-1) + endif + + do tile = 1, num_tiles_input_grid + print*,"- CALL FieldScatter FOR INPUT ", trim(tracers_input(i)) + call ESMF_FieldScatter(tracers_input_grid(i), data_one_tile_3d, rootpet=tile-1, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + enddo + + enddo + + if (localpet < num_tiles_input_grid) error=nf90_close(ncid) + +!--------------------------------------------------------------------------- +! Convert from 2-d to 3-d cartesian winds. +!--------------------------------------------------------------------------- + + call convert_winds_to_xyz + +!--------------------------------------------------------------------------- +! Compute pressures +!--------------------------------------------------------------------------- + + print*,"- CALL FieldGet FOR SURFACE PRESSURE." + call ESMF_FieldGet(ps_input_grid, & + farrayPtr=psptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + print*,"- CALL FieldGet FOR PRESSURE." + call ESMF_FieldGet(pres_input_grid, & + computationalLBound=clb, & + computationalUBound=cub, & + farrayPtr=presptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + print*,"- CALL FieldGet FOR DELTA PRESSURE." + call ESMF_FieldGet(dpres_input_grid, & + farrayPtr=dpresptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + allocate(pres_interface(levp1_input)) + + do i = clb(1), cub(1) + do j = clb(2), cub(2) + pres_interface(levp1_input) = ak(1) ! model top in Pa + do k = (levp1_input-1), 1, -1 + pres_interface(k) = pres_interface(k+1) + dpresptr(i,j,k) + enddo + do k = 1, lev_input + presptr(i,j,k) = (pres_interface(k) + pres_interface(k+1)) / 2.0_8 + enddo + psptr(i,j) = pres_interface(1) + enddo + enddo + + deallocate(ak) + deallocate(pres_interface) + + call ESMF_FieldDestroy(dpres_input_grid, rc=rc) + + deallocate(data_one_tile_3d, data_one_tile) + + end subroutine read_input_atm_restart_file + +!> Read fv3 netcdf gaussian history file. Each task reads a horizontal +!! slice. +!! +!! @param[in] localpet ESMF local persistent execution thread +!! @author George Gayno NCEP/EMC + subroutine read_input_atm_gaussian_netcdf_file(localpet) + + use mpi + + implicit none + + integer, intent(in) :: localpet + + character(len=500) :: tilefile + + integer :: start(3), count(3), iscnt + integer :: error, ncid, num_tracers_file + integer :: id_dim, idim_input, jdim_input + integer :: id_var, rc, nprocs, max_procs + integer :: kdim, remainder, myrank, i, j, k, n + integer :: clb(3), cub(3) + integer, allocatable :: kcount(:), startk(:), displ(:) + integer, allocatable :: ircnt(:) + + real(esmf_kind_r8), allocatable :: phalf(:) + real(esmf_kind_r8), allocatable :: pres_interface(:) + real(kind=4), allocatable :: dummy3d(:,:,:) + real(kind=4), allocatable :: dummy3dall(:,:,:) + real(esmf_kind_r8), allocatable :: dummy3dflip(:,:,:) + real(esmf_kind_r8), allocatable :: dummy(:,:) + real(esmf_kind_r8), pointer :: presptr(:,:,:), dpresptr(:,:,:) + real(esmf_kind_r8), pointer :: psptr(:,:) + + print*,"- READ INPUT ATMOS DATA FROM GAUSSIAN NETCDF FILE." + + tilefile = trim(data_dir_input_grid) // "/" // trim(atm_files_input_grid(1)) + error=nf90_open(trim(tilefile),nf90_nowrite,ncid) + call netcdf_err(error, 'opening: '//trim(tilefile) ) + + error=nf90_inq_dimid(ncid, 'grid_xt', id_dim) + call netcdf_err(error, 'reading grid_xt id' ) + error=nf90_inquire_dimension(ncid,id_dim,len=idim_input) + call netcdf_err(error, 'reading grid_xt value' ) + + error=nf90_inq_dimid(ncid, 'grid_yt', id_dim) + call netcdf_err(error, 'reading grid_yt id' ) + error=nf90_inquire_dimension(ncid,id_dim,len=jdim_input) + call netcdf_err(error, 'reading grid_yt value' ) + + if (idim_input /= i_input .or. jdim_input /= j_input) then + call error_handler("DIMENSION MISMATCH BETWEEN SFC AND OROG FILES.", 2) + endif + + error=nf90_inq_dimid(ncid, 'pfull', id_dim) + call netcdf_err(error, 'reading pfull id' ) + error=nf90_inquire_dimension(ncid,id_dim,len=lev_input) + call netcdf_err(error, 'reading pfull value' ) + + error=nf90_inq_dimid(ncid, 'phalf', id_dim) + call netcdf_err(error, 'reading phalf id' ) + error=nf90_inquire_dimension(ncid,id_dim,len=levp1_input) + call netcdf_err(error, 'reading phalf value' ) + allocate(phalf(levp1_input)) + error=nf90_inq_varid(ncid, 'phalf', id_var) + call netcdf_err(error, 'getting phalf varid' ) + error=nf90_get_var(ncid, id_var, phalf) + call netcdf_err(error, 'reading phalf varid' ) + + error=nf90_get_att(ncid, nf90_global, 'ncnsto', num_tracers_file) + call netcdf_err(error, 'reading ntracer value' ) + + call mpi_comm_size(mpi_comm_world, nprocs, error) + print*,'- Running with ', nprocs, ' processors' + + call mpi_comm_rank(mpi_comm_world, myrank, error) + print*,'- myrank/localpet is ',myrank,localpet + + max_procs = nprocs + if (nprocs > lev_input) then + max_procs = lev_input + endif + + kdim = lev_input / max_procs + remainder = lev_input - (max_procs*kdim) + + allocate(kcount(0:nprocs-1)) + kcount=0 + allocate(startk(0:nprocs-1)) + startk=0 + allocate(displ(0:nprocs-1)) + displ=0 + allocate(ircnt(0:nprocs-1)) + ircnt=0 + + do k = 0, max_procs-2 + kcount(k) = kdim + enddo + kcount(max_procs-1) = kdim + remainder + + startk(0) = 1 + do k = 1, max_procs-1 + startk(k) = startk(k-1) + kcount(k-1) + enddo + + ircnt(:) = idim_input * jdim_input * kcount(:) + + displ(0) = 0 + do k = 1, max_procs-1 + displ(k) = displ(k-1) + ircnt(k-1) + enddo + + iscnt=idim_input*jdim_input*kcount(myrank) + +! Account for case if number of tasks exceeds the number of vert levels. + + if (myrank <= max_procs-1) then + allocate(dummy3d(idim_input,jdim_input,kcount(myrank))) + else + allocate(dummy3d(0,0,0)) + endif + + if (myrank == 0) then + allocate(dummy3dall(idim_input,jdim_input,lev_input)) + dummy3dall = 0.0 + allocate(dummy3dflip(idim_input,jdim_input,lev_input)) + dummy3dflip = 0.0 + allocate(dummy(idim_input,jdim_input)) + dummy = 0.0 + else + allocate(dummy3dall(0,0,0)) + allocate(dummy3dflip(0,0,0)) + allocate(dummy(0,0)) + endif + +!--------------------------------------------------------------------------- +! Initialize esmf atmospheric fields. +!--------------------------------------------------------------------------- + + call init_atm_esmf_fields + + print*,"- CALL FieldCreate FOR INPUT GRID DELTA PRESSURE." + dpres_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + ungriddedLBound=(/1/), & + ungriddedUBound=(/lev_input/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + +! Temperature + + if (myrank <= max_procs-1) then + start = (/1,1,startk(myrank)/) + count = (/idim_input,jdim_input,kcount(myrank)/) + error=nf90_inq_varid(ncid, 'tmp', id_var) + call netcdf_err(error, 'reading tmp field id' ) + error=nf90_get_var(ncid, id_var, dummy3d, start=start, count=count) + call netcdf_err(error, 'reading tmp field' ) + endif + + call mpi_gatherv(dummy3d, iscnt, mpi_real, & + dummy3dall, ircnt, displ, mpi_real, & + 0, mpi_comm_world, error) + if (error /= 0) call error_handler("IN mpi_gatherv of temperature", error) + + if (myrank == 0) then + dummy3dflip(:,:,1:lev_input) = dummy3dall(:,:,lev_input:1:-1) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID TEMPERATURE " + call ESMF_FieldScatter(temp_input_grid, dummy3dflip, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! dpres + + if (myrank <= max_procs-1) then + error=nf90_inq_varid(ncid, 'dpres', id_var) + call netcdf_err(error, 'reading dpres field id' ) + error=nf90_get_var(ncid, id_var, dummy3d, start=start, count=count) + call netcdf_err(error, 'reading dpres field' ) + endif + + call mpi_gatherv(dummy3d, iscnt, mpi_real, & + dummy3dall, ircnt, displ, mpi_real, & + 0, mpi_comm_world, error) + if (error /= 0) call error_handler("IN mpi_gatherv of dpres", error) + + if (myrank == 0) then + dummy3dflip(:,:,1:lev_input) = dummy3dall(:,:,lev_input:1:-1) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID DPRES " + call ESMF_FieldScatter(dpres_input_grid, dummy3dflip, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! ugrd + + if (myrank <= max_procs-1) then + error=nf90_inq_varid(ncid, 'ugrd', id_var) + call netcdf_err(error, 'reading ugrd field id' ) + error=nf90_get_var(ncid, id_var, dummy3d, start=start, count=count) + call netcdf_err(error, 'reading ugrd field' ) + endif + + call mpi_gatherv(dummy3d, iscnt, mpi_real, & + dummy3dall, ircnt, displ, mpi_real, & + 0, mpi_comm_world, error) + if (error /= 0) call error_handler("IN mpi_gatherv of ugrd", error) + + if (myrank == 0) then + dummy3dflip(:,:,1:lev_input) = dummy3dall(:,:,lev_input:1:-1) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID UGRD " + call ESMF_FieldScatter(u_input_grid, dummy3dflip, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! vgrd + + if (myrank <= max_procs-1) then + error=nf90_inq_varid(ncid, 'vgrd', id_var) + call netcdf_err(error, 'reading vgrd field id' ) + error=nf90_get_var(ncid, id_var, dummy3d, start=start, count=count) + call netcdf_err(error, 'reading vgrd field' ) + endif + + call mpi_gatherv(dummy3d, iscnt, mpi_real, & + dummy3dall, ircnt, displ, mpi_real, & + 0, mpi_comm_world, error) + if (error /= 0) call error_handler("IN mpi_gatherv of vgrd", error) + + if (myrank == 0) then + dummy3dflip(:,:,1:lev_input) = dummy3dall(:,:,lev_input:1:-1) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID VGRD " + call ESMF_FieldScatter(v_input_grid, dummy3dflip, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! tracers + + do n = 1, num_tracers_input + + if (myrank <= max_procs-1) then + error=nf90_inq_varid(ncid, tracers_input(n), id_var) + call netcdf_err(error, 'reading tracer field id' ) + error=nf90_get_var(ncid, id_var, dummy3d, start=start, count=count) + call netcdf_err(error, 'reading tracer field' ) + endif + + call mpi_gatherv(dummy3d, iscnt, mpi_real, & + dummy3dall, ircnt, displ, mpi_real, & + 0, mpi_comm_world, error) + if (error /= 0) call error_handler("IN mpi_gatherv of tracer", error) + + if (myrank == 0) then + dummy3dflip(:,:,1:lev_input) = dummy3dall(:,:,lev_input:1:-1) + where(dummy3dflip < 0.0) dummy3dflip = 0.0 + endif + + print*,"- CALL FieldScatter FOR INPUT GRID ", tracers_input(n) + call ESMF_FieldScatter(tracers_input_grid(n), dummy3dflip, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + enddo + +! dzdt set to zero for now. + + if (myrank == 0) then + dummy3dflip = 0.0 + endif + + print*,"- CALL FieldScatter FOR INPUT GRID DZDT" + call ESMF_FieldScatter(dzdt_input_grid, dummy3dflip, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + deallocate(dummy3dflip, dummy3dall, dummy3d) + +! terrain + + if (myrank==0) then + print*,"- READ TERRAIN." + error=nf90_inq_varid(ncid, 'hgtsfc', id_var) + call netcdf_err(error, 'reading hgtsfc field id' ) + error=nf90_get_var(ncid, id_var, dummy) + call netcdf_err(error, 'reading hgtsfc field' ) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID TERRAIN." + call ESMF_FieldScatter(terrain_input_grid, dummy, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! surface pressure + + if (myrank==0) then + print*,"- READ SURFACE P." + error=nf90_inq_varid(ncid, 'pressfc', id_var) + call netcdf_err(error, 'reading pressfc field id' ) + error=nf90_get_var(ncid, id_var, dummy) + call netcdf_err(error, 'reading pressfc field' ) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SURFACE P." + call ESMF_FieldScatter(ps_input_grid, dummy, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + deallocate(kcount, startk, displ, ircnt, dummy) + +!--------------------------------------------------------------------------- +! Convert from 2-d to 3-d cartesian winds. +!--------------------------------------------------------------------------- + + call convert_winds_to_xyz + +!--------------------------------------------------------------------------- +! Compute pressure. +!--------------------------------------------------------------------------- + + print*,"- CALL FieldGet FOR PRESSURE." + call ESMF_FieldGet(pres_input_grid, & + computationalLBound=clb, & + computationalUBound=cub, & + farrayPtr=presptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + print*,"- CALL FieldGet FOR DELTA PRESSURE." + call ESMF_FieldGet(dpres_input_grid, & + farrayPtr=dpresptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + print*,"- CALL FieldGet FOR SURFACE PRESSURE." + call ESMF_FieldGet(ps_input_grid, & + farrayPtr=psptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + allocate(pres_interface(levp1_input)) + +!--------------------------------------------------------------------------- +! Compute 3-d pressure. +!--------------------------------------------------------------------------- + +!--------------------------------------------------------------------------- +! When ingesting gaussian netcdf files, the mid-layer +! surface pressure are computed top down from delta-p +! The surface pressure in the file is not used. According +! to Jun Wang, after the model's write component interpolates from the +! cubed-sphere grid to the gaussian grid, the surface pressure is +! no longer consistent with the delta p. +!--------------------------------------------------------------------------- + + do i = clb(1), cub(1) + do j = clb(2), cub(2) + pres_interface(levp1_input) = phalf(1) * 100.0_8 + do k = lev_input, 1, -1 + pres_interface(k) = pres_interface(k+1) + dpresptr(i,j,k) + enddo + psptr(i,j) = pres_interface(1) + do k = 1, lev_input + presptr(i,j,k) = (pres_interface(k) + pres_interface(k+1)) / 2.0_8 + enddo + enddo + enddo + + deallocate(pres_interface, phalf) + + call ESMF_FieldDestroy(dpres_input_grid, rc=rc) + + end subroutine read_input_atm_gaussian_netcdf_file + +!> Read input grid fv3 atmospheric tiled history files in netcdf +!! format. +!! +!! @note Routine reads tiled files in parallel. Tile 1 is read by +!! localpet 0; tile 2 by localpet 1, etc. The number of pets +!! must be equal to or greater than the number of tiled files. +!! +!! @param[in] localpet ESMF local persistent execution thread +!! @author George Gayno NCEP/EMC + subroutine read_input_atm_tiled_history_file(localpet) + + use mpi + + implicit none + + integer, intent(in) :: localpet + + character(len=500) :: tilefile + + integer :: error, ncid, rc, tile + integer :: id_dim, idim_input, jdim_input + integer :: id_var, i, j, k, n + integer :: clb(3), cub(3), num_tracers_file + + real(esmf_kind_r8), allocatable :: data_one_tile(:,:) + real(esmf_kind_r8), allocatable :: data_one_tile_3d(:,:,:) + real(esmf_kind_r8), pointer :: presptr(:,:,:), dpresptr(:,:,:) + real(esmf_kind_r8), pointer :: psptr(:,:) + real(esmf_kind_r8), allocatable :: pres_interface(:), phalf(:) + + print*,"- READ INPUT ATMOS DATA FROM TILED HISTORY FILES." + + tilefile = trim(data_dir_input_grid) // "/" // trim(atm_files_input_grid(1)) + error=nf90_open(trim(tilefile),nf90_nowrite,ncid) + call netcdf_err(error, 'opening: '//trim(tilefile) ) + + error=nf90_inq_dimid(ncid, 'grid_xt', id_dim) + call netcdf_err(error, 'reading grid_xt id' ) + error=nf90_inquire_dimension(ncid,id_dim,len=idim_input) + call netcdf_err(error, 'reading grid_xt value' ) + + error=nf90_inq_dimid(ncid, 'grid_yt', id_dim) + call netcdf_err(error, 'reading grid_yt id' ) + error=nf90_inquire_dimension(ncid,id_dim,len=jdim_input) + call netcdf_err(error, 'reading grid_yt value' ) + + if (idim_input /= i_input .or. jdim_input /= j_input) then + call error_handler("DIMENSION MISMATCH BETWEEN SFC AND OROG FILES.", 2) + endif + + error=nf90_inq_dimid(ncid, 'pfull', id_dim) + call netcdf_err(error, 'reading pfull id' ) + error=nf90_inquire_dimension(ncid,id_dim,len=lev_input) + call netcdf_err(error, 'reading pfull value' ) + + error=nf90_inq_dimid(ncid, 'phalf', id_dim) + call netcdf_err(error, 'reading phalf id' ) + error=nf90_inquire_dimension(ncid,id_dim,len=levp1_input) + call netcdf_err(error, 'reading phalf value' ) + allocate(phalf(levp1_input)) + error=nf90_inq_varid(ncid, 'phalf', id_var) + call netcdf_err(error, 'getting phalf varid' ) + error=nf90_get_var(ncid, id_var, phalf) + call netcdf_err(error, 'reading phalf varid' ) + + error=nf90_get_att(ncid, nf90_global, 'ncnsto', num_tracers_file) + call netcdf_err(error, 'reading ntracer value' ) + + error = nf90_close(ncid) + + print*,'- FILE HAS ', num_tracers_file, ' TRACERS.' + print*,'- WILL PROCESS ', num_tracers_input, ' TRACERS.' + +!--------------------------------------------------------------------------- +! Initialize esmf atmospheric fields. +!--------------------------------------------------------------------------- + + call init_atm_esmf_fields + + print*,"- CALL FieldCreate FOR INPUT GRID DELTA PRESSURE." + dpres_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + ungriddedLBound=(/1/), & + ungriddedUBound=(/lev_input/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + if (localpet < num_tiles_input_grid) then + allocate(data_one_tile(i_input,j_input)) + allocate(data_one_tile_3d(i_input,j_input,lev_input)) + else + allocate(data_one_tile(0,0)) + allocate(data_one_tile_3d(0,0,0)) + endif + + if (localpet < num_tiles_input_grid) then + tile = localpet+1 + tilefile= trim(data_dir_input_grid) // "/" // trim(atm_files_input_grid(tile)) + print*,"- READ ATMOSPHERIC DATA FROM: ", trim(tilefile) + error=nf90_open(trim(tilefile),nf90_nowrite,ncid) + call netcdf_err(error, 'opening: '//trim(tilefile) ) + endif + + if (localpet < num_tiles_input_grid) then +! print*,"- READ VERTICAL VELOCITY." +! error=nf90_inq_varid(ncid, 'dzdt', id_var) +! call netcdf_err(error, 'reading field id' ) +! error=nf90_get_var(ncid, id_var, data_one_tile_3d) +! call netcdf_err(error, 'reading field' ) +! data_one_tile_3d(:,:,1:lev_input) = data_one_tile_3d(:,:,lev_input:1:-1) + +! Using w from the tiled history files has caused problems. +! Set to zero. + data_one_tile_3d = 0.0_8 + endif + + do tile = 1, num_tiles_input_grid + print*,"- CALL FieldScatter FOR INPUT GRID VERTICAL VELOCITY." + call ESMF_FieldScatter(dzdt_input_grid, data_one_tile_3d, rootpet=tile-1, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + enddo + + do n = 1, num_tracers_input + + if (localpet < num_tiles_input_grid) then + print*,"- READ ", trim(tracers_input(n)) + error=nf90_inq_varid(ncid, tracers_input(n), id_var) + call netcdf_err(error, 'reading field id' ) + error=nf90_get_var(ncid, id_var, data_one_tile_3d) + call netcdf_err(error, 'reading field' ) + data_one_tile_3d(:,:,1:lev_input) = data_one_tile_3d(:,:,lev_input:1:-1) + endif + + do tile = 1, num_tiles_input_grid + print*,"- CALL FieldScatter FOR INPUT GRID TRACER ", trim(tracers_input(n)) + call ESMF_FieldScatter(tracers_input_grid(n), data_one_tile_3d, rootpet=tile-1, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + enddo + + enddo + + if (localpet < num_tiles_input_grid) then + print*,"- READ TEMPERATURE." + error=nf90_inq_varid(ncid, 'tmp', id_var) + call netcdf_err(error, 'reading field id' ) + error=nf90_get_var(ncid, id_var, data_one_tile_3d) + call netcdf_err(error, 'reading field' ) + data_one_tile_3d(:,:,1:lev_input) = data_one_tile_3d(:,:,lev_input:1:-1) + endif + + do tile = 1, num_tiles_input_grid + print*,"- CALL FieldScatter FOR INPUT GRID TEMPERATURE." + call ESMF_FieldScatter(temp_input_grid, data_one_tile_3d, rootpet=tile-1, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + enddo + + if (localpet < num_tiles_input_grid) then + print*,"- READ U-WIND." + error=nf90_inq_varid(ncid, 'ugrd', id_var) + call netcdf_err(error, 'reading field id' ) + error=nf90_get_var(ncid, id_var, data_one_tile_3d) + call netcdf_err(error, 'reading field' ) + data_one_tile_3d(:,:,1:lev_input) = data_one_tile_3d(:,:,lev_input:1:-1) + endif + + do tile = 1, num_tiles_input_grid + print*,"- CALL FieldScatter FOR INPUT GRID U." + call ESMF_FieldScatter(u_input_grid, data_one_tile_3d, rootpet=tile-1, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + enddo + + if (localpet < num_tiles_input_grid) then + print*,"- READ V-WIND." + error=nf90_inq_varid(ncid, 'vgrd', id_var) + call netcdf_err(error, 'reading field id' ) + error=nf90_get_var(ncid, id_var, data_one_tile_3d) + call netcdf_err(error, 'reading field' ) + data_one_tile_3d(:,:,1:lev_input) = data_one_tile_3d(:,:,lev_input:1:-1) + endif + + do tile = 1, num_tiles_input_grid + print*,"- CALL FieldScatter FOR INPUT GRID V." + call ESMF_FieldScatter(v_input_grid, data_one_tile_3d, rootpet=tile-1, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + enddo + + if (localpet < num_tiles_input_grid) then + print*,"- READ SURFACE PRESSURE." + error=nf90_inq_varid(ncid, 'pressfc', id_var) + call netcdf_err(error, 'reading field id' ) + error=nf90_get_var(ncid, id_var, data_one_tile) + call netcdf_err(error, 'reading field' ) + endif + + do tile = 1, num_tiles_input_grid + print*,"- CALL FieldScatter FOR INPUT GRID SURFACE PRESSURE." + call ESMF_FieldScatter(ps_input_grid, data_one_tile, rootpet=tile-1, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + enddo + + if (localpet < num_tiles_input_grid) then + print*,"- READ TERRAIN." + error=nf90_inq_varid(ncid, 'hgtsfc', id_var) + call netcdf_err(error, 'reading field id' ) + error=nf90_get_var(ncid, id_var, data_one_tile) + call netcdf_err(error, 'reading field' ) + endif + + do tile = 1, num_tiles_input_grid + print*,"- CALL FieldScatter FOR INPUT GRID TERRAIN." + call ESMF_FieldScatter(terrain_input_grid, data_one_tile, rootpet=tile-1, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + enddo + + if (localpet < num_tiles_input_grid) then + print*,"- READ DELTA PRESSURE." + error=nf90_inq_varid(ncid, 'dpres', id_var) + call netcdf_err(error, 'reading field id' ) + error=nf90_get_var(ncid, id_var, data_one_tile_3d) + call netcdf_err(error, 'reading field' ) + data_one_tile_3d(:,:,1:lev_input) = data_one_tile_3d(:,:,lev_input:1:-1) + endif + + do tile = 1, num_tiles_input_grid + print*,"- CALL FieldScatter FOR INPUT DELTA PRESSURE." + call ESMF_FieldScatter(dpres_input_grid, data_one_tile_3d, rootpet=tile-1, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + enddo + + if (localpet < num_tiles_input_grid) error = nf90_close(ncid) + + deallocate(data_one_tile_3d, data_one_tile) + +!--------------------------------------------------------------------------- +! Convert from 2-d to 3-d cartesian winds. +!--------------------------------------------------------------------------- + + call convert_winds_to_xyz + +!--------------------------------------------------------------------------- +! Compute pressure. +!--------------------------------------------------------------------------- + + print*,"- CALL FieldGet FOR PRESSURE." + call ESMF_FieldGet(pres_input_grid, & + computationalLBound=clb, & + computationalUBound=cub, & + farrayPtr=presptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + print*,"- CALL FieldGet FOR DELTA PRESSURE." + call ESMF_FieldGet(dpres_input_grid, & + farrayPtr=dpresptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + print*,"- CALL FieldGet FOR SURFACE PRESSURE." + call ESMF_FieldGet(ps_input_grid, & + farrayPtr=psptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + allocate(pres_interface(levp1_input)) + +!--------------------------------------------------------------------------- +! Compute 3-d pressure. +!--------------------------------------------------------------------------- + + do i = clb(1), cub(1) + do j = clb(2), cub(2) + pres_interface(1) = psptr(i,j) + do k = 2, levp1_input + pres_interface(k) = pres_interface(k-1) - dpresptr(i,j,k-1) + enddo + do k = 1, lev_input + presptr(i,j,k) = (pres_interface(k) + pres_interface(k+1)) / 2.0_8 + enddo + enddo + enddo + + deallocate(pres_interface, phalf) + + call ESMF_FieldDestroy(dpres_input_grid, rc=rc) + + end subroutine read_input_atm_tiled_history_file + +!> Read input grid atmospheric fv3gfs grib2 files. +!! +!! @param[in] localpet ESMF local persistent execution thread +!! @author George Gayno NCEP/EMC + subroutine read_input_atm_grib2_file(localpet) + + use mpi + use grib_mod + + use grib2_util, only : rh2spfh, rh2spfh_gfs, convert_omega + + implicit none + + integer, intent(in) :: localpet + + integer, parameter :: ntrac_max=14 + integer, parameter :: max_levs=1000 + + character(len=300) :: the_file + character(len=20) :: vname, & + trac_names_vmap(ntrac_max), & + tmpstr, & + method, tracers_input_vmap(num_tracers_input), & + tracers_default(ntrac_max) + + integer :: i, j, k, n + integer :: ii,jj + integer :: rc, clb(3), cub(3) + integer :: vlev, iret,varnum, o3n, pdt_num + integer :: intrp_ier, done_print + integer :: trac_names_oct10(ntrac_max) + integer :: tracers_input_oct10(num_tracers_input) + integer :: trac_names_oct11(ntrac_max) + integer :: tracers_input_oct11(num_tracers_input) + integer :: lugb, lugi, jdisc, jpdt(200), jgdt(200), iscale + integer :: jids(200), jpdtn, jgdtn, octet_23, octet_29 + integer :: count_spfh, count_rh, count_icmr, count_scliwc + integer :: count_cice, count_rwmr, count_scllwc, count + + logical :: conv_omega=.false., & + hasspfh=.true., & + isnative=.false., & + use_rh=.false. , unpack, & + all_empty, is_missing + + real(esmf_kind_r8), allocatable :: dum2d_1(:,:) + + + real(esmf_kind_r8) :: rlevs_hold(max_levs) + real(esmf_kind_r8), allocatable :: rlevs(:) + real(esmf_kind_r4), allocatable :: dummy2d(:,:) + real(esmf_kind_r8), allocatable :: dummy3d(:,:,:), dummy2d_8(:,:),& + u_tmp_3d(:,:,:), v_tmp_3d(:,:,:) + real(esmf_kind_r8), pointer :: presptr(:,:,:), psptr(:,:),tptr(:,:,:), & + qptr(:,:,:), wptr(:,:,:), & + uptr(:,:,:), vptr(:,:,:) + real(esmf_kind_r4) :: value + real(esmf_kind_r8), parameter :: p0 = 100000.0 + real(esmf_kind_r8), allocatable :: dummy3d_col_in(:),dummy3d_col_out(:) + real(esmf_kind_r8), parameter :: intrp_missing = -999.0 + real(esmf_kind_r4), parameter :: lev_no_tr_fill = 20000.0 + real(esmf_kind_r4), parameter :: lev_no_o3_fill = 40000.0 + + type(gribfield) :: gfld + + tracers(:) = "NULL" + + trac_names_oct10 = (/1, 1, 14, 1, 1, 1, 1, 6, 6, 1, 6, 13, 13, 2 /) + trac_names_oct11 = (/0, 22, 192, 23, 24, 25, 32, 1, 29, 100, 28, 193, 192, 2 /) + + trac_names_vmap = (/"sphum ", "liq_wat ", "o3mr ", "ice_wat ", & + "rainwat ", "snowwat ", "graupel ", "cld_amt ", "ice_nc ", & + "rain_nc ", "water_nc", "liq_aero", "ice_aero", & + "sgs_tke "/) + + tracers_default = (/"sphum ", "liq_wat ", "o3mr ", "ice_wat ", & + "rainwat ", "snowwat ", "graupel ", "cld_amt ", "ice_nc ", & + "rain_nc ", "water_nc", "liq_aero", "ice_aero", & + "sgs_tke "/) + + the_file = trim(data_dir_input_grid) // "/" // trim(grib2_file_input_grid) + + print*,"- READ ATMOS DATA FROM GRIB2 FILE: ", trim(the_file) + + if (localpet == 0) then + + lugb=14 + lugi=0 + call baopenr(lugb,the_file,iret) + if (iret /= 0) call error_handler("ERROR OPENING GRIB2 FILE.", iret) + + jdisc = 0 ! Search for discipline - meteorological products + j = 0 ! Search at beginning of file. + jpdt = -9999 ! Array of values in product definition template, set to wildcard + jids = -9999 ! Array of values in identification section, set to wildcard + jgdt = -9999 ! Array of values in grid definition template, set to wildcard + jgdtn = -1 ! Search for any grid definition number. + jpdtn = -1 ! Search for any product definition template number. + unpack =.false. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + +!---------------------------------------------------------------------- +! Read first record and check if this is NCEP GEFS data. +! This will determine what product definition template number to +! search for (Section 4/Octets 8-9). +! +! Section 1/Octets 6-7 is '7' (NCEP) +! Section 1/Octets 8-9 is '2' (NCEP Ensemble products). +!---------------------------------------------------------------------- + + if (iret == 0) then + if (gfld%idsect(1) == 7 .and. gfld%idsect(2) == 2) then + print*,'- THIS IS NCEP GEFS DATA.' + pdt_num = 1 ! Search for product definition template number 1. + ! Individual ensember forecast. + else + pdt_num = 0 ! Search for product definition template number 0. + ! Analysis or forecast. + endif + else + call error_handler("READING GRIB2 FILE", iret) + endif + +!---------------------------------------------------------------------- +! First, check for the vertical coordinate. If temperture at the 10 hybrid +! level is found, hybrid coordinates are assumed. Otherwise, data is on +! isobaric levels. +!---------------------------------------------------------------------- + + j = 0 + jpdtn = pdt_num ! Search for the specific product definition template number. + jpdt(1) = 0 ! Sect4/oct 10 - Parameter category - temperature field + jpdt(2) = 0 ! Sect4/oct 11 - Parameter number - temperature + jpdt(10) = 105 ! Sect4/oct 23 - Type of level - hybrid + jpdt(12) = 10 ! Sect4/octs 25/28 - Value of hybrid level + unpack=.false. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + + if (iret == 0) then + print*,'- DATA IS ON HYBRID LEVELS.' + octet_23 = 105 ! Section 4/Oct 23 - type of first fixed surface. + octet_29 = 255 ! Section 4/Oct 29 - type of second fixed surface (N/A). + isnative=.true. + else + print*,'- DATA IS ON ISOBARIC LEVELS.' + octet_23 = 100 ! Section 4/Oct 23 - type of first fixed surface. + octet_29 = 255 ! Section 4/Oct 29 - type of second fixed surface (N/A). + isnative=.false. + endif + +! Now count the number of vertical levels by searching for u-wind. +! Store the value of each level. + + rlevs_hold = -999.9 + lev_input = 0 + iret = 0 + j = 0 + jpdtn = -1 + jpdt = -9999 + + do + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + + if (iret /= 0) exit + + if (gfld%discipline == 0) then ! Discipline - meteorological products + if (gfld%ipdtnum == pdt_num) then ! Product definition template number. + if (gfld%ipdtmpl(1) == 2 .and. gfld%ipdtmpl(2) == 2) then ! u-wind + ! Sect4/octs 10 and 11. + if (gfld%ipdtmpl(10) == octet_23 .and. gfld%ipdtmpl(13) == octet_29) then + ! Sect4 octs 23 and 29. + ! Hybrid or isobaric. + lev_input = lev_input + 1 + iscale = 10 ** gfld%ipdtmpl(11) + rlevs_hold(lev_input) = float(gfld%ipdtmpl(12))/float(iscale) + endif + endif + endif + endif + + j = k + enddo + + endif ! read file on task 0. + + call mpi_barrier(MPI_COMM_WORLD, iret) + call MPI_BCAST(isnative,1,MPI_LOGICAL,0,MPI_COMM_WORLD,iret) + call MPI_BCAST(lev_input,1,MPI_INTEGER,0,MPI_COMM_WORLD,iret) + call MPI_BCAST(pdt_num,1,MPI_INTEGER,0,MPI_COMM_WORLD,iret) + call MPI_BCAST(rlevs_hold, max_levs, MPI_INTEGER,0,MPI_COMM_WORLD,iret) + + allocate(slevs(lev_input)) + allocate(rlevs(lev_input)) + allocate(dummy3d_col_in(lev_input)) + allocate(dummy3d_col_out(lev_input)) + + levp1_input = lev_input + 1 + +! Jili Dong add sort to re-order isobaric levels. + + do i = 1, lev_input + rlevs(i) = rlevs_hold(i) + enddo + + call quicksort(rlevs,1,lev_input) + + do i = 1, lev_input + if (isnative) then + write(slevs(i), '(i6)') nint(rlevs(i)) + slevs(i) = trim(slevs(i)) // " hybrid" + if (i>1) then + if (any(slevs(1:i-1)==slevs(i))) call error_handler("Duplicate vertical level entries found.",1) + endif + else + write(slevs(i), '(f11.2)') rlevs(i) + slevs(i) = trim(slevs(i)) // " Pa" + if (i>1) then + if (any(slevs(1:i-1)==slevs(i))) call error_handler("Duplicate vertical level entries found.",1) + endif + endif + enddo + + if(localpet == 0) then + do i = 1,lev_input + print*, "- LEVEL AFTER SORT = ",trim(slevs(i)) + enddo + endif + +! Check to see if specfic humidity exists at all the same levels as ugrd. + + if (localpet == 0) then + + jpdtn = pdt_num ! Product definition template number. + jpdt = -9999 + jpdt(1) = 1 ! Sect4/oct 10 - Parameter category - moisture + jpdt(2) = 0 ! Sect4/oct 11 - Parameter number - specific humidity + jpdt(10) = octet_23 ! Sect4/oct 23 - type of level. + unpack=.false. + + count_spfh=0 + + do vlev = 1, lev_input + j = 0 + jpdt(12) = nint(rlevs(vlev)) + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + + if (iret == 0) then + count_spfh = count_spfh + 1 + endif + enddo + + jpdt(1) = 1 ! Sec4/oct 10 - Parameter category - moisture + jpdt(2) = 1 ! Sec4/oct 11 - Parameter number - rel humidity + count_rh=0 + + do vlev = 1, lev_input + j = 0 + jpdt(12) = nint(rlevs(vlev)) + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + + if (iret == 0) then + count_rh = count_rh + 1 + endif + enddo + + if (count_spfh /= lev_input) then + use_rh = .true. + endif + + if (count_spfh == 0 .or. use_rh) then + if (count_rh == 0) then + call error_handler("READING ATMOSPHERIC WATER VAPOR VARIABLE.", 2) + endif + hasspfh = .false. ! Will read rh and convert to specific humidity. + trac_names_oct10(1) = 1 + trac_names_oct11(1) = 1 + print*,"- FILE CONTAINS RH." + else + print*,"- FILE CONTAINS SPFH." + endif + + endif + + call MPI_BARRIER(MPI_COMM_WORLD, rc) + call MPI_BCAST(hasspfh,1,MPI_LOGICAL,0,MPI_COMM_WORLD,rc) + +! Search for and count the number of tracers in the file. + + if (localpet == 0) then + + jpdtn = pdt_num ! Product definition template number. + jpdt = -9999 + jpdt(10) = octet_23 ! Sect4/oct 23 - type of level. + unpack=.false. + + count_icmr=0 + count_scliwc=0 + count_cice=0 + count_rwmr=0 + count_scllwc=0 + + do vlev = 1, lev_input + + j = 0 + jpdt(1) = 1 ! Sect4/oct 10 - Parameter category - moisture + jpdt(2) = 23 ! Sect4/oct 11 - Parameter number - ice water mixing ratio + jpdt(12) = nint(rlevs(vlev)) + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + + if (iret == 0) then + count_icmr = count_icmr + 1 + endif + + j = 0 + jpdt(1) = 1 ! Sect4/oct 10 - Parameter category - moisture + jpdt(2) = 84 ! Sect4/oct 11 - Parameter number - cloud ice water content. + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + + if (iret == 0) then + count_scliwc = count_scliwc + 1 + endif + + j = 0 + jpdt(1) = 6 ! Sect4/oct 10 - Parameter category - clouds + jpdt(2) = 0 ! Sect4/oct 11 - Parameter number - cloud ice + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + + if (iret == 0) then + count_cice = count_cice + 1 + endif + + j = 0 + jpdt(1) = 1 ! Sect4/oct 10 - Parameter category - moisture + jpdt(2) = 24 ! Sect4/oct 11 - Parameter number - rain mixing ratio + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + + if (iret == 0) then + count_rwmr = count_rwmr + 1 + endif + + j = 0 + jpdt(1) = 1 ! Sect4/oct 10 - Parameter category - moisture + jpdt(2) = 83 ! Sect4/oct 11 - Parameter number - specific cloud liquid + ! water content. + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + + if (iret == 0) then + count_scllwc = count_scllwc + 1 + endif + + enddo + + if (count_icmr == 0) then + if (count_scliwc == 0) then + if (count_cice == 0) then + print*,'- FILE DOES NOT CONTAIN CICE.' + else + trac_names_oct10(4) = 6 ! Sect4/oct 10 - Parameter category - clouds + trac_names_oct11(4) = 0 ! Sect4/oct 11 - Parameter number - cloud ice + print*,"- FILE CONTAINS CICE." + endif + else + trac_names_oct10(4) = 1 ! Sect4/oct 10 - Parameter category - moisture + trac_names_oct11(4) = 84 ! Sect4/oct 11 - Parameter number - cloud ice water content. + print*,"- FILE CONTAINS SCLIWC." + endif + else + print*,"- FILE CONTAINS ICMR." + endif ! count of icmr + + if (count_rwmr == 0) then + if (count_scllwc == 0) then + print*,"- FILE DOES NOT CONTAIN SCLLWC." + else + trac_names_oct10(4) = 1 ! Sect4/oct 10 - Parameter category - moisture + trac_names_oct11(4) = 83 ! Sect4/oct 11 - Parameter number - specific cloud liquid + ! water content. + print*,"- FILE CONTAINS SCLLWC." + endif + else + print*,"- FILE CONTAINS CLWMR." + endif + + endif ! count of tracers/localpet = 0 + + call MPI_BARRIER(MPI_COMM_WORLD, rc) + call MPI_BCAST(trac_names_oct10,ntrac_max,MPI_INTEGER,0,MPI_COMM_WORLD,rc) + call MPI_BCAST(trac_names_oct11,ntrac_max,MPI_INTEGER,0,MPI_COMM_WORLD,rc) + + print*,"- COUNT NUMBER OF TRACERS TO BE READ IN BASED ON PHYSICS SUITE TABLE" + do n = 1, num_tracers_input + + vname = tracers_input(n) + + i = maxloc(merge(1.,0.,trac_names_vmap == vname),dim=1) + + tracers_input_vmap(n)=trac_names_vmap(i) + tracers(n)=tracers_default(i) + if(trim(tracers(n)) .eq. "o3mr") o3n = n + + tracers_input_oct10(n) = trac_names_oct10(i) + tracers_input_oct11(n) = trac_names_oct11(i) + + enddo + +!--------------------------------------------------------------------------- +! Initialize esmf atmospheric fields. +!--------------------------------------------------------------------------- + + call init_atm_esmf_fields + + if (localpet == 0) then + allocate(dummy2d(i_input,j_input)) + allocate(dummy2d_8(i_input,j_input)) + allocate(dummy3d(i_input,j_input,lev_input)) + allocate(dum2d_1(i_input,j_input)) + else + allocate(dummy2d(0,0)) + allocate(dummy2d_8(0,0)) + allocate(dummy3d(0,0,0)) + allocate(dum2d_1(0,0)) + endif + +!---------------------------------------------------------------------------------- +! This program expects field levels from bottom to top. Fields in non-native +! files read in from top to bottom. We will flip indices later. Fields on +! native vertical coordinates read from bottom to top so those need no adjustments. +!---------------------------------------------------------------------------------- + + if (localpet == 0) then + + print*,"- READ TEMPERATURE." + + jdisc = 0 ! search for discipline - meteorological products + j = 0 ! search at beginning of file. + jpdt = -9999 ! array of values in product definition template, set to wildcard + jids = -9999 ! array of values in identification section, set to wildcard + jgdt = -9999 ! array of values in grid definition template, set to wildcard + jgdtn = -1 ! search for any grid definition number. + jpdtn = pdt_num ! Search for specific product definition template number. + jpdt(1) = 0 ! Sect 4/oct 10 - parameter category - temperature + jpdt(2) = 0 ! Sect 4/oct 11 - parameter number - temperature + jpdt(10) = octet_23 ! Sect4/oct 23 - type of level. + + unpack=.true. + + do vlev = 1, lev_input + + jpdt(12) = nint(rlevs(vlev)) + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + if (iret /= 0) then + call error_handler("READING IN TEMPERATURE AT LEVEL "//trim(slevs(vlev)),iret) + endif + + dum2d_1 = reshape(gfld%fld, (/i_input,j_input/) ) + + dummy3d(:,:,vlev) = dum2d_1 + + enddo + + endif ! Read of temperature + + if (localpet == 0) print*,"- CALL FieldScatter FOR INPUT GRID TEMPERATURE." + call ESMF_FieldScatter(temp_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! Read tracers + + do n = 1, num_tracers_input + + if (localpet == 0) print*,"- READ ", trim(tracers_input_vmap(n)) + + vname = tracers_input_vmap(n) + call get_var_cond(vname,this_miss_var_method=method, this_miss_var_value=value, & + this_field_var_name=tmpstr,loc=varnum) + + if (n==1 .and. .not. hasspfh) then + print*,"- CALL FieldGather TEMPERATURE." + call ESMF_FieldGather(temp_input_grid,dummy3d,rootPet=0, tile=1, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + endif + + if (localpet == 0) then + + jdisc = 0 ! search for discipline - meteorological products + jpdt = -9999 ! array of values in product definition template, set to wildcard + jids = -9999 ! array of values in identification section, set to wildcard + jgdt = -9999 ! array of values in grid definition template, set to wildcard + jgdtn = -1 ! search for any grid definition number. + jpdtn = pdt_num ! Search for the product definition template number. + jpdt(10) = octet_23 ! Sect4/oct 23 - type of level. + unpack = .false. + + count = 0 + + do vlev = 1, lev_input + + j = 0 + jpdt(1) = tracers_input_oct10(n) + jpdt(2) = tracers_input_oct11(n) + jpdt(12) = nint(rlevs(vlev)) + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + + if (iret == 0) then + count = count + 1 + endif + + enddo + iret=count + + ! Check to see if file has any data for this tracer + if (iret == 0) then + all_empty = .true. + else + all_empty = .false. + endif + + is_missing = .false. + + do vlev = 1, lev_input + + unpack=.true. + j = 0 + jpdt(1) = tracers_input_oct10(n) + jpdt(2) = tracers_input_oct11(n) + jpdt(12) = nint(rlevs(vlev) ) + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + + if (iret == 0) then ! found data + dummy2d = real((reshape(gfld%fld, (/i_input,j_input/) )), kind=esmf_kind_r4) + else ! did not find data. + if (trim(method) .eq. 'intrp' .and. .not.all_empty) then + dummy2d = intrp_missing + is_missing = .true. + else + ! Abort if input data has some data for current tracer, but has + ! missing data below 200 mb/ above 400mb + if (.not.all_empty .and. n == o3n) then + if (rlevs(vlev) .lt. lev_no_o3_fill) & + call error_handler("TRACER "//trim(tracers(n))//" HAS MISSING DATA AT "//trim(slevs(vlev))//& + ". SET MISSING VARIABLE CONDITION TO 'INTRP' TO AVOID THIS ERROR", 1) + elseif (.not.all_empty .and. n .ne. o3n) then + if (rlevs(vlev) .gt. lev_no_tr_fill) & + call error_handler("TRACER "//trim(tracers(n))//" HAS MISSING DATA AT "//trim(slevs(vlev))//& + ". SET MISSING VARIABLE CONDITION TO 'INTRP' TO AVOID THIS ERROR.", 1) + endif + ! If entire array is empty and method is set to intrp, switch method to fill + if (trim(method) .eq. 'intrp' .and. all_empty) method='set_to_fill' + + call handle_grib_error(vname, slevs(vlev),method,value,varnum,read_from_input,iret,var=dummy2d) + if (iret==1) then ! missing_var_method == skip or no entry + if ( (tracers_input_oct10(n) == 1 .and. tracers_input_oct11(n) == 0) .or. & ! spec humidity + (tracers_input_oct10(n) == 1 .and. tracers_input_oct11(n) == 1) .or. & ! rel humidity + (tracers_input_oct10(n) == 14 .and. tracers_input_oct11(n) == 192) ) then ! ozone + call error_handler("READING IN "//trim(tracers(n))//" AT LEVEL "//trim(slevs(vlev))& + //". SET A FILL VALUE IN THE VARMAP TABLE IF THIS ERROR IS NOT DESIRABLE.",iret) + endif + endif + endif ! method intrp + endif !iret<=0 + + if (n==1 .and. .not. hasspfh) then + if (trim(external_model) .eq. 'GFS') then + print *,'- CALL CALRH GFS' + call rh2spfh_gfs(dummy2d,rlevs(vlev),dummy3d(:,:,vlev)) + else + print *,'- CALL CALRH non-GFS' + call rh2spfh(dummy2d,rlevs(vlev),dummy3d(:,:,vlev)) + end if + endif + + dummy3d(:,:,vlev) = real(dummy2d,esmf_kind_r8) + + enddo !vlev + +! Jili Dong interpolation for missing levels + if (is_missing .and. trim(method) .eq. 'intrp') then + print *,'- INTERPOLATE TRACER '//trim(tracers(n)) + done_print = 0 + do jj = 1, j_input + do ii = 1, i_input + dummy3d_col_in=dummy3d(ii,jj,:) + call dint2p(rlevs,dummy3d_col_in,lev_input,rlevs,dummy3d_col_out, & + lev_input, 2, intrp_missing, intrp_ier) + if (intrp_ier .gt. 0) call error_handler("Interpolation failed.",intrp_ier) + dummy3d(ii,jj,:)=dummy3d_col_out + enddo + enddo + do vlev=1,lev_input + dummy2d = real(dummy3d(:,:,n) , kind=esmf_kind_r4) + if (any(dummy2d .eq. intrp_missing)) then + ! If we're outside the appropriate region, don't fill but error instead + if (n == o3n .and. rlevs(vlev) .lt. lev_no_o3_fill) then + call error_handler("TRACER "//trim(tracers(n))//" HAS MISSING DATA AT "//trim(slevs(vlev)),1) + elseif (n .ne. o3n .and. rlevs(vlev) .gt. lev_no_tr_fill) then + call error_handler("TRACER "//trim(tracers(n))//" HAS MISSING DATA AT "//trim(slevs(vlev)),1) + else ! we're okay to fill missing data with provided fill value + if (done_print .eq. 0) then + print*, "Pressure out of range of existing data. Defaulting to fill value." + done_print = 1 + end if !done print + where(dummy2d .eq. intrp_missing) dummy2d = value + dummy3d(:,:,vlev) = dummy2d + end if !n & lev + endif ! intrp_missing + ! zero out negative tracers from interpolation/extrapolation + where(dummy3d(:,:,vlev) .lt. 0.0) dummy3d(:,:,vlev) = 0.0 +! print*,'tracer af intrp',vlev, maxval(dummy3d(:,:,vlev)),minval(dummy3d(:,:,vlev)) + end do !nlevs do + end if !if intrp + endif !localpet == 0 + + if (localpet == 0) print*,"- CALL FieldScatter FOR INPUT ", trim(tracers_input_vmap(n)) + call ESMF_FieldScatter(tracers_input_grid(n), dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + enddo + + deallocate(dummy3d_col_in, dummy3d_col_out) + + call read_winds(u_tmp_3d,v_tmp_3d,localpet,octet_23,rlevs,lugb,pdt_num) + + if (localpet == 0) print*,"- CALL FieldScatter FOR INPUT U-WIND." + call ESMF_FieldScatter(u_input_grid, u_tmp_3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) print*,"- CALL FieldScatter FOR INPUT V-WIND." + call ESMF_FieldScatter(v_input_grid, v_tmp_3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + + print*,"- READ SURFACE PRESSURE." + jdisc = 0 ! search for discipline - meteorological products + j = 0 ! search at beginning of file. + jpdt = -9999 ! array of values in product definition template, set to wildcard + jids = -9999 ! array of values in identification section, set to wildcard + jgdt = -9999 ! array of values in grid definition template, set to wildcard + jgdtn = -1 ! search for any grid definition number. + jpdtn = pdt_num ! Search for the product definition template number. + jpdt(1) = 3 ! Sect4/oct 10 - param category - mass + jpdt(2) = 0 ! Sect4/oct 11 - param number - pressure + jpdt(10) = 1 ! Sect4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + if (iret /= 0) call error_handler("READING SURFACE PRESSURE RECORD.", iret) + + dummy2d_8 = reshape(gfld%fld, (/i_input,j_input/) ) + + endif ! Read surface pressure + + if (localpet == 0) print*,"- CALL FieldScatter FOR INPUT GRID SURFACE PRESSURE." + call ESMF_FieldScatter(ps_input_grid, dummy2d_8, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! Read dzdt. + + if (localpet == 0) then + + print*,"- READ DZDT." + vname = "dzdt" + call get_var_cond(vname,this_miss_var_method=method, this_miss_var_value=value, & + loc=varnum) + + jdisc = 0 ! search for discipline - meteorological products + j = 0 ! search at beginning of file. + jpdt = -9999 ! array of values in product definition template, set to wildcard + jids = -9999 ! array of values in identification section, set to wildcard + jgdt = -9999 ! array of values in grid definition template, set to wildcard + jgdtn = -1 ! search for any grid definition number. + jpdtn = pdt_num ! Search for the product definition template number. + jpdt(1) = 2 ! Sect4/oct 10 - param category - momentum + jpdt(2) = 9 ! Sect4/oct 11 - param number - dzdt + jpdt(10) = octet_23 ! Sect4/oct 23 - type of level + + unpack=.true. + + do vlev = 1, lev_input + + jpdt(12) = nint(rlevs(vlev)) + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + + if (iret /= 0) then ! dzdt not found, look for omega. + print*,"DZDT not available at level ", trim(slevs(vlev)), " so checking for VVEL" + jpdt(2) = 8 ! Sect4/oct 11 - parameter number - omega + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + if (iret /= 0) then + call handle_grib_error(vname, slevs(vlev),method,value,varnum,read_from_input,iret,var8=dum2d_1) + if (iret==1) then ! missing_var_method == skip + cycle + endif + else + conv_omega = .true. + dum2d_1 = reshape(gfld%fld, (/i_input,j_input/) ) + endif + else ! found dzdt + dum2d_1 = reshape(gfld%fld, (/i_input,j_input/) ) + endif + + dummy3d(:,:,vlev) = dum2d_1 + + enddo + + endif ! Read of dzdt + + call mpi_bcast(conv_omega,1,MPI_LOGICAL,0,MPI_COMM_WORLD,rc) + + if (localpet == 0) print*,"- CALL FieldScatter FOR INPUT DZDT." + call ESMF_FieldScatter(dzdt_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! Read terrain + + if (localpet == 0) then + + print*,"- READ TERRAIN." + jdisc = 0 ! search for discipline - meteorological products + j = 0 ! search at beginning of file. + jpdt = -9999 ! array of values in product definition template, set to wildcard + jids = -9999 ! array of values in identification section, set to wildcard + jgdt = -9999 ! array of values in grid definition template, set to wildcard + jgdtn = -1 ! search for any grid definition number. + jpdtn = pdt_num ! Search for the product definition template number. + jpdt(1) = 3 ! Sect4/oct 10 - param category - mass + jpdt(2) = 5 ! Sect4/oct 11 - param number - geopotential height + jpdt(10) = 1 ! Sect4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + if (iret /= 0) call error_handler("READING TERRAIN HEIGHT RECORD.", iret) + + dummy2d_8 = reshape(gfld%fld, (/i_input,j_input/) ) + + endif ! read of terrain. + + if (localpet == 0) print*,"- CALL FieldScatter FOR INPUT GRID TERRAIN." + call ESMF_FieldScatter(terrain_input_grid, dummy2d_8, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + deallocate(dummy2d, dummy2d_8) + +if (.not. isnative) then + + !--------------------------------------------------------------------------- + ! Flip 'z' indices to all 3-d variables. Data is read in from model + ! top to surface. This program expects surface to model top. + !--------------------------------------------------------------------------- + + if (localpet == 0) print*,"- CALL FieldGet FOR SURFACE PRESSURE." + nullify(psptr) + call ESMF_FieldGet(ps_input_grid, & + farrayPtr=psptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + nullify(presptr) + if (localpet == 0) print*,"- CALL FieldGet FOR 3-D PRESSURE." + call ESMF_FieldGet(pres_input_grid, & + computationalLBound=clb, & + computationalUBound=cub, & + farrayPtr=presptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + nullify(tptr) + if (localpet == 0) print*,"- CALL FieldGet TEMPERATURE." + call ESMF_FieldGet(temp_input_grid, & + farrayPtr=tptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + nullify(uptr) + if (localpet == 0) print*,"- CALL FieldGet FOR U" + call ESMF_FieldGet(u_input_grid, & + farrayPtr=uptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + nullify(vptr) + if (localpet == 0) print*,"- CALL FieldGet FOR V" + call ESMF_FieldGet(v_input_grid, & + farrayPtr=vptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + nullify(wptr) + if (localpet == 0) print*,"- CALL FieldGet FOR W" + call ESMF_FieldGet(dzdt_input_grid, & + farrayPtr=wptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + if (localpet == 0) print*,"- CALL FieldGet FOR TRACERS." + do n=1,num_tracers_input + nullify(qptr) + call ESMF_FieldGet(tracers_input_grid(n), & + farrayPtr=qptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + do i = clb(1),cub(1) + do j = clb(2),cub(2) + qptr(i,j,:) = qptr(i,j,lev_input:1:-1) + end do + end do + end do + + do i = clb(1),cub(1) + do j = clb(2),cub(2) + presptr(i,j,:) = rlevs(lev_input:1:-1) + tptr(i,j,:) = tptr(i,j,lev_input:1:-1) + uptr(i,j,:) = uptr(i,j,lev_input:1:-1) + vptr(i,j,:) = vptr(i,j,lev_input:1:-1) + wptr(i,j,:) = wptr(i,j,lev_input:1:-1) + end do + end do + + if (localpet == 0) then + print*,'psfc is ',clb(1),clb(2),psptr(clb(1),clb(2)) + print*,'pres is ',cub(1),cub(2),presptr(cub(1),cub(2),:) + + print*,'pres check 1',localpet,maxval(presptr(clb(1):cub(1),clb(2):cub(2),1)), & + minval(presptr(clb(1):cub(1),clb(2):cub(2),1)) + print*,'pres check lev',localpet,maxval(presptr(clb(1):cub(1),clb(2):cub(2), & + lev_input)),minval(presptr(clb(1):cub(1),clb(2):cub(2),lev_input)) + endif + +else ! is native coordinate (hybrid). + +! For native files, read in pressure field directly from file but don't flip levels + + if (localpet == 0) then + + print*,"- READ PRESSURE." + + jdisc = 0 ! search for discipline - meteorological products + j = 0 ! search at beginning of file. + jpdt = -9999 ! array of values in product definition template, set to wildcard + jids = -9999 ! array of values in identification section, set to wildcard + jgdt = -9999 ! array of values in grid definition template, set to wildcard + jgdtn = -1 ! search for any grid definition number. + jpdtn = pdt_num ! Search for the product definition template number. + jpdt(1) = 3 ! Sect4/oct 10 - parameter category - mass + jpdt(2) = 0 ! Sect4/oct 11 - parameter number - pressure + jpdt(10) = octet_23 ! Sect4/oct 23 - type of level. + unpack=.true. + + do vlev = 1, lev_input + + jpdt(12) = nint(rlevs(vlev)) + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + if (iret /= 0) then + call error_handler("READING IN PRESSURE AT LEVEL "//trim(slevs(vlev)),iret) + endif + + dum2d_1 = reshape(gfld%fld, (/i_input,j_input/) ) + + dummy3d(:,:,vlev) = dum2d_1 + + enddo + + endif ! localpet == 0 + + if (localpet == 0) print*,"- CALL FieldScatter FOR INPUT GRID PRESSURE." + call ESMF_FieldScatter(pres_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + endif + + deallocate(dummy3d, dum2d_1) + +!--------------------------------------------------------------------------- +! Convert from 2-d to 3-d component winds. +!--------------------------------------------------------------------------- + + call convert_winds_to_xyz + +!--------------------------------------------------------------------------- +! Convert dpdt to dzdt if needed +!--------------------------------------------------------------------------- + + if (conv_omega) then + + if (localpet == 0) print*,"- CONVERT FROM OMEGA TO DZDT." + + nullify(tptr) + if (localpet == 0) print*,"- CALL FieldGet TEMPERATURE." + call ESMF_FieldGet(temp_input_grid, & + farrayPtr=tptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + nullify(qptr) + if (localpet == 0) print*,"- CALL FieldGet SPECIFIC HUMIDITY." + call ESMF_FieldGet(tracers_input_grid(1), & + computationalLBound=clb, & + computationalUBound=cub, & + farrayPtr=qptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + nullify(wptr) + if (localpet == 0) print*,"- CALL FieldGet DZDT." + call ESMF_FieldGet(dzdt_input_grid, & + computationalLBound=clb, & + computationalUBound=cub, & + farrayPtr=wptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + nullify(presptr) + call ESMF_FieldGet(pres_input_grid, & + farrayPtr=presptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + call convert_omega(wptr,presptr,tptr,qptr,clb,cub) + + endif + + if (localpet == 0) call baclose(lugb, rc) + + end subroutine read_input_atm_grib2_file + + !> Read winds from a grib2 file. Rotate winds +!! to be earth relative if necessary. +!! +!! @param [inout] u u-component wind +!! @param [inout] v v-component wind +!! @param[in] localpet ESMF local persistent execution thread +!! @param[in] octet_23 Section 4/Octet 23 - Type of first fixed surface. +!! @param[in] rlevs Array of atmospheric level values +!! @param[in] lugb Logical unit number of GRIB2 file. +!! @param[in] pdt_num Product definition template number. +!! @author Larissa Reames + subroutine read_winds(u,v,localpet,octet_23,rlevs,lugb,pdt_num) + + use grib_mod + use program_setup, only : get_var_cond + + implicit none + + integer, intent(in) :: localpet, lugb + integer, intent(in) :: pdt_num, octet_23 + + real(esmf_kind_r8), intent(inout), allocatable :: u(:,:,:),v(:,:,:) + real(esmf_kind_r8), intent(in), dimension(lev_input) :: rlevs + + real(esmf_kind_r4), dimension(i_input,j_input) :: alpha + real(esmf_kind_r8), dimension(i_input,j_input) :: lon, lat + real(esmf_kind_r4), allocatable :: u_tmp(:,:),v_tmp(:,:) + real(esmf_kind_r8), allocatable :: dum2d(:,:) + real(esmf_kind_r4), dimension(i_input,j_input) :: ws,wd + real(esmf_kind_r4) :: value_u, value_v,lov,latin1,latin2 + real(esmf_kind_r8) :: d2r + + integer :: varnum_u, varnum_v, vlev, & + error, iret + integer :: j, k, lugi, jgdtn, jpdtn + integer :: jdisc, jids(200), jgdt(200), jpdt(200) + + character(len=20) :: vname + character(len=50) :: method_u, method_v + + logical :: unpack + + type(gribfield) :: gfld + + d2r=acos(-1.0_esmf_kind_r8) / 180.0_esmf_kind_r8 + if (localpet==0) then + allocate(u(i_input,j_input,lev_input)) + allocate(v(i_input,j_input,lev_input)) + else + allocate(u(0,0,0)) + allocate(v(0,0,0)) + endif + + vname = "u" + call get_var_cond(vname,this_miss_var_method=method_u, this_miss_var_value=value_u, & + loc=varnum_u) + vname = "v" + call get_var_cond(vname,this_miss_var_method=method_v, this_miss_var_value=value_v, & + loc=varnum_v) + + print*,"- CALL FieldGather FOR INPUT GRID LONGITUDE" + call ESMF_FieldGather(longitude_input_grid, lon, rootPet=0, tile=1, rc=error) + if(ESMF_logFoundError(rcToCheck=error,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGather", error) + + print*,"- CALL FieldGather FOR INPUT GRID LATITUDE" + call ESMF_FieldGather(latitude_input_grid, lat, rootPet=0, tile=1, rc=error) + if(ESMF_logFoundError(rcToCheck=error,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGather", error) + + if (localpet==0) then + + lugi = 0 ! index file unit number + jdisc = 0 ! search for discipline - meteorological products + j = 0 ! search at beginning of file. + jpdt = -9999 ! array of values in product definition template, set to wildcard + jids = -9999 ! array of values in identification section, set to wildcard + jgdt = -9999 ! array of values in grid definition template, set to wildcard + jgdtn = -1 ! search for any grid definition number. + jpdtn = pdt_num ! Search for the product definition template number. + unpack=.false. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + + if (iret /= 0) call error_handler("ERROR READING GRIB2 FILE.", iret) + + if (gfld%igdtnum == 32769) then ! grid definition template number - rotated lat/lon grid + + latin1 = real(float(gfld%igdtmpl(15))/1.0E6, kind=esmf_kind_r4) + lov = real(float(gfld%igdtmpl(16))/1.0E6, kind=esmf_kind_r4) + + print*, "- CALL CALCALPHA_ROTLATLON with center lat,lon = ",latin1,lov + call calcalpha_rotlatlon(lat,lon,latin1,lov,alpha) + + elseif (gfld%igdtnum == 30) then ! grid definition template number - lambert conformal grid. + + lov = real(float(gfld%igdtmpl(14))/1.0E6, kind=esmf_kind_r4) + latin1 = real(float(gfld%igdtmpl(19))/1.0E6, kind=esmf_kind_r4) + latin2 = real(float(gfld%igdtmpl(20))/1.0E6, kind=esmf_kind_r4) + + print*, "- CALL GRIDROT for LC grid with lov,latin1/2 = ",lov,latin1,latin2 + call gridrot(lov,latin1,latin2,lon,alpha) + + endif + + jpdt(10) = octet_23 ! Sec4/oct 23 - type of level. + + unpack=.true. + + allocate(dum2d(i_input,j_input)) + allocate(u_tmp(i_input,j_input)) + allocate(v_tmp(i_input,j_input)) + + do vlev = 1, lev_input + + vname = ":UGRD:" + + jpdt(1) = 2 ! Sec4/oct 10 - parameter category - momentum + jpdt(2) = 2 ! Sec4/oct 11 - parameter number - u-wind + jpdt(12) = nint(rlevs(vlev)) ! Sect4/octs 25-28 - scaled value of fixed surface. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + + if (iret /= 0) then + call handle_grib_error(vname, slevs(vlev),method_u,value_u,varnum_u,read_from_input,iret,var=u_tmp) + if (iret==1) then ! missing_var_method == skip + call error_handler("READING IN U AT LEVEL "//trim(slevs(vlev))//". SET A FILL "// & + "VALUE IN THE VARMAP TABLE IF THIS ERROR IS NOT DESIRABLE.",iret) + endif + else + dum2d = reshape(gfld%fld, (/i_input,j_input/) ) + u_tmp(:,:) = real(dum2d, kind=esmf_kind_r4) + endif + + vname = ":VGRD:" + + jpdt(2) = 3 ! Sec4/oct 11 - parameter number - v-wind + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, iret) + + if (iret /= 0) then + call handle_grib_error(vname, slevs(vlev),method_v,value_v,varnum_v,read_from_input,iret,var=v_tmp) + if (iret==1) then ! missing_var_method == skip + call error_handler("READING IN V AT LEVEL "//trim(slevs(vlev))//". SET A FILL "// & + "VALUE IN THE VARMAP TABLE IF THIS ERROR IS NOT DESIRABLE.",iret) + endif + else + dum2d = reshape(gfld%fld, (/i_input,j_input/) ) + v_tmp(:,:) = real(dum2d, kind=esmf_kind_r4) + endif + + deallocate(dum2d) + + if (gfld%igdtnum == 0) then ! grid definition template number - lat/lon grid + if (external_model == 'UKMET') then + u(:,:,vlev) = u_tmp + v(:,:,vlev) = (v_tmp(:,2:jp1_input) + v_tmp(:,1:j_input))/2 + else + u(:,:,vlev) = u_tmp + v(:,:,vlev) = v_tmp + endif + else if (gfld%igdtnum == 32769) then ! grid definition template number - rotated lat/lon grid + ws = sqrt(u_tmp**2 + v_tmp**2) + wd = real((atan2(-u_tmp,-v_tmp) / d2r), kind=esmf_kind_r4) ! calculate grid-relative wind direction + wd = real((wd + alpha + 180.0), kind=esmf_kind_r4) ! Rotate from grid- to earth-relative direction + wd = real((270.0 - wd), kind=esmf_kind_r4) ! Convert from meteorological (true N) to mathematical direction + u(:,:,vlev) = -ws*cos(wd*d2r) + v(:,:,vlev) = -ws*sin(wd*d2r) + else + u(:,:,vlev) = real(u_tmp * cos(alpha) + v_tmp * sin(alpha),esmf_kind_r8) + v(:,:,vlev) = real(v_tmp * cos(alpha) - u_tmp * sin(alpha),esmf_kind_r8) + endif + + print*, 'max, min U ', minval(u(:,:,vlev)), maxval(u(:,:,vlev)) + print*, 'max, min V ', minval(v(:,:,vlev)), maxval(v(:,:,vlev)) + enddo + endif + +end subroutine read_winds + +!> Convert winds from 2-d to 3-d components. +!! +!! @author George Gayno NCEP/EMC + subroutine convert_winds_to_xyz + + implicit none + + integer :: clb(3), cub(3) + integer :: i, j, k, rc + + real(esmf_kind_r8) :: latrad, lonrad + real(esmf_kind_r8), pointer :: xptr(:,:,:) + real(esmf_kind_r8), pointer :: yptr(:,:,:) + real(esmf_kind_r8), pointer :: zptr(:,:,:) + real(esmf_kind_r8), pointer :: uptr(:,:,:) + real(esmf_kind_r8), pointer :: vptr(:,:,:) + real(esmf_kind_r8), pointer :: latptr(:,:) + real(esmf_kind_r8), pointer :: lonptr(:,:) + + print*,"- CALL FieldGet FOR xwind." + call ESMF_FieldGet(xwind_input_grid, & + computationalLBound=clb, & + computationalUBound=cub, & + farrayPtr=xptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + print*,"- CALL FieldGet FOR ywind." + call ESMF_FieldGet(ywind_input_grid, & + farrayPtr=yptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + print*,"- CALL FieldGet FOR zwind." + call ESMF_FieldGet(zwind_input_grid, & + farrayPtr=zptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + print*,"- CALL FieldGet FOR U." + call ESMF_FieldGet(u_input_grid, & + farrayPtr=uptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + print*,"- CALL FieldGet FOR V." + call ESMF_FieldGet(v_input_grid, & + farrayPtr=vptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + print*,"- CALL FieldGet FOR LATITUDE." + call ESMF_FieldGet(latitude_input_grid, & + farrayPtr=latptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + print*,"- CALL FieldGet FOR LONGITUDE." + call ESMF_FieldGet(longitude_input_grid, & + farrayPtr=lonptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + do i = clb(1), cub(1) + do j = clb(2), cub(2) + latrad = latptr(i,j) * acos(-1.) / 180.0 + lonrad = lonptr(i,j) * acos(-1.) / 180.0 + do k = clb(3), cub(3) + xptr(i,j,k) = uptr(i,j,k) * cos(lonrad) - vptr(i,j,k) * sin(latrad) * sin(lonrad) + yptr(i,j,k) = uptr(i,j,k) * sin(lonrad) + vptr(i,j,k) * sin(latrad) * cos(lonrad) + zptr(i,j,k) = vptr(i,j,k) * cos(latrad) + enddo + enddo + enddo + + call ESMF_FieldDestroy(u_input_grid, rc=rc) + call ESMF_FieldDestroy(v_input_grid, rc=rc) + + end subroutine convert_winds_to_xyz + +!> Compute grid rotation angle for non-latlon grids. +!! +!! @note The original gridrot subroutine was specific to polar +!! stereographic grids. We need to compute it for Lambert Conformal +!! grids. So we need lat1,lat2. This follows the ncl_ncarg source +!! code: ncl_ncarg-6.6.2/ni/src/ncl/GetGrids.c +!! +!! @param [in] lov orientation angle +!! @param [in] latin1 first tangent latitude +!! @param [in] latin2 second tangent latitude +!! @param [in] lon longitude +!! @param [inout] rot rotation angle +!! @author Larissa Reames +subroutine gridrot(lov,latin1,latin2,lon,rot) + + use model_grid, only : i_input,j_input + implicit none + + + real(esmf_kind_r4), intent(in) :: lov,latin1,latin2 + real(esmf_kind_r4), intent(inout) :: rot(i_input,j_input) + real(esmf_kind_r8), intent(in) :: lon(i_input,j_input) + + real(esmf_kind_r4) :: trot(i_input,j_input), tlon(i_input,j_input) + real(esmf_kind_r4) :: dtor = 3.14159265359_esmf_kind_r4/180.0_esmf_kind_r4 + real(esmf_kind_r4) :: an + !trot_tmp = real(lon,esmf_kind_r4)-lov + !trot = trot_tmp + !where(trot_tmp > 180.0) trot = trot-360.0_esmf_kind_r4 + !where(trot_tmp < -180.0) trot = trot-360.0_esmf_kind_r4 + + if ( (latin1 - latin2) .lt. 0.000001 ) then + an = sin(latin1*dtor) + else + an = real(log( cos(latin1*dtor) / cos(latin2*dtor) ) / & + log( tan(dtor*(90.0-latin1)/2.) / tan(dtor*(90.0-latin2)/2.)), kind=esmf_kind_r4) + end if + + tlon = real((mod(lon - lov + 180. + 3600., 360.) - 180.), kind=esmf_kind_r4) + trot = an * tlon + + rot = trot * dtor + +end subroutine gridrot + +!> Calculate rotation angle for rotated latlon grids. +!! Needed to convert to earth-relative winds. +!! +!! @param [in] latgrid grid latitudes +!! @param [in] longrid grid longitudes +!! @param [in] cenlat center latitude +!! @param [in] cenlon center longitude +!! @param [out] alpha grid rotation angle +!! @author Larissa Reames +subroutine calcalpha_rotlatlon(latgrid,longrid,cenlat,cenlon,alpha) + + use model_grid, only : i_input,j_input + implicit none + + real(esmf_kind_r8), intent(in) :: latgrid(i_input,j_input), & + longrid(i_input,j_input) + real(esmf_kind_r4), intent(in) :: cenlat, cenlon + real(esmf_kind_r4), intent(out) :: alpha(i_input,j_input) + + ! Variables local to subroutine + real(esmf_kind_r8) :: D2R,lon0_r,lat0_r,sphi0,cphi0 + real(esmf_kind_r8), DIMENSION(i_input,j_input) :: tlat,tlon,tph,sinalpha + + D2R = acos(-1.0_esmf_kind_r8) / 180.0_esmf_kind_r8 + if (cenlon .lt. 0) then + lon0_r = (cenlon + 360.0)*D2R + else + lon0_r = cenlon*D2R + end if + lat0_r=cenlat*D2R + sphi0=sin(lat0_r) + cphi0=cos(lat0_r) + + ! deal with input lat/lon + tlat = latgrid * D2R + tlon = longrid * D2R + + ! Calculate alpha (rotation angle) + tlon = -tlon + lon0_r + tph = asin(cphi0*sin(tlat) - sphi0*cos(tlat)*cos(tlon)) + sinalpha = sphi0 * sin(tlon) / cos(tph) + alpha = real((-asin(sinalpha)/D2R), kind=esmf_kind_r4) + ! returns alpha in degrees +end subroutine calcalpha_rotlatlon + +!> Free up memory associated with atm data. +!! +!! @author George Gayno NCEP/EMC +subroutine cleanup_input_atm_data + + implicit none + + integer :: rc, n + + print*,'- DESTROY ATMOSPHERIC INPUT DATA.' + + call ESMF_FieldDestroy(terrain_input_grid, rc=rc) + call ESMF_FieldDestroy(pres_input_grid, rc=rc) + call ESMF_FieldDestroy(dzdt_input_grid, rc=rc) + call ESMF_FieldDestroy(temp_input_grid, rc=rc) + call ESMF_FieldDestroy(xwind_input_grid, rc=rc) + call ESMF_FieldDestroy(ywind_input_grid, rc=rc) + call ESMF_FieldDestroy(zwind_input_grid, rc=rc) + call ESMF_FieldDestroy(ps_input_grid, rc=rc) + + do n = 1, num_tracers_input + call ESMF_FieldDestroy(tracers_input_grid(n), rc=rc) + enddo + deallocate(tracers_input_grid) + + end subroutine cleanup_input_atm_data + +end module atm_input_data diff --git a/sorc/chgres_cube.fd/atmosphere.F90 b/sorc/chgres_cube.fd/atmosphere.F90 index 77926ac75..86d077d70 100644 --- a/sorc/chgres_cube.fd/atmosphere.F90 +++ b/sorc/chgres_cube.fd/atmosphere.F90 @@ -20,12 +20,24 @@ module atmosphere use esmf - use input_data, only : lev_input, & + use atmosphere_target_data, only : lev_target, levp1_target, nvcoord_target, & + vcoord_target, delp_target_grid, & + dzdt_target_grid, ps_target_grid, & + temp_target_grid, tracers_target_grid, & + u_s_target_grid, v_s_target_grid, & + u_w_target_grid, v_w_target_grid, & + zh_target_grid, qnwfa_climo_target_grid, & + qnifa_climo_target_grid, ua_target_grid, & + va_target_grid + + use atm_input_data, only : lev_input, & levp1_input, & tracers_input_grid, & dzdt_input_grid, & ps_input_grid, & - wind_input_grid, & + xwind_input_grid, & + ywind_input_grid, & + zwind_input_grid, & temp_input_grid, & pres_input_grid, & terrain_input_grid, & @@ -47,7 +59,7 @@ module atmosphere terrain_target_grid use program_setup, only : vcoord_file_target_grid, & - wam_cold_start, & + wam_cold_start, wam_parm_file, & cycle_year, cycle_mon, & cycle_day, cycle_hour, & regional, & @@ -63,52 +75,44 @@ module atmosphere thomp_pres_climo_input_grid, & lev_thomp_mp_climo - implicit none + use write_data, only : write_fv3_atm_header_netcdf, & + write_fv3_atm_bndy_data_netcdf, & + write_fv3_atm_data_netcdf, & + write_fv3_atm_warm_restart - private + use utilities, only : error_handler - integer, public :: lev_target !< num vertical levels - integer, public :: levp1_target !< num levels plus 1 - integer, public :: nvcoord_target !< num vertical coordinate variables + implicit none - real(esmf_kind_r8), allocatable, public :: vcoord_target(:,:) !< vertical coordinate + private - type(esmf_field), public :: delp_target_grid !< pressure thickness - type(esmf_field), public :: dzdt_target_grid !< vertical velocity type(esmf_field) :: dzdt_b4adj_target_grid !< vertical vel before vert adj - type(esmf_field), allocatable, public :: tracers_target_grid(:) !< tracers type(esmf_field), allocatable :: tracers_b4adj_target_grid(:) !< tracers before vert adj - type(esmf_field), public :: ps_target_grid !< surface pressure type(esmf_field) :: ps_b4adj_target_grid !< sfc pres before terrain adj type(esmf_field) :: pres_target_grid !< 3-d pressure type(esmf_field) :: pres_b4adj_target_grid !< 3-d pres before terrain adj - type(esmf_field), public :: temp_target_grid !< temperautre type(esmf_field) :: temp_b4adj_target_grid !< temp before vert adj type(esmf_field) :: terrain_interp_to_target_grid !< Input grid terrain interpolated to target grid. - type(esmf_field), public :: u_s_target_grid !< u-wind, 'south' edge - type(esmf_field), public :: v_s_target_grid !< v-wind, 'south' edge - type(esmf_field) :: wind_target_grid !< 3-d wind, grid box center - type(esmf_field) :: wind_b4adj_target_grid !< 3-d wind before vert adj - type(esmf_field) :: wind_s_target_grid !< 3-d wind, 'south' edge - type(esmf_field), public :: u_w_target_grid !< u-wind, 'west' edge - type(esmf_field), public :: v_w_target_grid !< v-wind, 'west' edge - type(esmf_field), public :: ua_target_grid - type(esmf_field), public :: va_target_grid - type(esmf_field) :: wind_w_target_grid !< 3-d wind, 'west' edge - type(esmf_field), public :: zh_target_grid !< 3-d height + + type(esmf_field) :: xwind_target_grid !< x-component wind, grid box center + type(esmf_field) :: ywind_target_grid !< y-component wind, grid box center + type(esmf_field) :: zwind_target_grid !< z-component wind, grid box center + type(esmf_field) :: xwind_b4adj_target_grid !< x-component wind, before vert adj + type(esmf_field) :: ywind_b4adj_target_grid !< y-component wind, before vert adj + type(esmf_field) :: zwind_b4adj_target_grid !< z-component wind, before vert adj + type(esmf_field) :: xwind_s_target_grid !< x-component wind, 'south' edge + type(esmf_field) :: ywind_s_target_grid !< y-component wind, 'south' edge + type(esmf_field) :: zwind_s_target_grid !< z-component wind, 'south' edge + type(esmf_field) :: xwind_w_target_grid !< x-component wind, 'west' edge + type(esmf_field) :: ywind_w_target_grid !< y-component wind, 'west' edge + type(esmf_field) :: zwind_w_target_grid !< z-component wind, 'west' edge ! Fields associated with thompson microphysics climatological tracers. type(esmf_field) :: qnifa_climo_b4adj_target_grid !< number concentration of ice !! friendly aerosols before vert adj - type(esmf_field), public :: qnifa_climo_target_grid !< number concentration of ice - !! friendly aerosols on target - !! horiz/vert grid. type(esmf_field) :: qnwfa_climo_b4adj_target_grid !< number concentration of water !! friendly aerosols before vert adj - type(esmf_field), public :: qnwfa_climo_target_grid !< number concentration of water - !! friendly aerosols on target - !! horiz/vert grid. type(esmf_field) :: thomp_pres_climo_b4adj_target_grid !< pressure of each level on !! target grid @@ -293,14 +297,32 @@ subroutine atmosphere_driver(localpet) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldRegrid", rc) - print*,"- CALL Field_Regrid FOR 3-D WIND." - call ESMF_FieldRegrid(wind_input_grid, & - wind_b4adj_target_grid, & + print*,"- CALL Field_Regrid FOR x WIND." + call ESMF_FieldRegrid(xwind_input_grid, & + xwind_b4adj_target_grid, & routehandle=regrid_bl, & termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldRegrid", rc) + print*,"- CALL Field_Regrid FOR y WIND." + call ESMF_FieldRegrid(ywind_input_grid, & + ywind_b4adj_target_grid, & + routehandle=regrid_bl, & + termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldRegrid", rc) + + print*,"- CALL Field_Regrid FOR z WIND." + call ESMF_FieldRegrid(zwind_input_grid, & + zwind_b4adj_target_grid, & + routehandle=regrid_bl, & + termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldRegrid", rc) + + + print*,"- CALL FieldRegridRelease." call ESMF_FieldRegridRelease(routehandle=regrid_bl, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & @@ -337,7 +359,7 @@ subroutine atmosphere_driver(localpet) call vintg if( wam_cold_start ) then - call vintg_wam (cycle_year,cycle_mon,cycle_day,cycle_hour) + call vintg_wam (cycle_year,cycle_mon,cycle_day,cycle_hour,wam_parm_file) endif !----------------------------------------------------------------------------------- @@ -359,9 +381,9 @@ subroutine atmosphere_driver(localpet) isrctermprocessing = 1 method=ESMF_REGRIDMETHOD_BILINEAR - print*,"- CALL FieldRegridStore FOR 3D-WIND WEST EDGE." - call ESMF_FieldRegridStore(wind_target_grid, & - wind_w_target_grid, & + print*,"- CALL FieldRegridStore FOR X-WIND WEST EDGE." + call ESMF_FieldRegridStore(xwind_target_grid, & + xwind_w_target_grid, & polemethod=ESMF_POLEMETHOD_ALLAVG, & srctermprocessing=isrctermprocessing, & routehandle=regrid_bl, & @@ -370,9 +392,25 @@ subroutine atmosphere_driver(localpet) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldRegridStore", rc) - print*,"- CALL Field_Regrid FOR 3-D WIND WEST EDGE." - call ESMF_FieldRegrid(wind_target_grid, & - wind_w_target_grid, & + print*,"- CALL Field_Regrid FOR X-WIND WEST EDGE." + call ESMF_FieldRegrid(xwind_target_grid, & + xwind_w_target_grid, & + routehandle=regrid_bl, & + termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldRegrid", rc) + + print*,"- CALL Field_Regrid FOR Y-WIND WEST EDGE." + call ESMF_FieldRegrid(ywind_target_grid, & + ywind_w_target_grid, & + routehandle=regrid_bl, & + termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldRegrid", rc) + + print*,"- CALL Field_Regrid FOR Z-WIND WEST EDGE." + call ESMF_FieldRegrid(zwind_target_grid, & + zwind_w_target_grid, & routehandle=regrid_bl, & termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & @@ -386,9 +424,9 @@ subroutine atmosphere_driver(localpet) isrctermprocessing = 1 method=ESMF_REGRIDMETHOD_BILINEAR - print*,"- CALL FieldRegridStore FOR 3D-WIND SOUTH EDGE." - call ESMF_FieldRegridStore(wind_target_grid, & - wind_s_target_grid, & + print*,"- CALL FieldRegridStore FOR X-WIND SOUTH EDGE." + call ESMF_FieldRegridStore(xwind_target_grid, & + xwind_s_target_grid, & polemethod=ESMF_POLEMETHOD_ALLAVG, & srctermprocessing=isrctermprocessing, & routehandle=regrid_bl, & @@ -397,9 +435,25 @@ subroutine atmosphere_driver(localpet) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldRegridStore", rc) - print*,"- CALL Field_Regrid FOR 3-D WIND SOUTH EDGE." - call ESMF_FieldRegrid(wind_target_grid, & - wind_s_target_grid, & + print*,"- CALL Field_Regrid FOR X-WIND SOUTH EDGE." + call ESMF_FieldRegrid(xwind_target_grid, & + xwind_s_target_grid, & + routehandle=regrid_bl, & + termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldRegrid", rc) + + print*,"- CALL Field_Regrid FOR Y-WIND SOUTH EDGE." + call ESMF_FieldRegrid(ywind_target_grid, & + ywind_s_target_grid, & + routehandle=regrid_bl, & + termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldRegrid", rc) + + print*,"- CALL Field_Regrid FOR Z-WIND SOUTH EDGE." + call ESMF_FieldRegrid(zwind_target_grid, & + zwind_s_target_grid, & routehandle=regrid_bl, & termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & @@ -414,7 +468,7 @@ subroutine atmosphere_driver(localpet) ! Convert from 3-d to 2-d cartesian winds. !----------------------------------------------------------------------------------- - call convert_winds + call convert_winds_to_uv call turn_winds(localpet) @@ -442,7 +496,7 @@ subroutine atmosphere_driver(localpet) ! Free up memory. !----------------------------------------------------------------------------------- - call cleanup_target_atm_data + call cleanup_all_target_atm_data end subroutine atmosphere_driver @@ -497,12 +551,30 @@ subroutine create_atm_b4adj_esmf_fields if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) - print*,"- CALL FieldCreate FOR TARGET GRID UNSTAGGERED WINDS BEFORE ADJUSTMENT." - wind_b4adj_target_grid = ESMF_FieldCreate(target_grid, & + print*,"- CALL FieldCreate FOR TARGET GRID xwind." + xwind_b4adj_target_grid = ESMF_FieldCreate(target_grid, & typekind=ESMF_TYPEKIND_R8, & staggerloc=ESMF_STAGGERLOC_CENTER, & - ungriddedLBound=(/1,1/), & - ungriddedUBound=(/lev_input,3/), rc=rc) + ungriddedLBound=(/1/), & + ungriddedUBound=(/lev_input/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR TARGET GRID ywind." + ywind_b4adj_target_grid = ESMF_FieldCreate(target_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + ungriddedLBound=(/1/), & + ungriddedUBound=(/lev_input/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR TARGET GRID zwind." + zwind_b4adj_target_grid = ESMF_FieldCreate(target_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + ungriddedLBound=(/1/), & + ungriddedUBound=(/lev_input/), rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) @@ -598,21 +670,39 @@ subroutine create_atm_esmf_fields if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) - print*,"- CALL FieldCreate FOR TARGET HEIGHT." - zh_target_grid = ESMF_FieldCreate(target_grid, & + print*,"- CALL FieldCreate FOR TARGET GRID xwind." + xwind_target_grid = ESMF_FieldCreate(target_grid, & typekind=ESMF_TYPEKIND_R8, & staggerloc=ESMF_STAGGERLOC_CENTER, & ungriddedLBound=(/1/), & - ungriddedUBound=(/levp1_target/), rc=rc) + ungriddedUBound=(/lev_target/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR TARGET GRID ywind." + ywind_target_grid = ESMF_FieldCreate(target_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + ungriddedLBound=(/1/), & + ungriddedUBound=(/lev_target/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR TARGET GRID zwind." + zwind_target_grid = ESMF_FieldCreate(target_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + ungriddedLBound=(/1/), & + ungriddedUBound=(/lev_target/), rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) - print*,"- CALL FieldCreate FOR TARGET UNSTAGGERED 3D-WIND." - wind_target_grid = ESMF_FieldCreate(target_grid, & + print*,"- CALL FieldCreate FOR TARGET HEIGHT." + zh_target_grid = ESMF_FieldCreate(target_grid, & typekind=ESMF_TYPEKIND_R8, & staggerloc=ESMF_STAGGERLOC_CENTER, & - ungriddedLBound=(/1,1/), & - ungriddedUBound=(/lev_target,3/), rc=rc) + ungriddedLBound=(/1/), & + ungriddedUBound=(/levp1_target/), rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) @@ -634,12 +724,30 @@ subroutine create_atm_esmf_fields if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) - print*,"- CALL FieldCreate FOR TARGET 3D-WIND_S." - wind_s_target_grid = ESMF_FieldCreate(target_grid, & + print*,"- CALL FieldCreate FOR TARGET xwind_S." + xwind_s_target_grid = ESMF_FieldCreate(target_grid, & typekind=ESMF_TYPEKIND_R8, & staggerloc=ESMF_STAGGERLOC_EDGE2, & - ungriddedLBound=(/1,1/), & - ungriddedUBound=(/lev_target,3/), rc=rc) + ungriddedLBound=(/1/), & + ungriddedUBound=(/lev_target/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR TARGET ywind_S." + ywind_s_target_grid = ESMF_FieldCreate(target_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_EDGE2, & + ungriddedLBound=(/1/), & + ungriddedUBound=(/lev_target/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR TARGET zwind_S." + zwind_s_target_grid = ESMF_FieldCreate(target_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_EDGE2, & + ungriddedLBound=(/1/), & + ungriddedUBound=(/lev_target/), rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) @@ -661,12 +769,30 @@ subroutine create_atm_esmf_fields if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) - print*,"- CALL FieldCreate FOR TARGET 3D-WIND_W." - wind_w_target_grid = ESMF_FieldCreate(target_grid, & + print*,"- CALL FieldCreate FOR TARGET xwind_W." + xwind_w_target_grid = ESMF_FieldCreate(target_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_EDGE1, & + ungriddedLBound=(/1/), & + ungriddedUBound=(/lev_target/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR TARGET ywind_W." + ywind_w_target_grid = ESMF_FieldCreate(target_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_EDGE1, & + ungriddedLBound=(/1/), & + ungriddedUBound=(/lev_target/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR TARGET zwind_W." + zwind_w_target_grid = ESMF_FieldCreate(target_grid, & typekind=ESMF_TYPEKIND_R8, & staggerloc=ESMF_STAGGERLOC_EDGE1, & - ungriddedLBound=(/1,1/), & - ungriddedUBound=(/lev_target,3/), rc=rc) + ungriddedLBound=(/1/), & + ungriddedUBound=(/lev_target/), rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) @@ -682,18 +808,20 @@ end subroutine create_atm_esmf_fields !> Convert 3-d component winds to u and v. !! !! @author George Gayno - subroutine convert_winds + subroutine convert_winds_to_uv implicit none - integer :: clb(4), cub(4) + integer :: clb(3), cub(3) integer :: i, j, k, rc real(esmf_kind_r8), pointer :: latptr(:,:) real(esmf_kind_r8), pointer :: lonptr(:,:) real(esmf_kind_r8), pointer :: uptr(:,:,:) real(esmf_kind_r8), pointer :: vptr(:,:,:) - real(esmf_kind_r8), pointer :: windptr(:,:,:,:) + real(esmf_kind_r8), pointer :: xwindptr(:,:,:) + real(esmf_kind_r8), pointer :: ywindptr(:,:,:) + real(esmf_kind_r8), pointer :: zwindptr(:,:,:) real(esmf_kind_r8) :: latrad, lonrad !----------------------------------------------------------------------------------- @@ -702,11 +830,23 @@ subroutine convert_winds print*,'- CONVERT WINDS.' - print*,"- CALL FieldGet FOR 3-D WIND_S." - call ESMF_FieldGet(wind_s_target_grid, & + print*,"- CALL FieldGet FOR xwind_S." + call ESMF_FieldGet(xwind_s_target_grid, & computationalLBound=clb, & computationalUBound=cub, & - farrayPtr=windptr, rc=rc) + farrayPtr=xwindptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + print*,"- CALL FieldGet FOR ywind_S." + call ESMF_FieldGet(ywind_s_target_grid, & + farrayPtr=ywindptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + print*,"- CALL FieldGet FOR zwind_S." + call ESMF_FieldGet(zwind_s_target_grid, & + farrayPtr=zwindptr, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldGet", rc) @@ -739,20 +879,31 @@ subroutine convert_winds latrad = latptr(i,j) * acos(-1.) / 180.0 lonrad = lonptr(i,j) * acos(-1.) / 180.0 do k = clb(3), cub(3) - uptr(i,j,k) = windptr(i,j,k,1) * cos(lonrad) + windptr(i,j,k,2) * sin(lonrad) - vptr(i,j,k) = -windptr(i,j,k,1) * sin(latrad) * sin(lonrad) + & - windptr(i,j,k,2) * sin(latrad) * cos(lonrad) + & - windptr(i,j,k,3) * cos(latrad) + uptr(i,j,k) = xwindptr(i,j,k) * cos(lonrad) + ywindptr(i,j,k) * sin(lonrad) + vptr(i,j,k) = -xwindptr(i,j,k) * sin(latrad) * sin(lonrad) + & + ywindptr(i,j,k) * sin(latrad) * cos(lonrad) + & + zwindptr(i,j,k) * cos(latrad) enddo enddo enddo - - print*,"- CALL FieldGet FOR 3-D WIND_W." - call ESMF_FieldGet(wind_w_target_grid, & + print*,"- CALL FieldGet FOR xwind_w." + call ESMF_FieldGet(xwind_w_target_grid, & computationalLBound=clb, & computationalUBound=cub, & - farrayPtr=windptr, rc=rc) + farrayPtr=xwindptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + print*,"- CALL FieldGet FOR ywind_w." + call ESMF_FieldGet(ywind_w_target_grid, & + farrayPtr=ywindptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + print*,"- CALL FieldGet FOR zwind_w." + call ESMF_FieldGet(zwind_w_target_grid, & + farrayPtr=zwindptr, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldGet", rc) @@ -785,22 +936,35 @@ subroutine convert_winds latrad = latptr(i,j) * acos(-1.) / 180.0 lonrad = lonptr(i,j) * acos(-1.) / 180.0 do k = clb(3), cub(3) - uptr(i,j,k) = windptr(i,j,k,1) * cos(lonrad) + windptr(i,j,k,2) * sin(lonrad) - vptr(i,j,k) = -windptr(i,j,k,1) * sin(latrad) * sin(lonrad) + & - windptr(i,j,k,2) * sin(latrad) * cos(lonrad) + & - windptr(i,j,k,3) * cos(latrad) + uptr(i,j,k) = xwindptr(i,j,k) * cos(lonrad) + ywindptr(i,j,k) * sin(lonrad) + vptr(i,j,k) = -xwindptr(i,j,k) * sin(latrad) * sin(lonrad) + & + ywindptr(i,j,k) * sin(latrad) * cos(lonrad) + & + zwindptr(i,j,k) * cos(latrad) enddo enddo enddo - print*,"- CALL FieldGet FOR 3-D WIND." - call ESMF_FieldGet(wind_target_grid, & + print*,"- CALL FieldGet FOR xwind." + call ESMF_FieldGet(xwind_target_grid, & computationalLBound=clb, & computationalUBound=cub, & - farrayPtr=windptr, rc=rc) + farrayPtr=xwindptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + print*,"- CALL FieldGet FOR ywind." + call ESMF_FieldGet(ywind_target_grid, & + farrayPtr=ywindptr, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + print*,"- CALL FieldGet FOR zwind." + call ESMF_FieldGet(zwind_target_grid, & + farrayPtr=zwindptr, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldGet", rc) +! for warm restart files - AMG print*,"- CALL FieldGet FOR Ua." call ESMF_FieldGet(ua_target_grid, & farrayPtr=uptr, rc=rc) @@ -818,7 +982,7 @@ subroutine convert_winds farrayPtr=latptr, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldGet", rc) - + print*,"- CALL FieldGet FOR LONGITUDE." call ESMF_FieldGet(longitude_target_grid, & farrayPtr=lonptr, rc=rc) @@ -830,17 +994,20 @@ subroutine convert_winds latrad = latptr(i,j) * acos(-1.) / 180.0 lonrad = lonptr(i,j) * acos(-1.) / 180.0 do k = clb(3), cub(3) - uptr(i,j,k) = windptr(i,j,k,1) * cos(lonrad) + windptr(i,j,k,2) * sin(lonrad) - vptr(i,j,k) = -windptr(i,j,k,1) * sin(latrad) * sin(lonrad) + & - windptr(i,j,k,2) * sin(latrad) * cos(lonrad) + & - windptr(i,j,k,3) * cos(latrad) + uptr(i,j,k) = xwindptr(i,j,k) * cos(lonrad) + ywindptr(i,j,k) * sin(lonrad) + vptr(i,j,k) = -xwindptr(i,j,k) * sin(latrad) * sin(lonrad) + & + ywindptr(i,j,k) * sin(latrad) * cos(lonrad) + & + zwindptr(i,j,k) * cos(latrad) enddo enddo enddo - end subroutine convert_winds + end subroutine convert_winds_to_uv subroutine turn_winds(localpet) +!! +!! converts winds from earth-relative to grid-relative +!! use atm_utils @@ -1595,15 +1762,17 @@ END SUBROUTINE VINTG_THOMP_MP_CLIMO !! @param [in] month initial month !! @param [in] day initial day !! @param [in] hour initial hour +!! @param [in] pf path to MSIS2.1 parm file !! !! @author Hann-Ming Henry Juang NCEP/EMC - SUBROUTINE VINTG_WAM (YEAR,MONTH,DAY,HOUR) + SUBROUTINE VINTG_WAM (YEAR,MONTH,DAY,HOUR,PF) IMPLICIT NONE include 'mpif.h' INTEGER, INTENT(IN) :: YEAR,MONTH,DAY,HOUR + CHARACTER(*), INTENT(IN) :: PF REAL(ESMF_KIND_R8), PARAMETER :: AMO = 15.9994 ! molecular weight of o REAL(ESMF_KIND_R8), PARAMETER :: AMO2 = 31.999 !molecular weight of o2 @@ -1626,7 +1795,9 @@ SUBROUTINE VINTG_WAM (YEAR,MONTH,DAY,HOUR) REAL(ESMF_KIND_R8), POINTER :: QOPTR(:,:,:) ! output tracer REAL(ESMF_KIND_R8), POINTER :: O2PTR(:,:,:) ! output tracer REAL(ESMF_KIND_R8), POINTER :: O3PTR(:,:,:) ! output tracer - REAL(ESMF_KIND_R8), POINTER :: WIND2PTR(:,:,:,:) ! output wind (x,y,z components) + REAL(ESMF_KIND_R8), POINTER :: XWIND2PTR(:,:,:) ! output wind (x component) + REAL(ESMF_KIND_R8), POINTER :: YWIND2PTR(:,:,:) ! output wind (y component) + REAL(ESMF_KIND_R8), POINTER :: ZWIND2PTR(:,:,:) ! output wind (z component) ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1696,9 +1867,20 @@ SUBROUTINE VINTG_WAM (YEAR,MONTH,DAY,HOUR) call error_handler("IN FieldGet", rc) ! wind - print*,"VINTG_WAM:- CALL FieldGet FOR 3-D ADJUSTED WIND." - call ESMF_FieldGet(wind_target_grid, & - farrayPtr=WIND2PTR, rc=rc) + print*,"VINTG_WAM:- CALL FieldGet FOR ADJUSTED WIND COMPONENTS." + + call ESMF_FieldGet(xwind_target_grid, & + farrayPtr=XWIND2PTR, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + call ESMF_FieldGet(ywind_target_grid, & + farrayPtr=YWIND2PTR, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + call ESMF_FieldGet(zwind_target_grid, & + farrayPtr=ZWIND2PTR, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldGet", rc) @@ -1711,17 +1893,15 @@ SUBROUTINE VINTG_WAM (YEAR,MONTH,DAY,HOUR) DO K=1,LEV_TARGET IF(P2PTR(I,J,K).le.P1PTR(I,J,LEV_INPUT)) THEN KREF =K-1 -!x print*,'VINTG_WAM: KREF P1 P2 ',KREF,P1PTR(I,J,LEV_INPUT),P2PTR(I,J,K) - GO TO 11 + EXIT ENDIF ENDDO - 11 CONTINUE ! DO K=KREF,LEV_TARGET COE = P2PTR(I,J,K) / P2PTR(I,J,KREF) - WIND2PTR(I,J,K,1) = COE*WIND2PTR(I,J,K,1) - WIND2PTR(I,J,K,2) = COE*WIND2PTR(I,J,K,2) - WIND2PTR(I,J,K,3) = COE*WIND2PTR(I,J,K,3) + XWIND2PTR(I,J,K) = COE*XWIND2PTR(I,J,K) + YWIND2PTR(I,J,K) = COE*YWIND2PTR(I,J,K) + ZWIND2PTR(I,J,K) = COE*ZWIND2PTR(I,J,K) DZDT2PTR(I,J,K) = COE*DZDT2PTR(I,J,K) ENDDO @@ -1744,10 +1924,9 @@ SUBROUTINE VINTG_WAM (YEAR,MONTH,DAY,HOUR) DO K=1,LEV_TARGET IF(P2PTR(I,J,K).le.P1PTR(I,J,LEV_INPUT)) THEN KREF =K-1 - GO TO 22 + EXIT ENDIF ENDDO - 22 CONTINUE ! DO K=KREF,LEV_TARGET COE = MIN(1.0, P2PTR(I,J,K) / P2PTR(I,J,KREF) ) @@ -1773,7 +1952,7 @@ SUBROUTINE VINTG_WAM (YEAR,MONTH,DAY,HOUR) DO K=1,LEV_TARGET PRMB(K) = P2PTR(I,J,K) * 0.01 ENDDO - CALL GETTEMP(ICDAY,1,DEGLAT,1,PRMB,LEV_TARGET,TEMP,ON,O2N,N2N) + CALL GETTEMP(ICDAY,DEGLAT,PRMB,LEV_TARGET,PF,TEMP,ON,O2N,N2N) ! DO K=1,LEV_TARGET SUMMASS = ON(K)*AMO+O2N(K)*AMO2+N2N(K)*AMN2 @@ -1791,10 +1970,9 @@ SUBROUTINE VINTG_WAM (YEAR,MONTH,DAY,HOUR) DO K=1,LEV_TARGET IF(P2PTR(I,J,K).le.P1PTR(I,J,LEV_INPUT)) THEN KREF =K-1 - GO TO 33 + EXIT ENDIF ENDDO - 33 CONTINUE ! DO K=KREF,LEV_TARGET T2PTR(I,J,K) = TEMP(K) @@ -1847,8 +2025,12 @@ SUBROUTINE VINTG REAL(ESMF_KIND_R8), POINTER :: T2PTR(:,:,:) ! output temperature REAL(ESMF_KIND_R8), POINTER :: Q1PTR(:,:,:) ! input tracer REAL(ESMF_KIND_R8), POINTER :: Q2PTR(:,:,:) ! output tracer - REAL(ESMF_KIND_R8), POINTER :: WIND1PTR(:,:,:,:) ! input wind (x,y,z components) - REAL(ESMF_KIND_R8), POINTER :: WIND2PTR(:,:,:,:) ! input wind (x,y,z components) + REAL(ESMF_KIND_R8), POINTER :: XWIND1PTR(:,:,:) ! input wind (x component) + REAL(ESMF_KIND_R8), POINTER :: YWIND1PTR(:,:,:) ! input wind (y component) + REAL(ESMF_KIND_R8), POINTER :: ZWIND1PTR(:,:,:) ! input wind (z component) + REAL(ESMF_KIND_R8), POINTER :: XWIND2PTR(:,:,:) ! output wind (x component) + REAL(ESMF_KIND_R8), POINTER :: YWIND2PTR(:,:,:) ! output wind (y component) + REAL(ESMF_KIND_R8), POINTER :: ZWIND2PTR(:,:,:) ! output wind (z component) ! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ! COMPUTE LOG PRESSURE INTERPOLATING COORDINATE @@ -1885,17 +2067,31 @@ SUBROUTINE VINTG call error_handler("IN FieldGet", rc) Z2 = -LOG(P2PTR) + + print*,"- CALL FieldGet FOR x WIND." + call ESMF_FieldGet(xwind_b4adj_target_grid, & + farrayPtr=XWIND1PTR, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) - print*,"- CALL FieldGet FOR 3-D WIND." - call ESMF_FieldGet(wind_b4adj_target_grid, & - farrayPtr=WIND1PTR, rc=rc) + C1(:,:,:,1) = XWIND1PTR(:,:,:) + + print*,"- CALL FieldGet FOR y WIND." + call ESMF_FieldGet(ywind_b4adj_target_grid, & + farrayPtr=YWIND1PTR, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldGet", rc) - C1(:,:,:,1) = WIND1PTR(:,:,:,1) - C1(:,:,:,2) = WIND1PTR(:,:,:,2) - C1(:,:,:,3) = WIND1PTR(:,:,:,3) - + C1(:,:,:,2) = YWIND1PTR(:,:,:) + + print*,"- CALL FieldGet FOR z WIND." + call ESMF_FieldGet(zwind_b4adj_target_grid, & + farrayPtr=ZWIND1PTR, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + C1(:,:,:,3) = ZWIND1PTR(:,:,:) + print*,"- CALL FieldGet FOR VERTICAL VELOCITY." call ESMF_FieldGet(dzdt_b4adj_target_grid, & farrayPtr=DZDT1PTR, rc=rc) @@ -1956,18 +2152,30 @@ SUBROUTINE VINTG if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldGet", rc) - print*,"- CALL FieldGet FOR 3-D ADJUSTED WIND." - call ESMF_FieldGet(wind_target_grid, & - farrayPtr=WIND2PTR, rc=rc) + print*,"- CALL FieldGet FOR ADJUSTED xwind." + call ESMF_FieldGet(xwind_target_grid, & + farrayPtr=XWIND2PTR, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + print*,"- CALL FieldGet FOR ADJUSTED ywind." + call ESMF_FieldGet(ywind_target_grid, & + farrayPtr=YWIND2PTR, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + + print*,"- CALL FieldGet FOR ADJUSTED zwind." + call ESMF_FieldGet(zwind_target_grid, & + farrayPtr=ZWIND2PTR, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldGet", rc) DO K=1,LEV_TARGET DO I=CLB(1),CUB(1) DO J=CLB(2),CUB(2) - WIND2PTR(I,J,K,1)=C2(I,J,K,1) - WIND2PTR(I,J,K,2)=C2(I,J,K,2) - WIND2PTR(I,J,K,3)=C2(I,J,K,3) + XWIND2PTR(I,J,K)=C2(I,J,K,1) + YWIND2PTR(I,J,K)=C2(I,J,K,2) + ZWIND2PTR(I,J,K)=C2(I,J,K,3) DZDT2PTR(I,J,K)=C2(I,J,K,4) DZ=Z2(I,J,K)-Z1(I,J,1) IF(DZ.GE.0) THEN @@ -2396,7 +2604,9 @@ subroutine cleanup_target_atm_b4adj_data print*,"- DESTROY TARGET GRID ATMOSPHERIC BEFORE ADJUSTMENT FIELDS." - call ESMF_FieldDestroy(wind_b4adj_target_grid, rc=rc) + call ESMF_FieldDestroy(xwind_b4adj_target_grid, rc=rc) + call ESMF_FieldDestroy(ywind_b4adj_target_grid, rc=rc) + call ESMF_FieldDestroy(zwind_b4adj_target_grid, rc=rc) call ESMF_FieldDestroy(dzdt_b4adj_target_grid, rc=rc) call ESMF_FieldDestroy(ps_b4adj_target_grid, rc=rc) call ESMF_FieldDestroy(pres_b4adj_target_grid, rc=rc) @@ -2413,42 +2623,29 @@ end subroutine cleanup_target_atm_b4adj_data !> Cleanup target grid atmospheric field objects. !! @author George Gayno - subroutine cleanup_target_atm_data + subroutine cleanup_all_target_atm_data + + use atmosphere_target_data, only : cleanup_atmosphere_target_data implicit none - integer :: i, rc + integer :: rc - print*,"- DESTROY TARGET GRID ATMOSPHERIC FIELDS." + print*,"- DESTROY LOCAL TARGET GRID ATMOSPHERIC FIELDS." - call ESMF_FieldDestroy(delp_target_grid, rc=rc) - call ESMF_FieldDestroy(dzdt_target_grid, rc=rc) - call ESMF_FieldDestroy(ps_target_grid, rc=rc) call ESMF_FieldDestroy(pres_target_grid, rc=rc) - call ESMF_FieldDestroy(temp_target_grid, rc=rc) - call ESMF_FieldDestroy(u_s_target_grid, rc=rc) - call ESMF_FieldDestroy(v_s_target_grid, rc=rc) - call ESMF_FieldDestroy(wind_target_grid, rc=rc) - call ESMF_FieldDestroy(wind_s_target_grid, rc=rc) - call ESMF_FieldDestroy(wind_w_target_grid, rc=rc) - call ESMF_FieldDestroy(u_w_target_grid, rc=rc) - call ESMF_FieldDestroy(v_w_target_grid, rc=rc) - call ESMF_FieldDestroy(zh_target_grid, rc=rc) - - do i = 1, num_tracers - call ESMF_FieldDestroy(tracers_target_grid(i), rc=rc) - enddo - - deallocate(tracers_target_grid) - - if (ESMF_FieldIsCreated(qnifa_climo_target_grid)) then - call ESMF_FieldDestroy(qnifa_climo_target_grid, rc=rc) - endif - - if (ESMF_FieldIsCreated(qnwfa_climo_target_grid)) then - call ESMF_FieldDestroy(qnwfa_climo_target_grid, rc=rc) - endif - - end subroutine cleanup_target_atm_data + call ESMF_FieldDestroy(xwind_target_grid, rc=rc) + call ESMF_FieldDestroy(ywind_target_grid, rc=rc) + call ESMF_FieldDestroy(zwind_target_grid, rc=rc) + call ESMF_FieldDestroy(xwind_s_target_grid, rc=rc) + call ESMF_FieldDestroy(ywind_s_target_grid, rc=rc) + call ESMF_FieldDestroy(zwind_s_target_grid, rc=rc) + call ESMF_FieldDestroy(xwind_w_target_grid, rc=rc) + call ESMF_FieldDestroy(ywind_w_target_grid, rc=rc) + call ESMF_FieldDestroy(zwind_w_target_grid, rc=rc) + + call cleanup_atmosphere_target_data + + end subroutine cleanup_all_target_atm_data end module atmosphere diff --git a/sorc/chgres_cube.fd/atmosphere_target_data.F90 b/sorc/chgres_cube.fd/atmosphere_target_data.F90 new file mode 100644 index 000000000..2b4edaf64 --- /dev/null +++ b/sorc/chgres_cube.fd/atmosphere_target_data.F90 @@ -0,0 +1,85 @@ +!> @file +!! @brief Define atmospheric target data variables. +!! @author George Gayno NCEP/EMC + +!> Module to hold variables and ESMF fields associated +!! with the target grid atmospheric data. +!! +!! @author George Gayno NCEP/EMC + module atmosphere_target_data + + use esmf + + implicit none + + private + + integer, public :: lev_target !< Number of vertical levels. + integer, public :: levp1_target !< Number of vertical levels plus 1. + integer, public :: nvcoord_target !< Number of vertical coordinate variables. + + real(esmf_kind_r8), allocatable, public :: vcoord_target(:,:) !< Vertical coordinate. + + type(esmf_field), public :: delp_target_grid !< Pressure thickness. + type(esmf_field), public :: dzdt_target_grid !< Vertical velocity. + type(esmf_field), public :: ps_target_grid !< Surface pressure. + type(esmf_field), public :: temp_target_grid !< Temperautre. + type(esmf_field), allocatable, public :: tracers_target_grid(:) !< Tracers. + type(esmf_field), public :: u_s_target_grid !< U-wind, 'south' edge of grid cell. + type(esmf_field), public :: v_s_target_grid !< V-wind, 'south' edge of grid cell. + type(esmf_field), public :: u_w_target_grid !< U-wind, 'west' edge of grid cell. + type(esmf_field), public :: v_w_target_grid !< V-wind, 'west' edge of grid cell. + type(esmf_field), public :: ua_target_grid + type(esmf_field), public :: va_target_grid + type(esmf_field), public :: zh_target_grid !< 3-d height. + type(esmf_field), public :: qnifa_climo_target_grid !< Number concentration of ice + !! friendly aerosols. + type(esmf_field), public :: qnwfa_climo_target_grid !< Number concentration of water + !! friendly aerosols. + + public :: cleanup_atmosphere_target_data + + contains + +!> Free up memory for fields and variables in this module. +!! +!! @author George.Gayno NOAA/EMC + subroutine cleanup_atmosphere_target_data + + use program_setup, only : num_tracers + + implicit none + + integer :: i, rc + + print*,"- DESTROY TARGET GRID ATMOSPHERIC FIELDS." + + if (ESMF_FieldIsCreated(delp_target_grid)) call ESMF_FieldDestroy(delp_target_grid, rc=rc) + if (ESMF_FieldIsCreated(dzdt_target_grid)) call ESMF_FieldDestroy(dzdt_target_grid, rc=rc) + if (ESMF_FieldIsCreated(ps_target_grid)) call ESMF_FieldDestroy(ps_target_grid, rc=rc) + if (ESMF_FieldIsCreated(temp_target_grid)) call ESMF_FieldDestroy(temp_target_grid, rc=rc) + if (ESMF_FieldIsCreated(u_s_target_grid)) call ESMF_FieldDestroy(u_s_target_grid, rc=rc) + if (ESMF_FieldIsCreated(v_s_target_grid)) call ESMF_FieldDestroy(v_s_target_grid, rc=rc) + if (ESMF_FieldIsCreated(u_w_target_grid)) call ESMF_FieldDestroy(u_w_target_grid, rc=rc) + if (ESMF_FieldIsCreated(v_w_target_grid)) call ESMF_FieldDestroy(v_w_target_grid, rc=rc) + if (ESMF_FieldIsCreated(zh_target_grid)) call ESMF_FieldDestroy(zh_target_grid, rc=rc) + + do i = 1, num_tracers + if (ESMF_FieldIsCreated(tracers_target_grid(i))) call ESMF_FieldDestroy(tracers_target_grid(i), rc=rc) + enddo + + if (allocated (tracers_target_grid)) deallocate(tracers_target_grid) + + if (ESMF_FieldIsCreated(qnifa_climo_target_grid)) then + call ESMF_FieldDestroy(qnifa_climo_target_grid, rc=rc) + endif + + if (ESMF_FieldIsCreated(qnwfa_climo_target_grid)) then + call ESMF_FieldDestroy(qnwfa_climo_target_grid, rc=rc) + endif + + if (allocated (vcoord_target)) deallocate(vcoord_target) + + end subroutine cleanup_atmosphere_target_data + + end module atmosphere_target_data diff --git a/sorc/chgres_cube.fd/chgres.F90 b/sorc/chgres_cube.fd/chgres.F90 index faf7a0d23..8b01656f2 100644 --- a/sorc/chgres_cube.fd/chgres.F90 +++ b/sorc/chgres_cube.fd/chgres.F90 @@ -39,6 +39,7 @@ program chgres use surface, only : surface_driver + use utilities, only : error_handler implicit none integer :: ierr, localpet, npets diff --git a/sorc/chgres_cube.fd/docs/Doxyfile.in b/sorc/chgres_cube.fd/docs/Doxyfile.in index b03185bc3..f66dd3943 100644 --- a/sorc/chgres_cube.fd/docs/Doxyfile.in +++ b/sorc/chgres_cube.fd/docs/Doxyfile.in @@ -897,7 +897,7 @@ FILE_PATTERNS = *.F90 \ # be searched for input files as well. # The default value is: NO. -RECURSIVE = YES +RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a @@ -906,7 +906,7 @@ RECURSIVE = YES # Note that relative paths are relative to the directory from which doxygen is # run. -EXCLUDE = ../../fre-nctools.fd +EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded diff --git a/sorc/chgres_cube.fd/docs/user_guide.md b/sorc/chgres_cube.fd/docs/user_guide.md index d2cb6f290..7fc9f4e68 100644 --- a/sorc/chgres_cube.fd/docs/user_guide.md +++ b/sorc/chgres_cube.fd/docs/user_guide.md @@ -2,383 +2,11 @@ # Introduction -The program chgres.F90 creates initial condition files to “coldstart” -the forecast model. The initial conditions are created from either -Global Forecast System (GFS) gridded binary version 2 (GRIB2), NOAA -Environmental Modeling System Input/Output (NEMSIO) data, or Network -Common Data Form (NetCDF) data. +The chgres_cube program creates initial condition files to coldstart +the forecast model. This document is part of the UFS_UTILS documentation. -The chgres_cube program is part of the [NCEPLIBS -UFS_UTILS](https://github.com/NOAA-EMC/UFS_UTILS) project. - -## Where to find GFS GRIB2, NEMSIO and NetCDF data - -### GRIB2 - -- 0.25-degree data (last 10 days only) - Use the - gfs.tHHz.pgrb2.0p25.f000 files in subdirectory - gfs.YYYYMMDD/HH here: - . - -- 0.5-degree data - Use the gfs_4_YYYYMMDD_00HH_000.grb2 file, - under GFS Forecasts 004 (0.5-deg) from the NCDC - Global - Forecast System - . Note: - Tests were not done with the AVN, MRF or analysis data. - -- 1.0-degree data - Use the gfs_3_YYYYMMDD_00HH_000.grb2 file, - under GFS Forecasts 003 (1-deg) from NCDC - Global Forecast - System - . Note: - Tests were not done with the AVN, MRF or analysis data. - -### NEMSIO - -- T1534 gaussian (last 10 days only) - Use the - gfs.tHHz.atmanl.nemsio (atmospheric fields) and - gfs.tHHz.sfcanl.nemsio (surface fields) files in subdirectory - gfs.YYYYMMDD/HH from - . - -### NetCDF - -- T1534 gaussian (don't have any more details at this time). - -# Initializing with GRIB2 data - some caveats - -Keep this in mind when using GFS GRIB2 data for model initialization: - -- GRIB2 data does not contain the fields needed for the Near Sea - Surface Temperature (NSST) scheme. See the next section for options - on running the forecast model in this situation. - -- Data is coarse (in vertical and horizontal) compared to the NCEP - operational GFS . May not provide a good initialization (especially - for the surface). Recommendations: - - - C96 - use 0.25, 0.5 or 1.0-degree GRIB2 data - - C192 - use 0.25 or 0.5-degree GRIB2 data - - C384 - use 0.25-degree GRIB2 data - - C768 - try the 0.25-degree GRIB2 data. But it may not work well. - -- Sea/lake ice thickness and column temperatures are not - available. So, nominal values of 1.5 m and 265 K are used. - -- Soil moisture in the GRIB2 files is created using bilinear - interpolation and, therefore, may be a mixture of values from - different soil types. Could result in poor latent/sensible heat - fluxes. - -- Ozone is not available at all isobaric levels. Missing levels are - set to a nominal value defined in the variable mapping (VARMAP) file - (1E-07). - -- Only tested with GRIB2 data from GFS v14 and v15 (from 12z July 19, - 2017 to current). May not work with older GFS data. Will not work - with GRIB2 data from other models. - -### Near Sea Surface Temperature (NSST) data and GRIB2 initialization - -The issue with not having NSST data is important. In GFS we use the -foundation temperature (Tref) and add a diurnal warming/cooling layer -using NSST. This is the surface temperature that is passed to the -atmospheric boundary layer. This is a critical feature, especially -when we are doing Data Assimilation. - -When using NEMSIO or NetCDF data to initialize the model, both the -foundation and surface temperature are available and the atmospheric -model should be run using the NSST option as this will properly -account for in the forward run of the model. - -In GRIB2 files only the Tsfc is stored and that is set as foundation -temperature as well. So the diurnal heating / cooling is baked into -the initial condition for the extent of the run. This can be critical -if the model is being initialized when the ocean is warm and -initialization is occuring at the peak of the diurnal warming. That -warm ocean will be baked in for the extent of the run and may spawn -off a number of fake hurricanes. The user has two options -- either to -use a spin up cycle to spin up NSST (set nstf_name = -[2,1,0,0,0] in input.nml of the model namelist file. This will -create a diurnal cycle after 24 hours of spin up), or to run the model -without any NSST option ( set nstf_name = [0,0,0,0,0] in -input.nml of the model namelist file. The user will also have -to choose one of the no NSST physics suite options in -input.nml). - -Note, that neither of these two options will get rid of the underlying -baked in heating/cooling in the surface temperature fields. For most -cases this may not be an issue, but where it is then the user will -either have to initialize the model with NEMSIO or NetCDF data, or -replace the surface temperature in the GRIB2 fields with independently -obtained foundation temperature. - -# chgres_cube namelist options - -Namelist variables with “input” in their name refer to data input to -chgres_cube. Namelist variables with “target” in their name refer to -the FV3 horizontal and vertical grid (i.e., the target grid -chgres_cube is mapping to). - -When using GRIB2 data as input to chgres_cube, set namelist as -follows: - - - fix_dir_target_grid - Path to the tiled FV3 surface climatological - files (such as albedo). - - - mosaic_file_target_grid - Path and name of the FV3 mosaic file. - - - orog_dir_target_grid - directory containing the tiled FV3 orography - and grid files (NetCDF). - - - orog_files_target_grid - names of the six tiled FV3 orography - files. - - - vcoord_file_target_grid - path and name of the model vertical - coordinate definition file (“global_hyblev.l$LEVS.txt). - - - data_dir_input_grid - directory containing the GRIB2 initial - conditions data - - - grib2_file_input_grid - name of the GRIB2 input data file - - - varmap_file - path and name of the variable mapping (VARMAP) table. - See below for details on this table. - - - input_type - input data type. Set to ‘grib2’ - - - cycle_mon/day/hour - month/day/hour of your model initialization - - - convert_atm - set to ‘true’ to process the atmospheric fields - - - convert_sfc - set to ‘true’ to process the surface fields - -When using NEMSIO data as input to chgres_cube, set namelist as follows: - - - fix_dir_target_grid - Path to the tiled FV3 surface climatological - files (such as albedo). - - - mosaic_file_target_grid - Path and name of the FV3 mosaic file. - - - orog_dir_target_grid - directory containing the tiled FV3 orography - and grid files (NetCDF). - - - orog_files_target_grid - names of the six tiled FV3 orography - files. - - - vcoord_file_target_grid - path and name of the model vertical - coordinate definition file (“global_hyblev.l$LEVS.txt). - - - data_dir_input_grid - directory containing the NEMSIO input data - - - atm_files_input_grid - name of the NEMSIO input atmospheric data - file - - - sfc_files_input_grid - name of the NEMSIO input surface/Near Sea - Surface Temperature (NSST) data file - - - input_type - input data type. Set to ‘gaussian_nemsio’. - - - cycle_mon/day/hour - month/day/hour of your model run - - - convert_atm - set to ‘true’ to process the atmospheric fields - - - convert_sfc - set to ‘true’ to process the surface fields - - - convert_nst - set to ‘true’ to process NSST fields - - - tracers_input - names of tracer records in input file. For GFDL - microphysics, set to - “spfh”,”clwmr”,”o3mr”,”icmr”,”rwmr”,”snmr”,”grle”. - - - tracers - names of tracer records in output file expected by model. - For GFDL microphysics, set to - “sphum”,”liq_wat”,”o3mr”,”ice_wat”,”rainwat”,”snowwat”,”graupel”. - -When using NetCDF data as input to chgres_cube, set namelist as follows: - - - fix_dir_target_grid - Path to the tiled FV3 surface climatological - files (such as albedo). - - - mosaic_file_target_grid - Path and name of the FV3 mosaic file. - - - orog_dir_target_grid - directory containing the tiled FV3 orography - and grid files (NetCDF). - - - orog_files_target_grid - names of the six tiled FV3 orography - files. - - - vcoord_file_target_grid - path and name of the model vertical - coordinate definition file (“global_hyblev.l$LEVS.txt). - - - data_dir_input_grid - directory containing the NetCDF input data - - - atm_files_input_grid - name of the NetCDF input atmospheric data - file - - - sfc_files_input_grid - name of the NetCDF input surface/Near Sea - Surface Temperature (NSST) data file - - - input_type - input data type. Set to ‘gaussian_netcdf’. - - - cycle_mon/day/hour - month/day/hour of your model run - - - convert_atm - set to ‘true’ to process the atmospheric fields - - - convert_sfc - set to ‘true’ to process the surface fields - - - convert_nst - set to ‘true’ to process NSST fields - - - tracers_input - names of tracer records in input file. For GFDL - microphysics, set to - “spfh”,”clwmr”,”o3mr”,”icmr”,”rwmr”,”snmr”,”grle”. - - - tracers - names of tracer records in output file expected by model. - For GFDL microphysics, set to - “sphum”,”liq_wat”,”o3mr”,”ice_wat”,”rainwat”,”snowwat”,”graupel”. - -# Program inputs and outputs - -## Inputs - -The following four sets of files are located here: -https://ftp.emc.ncep.noaa.gov/EIB/UFS/global/fix/fix_fv3_gmted2010.v20191213/ - - - FV3 mosaic file - (NetCDF format) - - CRES_mosaic.nc - - - FV3 grid files - (NetCDF format) - - CRES_grid.tile1.nc - - CRES_grid.tile2.nc - - CRES_grid.tile3.nc - - CRES_grid.tile4.nc - - CRES_grid.tile5.nc - - CRES_grid.tile6.nc - - - FV3 orography files - (NetCDF format) - - CRES_oro_data.tile1.nc - - CRES_oro_data.tile2.nc - - CRES_oro_data.tile3.nc - - CRES_oro_data.tile4.nc - - CRES_oro_data.tile5.nc - - CRES_oro_data.tile6.nc - - - FV3 surface climatological files - Located under the ./fix_sfc sub-directory. One file for each tile. NetCDF format. - - CRES.facsf.tileX.nc (fractional coverage for strong/weak zenith angle dependent albedo) - - CRES.maximum_snow_albedo.tileX.nc (maximum snow albedo) - - CRES.slope_type.tileX.nc (slope type) - - CRES.snowfree_albedo.tileX.nc (snow-free albedo) - - CRES.soil_type.tileX.nc (soil type) - - CRES.subtrate_temperature.tileX.nc (soil substrate temperature) - - CRES.vegetation_greenness.tileX.nc (vegetation greenness) - - CRES.vegetation_type.tileX.nc (vegetation type) - - - FV3 vertical coordinate file. Text file. Located here: https://ftp.emc.ncep.noaa.gov/EIB/UFS/global/fix/fix_am.v20191213/ - - global_hyblev.l$LEVS.txt - - - Input data files. GRIB2, NEMSIO or NetCDF. See above section for how to find this data. - -## Outputs - - - Atmospheric “coldstart” files. NetCDF. - - out.atm.tile1.nc - - out.atm.tile2.nc - - out.atm.tile3.nc - - out.atm.tile4.nc - - out.atm.tile5.nc - - out.atm.tile6.nc - - - Surface/Near Sea Surface Temperature (NSST) “coldstart” files. NetCDF - - out.sfc.tile1.nc - - out.sfc.tile1.nc - - out.sfc.tile1.nc - - out.sfc.tile1.nc - - out.sfc.tile1.nc - - out.sfc.tile1.nc - -# Running the program stand alone - - - Locate your input files. See above for a list. - - - Set the namelist for your experiment. See above for an explanation - of the namelist entries. - - - Link the namelist to Fortran unit number 41: -
 ln -fs your-namelist-file ./fort.41
- - - Load any required runtime libraries. For example, you may need to - load libraries for NetCDF and/or your Fortran compiler. - - - Run the program with an MPI task count that is a multiple of six. - This is an ESMF library requirement when processing a six-tiled - global grid. - -# Variable Mapping (VARMAP) table - -The VARMAP table, set in the chgres_cube namelist (variable -varmap_file), controls how chgres_cube handles variables that might be -missing from the GRIB2 files. Since there are so many different -versions of GRIB2 files, it's often uncertain what fields are -available even if you know what source model the data is coming from. -Each file contains the following: (Note, only the GFS physics suite is -currently supported.) - -Column 1: Name the code searches for in the table. Do not change. -Some definitions: - - - dzdt - vertical velocity - - sphum - specific humidity - - liq_wat - liquid water mixing ratio - - o3mr - ozone mixing ratio - - ice_wat - ice water mixing ratio - - rainwat - rain water mixing ratio - - snowwat - snow water mixing ratio - - graupel - graupel mixing ratio - - vtype - vegetation type - - sotype - soil type - - vfrac - plant greenness fraction - - fricv - friction velocity - - sfcr - roughness length - - tprcp - precipitation rate - - ffmm - surface exchange coefficient for momentum - - ffhh - surface exchange coefficient for heat - - f10m - log((sfcr+10)/sfcr) - - soilw - total volumetric soil moisture - - soill - liquid volumetric soil moisture - - soilt - soil column temperature - - cnwat - plant canopy water content - - hice - sea/lake ice thickness - - weasd - snow liquid equivalent - - snod - physical snow depth - -Column 2: Name of the variable in the output “coldstart” -files. Unimplemented. - -Column 3: Behavior when the code can't find the variable in the input -file. Options are: - - - "skip": Don't write to the output file. - - "set_to_fill": Set to user-specified field value (see column 4). - - "intrp": LnP interpolation to missing levels. No extrapolation allowd. - - "stop": Force an exception and stop code execution. Use this if you - absolutely require a field to be present. - -Column 4: If column 3 = "set_to_fill", then this value is used to fill -in all points in the input field. These values may be overwritten by -the code before output depending on the variable (especially for -surface variables). - -Column 5: Variable type descriptor. Variable names designated as -tracers are used to populate the list of tracers to read from the -GRIB2 file and write to output, so make sure all tracers you wish to -read have an entry. Note that if you wish to add a tracer name that is -not already included in the appropriate VARMAP file, this will require -modification of the chgres_cube code. Valid choices are: - - - “T”: 3-dimensional tracer array - - “D”: 3-dimensional non-tracer array - - “S”: 2-dimensional surface array - - +The chgres_cube program is part of the +[UFS_UTILS](https://github.com/ufs-community/UFS_UTILS) project. diff --git a/sorc/chgres_cube.fd/grib2_util.F90 b/sorc/chgres_cube.fd/grib2_util.F90 index 30eaf0f66..92479e840 100644 --- a/sorc/chgres_cube.fd/grib2_util.F90 +++ b/sorc/chgres_cube.fd/grib2_util.F90 @@ -17,10 +17,11 @@ module grib2_util implicit none +public :: rh2spfh +public :: convert_omega public :: rh2spfh_gfs public :: fpvsnew - contains !> Convert relative humidity to specific humidity. @@ -28,7 +29,7 @@ module grib2_util !> Brock and Richardson 2001 (Meterological Measurement !> Systems, p. 86, equation 5.1) !! -!! @param[inout] rh_sphum rel humidity on input. spec hum on output. +!! @param[inout] rh_sphum rel humidity (%) on input. spec hum (kg/kg) on output. !! @param[in] p pressure in Pa !! @param[in] t temperature !! @author Larissa Reames @@ -55,11 +56,11 @@ subroutine rh2spfh(rh_sphum,p,t) !print *, 'es = ', es e = rh * es / 100.0 !print *, 'e = ', e - rh_sphum = 0.622 * e / p + rh_sphum = real((0.622 * e / p),kind=esmf_kind_r4) !print *, 'q = ', sphum !if (P .eq. 100000.0) THEN - ! print *, 'T = ', T, ' RH = ', RH, ' P = ', P, ' es = ', es, ' e = ', e, ' q = ', sphum + !print *, 'T = ', t, ' RH = ', rh, ' P = ', p, ' es = ', es, ' e = ', e, ' q = ', rh_sphum !end if end subroutine RH2SPFH @@ -109,7 +110,7 @@ subroutine rh2spfh_gfs(rh_sphum,p,t) do i=1,i_input ES = MIN(FPVSNEW(T(I,J)),P) QC(i,j) = CON_EPS*ES/(P+CON_EPSM1*ES) - rh_sphum(i,j) = rh(i,j)*QC(i,j)/100.0 + rh_sphum(i,j) = real((rh(i,j)*QC(i,j)/100.0),kind=esmf_kind_r4) end do end do @@ -168,7 +169,7 @@ elemental function fpvsnew(t) c1xpvs=1.-xmin*c2xpvs ! xj=min(max(c1xpvs+c2xpvs*t,1.0),real(nxpvs,krealfp)) xj=min(max(c1xpvs+c2xpvs*t,1.0),float(nxpvs)) - jx=min(xj,float(nxpvs)-1.0) + jx=int(min(xj,float(nxpvs)-1.0)) x=xmin+(jx-1)*xinc tr=con_ttp/x diff --git a/sorc/chgres_cube.fd/input_data.F90 b/sorc/chgres_cube.fd/input_data.F90 deleted file mode 100644 index 67657b55c..000000000 --- a/sorc/chgres_cube.fd/input_data.F90 +++ /dev/null @@ -1,7031 +0,0 @@ -!> @file -!! @brief Read atmospheric and surface data from GRIB2, NEMSIO and NetCDF files. -!! @author George Gayno NCEP/EMC - -!> Read atmospheric, surface and nst data on the input grid. -!! Supported formats include fv3 tiled 'restart' files, fv3 tiled -!! 'history' files, fv3 gaussian history files, spectral gfs -!! gaussian nemsio files, and spectral gfs sigio/sfcio files. -!! -!! Public variables are defined below: "input" indicates field -!! associated with the input grid. -!! -!! @author George Gayno NCEP/EMC - module input_data - - use esmf - use netcdf - use nemsio_module - - use program_setup, only : data_dir_input_grid, & - nst_files_input_grid, & - sfc_files_input_grid, & - atm_files_input_grid, & - grib2_file_input_grid, & - atm_core_files_input_grid, & - atm_tracer_files_input_grid, & - convert_nst, & - orog_dir_input_grid, & - orog_files_input_grid, & - tracers_input, num_tracers_input, & - input_type, tracers, & - get_var_cond, read_from_input, & - geogrid_file_input_grid, & - external_model, & - vgfrc_from_climo, & - minmax_vgfrc_from_climo, & - lai_from_climo - - use model_grid, only : input_grid, & - i_input, j_input, & - ip1_input, jp1_input, & - num_tiles_input_grid, & - latitude_input_grid, & - longitude_input_grid, & - inv_file - - implicit none - - private - -! Fields associated with the atmospheric model. - - type(esmf_field), public :: dzdt_input_grid !< vert velocity - type(esmf_field) :: dpres_input_grid !< pressure thickness - type(esmf_field), public :: pres_input_grid !< 3-d pressure - type(esmf_field), public :: ps_input_grid !< surface pressure - type(esmf_field), public :: terrain_input_grid !< terrain height - type(esmf_field), public :: temp_input_grid !< temperature - - type(esmf_field), public :: u_input_grid !< u/v wind at grid - type(esmf_field), public :: v_input_grid !< box center - type(esmf_field), public :: wind_input_grid !< 3-component wind - type(esmf_field), allocatable, public :: tracers_input_grid(:) !< tracers - - integer, public :: lev_input !< number of atmospheric layers - integer, public :: levp1_input !< number of atmos layer interfaces - -! Fields associated with the land-surface model. - - integer, public :: veg_type_landice_input = 15 !< NOAH land ice option - !< defined at this veg type. - !< Default is igbp. - integer, parameter :: ICET_DEFAULT = 265.0 !< Default value of soil and skin - !< temperature (K) over ice. - type(esmf_field), public :: canopy_mc_input_grid !< canopy moist content - type(esmf_field), public :: f10m_input_grid !< log((z0+10)*1/z0) - type(esmf_field), public :: ffhh_input_grid !< log((ztmax+z1)*1/ztmax) - !! See sfc_diff.f for details. - type(esmf_field), public :: ffmm_input_grid !< log((z0+z1)*1/z0) - !! See sfc_diff.f for details. - type(esmf_field), public :: landsea_mask_input_grid !< land sea mask; - !! 0-water, 1-land, 2-ice - type(esmf_field), public :: q2m_input_grid !< 2-m spec hum - type(esmf_field), public :: seaice_depth_input_grid !< sea ice depth - type(esmf_field), public :: seaice_fract_input_grid !< sea ice fraction - type(esmf_field), public :: seaice_skin_temp_input_grid !< sea ice skin temp - type(esmf_field), public :: skin_temp_input_grid !< skin temp/sst - type(esmf_field), public :: snow_depth_input_grid !< snow dpeth - type(esmf_field), public :: snow_liq_equiv_input_grid !< snow liq equiv depth - type(esmf_field), public :: soil_temp_input_grid !< 3-d soil temp - type(esmf_field), public :: soil_type_input_grid !< soil type - type(esmf_field), public :: soilm_liq_input_grid !< 3-d liquid soil moisture - type(esmf_field), public :: soilm_tot_input_grid !< 3-d total soil moisture - type(esmf_field), public :: srflag_input_grid !< snow/rain flag - type(esmf_field), public :: t2m_input_grid !< 2-m temperature - type(esmf_field), public :: tprcp_input_grid !< precip - type(esmf_field), public :: ustar_input_grid !< fric velocity - type(esmf_field), public :: veg_type_input_grid !< vegetation type - type(esmf_field), public :: z0_input_grid !< roughness length - type(esmf_field), public :: veg_greenness_input_grid !< vegetation fraction - type(esmf_field), public :: lai_input_grid !< leaf area index - type(esmf_field), public :: max_veg_greenness_input_grid !< shdmax - type(esmf_field), public :: min_veg_greenness_input_grid !< shdmin - - integer, public :: lsoil_input=4 !< number of soil layers, no longer hardwired to allow - !! for 7 layers of soil for the RUC LSM - - character(len=50), private, allocatable :: slevs(:) !< The atmospheric levels in the GRIB2 input file. - -! Fields associated with the nst model. - - type(esmf_field), public :: c_d_input_grid !< Coefficient 2 to calculate d(tz)/d(ts) - type(esmf_field), public :: c_0_input_grid !< Coefficient 1 to calculate d(tz)/d(ts) - type(esmf_field), public :: d_conv_input_grid !< Thickness of free convection layer - type(esmf_field), public :: dt_cool_input_grid !< Sub-layer cooling amount - type(esmf_field), public :: ifd_input_grid !< Model mode index. 0-diurnal model not - !< started; 1-diurnal model started. - type(esmf_field), public :: qrain_input_grid !< Sensible heat flux due to rainfall - type(esmf_field), public :: tref_input_grid !< Reference temperature - type(esmf_field), public :: w_d_input_grid !< Coefficient 4 to calculate d(tz)/d(ts) - type(esmf_field), public :: w_0_input_grid !< Coefficient 3 to calculate d(tz)/d(ts) - type(esmf_field), public :: xs_input_grid !< Salinity content in diurnal thermocline layer - type(esmf_field), public :: xt_input_grid !< Heat content in diurnal thermocline layer - type(esmf_field), public :: xu_input_grid !< u-current content in diurnal thermocline layer - type(esmf_field), public :: xv_input_grid !< v-current content in diurnal thermocline layer - type(esmf_field), public :: xz_input_grid !< Diurnal thermocline layer thickness - type(esmf_field), public :: xtts_input_grid !< d(xt)/d(ts) - type(esmf_field), public :: xzts_input_grid !< d(xz)/d(ts) - type(esmf_field), public :: z_c_input_grid !< Sub-layer cooling thickness - type(esmf_field), public :: zm_input_grid !< Oceanic mixed layer depth - - public :: read_input_atm_data - public :: cleanup_input_atm_data - public :: read_input_sfc_data - public :: cleanup_input_sfc_data - public :: read_input_nst_data - public :: cleanup_input_nst_data - public :: check_soilt - public :: check_cnwat - public :: quicksort - public :: convert_winds - public :: init_sfc_esmf_fields - public :: dint2p - - contains - -!> Read input grid atmospheric data driver. -!! -!! @param[in] localpet ESMF local persistent execution thread -!! @author George Gayno NCEP/EMC - subroutine read_input_atm_data(localpet) - - implicit none - - integer, intent(in) :: localpet - -!------------------------------------------------------------------------------- -! Read the tiled 'warm' restart files. -!------------------------------------------------------------------------------- - - if (trim(input_type) == "restart") then - - call read_input_atm_restart_file(localpet) - -!------------------------------------------------------------------------------- -! Read the gaussian history files in netcdf format. -!------------------------------------------------------------------------------- - - elseif (trim(input_type) == "gaussian_netcdf") then - - call read_input_atm_gaussian_netcdf_file(localpet) - -!------------------------------------------------------------------------------- -! Read the tiled history files in netcdf format. -!------------------------------------------------------------------------------- - - elseif (trim(input_type) == "history") then - - call read_input_atm_tiled_history_file(localpet) - -!------------------------------------------------------------------------------- -! Read the gaussian history files in nemsio format. -!------------------------------------------------------------------------------- - - elseif (trim(input_type) == "gaussian_nemsio") then ! fv3gfs gaussian nemsio - - call read_input_atm_gaussian_nemsio_file(localpet) - -!------------------------------------------------------------------------------- -! Read the spectral gfs gaussian history files in nemsio format. -!------------------------------------------------------------------------------- - - elseif (trim(input_type) == "gfs_gaussian_nemsio") then ! spectral gfs gaussian - ! nemsio. - call read_input_atm_gfs_gaussian_nemsio_file(localpet) - -!------------------------------------------------------------------------------- -! Read the spectral gfs gaussian history files in sigio format. -!------------------------------------------------------------------------------- - - elseif (trim(input_type) == "gfs_sigio") then ! spectral gfs sigio format. - - call read_input_atm_gfs_sigio_file(localpet) - -!------------------------------------------------------------------------------- -! Read fv3gfs data in grib2 format. -!------------------------------------------------------------------------------- - - elseif (trim(input_type) == "grib2") then - - call read_input_atm_grib2_file(localpet) - - endif - - end subroutine read_input_atm_data - -!> Driver to read input grid nst data. -!! -!! @param[in] localpet ESMF local persistent execution thread -!! @author George Gayno NCEP/EMC - subroutine read_input_nst_data(localpet) - - implicit none - - integer, intent(in) :: localpet - - integer :: rc - - print*,"- READ INPUT GRID NST DATA." - - print*,"- CALL FieldCreate FOR INPUT GRID C_D." - c_d_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID C_0." - c_0_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID D_CONV." - d_conv_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID DT_COOL." - dt_cool_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID IFD." - ifd_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID QRAIN." - qrain_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID TREF." - tref_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID W_D." - w_d_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID W_0." - w_0_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID XS." - xs_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID XT." - xt_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID XU." - xu_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID XV." - xv_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID XZ." - xz_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID XTTS." - xtts_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID XZTS." - xzts_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID Z_C." - z_c_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID ZM." - zm_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - -!-------------------------------------------------------------------------- -! Read input grid nst data from a fv3 gaussian nemsio history file or -! spectral GFS nemsio file. -!-------------------------------------------------------------------------- - - if (trim(input_type) == "gaussian_nemsio" .or. trim(input_type) == "gfs_gaussian_nemsio") then - - call read_input_nst_nemsio_file(localpet) - -!--------------------------------------------------------------------------- -! Read nst data from these netcdf formatted fv3 files: tiled history, -! tiled warm restart, and gaussian history. -!--------------------------------------------------------------------------- - - else - - call read_input_nst_netcdf_file(localpet) - - endif - - end subroutine read_input_nst_data - -!> Driver to read input grid surface data. -!! -!! @param[in] localpet ESMF local persistent execution thread -!! @author George Gayno NCEP/EMC - subroutine read_input_sfc_data(localpet) - - implicit none - - integer, intent(in) :: localpet - - integer :: rc - - call init_sfc_esmf_fields() - -!------------------------------------------------------------------------------- -! Read the tiled 'warm' restart files. -!------------------------------------------------------------------------------- - - if (trim(input_type) == "restart") then - - call read_input_sfc_restart_file(localpet) - -!------------------------------------------------------------------------------- -! Read the tiled or gaussian history files in netcdf format. -!------------------------------------------------------------------------------- - - elseif (trim(input_type) == "history" .or. trim(input_type) == & - "gaussian_netcdf") then - - call read_input_sfc_netcdf_file(localpet) - -!------------------------------------------------------------------------------- -! Read the gaussian history files in nemsio format. -!------------------------------------------------------------------------------- - - elseif (trim(input_type) == "gaussian_nemsio") then - - call read_input_sfc_gaussian_nemsio_file(localpet) - -!------------------------------------------------------------------------------- -! Read the spectral gfs gaussian history files in nemsio format. -!------------------------------------------------------------------------------- - - elseif (trim(input_type) == "gfs_gaussian_nemsio") then - - call read_input_sfc_gfs_gaussian_nemsio_file(localpet) - -!------------------------------------------------------------------------------- -! Read the spectral gfs gaussian history files in sfcio format. -!------------------------------------------------------------------------------- - - elseif (trim(input_type) == "gfs_sigio") then - - call read_input_sfc_gfs_sfcio_file(localpet) - -!------------------------------------------------------------------------------- -! Read fv3gfs surface data in grib2 format. -!------------------------------------------------------------------------------- - - elseif (trim(input_type) == "grib2") then - - call read_input_sfc_grib2_file(localpet) - - endif - - end subroutine read_input_sfc_data - -!> Create atmospheric esmf fields. -!! -!! @author George Gayno NCEP/EMC - subroutine init_atm_esmf_fields - - implicit none - - integer :: i, rc - - print*,"- INITIALIZE ATMOSPHERIC ESMF FIELDS." - - print*,"- CALL FieldCreate FOR INPUT GRID 3-D WIND." - wind_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, & - ungriddedLBound=(/1,1/), & - ungriddedUBound=(/lev_input,3/), rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID SURFACE PRESSURE." - ps_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID TERRAIN." - terrain_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID TEMPERATURE." - temp_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, & - ungriddedLBound=(/1/), & - ungriddedUBound=(/lev_input/), rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - allocate(tracers_input_grid(num_tracers_input)) - - do i = 1, num_tracers_input - print*,"- CALL FieldCreate FOR INPUT GRID TRACER ", trim(tracers_input(i)) - tracers_input_grid(i) = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, & - ungriddedLBound=(/1/), & - ungriddedUBound=(/lev_input/), rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - enddo - - print*,"- CALL FieldCreate FOR INPUT GRID DZDT." - dzdt_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, & - ungriddedLBound=(/1/), & - ungriddedUBound=(/lev_input/), rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID U." - u_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, & - ungriddedLBound=(/1/), & - ungriddedUBound=(/lev_input/), rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID V." - v_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, & - ungriddedLBound=(/1/), & - ungriddedUBound=(/lev_input/), rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID PRESSURE." - pres_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, & - ungriddedLBound=(/1/), & - ungriddedUBound=(/lev_input/), rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - end subroutine init_atm_esmf_fields - -!> Create surface input grid esmf fields -!! -!! @author George Gayno NCEP/EMC - subroutine init_sfc_esmf_fields - - implicit none - - integer :: rc - - print*,"- CALL FieldCreate FOR INPUT GRID LANDSEA MASK." - landsea_mask_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID Z0." - z0_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID VEGETATION TYPE." - veg_type_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID CANOPY MOISTURE CONTENT." - canopy_mc_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID SEAICE FRACTION." - seaice_fract_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID SEAICE DEPTH." - seaice_depth_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID SEAICE SKIN TEMPERATURE." - seaice_skin_temp_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID SNOW DEPTH." - snow_depth_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID SNOW LIQUID EQUIVALENT." - snow_liq_equiv_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID T2M." - t2m_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID Q2M." - q2m_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID TPRCP." - tprcp_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID F10M." - f10m_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID USTAR." - ustar_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID FFHH." - ffhh_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID FFMM." - ffmm_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT GRID SRFLAG." - srflag_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT SKIN TEMPERATURE." - skin_temp_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT SOIL TYPE." - soil_type_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT TERRAIN." - terrain_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT SOIL TEMPERATURE." - soil_temp_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, & - ungriddedLBound=(/1/), & - ungriddedUBound=(/lsoil_input/), rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT TOTAL SOIL MOISTURE." - soilm_tot_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, & - ungriddedLBound=(/1/), & - ungriddedUBound=(/lsoil_input/), rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT LIQUID SOIL MOISTURE." - soilm_liq_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, & - ungriddedLBound=(/1/), & - ungriddedUBound=(/lsoil_input/), rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - - - if (.not. vgfrc_from_climo) then - print*,"- CALL FieldCreate FOR INPUT VEGETATION GREENNESS." - veg_greenness_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - endif - - if (.not. minmax_vgfrc_from_climo) then - print*,"- CALL FieldCreate FOR INPUT MIN VEGETATION GREENNESS." - min_veg_greenness_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT MAX VEGETATION GREENNESS." - max_veg_greenness_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldCreate", rc) - endif - - if (.not. lai_from_climo) then - print*,"- CALL FieldCreate FOR INPUT LEAF AREA INDEX." - lai_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldCreate", rc) - endif - end subroutine init_sfc_esmf_fields - -!> Read input atmospheric data from spectral gfs (old sigio format). -!! -!! @note Format used prior to July 19, 2017. -!! @param[in] localpet ESMF local persistent execution thread -!! @author George Gayno NCEP/EMC - subroutine read_input_atm_gfs_sigio_file(localpet) - - use sigio_module - - implicit none - - integer, intent(in) :: localpet - - character(len=300) :: the_file - - integer(sigio_intkind) :: iret - integer :: rc, i, j, k - integer :: clb(3), cub(3) - - real(esmf_kind_r8) :: ak, bk - real(esmf_kind_r8), allocatable :: dummy2d(:,:) - real(esmf_kind_r8), allocatable :: dummy3d(:,:,:) - real(esmf_kind_r8), allocatable :: dummy3d2(:,:,:) - real(esmf_kind_r8), pointer :: pptr(:,:,:), psptr(:,:) - real(esmf_kind_r8), allocatable :: pi(:,:,:) - - type(sigio_head) :: sighead - type(sigio_dbta) :: sigdata - - the_file = trim(data_dir_input_grid) // "/" // trim(atm_files_input_grid(1)) - - print*,"- ATMOSPHERIC DATA IN SIGIO FORMAT." - print*,"- OPEN AND READ: ", trim(the_file) - - call sigio_sropen(21, trim(the_file), iret) - if (iret /= 0) then - rc = iret - call error_handler("OPENING SPECTRAL GFS SIGIO FILE.", rc) - endif - call sigio_srhead(21, sighead, iret) - if (iret /= 0) then - rc = iret - call error_handler("READING SPECTRAL GFS SIGIO FILE.", rc) - endif - - lev_input = sighead%levs - levp1_input = lev_input + 1 - - if (num_tracers_input /= sighead%ntrac) then - call error_handler("WRONG NUMBER OF TRACERS EXPECTED.", 99) - endif - - if (sighead%idvt == 0 .or. sighead%idvt == 21) then - if (trim(tracers_input(1)) /= 'spfh' .or. & - trim(tracers_input(2)) /= 'o3mr' .or. & - trim(tracers_input(3)) /= 'clwmr') then - call error_handler("TRACERS SELECTED DO NOT MATCH FILE CONTENTS.", 99) - endif - else - print*,'- UNRECOGNIZED IDVT: ', sighead%idvt - call error_handler("UNRECOGNIZED IDVT", 99) - endif - -!--------------------------------------------------------------------------- -! Initialize esmf atmospheric fields. -!--------------------------------------------------------------------------- - - call init_atm_esmf_fields - - if (localpet == 0) then - allocate(dummy2d(i_input,j_input)) - allocate(dummy3d(i_input,j_input,lev_input)) - allocate(dummy3d2(i_input,j_input,lev_input)) - else - allocate(dummy2d(0,0)) - allocate(dummy3d(0,0,0)) - allocate(dummy3d2(0,0,0)) - endif - - if (localpet == 0) then - call sigio_aldbta(sighead, sigdata, iret) - if (iret /= 0) then - rc = iret - call error_handler("ALLOCATING SIGDATA.", rc) - endif - call sigio_srdbta(21, sighead, sigdata, iret) - if (iret /= 0) then - rc = iret - call error_handler("READING SIGDATA.", rc) - endif - call sptez(0,sighead%jcap,4,i_input, j_input, sigdata%ps, dummy2d, 1) - dummy2d = exp(dummy2d) * 1000.0 - print*,'surface pres ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR SURFACE PRESSURE." - call ESMF_FieldScatter(ps_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - call sptez(0,sighead%jcap,4,i_input, j_input, sigdata%hs, dummy2d, 1) - print*,'terrain ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR TERRAIN." - call ESMF_FieldScatter(terrain_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - do k = 1, num_tracers_input - - if (localpet == 0) then - call sptezm(0,sighead%jcap,4,i_input, j_input, lev_input, sigdata%q(:,:,k), dummy3d, 1) - print*,trim(tracers_input(k)),maxval(dummy3d),minval(dummy3d) - endif - - print*,"- CALL FieldScatter FOR INPUT ", trim(tracers_input(k)) - call ESMF_FieldScatter(tracers_input_grid(k), dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - enddo - - if (localpet == 0) then - call sptezm(0,sighead%jcap,4,i_input, j_input, lev_input, sigdata%t, dummy3d, 1) - print*,'temp ',maxval(dummy3d),minval(dummy3d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID TEMPERATURE." - call ESMF_FieldScatter(temp_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -!--------------------------------------------------------------------------- -! The spectral gfs files have omega, not vertical velocity. Set to -! zero for now. Convert from omega to vv in the future? -!--------------------------------------------------------------------------- - - if (localpet == 0) then - print*,"- NO VERTICAL VELOCITY RECORD. SET TO ZERO." - dummy3d = 0.0 - endif - - print*,"- CALL FieldScatter FOR INPUT DZDT." - call ESMF_FieldScatter(dzdt_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - call sptezmv(0, sighead%jcap, 4, i_input, j_input, lev_input, sigdata%d, sigdata%z, dummy3d, dummy3d2, 1) - print*,'u ',maxval(dummy3d),minval(dummy3d) - print*,'v ',maxval(dummy3d2),minval(dummy3d2) - endif - - print*,"- CALL FieldScatter FOR INPUT U-WIND." - call ESMF_FieldScatter(u_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - print*,"- CALL FieldScatter FOR INPUT V-WIND." - call ESMF_FieldScatter(v_input_grid, dummy3d2, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - deallocate(dummy2d, dummy3d, dummy3d2) - - if (localpet == 0) call sigio_axdbta(sigdata, iret) - - call sigio_sclose(21, iret) - -!--------------------------------------------------------------------------- -! Convert from 2-d to 3-d component winds. -!--------------------------------------------------------------------------- - - call convert_winds - -!--------------------------------------------------------------------------- -! Compute 3-d pressure from 'ak' and 'bk'. -!--------------------------------------------------------------------------- - - print*,"- COMPUTE 3-D PRESSURE." - - print*,"- CALL FieldGet FOR 3-D PRES." - nullify(pptr) - call ESMF_FieldGet(pres_input_grid, & - computationalLBound=clb, & - computationalUBound=cub, & - farrayPtr=pptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR SURFACE PRESSURE." - nullify(psptr) - call ESMF_FieldGet(ps_input_grid, & - farrayPtr=psptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - -!--------------------------------------------------------------------------- -! First, compute interface pressure. -!--------------------------------------------------------------------------- - - allocate(pi(clb(1):cub(1),clb(2):cub(2),1:levp1_input),stat=rc) - - do k=1,levp1_input - ak = sighead%vcoord(k,1) - bk = sighead%vcoord(k,2) - do i= clb(1), cub(1) - do j= clb(2), cub(2) - pi(i,j,k) = ak + bk*psptr(i,j) - enddo - enddo - enddo - - if (localpet == 0) then - print*,'pres int ',psptr(clb(1),clb(2)),pi(clb(1),clb(2),:) - endif - -!--------------------------------------------------------------------------- -! Now comput mid-layer pressure from interface pressure. -!--------------------------------------------------------------------------- - - do k=1,lev_input - do i= clb(1), cub(1) - do j= clb(2), cub(2) - pptr(i,j,k) = (pi(i,j,k)+pi(i,j,k+1))/2.0_esmf_kind_r8 - enddo - enddo - enddo - - deallocate(pi) - - if (localpet == 0) then - print*,'pres ',psptr(clb(1),clb(2)),pptr(clb(1),clb(2),:) - endif - - end subroutine read_input_atm_gfs_sigio_file - -!> Read input atmospheric data from spectral gfs (global gaussian in -!! nemsio format. Starting July 19, 2017). -!! -!! @param[in] localpet ESMF local persistent execution thread -!! @author George Gayno NCEP/EMC - subroutine read_input_atm_gfs_gaussian_nemsio_file(localpet) - - implicit none - - integer, intent(in) :: localpet - - character(len=300) :: the_file - character(len=20) :: vlevtyp, vname - - integer(nemsio_intkind) :: vlev, iret - integer :: i, j, k, n, rc - integer :: clb(3), cub(3) - - real(nemsio_realkind), allocatable :: vcoord(:,:,:) - real(nemsio_realkind), allocatable :: dummy(:) - real(esmf_kind_r8), allocatable :: dummy2d(:,:) - real(esmf_kind_r8), allocatable :: dummy3d(:,:,:) - real(esmf_kind_r8) :: ak, bk - real(esmf_kind_r8), allocatable :: pi(:,:,:) - real(esmf_kind_r8), pointer :: pptr(:,:,:), psptr(:,:) - - type(nemsio_gfile) :: gfile - - the_file = trim(data_dir_input_grid) // "/" // trim(atm_files_input_grid(1)) - - print*,"- READ ATMOS DATA FROM SPECTRAL GFS NEMSIO FILE: ", trim(the_file) - - print*,"- OPEN FILE." - call nemsio_open(gfile, the_file, "read", iret=iret) - if (iret /= 0) call error_handler("OPENING SPECTRAL GFS NEMSIO ATM FILE.", iret) - - print*,"- READ NUMBER OF VERTICAL LEVELS." - call nemsio_getfilehead(gfile, iret=iret, dimz=lev_input) - if (iret /= 0) call error_handler("READING NUMBER OF VERTICAL LEVLES.", iret) - - levp1_input = lev_input + 1 - - allocate(vcoord(levp1_input,3,2)) - - print*,"- READ VERTICAL COORDINATE INFO." - call nemsio_getfilehead(gfile, iret=iret, vcoord=vcoord) - if (iret /= 0) call error_handler("READING VERTICAL COORDINATE INFO.", iret) - -!--------------------------------------------------------------------------- -! Initialize esmf atmospheric fields. -!--------------------------------------------------------------------------- - - call init_atm_esmf_fields - - if (localpet == 0) then - allocate(dummy(i_input*j_input)) - allocate(dummy2d(i_input,j_input)) - allocate(dummy3d(i_input,j_input,lev_input)) - else - allocate(dummy(0)) - allocate(dummy2d(0,0)) - allocate(dummy3d(0,0,0)) - endif - -!----------------------------------------------------------------------- -! 3-d fields in gaussian files increment from bottom to model top. -! That is what is expected by this program, so no need to flip indices. -!----------------------------------------------------------------------- - - if (localpet == 0) then - print*,"- READ TEMPERATURE." - vname = "tmp" - vlevtyp = "mid layer" - do vlev = 1, lev_input - call nemsio_readrecv(gfile, vname, vlevtyp, vlev, dummy, 0, iret) - if (iret /= 0) call error_handler("READING TEMPERATURE RECORD.", iret) - dummy3d(:,:,vlev) = reshape(dummy, (/i_input,j_input/)) -! print*,'temp check after read ',vlev, dummy3d(1,1,vlev) - enddo - endif - - print*,"- CALL FieldScatter FOR INPUT GRID TEMPERATURE." - call ESMF_FieldScatter(temp_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - do n = 1, num_tracers_input - - if (localpet == 0) then - print*,"- READ ", trim(tracers_input(n)) - vname = trim(tracers_input(n)) - vlevtyp = "mid layer" - do vlev = 1, lev_input - call nemsio_readrecv(gfile, vname, vlevtyp, vlev, dummy, 0, iret) - if (iret /= 0) call error_handler("READING TRACER RECORD.", iret) -! print*,'tracer ',vlev, maxval(dummy),minval(dummy) - dummy3d(:,:,vlev) = reshape(dummy, (/i_input,j_input/)) - enddo - endif - - print*,"- CALL FieldScatter FOR INPUT ", trim(tracers_input(n)) - call ESMF_FieldScatter(tracers_input_grid(n), dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - enddo - - if (localpet == 0) then - print*,"- READ U-WINDS." - vname = "ugrd" - vlevtyp = "mid layer" - do vlev = 1, lev_input - call nemsio_readrecv(gfile, vname, vlevtyp, vlev, dummy, 0, iret) - if (iret /= 0) call error_handler("READING U-WIND RECORD.", iret) -! print*,'ugrd ',vlev, maxval(dummy),minval(dummy) - dummy3d(:,:,vlev) = reshape(dummy, (/i_input,j_input/)) - enddo - endif - - print*,"- CALL FieldScatter FOR INPUT U-WIND." - call ESMF_FieldScatter(u_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ V-WINDS." - vname = "vgrd" - vlevtyp = "mid layer" - do vlev = 1, lev_input - call nemsio_readrecv(gfile, vname, vlevtyp, vlev, dummy, 0, iret) - if (iret /= 0) call error_handler("READING V-WIND RECORD.", iret) -! print*,'vgrd ',vlev, maxval(dummy),minval(dummy) - dummy3d(:,:,vlev) = reshape(dummy, (/i_input,j_input/)) - enddo - endif - - print*,"- CALL FieldScatter FOR INPUT V-WIND." - call ESMF_FieldScatter(v_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -!--------------------------------------------------------------------------- -! The spectral gfs nemsio files do not have a vertical velocity or -! omega record. So set to zero for now. -!--------------------------------------------------------------------------- - - if (localpet == 0) then - print*,"- NO VERTICAL VELOCITY RECORD. SET TO ZERO." - dummy3d = 0.0 - endif - - print*,"- CALL FieldScatter FOR INPUT DZDT." - call ESMF_FieldScatter(dzdt_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ HGT." - vname = "hgt" - vlevtyp = "sfc" - vlev = 1 - call nemsio_readrecv(gfile, vname, vlevtyp, vlev, dummy, 0, iret) - if (iret /= 0) call error_handler("READING HGT RECORD.", iret) -! print*,'hgt ',vlev, maxval(dummy),minval(dummy) - dummy2d = reshape(dummy, (/i_input,j_input/)) - endif - - print*,"- CALL FieldScatter FOR TERRAIN." - call ESMF_FieldScatter(terrain_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ PRES." - vname = "pres" - vlevtyp = "sfc" - vlev = 1 - call nemsio_readrecv(gfile, vname, vlevtyp, vlev, dummy, 0, iret) - if (iret /= 0) call error_handler("READING PRES RECORD.", iret) -! print*,'pres ',vlev, maxval(dummy),minval(dummy) - dummy2d = reshape(dummy, (/i_input,j_input/)) - endif - - print*,"- CALL FieldScatter FOR SURFACE PRESSURE." - call ESMF_FieldScatter(ps_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - call nemsio_close(gfile) - - deallocate(dummy, dummy2d, dummy3d) - -!--------------------------------------------------------------------------- -! Convert from 2-d to 3-d component winds. -!--------------------------------------------------------------------------- - - call convert_winds - -!--------------------------------------------------------------------------- -! Compute 3-d pressure from 'ak' and 'bk'. -!--------------------------------------------------------------------------- - - print*,"- COMPUTE 3-D PRESSURE." - - print*,"- CALL FieldGet FOR 3-D PRES." - nullify(pptr) - call ESMF_FieldGet(pres_input_grid, & - computationalLBound=clb, & - computationalUBound=cub, & - farrayPtr=pptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR SURFACE PRESSURE." - nullify(psptr) - call ESMF_FieldGet(ps_input_grid, & - farrayPtr=psptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - -!--------------------------------------------------------------------------- -! First, compute interface pressure. -!--------------------------------------------------------------------------- - - allocate(pi(clb(1):cub(1),clb(2):cub(2),1:levp1_input)) - - do k=1,levp1_input - ak = vcoord(k,1,1) - bk = vcoord(k,2,1) - do i= clb(1), cub(1) - do j= clb(2), cub(2) - pi(i,j,k) = ak + bk*psptr(i,j) - enddo - enddo - enddo - - deallocate(vcoord) - -!--------------------------------------------------------------------------- -! Now comput mid-layer pressure from interface pressure. -!--------------------------------------------------------------------------- - - do k=1,lev_input - do i= clb(1), cub(1) - do j= clb(2), cub(2) - pptr(i,j,k) = (pi(i,j,k)+pi(i,j,k+1))/2.0 - enddo - enddo - enddo - - deallocate(pi) - - end subroutine read_input_atm_gfs_gaussian_nemsio_file - -!> Read input grid atmospheric fv3 gaussian nemsio files. -!! -!! @param[in] localpet ESMF local persistent execution thread -!! @author George Gayno NCEP/EMC - subroutine read_input_atm_gaussian_nemsio_file(localpet) - - implicit none - - integer, intent(in) :: localpet - - character(len=300) :: the_file - character(len=20) :: vlevtyp, vname - - integer :: i, j, k, n - integer :: rc, clb(3), cub(3) - integer(nemsio_intkind) :: vlev, iret - - real(nemsio_realkind), allocatable :: vcoord(:,:,:) - real(nemsio_realkind), allocatable :: dummy(:) - real(esmf_kind_r8), allocatable :: dummy2d(:,:) - real(esmf_kind_r8), allocatable :: dummy3d(:,:,:) - real(esmf_kind_r8), pointer :: presptr(:,:,:), psptr(:,:) - real(esmf_kind_r8), pointer :: dpresptr(:,:,:) - real(esmf_kind_r8), allocatable :: pres_interface(:) - - type(nemsio_gfile) :: gfile - - the_file = trim(data_dir_input_grid) // "/" // trim(atm_files_input_grid(1)) - - print*,"- READ ATMOS DATA FROM GAUSSIAN NEMSIO FILE: ", trim(the_file) - - print*,"- OPEN FILE." - call nemsio_open(gfile, the_file, "read", iret=iret) - if (iret /= 0) call error_handler("OPENING GAUSSIAN NEMSIO ATM FILE.", iret) - - print*,"- READ NUMBER OF VERTICAL LEVELS." - call nemsio_getfilehead(gfile, iret=iret, dimz=lev_input) - if (iret /= 0) call error_handler("READING NUMBER OF VERTICAL LEVLES.", iret) - - levp1_input = lev_input + 1 - - allocate(vcoord(levp1_input,3,2)) - - print*,"- READ VERTICAL COORDINATE INFO." - call nemsio_getfilehead(gfile, iret=iret, vcoord=vcoord) - if (iret /= 0) call error_handler("READING VERTICAL COORDINATE INFO.", iret) - -!--------------------------------------------------------------------------- -! Initialize esmf atmospheric fields. -!--------------------------------------------------------------------------- - - call init_atm_esmf_fields - - print*,"- CALL FieldCreate FOR INPUT DPRES." - dpres_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, & - ungriddedLBound=(/1/), & - ungriddedUBound=(/lev_input/), rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - if (localpet == 0) then - allocate(dummy(i_input*j_input)) - allocate(dummy2d(i_input,j_input)) - allocate(dummy3d(i_input,j_input,lev_input)) - else - allocate(dummy(0)) - allocate(dummy2d(0,0)) - allocate(dummy3d(0,0,0)) - endif - -!----------------------------------------------------------------------- -! 3-d fields in gaussian files increment from bottom to model top. -! That is what is expected by this program, so no need to flip indices. -!----------------------------------------------------------------------- - - if (localpet == 0) then - print*,"- READ TEMPERATURE." - vname = "tmp" - vlevtyp = "mid layer" - do vlev = 1, lev_input - call nemsio_readrecv(gfile, vname, vlevtyp, vlev, dummy, 0, iret) - if (iret /= 0) call error_handler("READING TEMPERATURE RECORD.", iret) - dummy3d(:,:,vlev) = reshape(dummy, (/i_input,j_input/)) - print*,'temp check after read ',vlev, dummy3d(1,1,vlev) - enddo - endif - - print*,"- CALL FieldScatter FOR INPUT GRID TEMPERATURE." - call ESMF_FieldScatter(temp_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - do n = 1, num_tracers_input - - if (localpet == 0) then - print*,"- READ ", trim(tracers_input(n)) - vname = trim(tracers_input(n)) - vlevtyp = "mid layer" - do vlev = 1, lev_input - call nemsio_readrecv(gfile, vname, vlevtyp, vlev, dummy, 0, iret) - if (iret /= 0) call error_handler("READING TRACER RECORD.", iret) - print*,'tracer ',vlev, maxval(dummy),minval(dummy) - dummy3d(:,:,vlev) = reshape(dummy, (/i_input,j_input/)) - enddo - endif - - print*,"- CALL FieldScatter FOR INPUT ", trim(tracers_input(n)) - call ESMF_FieldScatter(tracers_input_grid(n), dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - enddo - - if (localpet == 0) then - print*,"- READ U-WINDS." - vname = "ugrd" - vlevtyp = "mid layer" - do vlev = 1, lev_input - call nemsio_readrecv(gfile, vname, vlevtyp, vlev, dummy, 0, iret) - if (iret /= 0) call error_handler("READING U-WIND RECORD.", iret) - print*,'ugrd ',vlev, maxval(dummy),minval(dummy) - dummy3d(:,:,vlev) = reshape(dummy, (/i_input,j_input/)) - enddo - endif - - print*,"- CALL FieldScatter FOR INPUT U-WIND." - call ESMF_FieldScatter(u_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ V-WINDS." - vname = "vgrd" - vlevtyp = "mid layer" - do vlev = 1, lev_input - call nemsio_readrecv(gfile, vname, vlevtyp, vlev, dummy, 0, iret) - if (iret /= 0) call error_handler("READING V-WIND RECORD.", iret) - print*,'vgrd ',vlev, maxval(dummy),minval(dummy) - dummy3d(:,:,vlev) = reshape(dummy, (/i_input,j_input/)) - enddo - endif - - print*,"- CALL FieldScatter FOR INPUT V-WIND." - call ESMF_FieldScatter(v_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ DPRES." - vname = "dpres" - vlevtyp = "mid layer" - do vlev = 1, lev_input - call nemsio_readrecv(gfile, vname, vlevtyp, vlev, dummy, 0, iret) - if (iret /= 0) call error_handler("READING DPRES RECORD.", iret) - print*,'dpres ',vlev, maxval(dummy),minval(dummy) - dummy3d(:,:,vlev) = reshape(dummy, (/i_input,j_input/)) - enddo - endif - - print*,"- CALL FieldScatter FOR INPUT DPRES." - call ESMF_FieldScatter(dpres_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ DZDT." - vname = "dzdt" - vlevtyp = "mid layer" - do vlev = 1, lev_input - call nemsio_readrecv(gfile, vname, vlevtyp, vlev, dummy, 0, iret) - if (iret /= 0) call error_handler("READING DZDT RECORD.", iret) - print*,'dzdt ',vlev, maxval(dummy),minval(dummy) - dummy3d(:,:,vlev) = reshape(dummy, (/i_input,j_input/)) - enddo - endif - - print*,"- CALL FieldScatter FOR INPUT DZDT." - call ESMF_FieldScatter(dzdt_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ HGT." - vname = "hgt" - vlevtyp = "sfc" - vlev = 1 - call nemsio_readrecv(gfile, vname, vlevtyp, vlev, dummy, 0, iret) - if (iret /= 0) call error_handler("READING HGT RECORD.", iret) - print*,'hgt ',vlev, maxval(dummy),minval(dummy) - dummy2d = reshape(dummy, (/i_input,j_input/)) - endif - - print*,"- CALL FieldScatter FOR TERRAIN." - call ESMF_FieldScatter(terrain_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - call nemsio_close(gfile) - - deallocate(dummy, dummy2d, dummy3d) - -!--------------------------------------------------------------------------- -! Convert from 2-d to 3-d component winds. -!--------------------------------------------------------------------------- - - call convert_winds - -!--------------------------------------------------------------------------- -! Compute 3-d pressure. Mid-layer and surface pressure are computed -! from delta p. The surface pressure in the file is not used. After -! the model's write component interpolates from the cubed-sphere grid -! to the gaussian grid, the surface pressure is no longer consistent -! with the delta p (per Jun Wang). -!--------------------------------------------------------------------------- - - print*,"- COMPUTE 3-D PRESSURE." - - print*,"- CALL FieldGet FOR DELTA PRESSURE." - nullify(dpresptr) - call ESMF_FieldGet(dpres_input_grid, & - computationalLBound=clb, & - computationalUBound=cub, & - farrayPtr=dpresptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR 3-D PRESSURE." - nullify(presptr) - call ESMF_FieldGet(pres_input_grid, & - farrayPtr=presptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR SURFACE PRESSURE." - nullify(psptr) - call ESMF_FieldGet(ps_input_grid, & - farrayPtr=psptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - allocate(pres_interface(levp1_input)) - - if (localpet == 0) then - do k = clb(3), cub(3) - print*,'dpres is ',cub(1),cub(2),k, dpresptr(cub(1),cub(2),k) - enddo - endif - - do i = clb(1), cub(1) - do j = clb(2), cub(2) - pres_interface(levp1_input) = vcoord(levp1_input,1,1) - do k = lev_input, 1, -1 - pres_interface(k) = pres_interface(k+1) + dpresptr(i,j,k) - enddo - psptr(i,j) = pres_interface(1) - do k = 1, lev_input - presptr(i,j,k) = (pres_interface(k) + pres_interface(k+1)) / 2.0_8 - enddo - enddo - enddo - - deallocate(vcoord) - - if (localpet == 0) then - print*,'psfc is ',clb(1),clb(2),psptr(clb(1),clb(2)) - print*,'pres is ',clb(1),clb(2),presptr(clb(1),clb(2),:) - endif - - print*,'pres check 1',localpet,maxval(presptr(:,:,1)),minval(presptr(:,:,1)) - print*,'pres check lev',localpet,maxval(presptr(:,:,lev_input)),minval(presptr(:,:,lev_input)) - - deallocate(pres_interface) - - call ESMF_FieldDestroy(dpres_input_grid, rc=rc) - - end subroutine read_input_atm_gaussian_nemsio_file - -!> Read input grid fv3 atmospheric data 'warm' restart files. -!! -!! @note Routine reads tiled files in parallel. Tile 1 is read by -!! localpet 0; tile 2 by localpet 1, etc. The number of pets -!! must be equal to or greater than the number of tiled files. -!! Logic only tested with global input data of six tiles. -!! @param[in] localpet ESMF local persistent execution thread -!! @author George Gayno NCEP/EMC - subroutine read_input_atm_restart_file(localpet) - - implicit none - - integer, intent(in) :: localpet - - character(len=500) :: tilefile - - integer :: i, j, k - integer :: clb(3), cub(3) - integer :: rc, tile, ncid, id_var - integer :: error, id_dim - - real(esmf_kind_r8), allocatable :: ak(:) - real(esmf_kind_r8), pointer :: presptr(:,:,:), psptr(:,:) - real(esmf_kind_r8), pointer :: dpresptr(:,:,:) - real(esmf_kind_r8), allocatable :: data_one_tile(:,:) - real(esmf_kind_r8), allocatable :: data_one_tile_3d(:,:,:) - real(esmf_kind_r8), allocatable :: pres_interface(:) - -!--------------------------------------------------------------------------- -! Get number of vertical levels and model top pressure. -!--------------------------------------------------------------------------- - - tilefile = trim(data_dir_input_grid) // "/" // trim(atm_core_files_input_grid(7)) - print*,"- READ ATM VERTICAL LEVELS FROM: ", trim(tilefile) - error=nf90_open(trim(tilefile),nf90_nowrite,ncid) - call netcdf_err(error, 'opening: '//trim(tilefile) ) - - error=nf90_inq_dimid(ncid, 'xaxis_1', id_dim) - call netcdf_err(error, 'reading xaxis_1 id' ) - error=nf90_inquire_dimension(ncid,id_dim,len=levp1_input) - call netcdf_err(error, 'reading xaxis_1 value' ) - - lev_input = levp1_input - 1 - - allocate(ak(levp1_input)) - - error=nf90_inq_varid(ncid, 'ak', id_var) - call netcdf_err(error, 'reading field id' ) - error=nf90_get_var(ncid, id_var, ak) - call netcdf_err(error, 'reading ak' ) - - error = nf90_close(ncid) - -!--------------------------------------------------------------------------- -! Initialize esmf atmospheric fields. -!--------------------------------------------------------------------------- - - call init_atm_esmf_fields - - print*,"- CALL FieldCreate FOR INPUT GRID DELTA PRESSURE." - dpres_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, & - ungriddedLBound=(/1/), & - ungriddedUBound=(/lev_input/), rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - if (localpet < num_tiles_input_grid) then - allocate(data_one_tile_3d(i_input,j_input,lev_input)) - allocate(data_one_tile(i_input,j_input)) - else - allocate(data_one_tile_3d(0,0,0)) - allocate(data_one_tile(0,0)) - endif - - if (localpet < num_tiles_input_grid) then - tile = localpet+1 - tilefile= trim(data_dir_input_grid) // "/" // trim(atm_core_files_input_grid(tile)) - print*,"- READ ATMOSPHERIC CORE FILE: ", trim(tilefile) - error=nf90_open(trim(tilefile),nf90_nowrite,ncid) - call netcdf_err(error, 'opening: '//trim(tilefile) ) - endif - - if (localpet < num_tiles_input_grid) then - error=nf90_inq_varid(ncid, 'phis', id_var) - call netcdf_err(error, 'reading field id' ) - error=nf90_get_var(ncid, id_var, data_one_tile) - call netcdf_err(error, 'reading field' ) - data_one_tile = data_one_tile / 9.806_8 ! geopotential height - endif - - do tile = 1, num_tiles_input_grid - print*,"- CALL FieldScatter FOR INPUT GRID TERRAIN for tile ",tile - call ESMF_FieldScatter(terrain_input_grid, data_one_tile, rootpet=tile-1, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - enddo - - if (localpet < num_tiles_input_grid) then -!cggg when outputting warm restart files, use w. - error=nf90_inq_varid(ncid, 'W', id_var) - call netcdf_err(error, 'reading field id' ) - error=nf90_get_var(ncid, id_var, data_one_tile_3d) - call netcdf_err(error, 'reading field' ) - data_one_tile_3d(:,:,1:lev_input) = data_one_tile_3d(:,:,lev_input:1:-1) - -! Using 'w' from restart files has caused problems. Set to zero. -! data_one_tile_3d = 0.0_8 - endif - - do tile = 1, num_tiles_input_grid - print*,"- CALL FieldScatter FOR INPUT GRID VERTICAL VELOCITY for tile ",tile - call ESMF_FieldScatter(dzdt_input_grid, data_one_tile_3d, rootpet=tile-1, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - enddo - - if (localpet < num_tiles_input_grid) then - error=nf90_inq_varid(ncid, 'T', id_var) - call netcdf_err(error, 'reading field id' ) - error=nf90_get_var(ncid, id_var, data_one_tile_3d) - call netcdf_err(error, 'reading field' ) - data_one_tile_3d(:,:,1:lev_input) = data_one_tile_3d(:,:,lev_input:1:-1) - endif - - do tile = 1, num_tiles_input_grid - print*,"- CALL FieldScatter FOR INPUT GRID TEMPERATURE." - call ESMF_FieldScatter(temp_input_grid, data_one_tile_3d, rootpet=tile-1, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - enddo - - if (localpet < num_tiles_input_grid) then - error=nf90_inq_varid(ncid, 'delp', id_var) - call netcdf_err(error, 'reading field id' ) - error=nf90_get_var(ncid, id_var, data_one_tile_3d) - call netcdf_err(error, 'reading field' ) - data_one_tile_3d(:,:,1:lev_input) = data_one_tile_3d(:,:,lev_input:1:-1) - endif - - do tile = 1, num_tiles_input_grid - print*,"- CALL FieldScatter FOR INPUT DELTA PRESSURE." - call ESMF_FieldScatter(dpres_input_grid, data_one_tile_3d, rootpet=tile-1, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - enddo - - if (localpet < num_tiles_input_grid) then - error=nf90_inq_varid(ncid, 'ua', id_var) - call netcdf_err(error, 'reading field id' ) - error=nf90_get_var(ncid, id_var, data_one_tile_3d) - call netcdf_err(error, 'reading field' ) - data_one_tile_3d(:,:,1:lev_input) = data_one_tile_3d(:,:,lev_input:1:-1) - endif - - do tile = 1, num_tiles_input_grid - print*,"- CALL FieldScatter FOR INPUT GRID U." - call ESMF_FieldScatter(u_input_grid, data_one_tile_3d, rootpet=tile-1, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - enddo - - if (localpet < num_tiles_input_grid) then - error=nf90_inq_varid(ncid, 'va', id_var) - call netcdf_err(error, 'reading field id' ) - error=nf90_get_var(ncid, id_var, data_one_tile_3d) - call netcdf_err(error, 'reading field' ) - data_one_tile_3d(:,:,1:lev_input) = data_one_tile_3d(:,:,lev_input:1:-1) - endif - - do tile = 1, num_tiles_input_grid - print*,"- CALL FieldScatter FOR INPUT GRID V." - call ESMF_FieldScatter(v_input_grid, data_one_tile_3d, rootpet=tile-1, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - enddo - - if (localpet < num_tiles_input_grid) error = nf90_close(ncid) - - if (localpet < num_tiles_input_grid) then - tile = localpet+1 - tilefile= trim(data_dir_input_grid) // "/" // trim(atm_tracer_files_input_grid(tile)) - print*,"- READ ATMOSPHERIC TRACER FILE: ", trim(tilefile) - error=nf90_open(trim(tilefile),nf90_nowrite,ncid) - call netcdf_err(error, 'opening: '//trim(tilefile) ) - endif - - do i = 1, num_tracers_input - - if (localpet < num_tiles_input_grid) then - error=nf90_inq_varid(ncid, tracers_input(i), id_var) - call netcdf_err(error, 'reading field id' ) - error=nf90_get_var(ncid, id_var, data_one_tile_3d) - call netcdf_err(error, 'reading field' ) - data_one_tile_3d(:,:,1:lev_input) = data_one_tile_3d(:,:,lev_input:1:-1) - endif - - do tile = 1, num_tiles_input_grid - print*,"- CALL FieldScatter FOR INPUT ", trim(tracers_input(i)) - call ESMF_FieldScatter(tracers_input_grid(i), data_one_tile_3d, rootpet=tile-1, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - enddo - - enddo - - if (localpet < num_tiles_input_grid) error=nf90_close(ncid) - -!--------------------------------------------------------------------------- -! Convert from 2-d to 3-d cartesian winds. -!--------------------------------------------------------------------------- - - call convert_winds - -!--------------------------------------------------------------------------- -! Compute pressures -!--------------------------------------------------------------------------- - - print*,"- CALL FieldGet FOR SURFACE PRESSURE." - call ESMF_FieldGet(ps_input_grid, & - farrayPtr=psptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR PRESSURE." - call ESMF_FieldGet(pres_input_grid, & - computationalLBound=clb, & - computationalUBound=cub, & - farrayPtr=presptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR DELTA PRESSURE." - call ESMF_FieldGet(dpres_input_grid, & - farrayPtr=dpresptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - allocate(pres_interface(levp1_input)) - - do i = clb(1), cub(1) - do j = clb(2), cub(2) - pres_interface(levp1_input) = ak(1) ! model top in Pa - do k = (levp1_input-1), 1, -1 - pres_interface(k) = pres_interface(k+1) + dpresptr(i,j,k) - enddo - do k = 1, lev_input - presptr(i,j,k) = (pres_interface(k) + pres_interface(k+1)) / 2.0_8 - enddo - psptr(i,j) = pres_interface(1) - enddo - enddo - - deallocate(ak) - deallocate(pres_interface) - - call ESMF_FieldDestroy(dpres_input_grid, rc=rc) - - deallocate(data_one_tile_3d, data_one_tile) - - end subroutine read_input_atm_restart_file - -!> Read fv3 netcdf gaussian history file. Each task reads a horizontal -!! slice. -!! -!! @param[in] localpet ESMF local persistent execution thread -!! @author George Gayno NCEP/EMC - subroutine read_input_atm_gaussian_netcdf_file(localpet) - - use mpi - - implicit none - - integer, intent(in) :: localpet - - character(len=500) :: tilefile - - integer :: start(3), count(3), iscnt - integer :: error, ncid, num_tracers_file - integer :: id_dim, idim_input, jdim_input - integer :: id_var, rc, nprocs, max_procs - integer :: kdim, remainder, myrank, i, j, k, n - integer :: clb(3), cub(3) - integer, allocatable :: kcount(:), startk(:), displ(:) - integer, allocatable :: ircnt(:) - - real(esmf_kind_r8), allocatable :: phalf(:) - real(esmf_kind_r8), allocatable :: pres_interface(:) - real(kind=4), allocatable :: dummy3d(:,:,:) - real(kind=4), allocatable :: dummy3dall(:,:,:) - real(esmf_kind_r8), allocatable :: dummy3dflip(:,:,:) - real(esmf_kind_r8), allocatable :: dummy(:,:) - real(esmf_kind_r8), pointer :: presptr(:,:,:), dpresptr(:,:,:) - real(esmf_kind_r8), pointer :: psptr(:,:) - - print*,"- READ INPUT ATMOS DATA FROM GAUSSIAN NETCDF FILE." - - tilefile = trim(data_dir_input_grid) // "/" // trim(atm_files_input_grid(1)) - error=nf90_open(trim(tilefile),nf90_nowrite,ncid) - call netcdf_err(error, 'opening: '//trim(tilefile) ) - - error=nf90_inq_dimid(ncid, 'grid_xt', id_dim) - call netcdf_err(error, 'reading grid_xt id' ) - error=nf90_inquire_dimension(ncid,id_dim,len=idim_input) - call netcdf_err(error, 'reading grid_xt value' ) - - error=nf90_inq_dimid(ncid, 'grid_yt', id_dim) - call netcdf_err(error, 'reading grid_yt id' ) - error=nf90_inquire_dimension(ncid,id_dim,len=jdim_input) - call netcdf_err(error, 'reading grid_yt value' ) - - if (idim_input /= i_input .or. jdim_input /= j_input) then - call error_handler("DIMENSION MISMATCH BETWEEN SFC AND OROG FILES.", 2) - endif - - error=nf90_inq_dimid(ncid, 'pfull', id_dim) - call netcdf_err(error, 'reading pfull id' ) - error=nf90_inquire_dimension(ncid,id_dim,len=lev_input) - call netcdf_err(error, 'reading pfull value' ) - - error=nf90_inq_dimid(ncid, 'phalf', id_dim) - call netcdf_err(error, 'reading phalf id' ) - error=nf90_inquire_dimension(ncid,id_dim,len=levp1_input) - call netcdf_err(error, 'reading phalf value' ) - allocate(phalf(levp1_input)) - error=nf90_inq_varid(ncid, 'phalf', id_var) - call netcdf_err(error, 'getting phalf varid' ) - error=nf90_get_var(ncid, id_var, phalf) - call netcdf_err(error, 'reading phalf varid' ) - - error=nf90_get_att(ncid, nf90_global, 'ncnsto', num_tracers_file) - call netcdf_err(error, 'reading ntracer value' ) - - call mpi_comm_size(mpi_comm_world, nprocs, error) - print*,'- Running with ', nprocs, ' processors' - - call mpi_comm_rank(mpi_comm_world, myrank, error) - print*,'- myrank/localpet is ',myrank,localpet - - max_procs = nprocs - if (nprocs > lev_input) then - max_procs = lev_input - endif - - kdim = lev_input / max_procs - remainder = lev_input - (max_procs*kdim) - - allocate(kcount(0:nprocs-1)) - kcount=0 - allocate(startk(0:nprocs-1)) - startk=0 - allocate(displ(0:nprocs-1)) - displ=0 - allocate(ircnt(0:nprocs-1)) - ircnt=0 - - do k = 0, max_procs-2 - kcount(k) = kdim - enddo - kcount(max_procs-1) = kdim + remainder - - startk(0) = 1 - do k = 1, max_procs-1 - startk(k) = startk(k-1) + kcount(k-1) - enddo - - ircnt(:) = idim_input * jdim_input * kcount(:) - - displ(0) = 0 - do k = 1, max_procs-1 - displ(k) = displ(k-1) + ircnt(k-1) - enddo - - iscnt=idim_input*jdim_input*kcount(myrank) - -! Account for case if number of tasks exceeds the number of vert levels. - - if (myrank <= max_procs-1) then - allocate(dummy3d(idim_input,jdim_input,kcount(myrank))) - else - allocate(dummy3d(0,0,0)) - endif - - if (myrank == 0) then - allocate(dummy3dall(idim_input,jdim_input,lev_input)) - dummy3dall = 0.0 - allocate(dummy3dflip(idim_input,jdim_input,lev_input)) - dummy3dflip = 0.0 - allocate(dummy(idim_input,jdim_input)) - dummy = 0.0 - else - allocate(dummy3dall(0,0,0)) - allocate(dummy3dflip(0,0,0)) - allocate(dummy(0,0)) - endif - -!--------------------------------------------------------------------------- -! Initialize esmf atmospheric fields. -!--------------------------------------------------------------------------- - - call init_atm_esmf_fields - - print*,"- CALL FieldCreate FOR INPUT GRID DELTA PRESSURE." - dpres_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, & - ungriddedLBound=(/1/), & - ungriddedUBound=(/lev_input/), rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - -! Temperature - - if (myrank <= max_procs-1) then - start = (/1,1,startk(myrank)/) - count = (/idim_input,jdim_input,kcount(myrank)/) - error=nf90_inq_varid(ncid, 'tmp', id_var) - call netcdf_err(error, 'reading tmp field id' ) - error=nf90_get_var(ncid, id_var, dummy3d, start=start, count=count) - call netcdf_err(error, 'reading tmp field' ) - endif - - call mpi_gatherv(dummy3d, iscnt, mpi_real, & - dummy3dall, ircnt, displ, mpi_real, & - 0, mpi_comm_world, error) - if (error /= 0) call error_handler("IN mpi_gatherv of temperature", error) - - if (myrank == 0) then - dummy3dflip(:,:,1:lev_input) = dummy3dall(:,:,lev_input:1:-1) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID TEMPERATURE " - call ESMF_FieldScatter(temp_input_grid, dummy3dflip, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! dpres - - if (myrank <= max_procs-1) then - error=nf90_inq_varid(ncid, 'dpres', id_var) - call netcdf_err(error, 'reading dpres field id' ) - error=nf90_get_var(ncid, id_var, dummy3d, start=start, count=count) - call netcdf_err(error, 'reading dpres field' ) - endif - - call mpi_gatherv(dummy3d, iscnt, mpi_real, & - dummy3dall, ircnt, displ, mpi_real, & - 0, mpi_comm_world, error) - if (error /= 0) call error_handler("IN mpi_gatherv of dpres", error) - - if (myrank == 0) then - dummy3dflip(:,:,1:lev_input) = dummy3dall(:,:,lev_input:1:-1) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID DPRES " - call ESMF_FieldScatter(dpres_input_grid, dummy3dflip, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! ugrd - - if (myrank <= max_procs-1) then - error=nf90_inq_varid(ncid, 'ugrd', id_var) - call netcdf_err(error, 'reading ugrd field id' ) - error=nf90_get_var(ncid, id_var, dummy3d, start=start, count=count) - call netcdf_err(error, 'reading ugrd field' ) - endif - - call mpi_gatherv(dummy3d, iscnt, mpi_real, & - dummy3dall, ircnt, displ, mpi_real, & - 0, mpi_comm_world, error) - if (error /= 0) call error_handler("IN mpi_gatherv of ugrd", error) - - if (myrank == 0) then - dummy3dflip(:,:,1:lev_input) = dummy3dall(:,:,lev_input:1:-1) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID UGRD " - call ESMF_FieldScatter(u_input_grid, dummy3dflip, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! vgrd - - if (myrank <= max_procs-1) then - error=nf90_inq_varid(ncid, 'vgrd', id_var) - call netcdf_err(error, 'reading vgrd field id' ) - error=nf90_get_var(ncid, id_var, dummy3d, start=start, count=count) - call netcdf_err(error, 'reading vgrd field' ) - endif - - call mpi_gatherv(dummy3d, iscnt, mpi_real, & - dummy3dall, ircnt, displ, mpi_real, & - 0, mpi_comm_world, error) - if (error /= 0) call error_handler("IN mpi_gatherv of vgrd", error) - - if (myrank == 0) then - dummy3dflip(:,:,1:lev_input) = dummy3dall(:,:,lev_input:1:-1) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID VGRD " - call ESMF_FieldScatter(v_input_grid, dummy3dflip, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! tracers - - do n = 1, num_tracers_input - - if (myrank <= max_procs-1) then - error=nf90_inq_varid(ncid, tracers_input(n), id_var) - call netcdf_err(error, 'reading tracer field id' ) - error=nf90_get_var(ncid, id_var, dummy3d, start=start, count=count) - call netcdf_err(error, 'reading tracer field' ) - endif - - call mpi_gatherv(dummy3d, iscnt, mpi_real, & - dummy3dall, ircnt, displ, mpi_real, & - 0, mpi_comm_world, error) - if (error /= 0) call error_handler("IN mpi_gatherv of tracer", error) - - if (myrank == 0) then - dummy3dflip(:,:,1:lev_input) = dummy3dall(:,:,lev_input:1:-1) - where(dummy3dflip < 0.0) dummy3dflip = 0.0 - endif - - print*,"- CALL FieldScatter FOR INPUT GRID ", tracers_input(n) - call ESMF_FieldScatter(tracers_input_grid(n), dummy3dflip, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - enddo - -! dzdt set to zero for now. - - if (myrank == 0) then - dummy3dflip = 0.0 - endif - - print*,"- CALL FieldScatter FOR INPUT GRID DZDT" - call ESMF_FieldScatter(dzdt_input_grid, dummy3dflip, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - deallocate(dummy3dflip, dummy3dall, dummy3d) - -! terrain - - if (myrank==0) then - print*,"- READ TERRAIN." - error=nf90_inq_varid(ncid, 'hgtsfc', id_var) - call netcdf_err(error, 'reading hgtsfc field id' ) - error=nf90_get_var(ncid, id_var, dummy) - call netcdf_err(error, 'reading hgtsfc field' ) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID TERRAIN." - call ESMF_FieldScatter(terrain_input_grid, dummy, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! surface pressure - - if (myrank==0) then - print*,"- READ SURFACE P." - error=nf90_inq_varid(ncid, 'pressfc', id_var) - call netcdf_err(error, 'reading pressfc field id' ) - error=nf90_get_var(ncid, id_var, dummy) - call netcdf_err(error, 'reading pressfc field' ) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SURFACE P." - call ESMF_FieldScatter(ps_input_grid, dummy, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - deallocate(kcount, startk, displ, ircnt, dummy) - -!--------------------------------------------------------------------------- -! Convert from 2-d to 3-d cartesian winds. -!--------------------------------------------------------------------------- - - call convert_winds - -!--------------------------------------------------------------------------- -! Compute pressure. -!--------------------------------------------------------------------------- - - print*,"- CALL FieldGet FOR PRESSURE." - call ESMF_FieldGet(pres_input_grid, & - computationalLBound=clb, & - computationalUBound=cub, & - farrayPtr=presptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR DELTA PRESSURE." - call ESMF_FieldGet(dpres_input_grid, & - farrayPtr=dpresptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR SURFACE PRESSURE." - call ESMF_FieldGet(ps_input_grid, & - farrayPtr=psptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - allocate(pres_interface(levp1_input)) - -!--------------------------------------------------------------------------- -! Compute 3-d pressure. -!--------------------------------------------------------------------------- - -!--------------------------------------------------------------------------- -! When ingesting gaussian netcdf files, the mid-layer -! surface pressure are computed top down from delta-p -! The surface pressure in the file is not used. According -! to Jun Wang, after the model's write component interpolates from the -! cubed-sphere grid to the gaussian grid, the surface pressure is -! no longer consistent with the delta p. -!--------------------------------------------------------------------------- - - do i = clb(1), cub(1) - do j = clb(2), cub(2) - pres_interface(levp1_input) = phalf(1) * 100.0_8 - do k = lev_input, 1, -1 - pres_interface(k) = pres_interface(k+1) + dpresptr(i,j,k) - enddo - psptr(i,j) = pres_interface(1) - do k = 1, lev_input - presptr(i,j,k) = (pres_interface(k) + pres_interface(k+1)) / 2.0_8 - enddo - enddo - enddo - - deallocate(pres_interface, phalf) - - call ESMF_FieldDestroy(dpres_input_grid, rc=rc) - - end subroutine read_input_atm_gaussian_netcdf_file - -!> Read input grid fv3 atmospheric tiled history files in netcdf -!! format. -!! -!! @note Routine reads tiled files in parallel. Tile 1 is read by -!! localpet 0; tile 2 by localpet 1, etc. The number of pets -!! must be equal to or greater than the number of tiled files. -!! -!! @param[in] localpet ESMF local persistent execution thread -!! @author George Gayno NCEP/EMC - subroutine read_input_atm_tiled_history_file(localpet) - - use mpi - - implicit none - - integer, intent(in) :: localpet - - character(len=500) :: tilefile - - integer :: error, ncid, rc, tile - integer :: id_dim, idim_input, jdim_input - integer :: id_var, i, j, k, n - integer :: clb(3), cub(3), num_tracers_file - - real(esmf_kind_r8), allocatable :: data_one_tile(:,:) - real(esmf_kind_r8), allocatable :: data_one_tile_3d(:,:,:) - real(esmf_kind_r8), pointer :: presptr(:,:,:), dpresptr(:,:,:) - real(esmf_kind_r8), pointer :: psptr(:,:) - real(esmf_kind_r8), allocatable :: pres_interface(:), phalf(:) - - print*,"- READ INPUT ATMOS DATA FROM TILED HISTORY FILES." - - tilefile = trim(data_dir_input_grid) // "/" // trim(atm_files_input_grid(1)) - error=nf90_open(trim(tilefile),nf90_nowrite,ncid) - call netcdf_err(error, 'opening: '//trim(tilefile) ) - - error=nf90_inq_dimid(ncid, 'grid_xt', id_dim) - call netcdf_err(error, 'reading grid_xt id' ) - error=nf90_inquire_dimension(ncid,id_dim,len=idim_input) - call netcdf_err(error, 'reading grid_xt value' ) - - error=nf90_inq_dimid(ncid, 'grid_yt', id_dim) - call netcdf_err(error, 'reading grid_yt id' ) - error=nf90_inquire_dimension(ncid,id_dim,len=jdim_input) - call netcdf_err(error, 'reading grid_yt value' ) - - if (idim_input /= i_input .or. jdim_input /= j_input) then - call error_handler("DIMENSION MISMATCH BETWEEN SFC AND OROG FILES.", 2) - endif - - error=nf90_inq_dimid(ncid, 'pfull', id_dim) - call netcdf_err(error, 'reading pfull id' ) - error=nf90_inquire_dimension(ncid,id_dim,len=lev_input) - call netcdf_err(error, 'reading pfull value' ) - - error=nf90_inq_dimid(ncid, 'phalf', id_dim) - call netcdf_err(error, 'reading phalf id' ) - error=nf90_inquire_dimension(ncid,id_dim,len=levp1_input) - call netcdf_err(error, 'reading phalf value' ) - allocate(phalf(levp1_input)) - error=nf90_inq_varid(ncid, 'phalf', id_var) - call netcdf_err(error, 'getting phalf varid' ) - error=nf90_get_var(ncid, id_var, phalf) - call netcdf_err(error, 'reading phalf varid' ) - - error=nf90_get_att(ncid, nf90_global, 'ncnsto', num_tracers_file) - call netcdf_err(error, 'reading ntracer value' ) - - error = nf90_close(ncid) - - print*,'- FILE HAS ', num_tracers_file, ' TRACERS.' - print*,'- WILL PROCESS ', num_tracers_input, ' TRACERS.' - -!--------------------------------------------------------------------------- -! Initialize esmf atmospheric fields. -!--------------------------------------------------------------------------- - - call init_atm_esmf_fields - - print*,"- CALL FieldCreate FOR INPUT GRID DELTA PRESSURE." - dpres_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, & - ungriddedLBound=(/1/), & - ungriddedUBound=(/lev_input/), rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - if (localpet < num_tiles_input_grid) then - allocate(data_one_tile(i_input,j_input)) - allocate(data_one_tile_3d(i_input,j_input,lev_input)) - else - allocate(data_one_tile(0,0)) - allocate(data_one_tile_3d(0,0,0)) - endif - - if (localpet < num_tiles_input_grid) then - tile = localpet+1 - tilefile= trim(data_dir_input_grid) // "/" // trim(atm_files_input_grid(tile)) - print*,"- READ ATMOSPHERIC DATA FROM: ", trim(tilefile) - error=nf90_open(trim(tilefile),nf90_nowrite,ncid) - call netcdf_err(error, 'opening: '//trim(tilefile) ) - endif - - if (localpet < num_tiles_input_grid) then -! print*,"- READ VERTICAL VELOCITY." -! error=nf90_inq_varid(ncid, 'dzdt', id_var) -! call netcdf_err(error, 'reading field id' ) -! error=nf90_get_var(ncid, id_var, data_one_tile_3d) -! call netcdf_err(error, 'reading field' ) -! data_one_tile_3d(:,:,1:lev_input) = data_one_tile_3d(:,:,lev_input:1:-1) - -! Using w from the tiled history files has caused problems. -! Set to zero. - data_one_tile_3d = 0.0_8 - endif - - do tile = 1, num_tiles_input_grid - print*,"- CALL FieldScatter FOR INPUT GRID VERTICAL VELOCITY." - call ESMF_FieldScatter(dzdt_input_grid, data_one_tile_3d, rootpet=tile-1, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - enddo - - do n = 1, num_tracers_input - - if (localpet < num_tiles_input_grid) then - print*,"- READ ", trim(tracers_input(n)) - error=nf90_inq_varid(ncid, tracers_input(n), id_var) - call netcdf_err(error, 'reading field id' ) - error=nf90_get_var(ncid, id_var, data_one_tile_3d) - call netcdf_err(error, 'reading field' ) - data_one_tile_3d(:,:,1:lev_input) = data_one_tile_3d(:,:,lev_input:1:-1) - endif - - do tile = 1, num_tiles_input_grid - print*,"- CALL FieldScatter FOR INPUT GRID TRACER ", trim(tracers_input(n)) - call ESMF_FieldScatter(tracers_input_grid(n), data_one_tile_3d, rootpet=tile-1, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - enddo - - enddo - - if (localpet < num_tiles_input_grid) then - print*,"- READ TEMPERATURE." - error=nf90_inq_varid(ncid, 'tmp', id_var) - call netcdf_err(error, 'reading field id' ) - error=nf90_get_var(ncid, id_var, data_one_tile_3d) - call netcdf_err(error, 'reading field' ) - data_one_tile_3d(:,:,1:lev_input) = data_one_tile_3d(:,:,lev_input:1:-1) - endif - - do tile = 1, num_tiles_input_grid - print*,"- CALL FieldScatter FOR INPUT GRID TEMPERATURE." - call ESMF_FieldScatter(temp_input_grid, data_one_tile_3d, rootpet=tile-1, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - enddo - - if (localpet < num_tiles_input_grid) then - print*,"- READ U-WIND." - error=nf90_inq_varid(ncid, 'ugrd', id_var) - call netcdf_err(error, 'reading field id' ) - error=nf90_get_var(ncid, id_var, data_one_tile_3d) - call netcdf_err(error, 'reading field' ) - data_one_tile_3d(:,:,1:lev_input) = data_one_tile_3d(:,:,lev_input:1:-1) - endif - - do tile = 1, num_tiles_input_grid - print*,"- CALL FieldScatter FOR INPUT GRID U." - call ESMF_FieldScatter(u_input_grid, data_one_tile_3d, rootpet=tile-1, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - enddo - - if (localpet < num_tiles_input_grid) then - print*,"- READ V-WIND." - error=nf90_inq_varid(ncid, 'vgrd', id_var) - call netcdf_err(error, 'reading field id' ) - error=nf90_get_var(ncid, id_var, data_one_tile_3d) - call netcdf_err(error, 'reading field' ) - data_one_tile_3d(:,:,1:lev_input) = data_one_tile_3d(:,:,lev_input:1:-1) - endif - - do tile = 1, num_tiles_input_grid - print*,"- CALL FieldScatter FOR INPUT GRID V." - call ESMF_FieldScatter(v_input_grid, data_one_tile_3d, rootpet=tile-1, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - enddo - - if (localpet < num_tiles_input_grid) then - print*,"- READ SURFACE PRESSURE." - error=nf90_inq_varid(ncid, 'pressfc', id_var) - call netcdf_err(error, 'reading field id' ) - error=nf90_get_var(ncid, id_var, data_one_tile) - call netcdf_err(error, 'reading field' ) - endif - - do tile = 1, num_tiles_input_grid - print*,"- CALL FieldScatter FOR INPUT GRID SURFACE PRESSURE." - call ESMF_FieldScatter(ps_input_grid, data_one_tile, rootpet=tile-1, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - enddo - - if (localpet < num_tiles_input_grid) then - print*,"- READ TERRAIN." - error=nf90_inq_varid(ncid, 'hgtsfc', id_var) - call netcdf_err(error, 'reading field id' ) - error=nf90_get_var(ncid, id_var, data_one_tile) - call netcdf_err(error, 'reading field' ) - endif - - do tile = 1, num_tiles_input_grid - print*,"- CALL FieldScatter FOR INPUT GRID TERRAIN." - call ESMF_FieldScatter(terrain_input_grid, data_one_tile, rootpet=tile-1, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - enddo - - if (localpet < num_tiles_input_grid) then - print*,"- READ DELTA PRESSURE." - error=nf90_inq_varid(ncid, 'dpres', id_var) - call netcdf_err(error, 'reading field id' ) - error=nf90_get_var(ncid, id_var, data_one_tile_3d) - call netcdf_err(error, 'reading field' ) - data_one_tile_3d(:,:,1:lev_input) = data_one_tile_3d(:,:,lev_input:1:-1) - endif - - do tile = 1, num_tiles_input_grid - print*,"- CALL FieldScatter FOR INPUT DELTA PRESSURE." - call ESMF_FieldScatter(dpres_input_grid, data_one_tile_3d, rootpet=tile-1, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - enddo - - if (localpet < num_tiles_input_grid) error = nf90_close(ncid) - - deallocate(data_one_tile_3d, data_one_tile) - -!--------------------------------------------------------------------------- -! Convert from 2-d to 3-d cartesian winds. -!--------------------------------------------------------------------------- - - call convert_winds - -!--------------------------------------------------------------------------- -! Compute pressure. -!--------------------------------------------------------------------------- - - print*,"- CALL FieldGet FOR PRESSURE." - call ESMF_FieldGet(pres_input_grid, & - computationalLBound=clb, & - computationalUBound=cub, & - farrayPtr=presptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR DELTA PRESSURE." - call ESMF_FieldGet(dpres_input_grid, & - farrayPtr=dpresptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR SURFACE PRESSURE." - call ESMF_FieldGet(ps_input_grid, & - farrayPtr=psptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - allocate(pres_interface(levp1_input)) - -!--------------------------------------------------------------------------- -! Compute 3-d pressure. -!--------------------------------------------------------------------------- - - do i = clb(1), cub(1) - do j = clb(2), cub(2) - pres_interface(1) = psptr(i,j) - do k = 2, levp1_input - pres_interface(k) = pres_interface(k-1) - dpresptr(i,j,k-1) - enddo - do k = 1, lev_input - presptr(i,j,k) = (pres_interface(k) + pres_interface(k+1)) / 2.0_8 - enddo - enddo - enddo - - deallocate(pres_interface, phalf) - - call ESMF_FieldDestroy(dpres_input_grid, rc=rc) - - end subroutine read_input_atm_tiled_history_file - -!> Read input grid atmospheric fv3gfs grib2 files. -!! -!! @param[in] localpet ESMF local persistent execution thread -!! @author George Gayno NCEP/EMC - subroutine read_input_atm_grib2_file(localpet) - - use wgrib2api - - use grib2_util, only : rh2spfh, rh2spfh_gfs, convert_omega - - implicit none - - integer, intent(in) :: localpet - - integer, parameter :: ntrac_max=14 - - character(len=300) :: the_file - character(len=20) :: vlevtyp, vname, lvl_str,lvl_str_space, & - trac_names_grib_1(ntrac_max), & - trac_names_grib_2(ntrac_max), & - trac_names_vmap(ntrac_max), & - tracers_input_grib_1(num_tracers_input), & - tracers_input_grib_2(num_tracers_input), & - tmpstr, & - method, tracers_input_vmap(num_tracers_input), & - tracers_default(ntrac_max), vname2 - character (len=500) :: metadata - - integer :: i, j, k, n, lvl_str_space_len - integer :: ii,jj - integer :: rc, clb(3), cub(3) - integer :: vlev, iret,varnum - integer :: all_empty, o3n - integer :: len_str - integer :: is_missing, intrp_ier, done_print - - logical :: lret - logical :: conv_omega=.false., & - hasspfh=.true., & - isnative=.false., & - use_rh=.false. - - - real(esmf_kind_r8), allocatable :: rlevs(:) - real(esmf_kind_r4), allocatable :: dummy2d(:,:) - real(esmf_kind_r8), allocatable :: dummy3d(:,:,:), dummy2d_8(:,:),& - u_tmp_3d(:,:,:), v_tmp_3d(:,:,:) - real(esmf_kind_r8), pointer :: presptr(:,:,:), psptr(:,:),tptr(:,:,:), & - qptr(:,:,:), wptr(:,:,:), & - uptr(:,:,:), vptr(:,:,:) - real(esmf_kind_r4) :: value - real(esmf_kind_r8), parameter :: p0 = 100000.0 - real(esmf_kind_r8), allocatable :: dummy3d_col_in(:),dummy3d_col_out(:) - real(esmf_kind_r8), parameter :: intrp_missing = -999.0 - real(esmf_kind_r4), parameter :: lev_no_tr_fill = 20000.0 - real(esmf_kind_r4), parameter :: lev_no_o3_fill = 40000.0 - - - tracers(:) = "NULL" - !trac_names_grib = (/":SPFH:",":CLWR:", "O3MR",":CICE:", ":RWMR:",":SNMR:",":GRLE:", & - ! ":TCDC:", ":NCCICE:",":SPNCR:", ":NCONCD:",":PMTF:",":PMTC:",":TKE:"/) - trac_names_grib_1 = (/":var0_2", ":var0_2", ":var0_2", ":var0_2", ":var0_2",":var0_2", \ - ":var0_2", ":var0_2", ":var0_2", ":var0_2", ":var0_2",":var0_2", \ - ":var0_2", ":var0_2"/) - trac_names_grib_2 = (/"_1_0: ", "_1_22: ", "_14_192:", "_1_23: ", "_1_24: ","_1_25: ", \ - "_1_32: ", "_6_1: ", "_6_29: ", "_1_100: ", "_6_28: ","_13_193:", \ - "_13_192:", "_2_2: "/) - trac_names_vmap = (/"sphum ", "liq_wat ", "o3mr ", "ice_wat ", & - "rainwat ", "snowwat ", "graupel ", "cld_amt ", "ice_nc ", & - "rain_nc ", "water_nc", "liq_aero", "ice_aero", & - "sgs_tke "/) - tracers_default = (/"sphum ", "liq_wat ", "o3mr ", "ice_wat ", & - "rainwat ", "snowwat ", "graupel ", "cld_amt ", "ice_nc ", & - "rain_nc ", "water_nc", "liq_aero", "ice_aero", & - "sgs_tke "/) - - the_file = trim(data_dir_input_grid) // "/" // trim(grib2_file_input_grid) - - print*,"- READ ATMOS DATA FROM GRIB2 FILE: ", trim(the_file) - print*,"- USE INVENTORY FILE ", inv_file - - print*,"- OPEN FILE." - inquire(file=the_file,exist=lret) - if (.not.lret) call error_handler("OPENING GRIB2 ATM FILE.", iret) - - print*,"- READ VERTICAL COORDINATE." - iret = grb2_inq(the_file,inv_file,":var0_2","_0_0:",":10 hybrid level:") - - if (iret <= 0) then - lvl_str = "mb:" - lvl_str_space = " mb:" - lvl_str_space_len = 4 - isnative = .false. - iret = grb2_inq(the_file,inv_file,":UGRD:",lvl_str_space) - lev_input=iret - if (localpet == 0) print*,"- DATA IS ON ", lev_input, " ISOBARIC LEVELS." - else - lvl_str = " level:" - lvl_str_space = " hybrid " - lvl_str_space_len = 7 - isnative = .true. - iret = grb2_inq(the_file,inv_file,":UGRD:",lvl_str_space, " level:") - if (iret < 0) call error_handler("READING VERTICAL LEVEL TYPE.", iret) - lev_input=iret - endif - - allocate(slevs(lev_input)) - allocate(rlevs(lev_input)) - allocate(dummy3d_col_in(lev_input)) - allocate(dummy3d_col_out(lev_input)) - - levp1_input = lev_input + 1 - -! Get the vertical levels, and search string by sequential reads - - do i = 1,lev_input - iret=grb2_inq(the_file,inv_file,':UGRD:',trim(lvl_str),sequential=i-1,desc=metadata) - if (iret.ne.1) call error_handler(" IN SEQUENTIAL FILE READ.", iret) - - j = index(metadata,':UGRD:') + len(':UGRD:') - k = index(metadata,trim(lvl_str_space)) + len(trim(lvl_str_space))-1 - - read(metadata(j:k),*) rlevs(i) - - slevs(i) = metadata(j-1:k) - if (.not. isnative) rlevs(i) = rlevs(i) * 100.0 - if (localpet==0) print*, "- LEVEL = ", slevs(i) - enddo - -! Jili Dong add sort to re-order isobaric levels. - - call quicksort(rlevs,1,lev_input) - - if (.not. isnative) then - do i = 1,lev_input - write(slevs(i),"(F20.10)") rlevs(i)/100.0 - len_str = len_trim(slevs(i)) - - do while (slevs(i)(len_str:len_str) .eq. '0') - slevs(i) = slevs(i)(:len_str-1) - len_str = len_str - 1 - end do - - if (slevs(i)(len_str:len_str) .eq. '.') then - slevs(i) = slevs(i)(:len_str-1) - len_str = len_str - 1 - end if - - slevs(i) = trim(slevs(i)) - - slevs(i) = ":"//trim(adjustl(slevs(i)))//" mb:" - if (localpet==0) print*, "- LEVEL AFTER SORT = ",slevs(i) - enddo - endif - -! Is SPFH on full levels Jili Dong - do vlev = 1, lev_input - iret = grb2_inq(the_file,inv_file,':SPFH:',slevs(vlev)) - if (iret <= 0) then - use_rh = .TRUE. - if (localpet == 0) print*, ':SPFH on level '//trim(slevs(vlev))//' does not exist. & - Will read in RH and convert to SPFH instead.' - exit - end if - end do - - - if (localpet == 0) print*,"- FIND SPFH OR RH IN FILE" - iret = grb2_inq(the_file,inv_file,trim(trac_names_grib_1(1)),trac_names_grib_2(1),lvl_str_space) - - if (iret <= 0 .or. use_rh) then - iret = grb2_inq(the_file,inv_file, ':var0_2','_1_1:',lvl_str_space) - if (iret <= 0) call error_handler("READING ATMOSPHERIC WATER VAPOR VARIABLE.", iret) - hasspfh = .false. - trac_names_grib_2(1)='_1_1:' - if (localpet == 0) print*,"- FILE CONTAINS RH." - else - if (localpet == 0) print*,"- FILE CONTAINS SPFH." - endif - - if (localpet == 0) print*,"- FIND ICMR, SCLIWC, OR CICE IN FILE" - iret = grb2_inq(the_file,inv_file,trac_names_grib_1(4),trac_names_grib_2(4),lvl_str_space) - - if (iret <= 0) then - vname = trac_names_vmap(4) - print*, "vname = ", vname - call get_var_cond(vname,this_miss_var_method=method, this_miss_var_value=value, & - this_field_var_name=tmpstr,loc=varnum) - iret = grb2_inq(the_file,inv_file, ':var0_2','_1_84:',lvl_str_space) - if (iret <= 0) then - iret = grb2_inq(the_file,inv_file, ':var0_2','_6_0:',lvl_str_space) - if (iret <= 0 ) then - call handle_grib_error(vname, slevs(1),method,value,varnum,rc,var=dummy2d) - else - trac_names_grib_2(4) = '_6_0' - if (localpet == 0) print*,"- FILE CONTAINS CICE." - endif - else - trac_names_grib_2(4)='_1_84:' - if (localpet == 0) print*,"- FILE CONTAINS SCLIWC." - endif - else - if (localpet == 0) print*,"- FILE CONTAINS ICMR." - endif - - if (localpet == 0) print*,"- FIND CLWMR or SCLLWC IN FILE" - iret = grb2_inq(the_file,inv_file,trac_names_grib_1(5),trac_names_grib_2(5),lvl_str_space) - - if (iret <= 0) then - vname = trac_names_vmap(5) - print*, "vname = ", vname - call get_var_cond(vname,this_miss_var_method=method, this_miss_var_value=value, & - this_field_var_name=tmpstr,loc=varnum) - iret = grb2_inq(the_file,inv_file, ':var0_2','_1_83:',lvl_str_space) - if (iret <= 0) then - call handle_grib_error(vname, slevs(1),method,value,varnum,rc,var=dummy2d) - elseif (iret <=0 .and. rc .ne. 1) then - call error_handler("READING CLOUD WATER VARIABLE.", iret) - else - trac_names_grib_2(4)='_1_83:' - if (localpet == 0) print*,"- FILE CONTAINS SCLLWC." - endif - else - if (localpet == 0) print*,"- FILE CONTAINS CLWMR." - endif - - print*,"- COUNT NUMBER OF TRACERS TO BE READ IN BASED ON PHYSICS SUITE TABLE" - do n = 1, num_tracers_input - - vname = tracers_input(n) - - i = maxloc(merge(1.,0.,trac_names_vmap == vname),dim=1) - - tracers_input_grib_1(n) = trac_names_grib_1(i) - tracers_input_grib_2(n) = trac_names_grib_2(i) - tracers_input_vmap(n)=trac_names_vmap(i) - tracers(n)=tracers_default(i) - if(trim(tracers(n)) .eq. "o3mr") o3n = n - - enddo - - if (localpet==0) then - print*, "- NUMBER OF TRACERS IN THE INPUT FILE = ", num_tracers_input - endif - -!--------------------------------------------------------------------------- -! Initialize esmf atmospheric fields. -!--------------------------------------------------------------------------- - - call init_atm_esmf_fields - - if (localpet == 0) then - allocate(dummy2d(i_input,j_input)) - allocate(dummy2d_8(i_input,j_input)) - allocate(dummy3d(i_input,j_input,lev_input)) - else - allocate(dummy2d(0,0)) - allocate(dummy2d_8(0,0)) - allocate(dummy3d(0,0,0)) - endif - -!---------------------------------------------------------------------------------- -! This program expects field levels from bottom to top. Fields in non-native -! files read in from top to bottom. We will flip indices later. Fields on -! native vertical coordinates read from bottom to top so those need no adjustments. -!---------------------------------------------------------------------------------- - - if (localpet == 0) then - print*,"- READ TEMPERATURE." - vname = ":TMP:" - do vlev = 1, lev_input - iret = grb2_inq(the_file,inv_file,vname,slevs(vlev),data2=dummy2d) - if (iret<=0) then - call error_handler("READING IN TEMPERATURE AT LEVEL "//trim(slevs(vlev)),iret) - endif - dummy3d(:,:,vlev) = real(dummy2d,esmf_kind_r8) - print*,'temp check after read ',vlev, dummy3d(1,1,vlev) - enddo - endif - - if (localpet == 0) print*,"- CALL FieldScatter FOR INPUT GRID TEMPERATURE." - call ESMF_FieldScatter(temp_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - do n = 1, num_tracers_input - - if (localpet == 0) print*,"- READ ", trim(tracers_input_vmap(n)) - vname = tracers_input_vmap(n) - call get_var_cond(vname,this_miss_var_method=method, this_miss_var_value=value, & - this_field_var_name=tmpstr,loc=varnum) - if (n==1 .and. .not. hasspfh) then - print*,"- CALL FieldGather TEMPERATURE." - call ESMF_FieldGather(temp_input_grid,dummy3d,rootPet=0, tile=1, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - endif - - if (localpet == 0) then - vname = trim(tracers_input_grib_1(n)) - vname2 = trim(tracers_input_grib_2(n)) - iret = grb2_inq(the_file,inv_file,vname,lvl_str_space,vname2) - - ! Check to see if file has any data for this tracer - if (iret == 0) then - all_empty = 1 - else - all_empty = 0 - endif - - is_missing = 0 - do vlev = 1, lev_input - iret = grb2_inq(the_file,inv_file,vname,slevs(vlev),vname2,data2=dummy2d) - - if (iret <= 0) then - if (trim(method) .eq. 'intrp' .and. all_empty == 0) then - dummy2d = intrp_missing - is_missing = 1 - else - ! Abort if input data has some data for current tracer, but has - ! missing data below 200 mb/ above 400mb - if (all_empty == 0 .and. n == o3n) then - if (rlevs(vlev) .lt. lev_no_o3_fill) & - call error_handler("TRACER "//trim(tracers(n))//" HAS MISSING DATA AT "//trim(slevs(vlev))//& - ". SET MISSING VARIABLE CONDITION TO 'INTRP' TO AVOID THIS ERROR", 1) - elseif (all_empty == 0 .and. n .ne. o3n) then - if (rlevs(vlev) .gt. lev_no_tr_fill) & - call error_handler("TRACER "//trim(tracers(n))//" HAS MISSING DATA AT "//trim(slevs(vlev))//& - ". SET MISSING VARIABLE CONDITION TO 'INTRP' TO AVOID THIS ERROR.", 1) - endif - ! If entire array is empty and method is set to intrp, switch method to fill - if (trim(method) .eq. 'intrp' .and. all_empty == 1) method='set_to_fill' - - call handle_grib_error(vname, slevs(vlev),method,value,varnum,iret,var=dummy2d) - if (iret==1) then ! missing_var_method == skip or no entry - if (trim(vname2)=="_1_0:" .or. trim(vname2) == "_1_1:" .or. & - trim(vname2) == ":14:192:") then - call error_handler("READING IN "//trim(tracers(n))//" AT LEVEL "//trim(slevs(vlev))& - //". SET A FILL VALUE IN THE VARMAP TABLE IF THIS ERROR IS NOT DESIRABLE.",iret) - endif - endif - endif ! method intrp - endif !iret<=0 - - if (n==1 .and. .not. hasspfh) then - if (trim(external_model) .eq. 'GFS') then - print *,'CALRH GFS' - call rh2spfh_gfs(dummy2d,rlevs(vlev),dummy3d(:,:,vlev)) - else - print *,'CALRH non-GFS' - call rh2spfh(dummy2d,rlevs(vlev),dummy3d(:,:,vlev)) - end if - endif - - print*,'tracer ',vlev, maxval(dummy2d),minval(dummy2d) - dummy3d(:,:,vlev) = real(dummy2d,esmf_kind_r8) - enddo !vlev -! Jili Dong interpolation for missing levels - if (is_missing .gt. 0 .and. trim(method) .eq. 'intrp') then - print *,'intrp tracer '//trim(tracers(n)) - done_print = 0 - do jj = 1, j_input - do ii = 1, i_input - dummy3d_col_in=dummy3d(ii,jj,:) - call dint2p(rlevs,dummy3d_col_in,lev_input,rlevs,dummy3d_col_out, & - lev_input, 2, intrp_missing, intrp_ier) - if (intrp_ier .gt. 0) call error_handler("Interpolation failed.",intrp_ier) - dummy3d(ii,jj,:)=dummy3d_col_out - enddo - enddo - do vlev=1,lev_input - dummy2d = dummy3d(:,:,n) - if (any(dummy2d .eq. intrp_missing)) then - ! If we're outside the appropriate region, don't fill but error instead - if (n == o3n .and. rlevs(vlev) .lt. lev_no_o3_fill) then - call error_handler("TRACER "//trim(tracers(n))//" HAS MISSING DATA AT "//trim(slevs(vlev)),1) - elseif (n .ne. o3n .and. rlevs(vlev) .gt. lev_no_tr_fill) then - call error_handler("TRACER "//trim(tracers(n))//" HAS MISSING DATA AT "//trim(slevs(vlev)),1) - else ! we're okay to fill missing data with provided fill value - if (done_print .eq. 0) then - print*, "Pressure out of range of existing data. Defaulting to fill value." - done_print = 1 - end if !done print - where(dummy2d .eq. intrp_missing) dummy2d = value - dummy3d(:,:,vlev) = dummy2d - end if !n & lev - endif ! intrp_missing - ! zero out negative tracers from interpolation/extrapolation - where(dummy3d(:,:,vlev) .lt. 0.0) dummy3d(:,:,vlev) = 0.0 - print*,'tracer af intrp',vlev, maxval(dummy3d(:,:,vlev)),minval(dummy3d(:,:,vlev)) - end do !nlevs do - end if !if intrp - endif !localpet == 0 - - if (localpet == 0) print*,"- CALL FieldScatter FOR INPUT ", trim(tracers_input_vmap(n)) - call ESMF_FieldScatter(tracers_input_grid(n), dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - enddo - - deallocate(dummy3d_col_in, dummy3d_col_out) - -call read_winds(the_file,inv_file,u_tmp_3d,v_tmp_3d, localpet) - - if (localpet == 0) print*,"- CALL FieldScatter FOR INPUT U-WIND." - call ESMF_FieldScatter(u_input_grid, u_tmp_3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) print*,"- CALL FieldScatter FOR INPUT V-WIND." - call ESMF_FieldScatter(v_input_grid, v_tmp_3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ SURFACE PRESSURE." - vname = ":var0_2" - vname2 = "_3_0:" - vlevtyp = ":surface:" - iret = grb2_inq(the_file,inv_file,vname,vname2,vlevtyp,data2=dummy2d) - if (iret <= 0) call error_handler("READING SURFACE PRESSURE RECORD.", iret) - dummy2d_8 = real(dummy2d,esmf_kind_r8) - endif - - if (localpet == 0) print*,"- CALL FieldScatter FOR INPUT GRID SURFACE PRESSURE." - call ESMF_FieldScatter(ps_input_grid, dummy2d_8, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ DZDT." - vname = "dzdt" - call get_var_cond(vname,this_miss_var_method=method, this_miss_var_value=value, & - loc=varnum) - vname = ":var0_2" - vname2 = "_2_9:" - do vlev = 1, lev_input - iret = grb2_inq(the_file,inv_file,vname,vname2,slevs(vlev),data2=dummy2d) - if (iret <= 0 ) then - print*,"DZDT not available at level ", trim(slevs(vlev)), " so checking for VVEL" - vname2 = "_2_8:" - iret = grb2_inq(the_file,inv_file,vname,vname2,slevs(vlev),data2=dummy2d) - if (iret <= 0) then - call handle_grib_error(vname, slevs(vlev),method,value,varnum,iret,var=dummy2d) - if (iret==1) then ! missing_var_method == skip - cycle - endif - else - conv_omega = .true. - endif - - endif - print*,'dzdt ',vlev, maxval(dummy2d),minval(dummy2d) - dummy3d(:,:,vlev) = dummy2d - enddo - endif - - if (localpet == 0) print*,"- CALL FieldScatter FOR INPUT DZDT." - call ESMF_FieldScatter(dzdt_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ TERRAIN." - vname = ":var0_2" - vname2 = "_3_5:" - vlevtyp = ":surface:" - iret = grb2_inq(the_file,inv_file,vname,vname2,vlevtyp,data2=dummy2d) - if (iret <= 0) call error_handler("READING TERRAIN HEIGHT RECORD.", iret) - dummy2d_8 = real(dummy2d,esmf_kind_r8) - endif - - if (localpet == 0) print*,"- CALL FieldScatter FOR INPUT GRID TERRAIN." - call ESMF_FieldScatter(terrain_input_grid, dummy2d_8, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - deallocate(dummy2d, dummy2d_8) - -if (.not. isnative) then - !--------------------------------------------------------------------------- - ! Flip 'z' indices to all 3-d variables. Data is read in from model - ! top to surface. This program expects surface to model top. - !--------------------------------------------------------------------------- - - if (localpet == 0) print*,"- CALL FieldGet FOR SURFACE PRESSURE." - nullify(psptr) - call ESMF_FieldGet(ps_input_grid, & - farrayPtr=psptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - nullify(presptr) - if (localpet == 0) print*,"- CALL FieldGet FOR 3-D PRESSURE." - call ESMF_FieldGet(pres_input_grid, & - computationalLBound=clb, & - computationalUBound=cub, & - farrayPtr=presptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - nullify(tptr) - if (localpet == 0) print*,"- CALL FieldGet TEMPERATURE." - call ESMF_FieldGet(temp_input_grid, & - farrayPtr=tptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - nullify(uptr) - if (localpet == 0) print*,"- CALL FieldGet FOR U" - call ESMF_FieldGet(u_input_grid, & - farrayPtr=uptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - nullify(vptr) - if (localpet == 0) print*,"- CALL FieldGet FOR V" - call ESMF_FieldGet(v_input_grid, & - farrayPtr=vptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - nullify(wptr) - if (localpet == 0) print*,"- CALL FieldGet FOR W" - call ESMF_FieldGet(dzdt_input_grid, & - farrayPtr=wptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - if (localpet == 0) print*,"- CALL FieldGet FOR TRACERS." - do n=1,num_tracers_input - nullify(qptr) - call ESMF_FieldGet(tracers_input_grid(n), & - farrayPtr=qptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - do i = clb(1),cub(1) - do j = clb(2),cub(2) - qptr(i,j,:) = qptr(i,j,lev_input:1:-1) - end do - end do - end do - - do i = clb(1),cub(1) - do j = clb(2),cub(2) - presptr(i,j,:) = rlevs(lev_input:1:-1) - tptr(i,j,:) = tptr(i,j,lev_input:1:-1) - uptr(i,j,:) = uptr(i,j,lev_input:1:-1) - vptr(i,j,:) = vptr(i,j,lev_input:1:-1) - wptr(i,j,:) = wptr(i,j,lev_input:1:-1) - end do - end do - - if (localpet == 0) then - print*,'psfc is ',clb(1),clb(2),psptr(clb(1),clb(2)) - print*,'pres is ',cub(1),cub(2),presptr(cub(1),cub(2),:) - - print*,'pres check 1',localpet,maxval(presptr(clb(1):cub(1),clb(2):cub(2),1)), & - minval(presptr(clb(1):cub(1),clb(2):cub(2),1)) - print*,'pres check lev',localpet,maxval(presptr(clb(1):cub(1),clb(2):cub(2), & - lev_input)),minval(presptr(clb(1):cub(1),clb(2):cub(2),lev_input)) - endif - -else - ! For native files, read in pressure field directly from file but don't flip levels - if (localpet == 0) then - print*,"- READ PRESSURE." - vname = ":PRES:" - do vlev = 1, lev_input - iret = grb2_inq(the_file,inv_file,vname,slevs(vlev),data2=dummy2d) - if (iret<=0) then - call error_handler("READING IN PRESSURE AT LEVEL "//trim(slevs(vlev)),iret) - endif - dummy3d(:,:,vlev) = real(dummy2d,esmf_kind_r8) - print*,'pres check after read ',vlev, dummy3d(1,1,vlev) - enddo - endif - - if (localpet == 0) print*,"- CALL FieldScatter FOR INPUT GRID PRESSURE." - call ESMF_FieldScatter(pres_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - endif - deallocate(dummy3d) - -!--------------------------------------------------------------------------- -! Convert from 2-d to 3-d component winds. -!--------------------------------------------------------------------------- - - call convert_winds - -!--------------------------------------------------------------------------- -! Convert dpdt to dzdt if needed -!--------------------------------------------------------------------------- - - if (conv_omega) then - - if (localpet == 0) print*,"- CONVERT FROM OMEGA TO DZDT." - - nullify(tptr) - if (localpet == 0) print*,"- CALL FieldGet TEMPERATURE." - call ESMF_FieldGet(temp_input_grid, & - farrayPtr=tptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - nullify(qptr) - if (localpet == 0) print*,"- CALL FieldGet SPECIFIC HUMIDITY." - call ESMF_FieldGet(tracers_input_grid(1), & - computationalLBound=clb, & - computationalUBound=cub, & - farrayPtr=qptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - nullify(wptr) - if (localpet == 0) print*,"- CALL FieldGet DZDT." - call ESMF_FieldGet(dzdt_input_grid, & - computationalLBound=clb, & - computationalUBound=cub, & - farrayPtr=wptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - nullify(presptr) - call ESMF_FieldGet(pres_input_grid, & - farrayPtr=presptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - call convert_omega(wptr,presptr,tptr,qptr,clb,cub) - - endif - - end subroutine read_input_atm_grib2_file - -!> Read input grid surface data from a spectral gfs gaussian sfcio -!! file. -!! -!! @note Prior to July 19, 2017. -!! -!! @param[in] localpet ESMF local persistent execution thread -!! @author George Gayno NCEP/EMC - subroutine read_input_sfc_gfs_sfcio_file(localpet) - - use sfcio_module - - implicit none - - integer, intent(in) :: localpet - - character(len=300) :: the_file - - integer(sfcio_intkind) :: iret - integer :: rc - - real(esmf_kind_r8), allocatable :: dummy2d(:,:) - real(esmf_kind_r8), allocatable :: dummy3d(:,:,:) - - type(sfcio_head) :: sfchead - type(sfcio_dbta) :: sfcdata - - the_file = trim(data_dir_input_grid) // "/" // trim(sfc_files_input_grid(1)) - - print*,"- READ SURFACE DATA IN SFCIO FORMAT." - print*,"- OPEN AND READ: ",trim(the_file) - call sfcio_sropen(23, trim(the_file), iret) - if (iret /= 0) then - rc=iret - call error_handler("OPENING FILE", rc) - endif - - call sfcio_srhead(23, sfchead, iret) - if (iret /= 0) then - rc=iret - call error_handler("READING HEADER", rc) - endif - - if (localpet == 0) then - call sfcio_aldbta(sfchead, sfcdata, iret) - if (iret /= 0) then - rc=iret - call error_handler("ALLOCATING DATA.", rc) - endif - call sfcio_srdbta(23, sfchead, sfcdata, iret) - if (iret /= 0) then - rc=iret - call error_handler("READING DATA.", rc) - endif - allocate(dummy2d(i_input,j_input)) - allocate(dummy3d(i_input,j_input,lsoil_input)) - else - allocate(dummy2d(0,0)) - allocate(dummy3d(0,0,0)) - endif - - if (localpet == 0) dummy2d = sfcdata%slmsk - - print*,"- CALL FieldScatter FOR INPUT LANDSEA MASK." - call ESMF_FieldScatter(landsea_mask_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) dummy2d = sfcdata%zorl - - print*,"- CALL FieldScatter FOR INPUT Z0." - call ESMF_FieldScatter(z0_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) dummy2d = nint(sfcdata%vtype) - - print*,"- CALL FieldScatter FOR INPUT VEG TYPE." - call ESMF_FieldScatter(veg_type_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! Prior to July, 2017, gfs used zobler soil types. '13' indicates permanent land ice. - veg_type_landice_input = 13 - - if (localpet == 0) dummy2d = sfcdata%canopy - - print*,"- CALL FieldScatter FOR INPUT CANOPY MC." - call ESMF_FieldScatter(canopy_mc_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) dummy2d = sfcdata%fice - - print*,"- CALL FieldScatter FOR INPUT ICE FRACTION." - call ESMF_FieldScatter(seaice_fract_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) dummy2d = sfcdata%hice - - print*,"- CALL FieldScatter FOR INPUT ICE DEPTH." - call ESMF_FieldScatter(seaice_depth_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) dummy2d = sfcdata%tisfc - - print*,"- CALL FieldScatter FOR INPUT ICE SKIN TEMP." - call ESMF_FieldScatter(seaice_skin_temp_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) dummy2d = sfcdata%snwdph ! mm (expected by program) - - print*,"- CALL FieldScatter FOR INPUT SNOW DEPTH." - call ESMF_FieldScatter(snow_depth_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) dummy2d = sfcdata%sheleg - - print*,"- CALL FieldScatter FOR INPUT SNOW LIQUID EQUIV." - call ESMF_FieldScatter(snow_liq_equiv_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) dummy2d = sfcdata%t2m - - print*,"- CALL FieldScatter FOR INPUT T2M." - call ESMF_FieldScatter(t2m_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) dummy2d = sfcdata%q2m - - print*,"- CALL FieldScatter FOR INPUT Q2M." - call ESMF_FieldScatter(q2m_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) dummy2d = sfcdata%tprcp - - print*,"- CALL FieldScatter FOR INPUT TPRCP." - call ESMF_FieldScatter(tprcp_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) dummy2d = sfcdata%f10m - - print*,"- CALL FieldScatter FOR INPUT F10M." - call ESMF_FieldScatter(f10m_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) dummy2d = sfcdata%uustar - - print*,"- CALL FieldScatter FOR INPUT USTAR." - call ESMF_FieldScatter(ustar_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) dummy2d = sfcdata%ffmm - - print*,"- CALL FieldScatter FOR INPUT FFMM." - call ESMF_FieldScatter(ffmm_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) dummy2d = sfcdata%srflag - - print*,"- CALL FieldScatter FOR INPUT SRFLAG." - call ESMF_FieldScatter(srflag_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) dummy2d = sfcdata%tsea - - print*,"- CALL FieldScatter FOR INPUT SKIN TEMP." - call ESMF_FieldScatter(skin_temp_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) dummy2d = nint(sfcdata%stype) - - print*,"- CALL FieldScatter FOR INPUT SOIL TYPE." - call ESMF_FieldScatter(soil_type_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) dummy2d = sfcdata%orog - - print*,"- CALL FieldScatter FOR INPUT TERRAIN." - call ESMF_FieldScatter(terrain_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) dummy3d = sfcdata%slc - - print*,"- CALL FieldScatter FOR INPUT LIQUID SOIL MOISTURE." - call ESMF_FieldScatter(soilm_liq_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) dummy3d = sfcdata%smc - - print*,"- CALL FieldScatter FOR INPUT TOTAL SOIL MOISTURE." - call ESMF_FieldScatter(soilm_tot_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) dummy3d = sfcdata%stc - - print*,"- CALL FieldScatter FOR INPUT SOIL TEMPERATURE." - call ESMF_FieldScatter(soil_temp_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - deallocate(dummy2d, dummy3d) - call sfcio_axdbta(sfcdata, iret) - - call sfcio_sclose(23, iret) - - end subroutine read_input_sfc_gfs_sfcio_file - -!> Read input grid surface data from a spectral gfs gaussian nemsio -!! file. -!! -!! @note Format used by gfs starting July 19, 2017. -!! -!! @param[in] localpet ESMF local persistent execution thread -!! @author George Gayno NCEP/EMC - subroutine read_input_sfc_gfs_gaussian_nemsio_file(localpet) - - implicit none - - integer, intent(in) :: localpet - - character(len=300) :: the_file - - integer :: rc - - real(nemsio_realkind), allocatable :: dummy(:) - real(esmf_kind_r8), allocatable :: dummy2d(:,:) - real(esmf_kind_r8), allocatable :: dummy3d(:,:,:) - - type(nemsio_gfile) :: gfile - - the_file = trim(data_dir_input_grid) // "/" // trim(sfc_files_input_grid(1)) - - if (localpet == 0) then - allocate(dummy3d(i_input,j_input,lsoil_input)) - allocate(dummy2d(i_input,j_input)) - allocate(dummy(i_input*j_input)) - print*,"- OPEN FILE ", trim(the_file) - call nemsio_open(gfile, the_file, "read", iret=rc) - if (rc /= 0) call error_handler("OPENING FILE.", rc) - else - allocate(dummy3d(0,0,0)) - allocate(dummy2d(0,0)) - allocate(dummy(0)) - endif - - if (localpet == 0) then - print*,"- READ TERRAIN." - call nemsio_readrecv(gfile, "orog", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING TERRAIN.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'orog ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT TERRAIN." - call ESMF_FieldScatter(terrain_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ LANDSEA MASK." - call nemsio_readrecv(gfile, "land", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING LANDSEA MASK.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'landmask ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT LANDSEA MASK." - call ESMF_FieldScatter(landsea_mask_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ SEAICE FRACTION." - call nemsio_readrecv(gfile, "icec", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING SEAICE FRACTION.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'icec ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SEAICE FRACTION." - call ESMF_FieldScatter(seaice_fract_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ SEAICE DEPTH." - call nemsio_readrecv(gfile, "icetk", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING SEAICE DEPTH.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'icetk ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SEAICE DEPTH." - call ESMF_FieldScatter(seaice_depth_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ SEAICE SKIN TEMPERATURE." - call nemsio_readrecv(gfile, "tisfc", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING SEAICE SKIN TEMP.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'ti ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SEAICE SKIN TEMPERATURE." - call ESMF_FieldScatter(seaice_skin_temp_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ SNOW LIQUID EQUIVALENT." - call nemsio_readrecv(gfile, "weasd", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING SNOW LIQUID EQUIVALENT.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'weasd ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SNOW LIQUID EQUIVALENT." - call ESMF_FieldScatter(snow_liq_equiv_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ SNOW DEPTH." - call nemsio_readrecv(gfile, "snod", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING SNOW DEPTH.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'snod ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SNOW DEPTH." - call ESMF_FieldScatter(snow_depth_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ VEG TYPE." - call nemsio_readrecv(gfile, "vtype", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING VEG TYPE", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'vtype ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID VEG TYPE." - call ESMF_FieldScatter(veg_type_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ SOIL TYPE." - call nemsio_readrecv(gfile, "sotyp", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING SOIL TYPE.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'sotype ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SOIL TYPE." - call ESMF_FieldScatter(soil_type_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ T2M." - call nemsio_readrecv(gfile, "tmp", "2 m above gnd", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING T2M.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'t2m ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID T2M." - call ESMF_FieldScatter(t2m_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ Q2M." - call nemsio_readrecv(gfile, "spfh", "2 m above gnd", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING Q2M.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'q2m ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID Q2M." - call ESMF_FieldScatter(q2m_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ TPRCP." - call nemsio_readrecv(gfile, "tprcp", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING TPRCP.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'tprcp ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID TPRCP." - call ESMF_FieldScatter(tprcp_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ FFMM." - call nemsio_readrecv(gfile, "ffmm", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING FFMM.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'ffmm ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID FFMM" - call ESMF_FieldScatter(ffmm_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ USTAR." - call nemsio_readrecv(gfile, "fricv", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING USTAR.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'fricv ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID USTAR" - call ESMF_FieldScatter(ustar_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) dummy2d = 0.0 - print*,"- CALL FieldScatter FOR INPUT GRID SRFLAG" - call ESMF_FieldScatter(srflag_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ SKIN TEMPERATURE." - call nemsio_readrecv(gfile, "tmp", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING SKIN TEMPERATURE.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'tmp ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SKIN TEMPERATURE" - call ESMF_FieldScatter(skin_temp_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ F10M." - call nemsio_readrecv(gfile, "f10m", "10 m above gnd", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING F10M.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'f10m ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID F10M." - call ESMF_FieldScatter(f10m_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ CANOPY MOISTURE CONTENT." - call nemsio_readrecv(gfile, "cnwat", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING CANOPY MOISTURE CONTENT.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'cnwat ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID CANOPY MOISTURE CONTENT." - call ESMF_FieldScatter(canopy_mc_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ Z0." - call nemsio_readrecv(gfile, "sfcr", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING Z0.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'sfcr ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID Z0." - call ESMF_FieldScatter(z0_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - deallocate(dummy2d) - - if (localpet == 0) then - print*,"- READ LIQUID SOIL MOISTURE." - call nemsio_readrecv(gfile, "slc", "soil layer", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING LAYER 1 LIQUID SOIL MOIST.", rc) - dummy3d(:,:,1) = reshape(dummy, (/i_input,j_input/)) - call nemsio_readrecv(gfile, "slc", "soil layer", 2, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING LAYER 2 LIQUID SOIL MOIST.", rc) - dummy3d(:,:,2) = reshape(dummy, (/i_input,j_input/)) - call nemsio_readrecv(gfile, "slc", "soil layer", 3, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING LAYER 3 LIQUID SOIL MOIST.", rc) - dummy3d(:,:,3) = reshape(dummy, (/i_input,j_input/)) - call nemsio_readrecv(gfile, "slc", "soil layer", 4, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING LAYER 4 LIQUID SOIL MOIST.", rc) - dummy3d(:,:,4) = reshape(dummy, (/i_input,j_input/)) - print*,'slc ',maxval(dummy3d),minval(dummy3d) - endif - - print*,"- CALL FieldScatter FOR INPUT LIQUID SOIL MOISTURE." - call ESMF_FieldScatter(soilm_liq_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ TOTAL SOIL MOISTURE." - call nemsio_readrecv(gfile, "smc", "soil layer", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING LAYER 1 TOTAL SOIL MOIST.", rc) - dummy3d(:,:,1) = reshape(dummy, (/i_input,j_input/)) - call nemsio_readrecv(gfile, "smc", "soil layer", 2, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING LAYER 2 TOTAL SOIL MOIST.", rc) - dummy3d(:,:,2) = reshape(dummy, (/i_input,j_input/)) - call nemsio_readrecv(gfile, "smc", "soil layer", 3, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING LAYER 3 TOTAL SOIL MOIST.", rc) - dummy3d(:,:,3) = reshape(dummy, (/i_input,j_input/)) - call nemsio_readrecv(gfile, "smc", "soil layer", 4, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING LAYER 4 TOTAL SOIL MOIST.", rc) - dummy3d(:,:,4) = reshape(dummy, (/i_input,j_input/)) - print*,'smc ',maxval(dummy3d),minval(dummy3d) - endif - - print*,"- CALL FieldScatter FOR INPUT TOTAL SOIL MOISTURE." - call ESMF_FieldScatter(soilm_tot_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ SOIL TEMPERATURE." - call nemsio_readrecv(gfile, "stc", "soil layer", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING LAYER 1 SOIL TEMP.", rc) - dummy3d(:,:,1) = reshape(dummy, (/i_input,j_input/)) - call nemsio_readrecv(gfile, "stc", "soil layer", 2, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING LAYER 2 SOIL TEMP.", rc) - dummy3d(:,:,2) = reshape(dummy, (/i_input,j_input/)) - call nemsio_readrecv(gfile, "stc", "soil layer", 3, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING LAYER 3 SOIL TEMP.", rc) - dummy3d(:,:,3) = reshape(dummy, (/i_input,j_input/)) - call nemsio_readrecv(gfile, "stc", "soil layer", 4, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING LAYER 4 SOIL TEMP.", rc) - dummy3d(:,:,4) = reshape(dummy, (/i_input,j_input/)) - print*,'stc ',maxval(dummy3d),minval(dummy3d) - endif - - print*,"- CALL FieldScatter FOR INPUT SOIL TEMPERATURE." - call ESMF_FieldScatter(soil_temp_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - deallocate(dummy3d, dummy) - - if (localpet == 0) call nemsio_close(gfile) - - end subroutine read_input_sfc_gfs_gaussian_nemsio_file - -!> Read input grid surface data from an fv3 gaussian nemsio file. -!! -!! @param[in] localpet ESMF local persistent execution thread -!! @author George Gayno NCEP/EMC - subroutine read_input_sfc_gaussian_nemsio_file(localpet) - - implicit none - - integer, intent(in) :: localpet - - character(len=250) :: the_file - - integer :: rc - - real(nemsio_realkind), allocatable :: dummy(:) - real(esmf_kind_r8), allocatable :: dummy2d(:,:) - real(esmf_kind_r8), allocatable :: dummy3d(:,:,:) - - type(nemsio_gfile) :: gfile - - the_file = trim(data_dir_input_grid) // "/" // trim(sfc_files_input_grid(1)) - - if (localpet == 0) then - allocate(dummy3d(i_input,j_input,lsoil_input)) - allocate(dummy2d(i_input,j_input)) - allocate(dummy(i_input*j_input)) - print*,"- OPEN FILE ", trim(the_file) - call nemsio_open(gfile, the_file, "read", iret=rc) - if (rc /= 0) call error_handler("OPENING FILE.", rc) - else - allocate(dummy3d(0,0,0)) - allocate(dummy2d(0,0)) - allocate(dummy(0)) - endif - - if (localpet == 0) then - print*,"- READ TERRAIN." - call nemsio_readrecv(gfile, "orog", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING TERRAIN.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'orog ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT TERRAIN." - call ESMF_FieldScatter(terrain_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ LANDSEA MASK." - call nemsio_readrecv(gfile, "land", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING LANDSEA MASK.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'landmask ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT LANDSEA MASK." - call ESMF_FieldScatter(landsea_mask_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ SEAICE FRACTION." - call nemsio_readrecv(gfile, "icec", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING SEAICE FRACTION.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'icec ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SEAICE FRACTION." - call ESMF_FieldScatter(seaice_fract_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ SEAICE DEPTH." - call nemsio_readrecv(gfile, "icetk", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING SEAICE DEPTH.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'icetk ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SEAICE DEPTH." - call ESMF_FieldScatter(seaice_depth_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ SEAICE SKIN TEMPERATURE." - call nemsio_readrecv(gfile, "ti", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING SEAICE SKIN TEMP.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'ti ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SEAICE SKIN TEMPERATURE." - call ESMF_FieldScatter(seaice_skin_temp_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ SNOW LIQUID EQUIVALENT." - call nemsio_readrecv(gfile, "weasd", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING SNOW LIQUID EQUIVALENT.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'weasd ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SNOW LIQUID EQUIVALENT." - call ESMF_FieldScatter(snow_liq_equiv_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ SNOW DEPTH." - call nemsio_readrecv(gfile, "snod", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING SNOW DEPTH.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) * 1000.0_8 - print*,'snod ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SNOW DEPTH." - call ESMF_FieldScatter(snow_depth_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ VEG TYPE." - call nemsio_readrecv(gfile, "vtype", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING VEG TYPE", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'vtype ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID VEG TYPE." - call ESMF_FieldScatter(veg_type_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ SOIL TYPE." - call nemsio_readrecv(gfile, "sotyp", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING SOIL TYPE.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'sotype ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SOIL TYPE." - call ESMF_FieldScatter(soil_type_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ T2M." - call nemsio_readrecv(gfile, "tmp", "2 m above gnd", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING T2M.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'t2m ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID T2M." - call ESMF_FieldScatter(t2m_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ Q2M." - call nemsio_readrecv(gfile, "spfh", "2 m above gnd", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING Q2M.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'q2m ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID Q2M." - call ESMF_FieldScatter(q2m_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ TPRCP." - call nemsio_readrecv(gfile, "tprcp", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING TPRCP.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'tprcp ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID TPRCP." - call ESMF_FieldScatter(tprcp_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ FFMM." - call nemsio_readrecv(gfile, "ffmm", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING FFMM.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'ffmm ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID FFMM" - call ESMF_FieldScatter(ffmm_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ USTAR." - call nemsio_readrecv(gfile, "fricv", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING USTAR.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'fricv ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID USTAR" - call ESMF_FieldScatter(ustar_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) dummy2d = 0.0 - print*,"- CALL FieldScatter FOR INPUT GRID SRFLAG" - call ESMF_FieldScatter(srflag_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ SKIN TEMPERATURE." - call nemsio_readrecv(gfile, "tmp", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING SKIN TEMPERATURE.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'tmp ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SKIN TEMPERATURE" - call ESMF_FieldScatter(skin_temp_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ F10M." - call nemsio_readrecv(gfile, "f10m", "10 m above gnd", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING F10M.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'f10m ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID F10M." - call ESMF_FieldScatter(f10m_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ CANOPY MOISTURE CONTENT." - call nemsio_readrecv(gfile, "cnwat", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING CANOPY MOISTURE CONTENT.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'cnwat ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID CANOPY MOISTURE CONTENT." - call ESMF_FieldScatter(canopy_mc_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ Z0." - call nemsio_readrecv(gfile, "sfcr", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING Z0.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) * 100.0_8 ! convert to cm - print*,'sfcr ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID Z0." - call ESMF_FieldScatter(z0_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - deallocate(dummy2d) - - if (localpet == 0) then - print*,"- READ LIQUID SOIL MOISTURE." - call nemsio_readrecv(gfile, "soill", "0-10 cm down", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING LAYER 1 LIQUID SOIL MOIST.", rc) - dummy3d(:,:,1) = reshape(dummy, (/i_input,j_input/)) - call nemsio_readrecv(gfile, "soill", "10-40 cm down", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING LAYER 2 LIQUID SOIL MOIST.", rc) - dummy3d(:,:,2) = reshape(dummy, (/i_input,j_input/)) - call nemsio_readrecv(gfile, "soill", "40-100 cm down", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING LAYER 3 LIQUID SOIL MOIST.", rc) - dummy3d(:,:,3) = reshape(dummy, (/i_input,j_input/)) - call nemsio_readrecv(gfile, "soill", "100-200 cm down", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING LAYER 4 LIQUID SOIL MOIST.", rc) - dummy3d(:,:,4) = reshape(dummy, (/i_input,j_input/)) - print*,'soill ',maxval(dummy3d),minval(dummy3d) - endif - - print*,"- CALL FieldScatter FOR INPUT LIQUID SOIL MOISTURE." - call ESMF_FieldScatter(soilm_liq_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ TOTAL SOIL MOISTURE." - call nemsio_readrecv(gfile, "soilw", "0-10 cm down", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING LAYER 1 TOTAL SOIL MOIST.", rc) - dummy3d(:,:,1) = reshape(dummy, (/i_input,j_input/)) - call nemsio_readrecv(gfile, "soilw", "10-40 cm down", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING LAYER 2 TOTAL SOIL MOIST.", rc) - dummy3d(:,:,2) = reshape(dummy, (/i_input,j_input/)) - call nemsio_readrecv(gfile, "soilw", "40-100 cm down", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING LAYER 3 TOTAL SOIL MOIST.", rc) - dummy3d(:,:,3) = reshape(dummy, (/i_input,j_input/)) - call nemsio_readrecv(gfile, "soilw", "100-200 cm down", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING LAYER 4 TOTAL SOIL MOIST.", rc) - dummy3d(:,:,4) = reshape(dummy, (/i_input,j_input/)) - print*,'soilm ',maxval(dummy3d),minval(dummy3d) - endif - - print*,"- CALL FieldScatter FOR INPUT TOTAL SOIL MOISTURE." - call ESMF_FieldScatter(soilm_tot_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ SOIL TEMPERATURE." - call nemsio_readrecv(gfile, "tmp", "0-10 cm down", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING LAYER 1 SOIL TEMP.", rc) - dummy3d(:,:,1) = reshape(dummy, (/i_input,j_input/)) - call nemsio_readrecv(gfile, "tmp", "10-40 cm down", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING LAYER 2 SOIL TEMP.", rc) - dummy3d(:,:,2) = reshape(dummy, (/i_input,j_input/)) - call nemsio_readrecv(gfile, "tmp", "40-100 cm down", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING LAYER 3 SOIL TEMP.", rc) - dummy3d(:,:,3) = reshape(dummy, (/i_input,j_input/)) - call nemsio_readrecv(gfile, "tmp", "100-200 cm down", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING LAYER 4 SOIL TEMP.", rc) - dummy3d(:,:,4) = reshape(dummy, (/i_input,j_input/)) - print*,'soilt ',maxval(dummy3d),minval(dummy3d) - endif - - print*,"- CALL FieldScatter FOR INPUT SOIL TEMPERATURE." - call ESMF_FieldScatter(soil_temp_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - deallocate(dummy3d, dummy) - - if (localpet == 0) call nemsio_close(gfile) - - end subroutine read_input_sfc_gaussian_nemsio_file - -!> Read input grid surface data from fv3 tiled warm 'restart' files. -!! -!! @param[in] localpet ESMF local persistent execution thread -!! @author George Gayno NCEP/EMC - subroutine read_input_sfc_restart_file(localpet) - - implicit none - - integer, intent(in) :: localpet - - character(len=500) :: tilefile - - integer :: error, rc - integer :: id_dim, idim_input, jdim_input - integer :: ncid, tile, id_var - - real(esmf_kind_r8), allocatable :: data_one_tile(:,:) - real(esmf_kind_r8), allocatable :: data_one_tile_3d(:,:,:) - -!--------------------------------------------------------------------------- -! Get i/j dimensions and number of soil layers from first surface file. -! Do dimensions match those from the orography file? -!--------------------------------------------------------------------------- - - tilefile = trim(data_dir_input_grid) // "/" // trim(sfc_files_input_grid(1)) - print*,"- READ GRID DIMENSIONS FROM: ", trim(tilefile) - error=nf90_open(trim(tilefile),nf90_nowrite,ncid) - call netcdf_err(error, 'opening: '//trim(tilefile) ) - - error=nf90_inq_dimid(ncid, 'xaxis_1', id_dim) - call netcdf_err(error, 'reading xaxis_1 id' ) - error=nf90_inquire_dimension(ncid,id_dim,len=idim_input) - call netcdf_err(error, 'reading xaxis_1 value' ) - - error=nf90_inq_dimid(ncid, 'yaxis_1', id_dim) - call netcdf_err(error, 'reading yaxis_1 id' ) - error=nf90_inquire_dimension(ncid,id_dim,len=jdim_input) - call netcdf_err(error, 'reading yaxis_1 value' ) - - if (idim_input /= i_input .or. jdim_input /= j_input) then - call error_handler("DIMENSION MISMATCH BETWEEN SFC AND OROG FILES.", 1) - endif - - error = nf90_close(ncid) - - if (localpet == 0) then - allocate(data_one_tile(idim_input,jdim_input)) - allocate(data_one_tile_3d(idim_input,jdim_input,lsoil_input)) - else - allocate(data_one_tile(0,0)) - allocate(data_one_tile_3d(0,0,0)) - endif - - TERRAIN_LOOP: do tile = 1, num_tiles_input_grid - - if (localpet == 0) then - tilefile = trim(orog_dir_input_grid) // trim(orog_files_input_grid(tile)) - print*,'- OPEN OROGRAPHY FILE: ', trim(tilefile) - error=nf90_open(tilefile,nf90_nowrite,ncid) - call netcdf_err(error, 'OPENING OROGRAPHY FILE' ) - error=nf90_inq_varid(ncid, 'orog_raw', id_var) - call netcdf_err(error, 'READING OROG RECORD ID' ) - error=nf90_get_var(ncid, id_var, data_one_tile) - call netcdf_err(error, 'READING OROG RECORD' ) - print*,'terrain check ',tile, maxval(data_one_tile) - error=nf90_close(ncid) - endif - - print*,"- CALL FieldScatter FOR INPUT TERRAIN." - call ESMF_FieldScatter(terrain_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - enddo TERRAIN_LOOP - - TILE_LOOP : do tile = 1, num_tiles_input_grid - -! liquid soil moisture - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('slc', tile, idim_input, jdim_input, & - lsoil_input, sfcdata_3d=data_one_tile_3d) - endif - - print*,"- CALL FieldScatter FOR INPUT LIQUID SOIL MOISTURE." - call ESMF_FieldScatter(soilm_liq_input_grid, data_one_tile_3d, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('smc', tile, idim_input, jdim_input, & - lsoil_input, sfcdata_3d=data_one_tile_3d) - endif - - print*,"- CALL FieldScatter FOR INPUT TOTAL SOIL MOISTURE." - call ESMF_FieldScatter(soilm_tot_input_grid, data_one_tile_3d, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('stc', tile, idim_input, jdim_input, & - lsoil_input, sfcdata_3d=data_one_tile_3d) - endif - - print*,"- CALL FieldScatter FOR INPUT SOIL TEMPERATURE." - call ESMF_FieldScatter(soil_temp_input_grid, data_one_tile_3d, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! land mask - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('slmsk', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT LANDSEA MASK." - call ESMF_FieldScatter(landsea_mask_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! sea ice fraction - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('fice', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SEAICE FRACTION." - call ESMF_FieldScatter(seaice_fract_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! sea ice depth - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('hice', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SEAICE DEPTH." - call ESMF_FieldScatter(seaice_depth_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! sea ice skin temperature - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('tisfc', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SEAICE SKIN TEMPERATURE." - call ESMF_FieldScatter(seaice_skin_temp_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! liquid equivalent snow depth - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('sheleg', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SNOW LIQUID EQUIVALENT." - call ESMF_FieldScatter(snow_liq_equiv_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! physical snow depth - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('snwdph', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - data_one_tile = data_one_tile - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SNOW DEPTH." - call ESMF_FieldScatter(snow_depth_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! Vegetation type - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('vtype', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID VEG TYPE." - call ESMF_FieldScatter(veg_type_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! Soil type - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('stype', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SOIL TYPE." - call ESMF_FieldScatter(soil_type_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! Two-meter temperature - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('t2m', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID T2M." - call ESMF_FieldScatter(t2m_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! Two-meter q - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('q2m', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID Q2M." - call ESMF_FieldScatter(q2m_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('tprcp', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID TPRCP." - call ESMF_FieldScatter(tprcp_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('f10m', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID F10M" - call ESMF_FieldScatter(f10m_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('ffhh', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID FFHH" - call ESMF_FieldScatter(ffhh_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('ffmm', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID FFMM" - call ESMF_FieldScatter(ffmm_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('uustar', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID USTAR" - call ESMF_FieldScatter(ustar_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('srflag', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SRFLAG" - call ESMF_FieldScatter(srflag_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('tsea', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SKIN TEMPERATURE" - call ESMF_FieldScatter(skin_temp_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('canopy', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID CANOPY MOISTURE CONTENT." - call ESMF_FieldScatter(canopy_mc_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('zorl', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID Z0." - call ESMF_FieldScatter(z0_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - enddo TILE_LOOP - - deallocate(data_one_tile, data_one_tile_3d) - - end subroutine read_input_sfc_restart_file - -!> Read input grid surface data from tiled 'history' files (netcdf) or -!! gaussian netcdf files. -!! -!! @param[in] localpet ESMF local persistent execution thread -!! @author George Gayno NCEP/EMC - subroutine read_input_sfc_netcdf_file(localpet) - - implicit none - - integer, intent(in) :: localpet - - character(len=500) :: tilefile - - integer :: error, id_var - integer :: id_dim, idim_input, jdim_input - integer :: ncid, rc, tile - - real(esmf_kind_r8), allocatable :: data_one_tile(:,:) - real(esmf_kind_r8), allocatable :: data_one_tile_3d(:,:,:) - -!--------------------------------------------------------------------------- -! Get i/j dimensions and number of soil layers from first surface file. -! Do dimensions match those from the orography file? -!--------------------------------------------------------------------------- - - tilefile = trim(data_dir_input_grid) // "/" // trim(sfc_files_input_grid(1)) - print*,"- READ GRID DIMENSIONS FROM: ", trim(tilefile) - error=nf90_open(trim(tilefile),nf90_nowrite,ncid) - call netcdf_err(error, 'opening: '//trim(tilefile) ) - - error=nf90_inq_dimid(ncid, 'grid_xt', id_dim) - call netcdf_err(error, 'reading grid_xt id' ) - error=nf90_inquire_dimension(ncid,id_dim,len=idim_input) - call netcdf_err(error, 'reading grid_xt value' ) - - error=nf90_inq_dimid(ncid, 'grid_yt', id_dim) - call netcdf_err(error, 'reading grid_yt id' ) - error=nf90_inquire_dimension(ncid,id_dim,len=jdim_input) - call netcdf_err(error, 'reading grid_yt value' ) - - if (idim_input /= i_input .or. jdim_input /= j_input) then - call error_handler("DIMENSION MISMATCH BETWEEN SFC AND OROG FILES.", 3) - endif - - error = nf90_close(ncid) - - if (localpet == 0) then - allocate(data_one_tile(idim_input,jdim_input)) - allocate(data_one_tile_3d(idim_input,jdim_input,lsoil_input)) - else - allocate(data_one_tile(0,0)) - allocate(data_one_tile_3d(0,0,0)) - endif - - TERRAIN_LOOP: do tile = 1, num_tiles_input_grid - - if (trim(input_type) == "gaussian_netcdf") then - if (localpet == 0) then - call read_fv3_grid_data_netcdf('orog', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - else - - if (localpet == 0) then - tilefile = trim(orog_dir_input_grid) // trim(orog_files_input_grid(tile)) - print*,'- OPEN OROGRAPHY FILE: ', trim(tilefile) - error=nf90_open(tilefile,nf90_nowrite,ncid) - call netcdf_err(error, 'OPENING OROGRAPHY FILE.' ) - error=nf90_inq_varid(ncid, 'orog_raw', id_var) - call netcdf_err(error, 'READING OROGRAPHY RECORD ID.' ) - error=nf90_get_var(ncid, id_var, data_one_tile) - call netcdf_err(error, 'READING OROGRAPHY RECORD.' ) - print*,'terrain check history ',tile, maxval(data_one_tile) - error=nf90_close(ncid) - endif - - endif - - print*,"- CALL FieldScatter FOR INPUT TERRAIN." - call ESMF_FieldScatter(terrain_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - enddo TERRAIN_LOOP - - TILE_LOOP : do tile = 1, num_tiles_input_grid - -! liquid soil moisture - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('soill1', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - data_one_tile_3d(:,:,1) = data_one_tile - call read_fv3_grid_data_netcdf('soill2', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - data_one_tile_3d(:,:,2) = data_one_tile - call read_fv3_grid_data_netcdf('soill3', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - data_one_tile_3d(:,:,3) = data_one_tile - call read_fv3_grid_data_netcdf('soill4', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - data_one_tile_3d(:,:,4) = data_one_tile - endif - - print*,"- CALL FieldScatter FOR INPUT LIQUID SOIL MOISTURE." - call ESMF_FieldScatter(soilm_liq_input_grid, data_one_tile_3d, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! total soil moisture - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('soilw1', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - data_one_tile_3d(:,:,1) = data_one_tile - call read_fv3_grid_data_netcdf('soilw2', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - data_one_tile_3d(:,:,2) = data_one_tile - call read_fv3_grid_data_netcdf('soilw3', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - data_one_tile_3d(:,:,3) = data_one_tile - call read_fv3_grid_data_netcdf('soilw4', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - data_one_tile_3d(:,:,4) = data_one_tile - endif - - print*,"- CALL FieldScatter FOR INPUT TOTAL SOIL MOISTURE." - call ESMF_FieldScatter(soilm_tot_input_grid, data_one_tile_3d, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! soil tempeature (ice temp at land ice points) - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('soilt1', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - data_one_tile_3d(:,:,1) = data_one_tile - call read_fv3_grid_data_netcdf('soilt2', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - data_one_tile_3d(:,:,2) = data_one_tile - call read_fv3_grid_data_netcdf('soilt3', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - data_one_tile_3d(:,:,3) = data_one_tile - call read_fv3_grid_data_netcdf('soilt4', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - data_one_tile_3d(:,:,4) = data_one_tile - endif - - print*,"- CALL FieldScatter FOR INPUT SOIL TEMPERATURE." - call ESMF_FieldScatter(soil_temp_input_grid, data_one_tile_3d, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! land mask - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('land', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT LANDSEA MASK." - call ESMF_FieldScatter(landsea_mask_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! sea ice fraction - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('icec', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SEAICE FRACTION." - call ESMF_FieldScatter(seaice_fract_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! sea ice depth - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('icetk', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SEAICE DEPTH." - call ESMF_FieldScatter(seaice_depth_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! sea ice skin temperature - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('tisfc', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SEAICE SKIN TEMPERATURE." - call ESMF_FieldScatter(seaice_skin_temp_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! liquid equivalent snow depth - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('weasd', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SNOW LIQUID EQUIVALENT." - call ESMF_FieldScatter(snow_liq_equiv_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! physical snow depth - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('snod', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - data_one_tile = data_one_tile * 1000.0 ! convert from meters to mm. - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SNOW DEPTH." - call ESMF_FieldScatter(snow_depth_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! Vegetation type - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('vtype', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID VEG TYPE." - call ESMF_FieldScatter(veg_type_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! Soil type - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('sotyp', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SOIL TYPE." - call ESMF_FieldScatter(soil_type_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! Two-meter temperature - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('tmp2m', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID T2M." - call ESMF_FieldScatter(t2m_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! Two-meter q - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('spfh2m', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID Q2M." - call ESMF_FieldScatter(q2m_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('tprcp', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID TPRCP." - call ESMF_FieldScatter(tprcp_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('f10m', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID F10M" - call ESMF_FieldScatter(f10m_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('ffmm', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID FFMM" - call ESMF_FieldScatter(ffmm_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('fricv', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID USTAR" - call ESMF_FieldScatter(ustar_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then -! call read_fv3_grid_data_netcdf('srflag', tile, idim_input, jdim_input, & -! lsoil_input, sfcdata=data_one_tile) - data_one_tile = 0.0 - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SRFLAG" - call ESMF_FieldScatter(srflag_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('tmpsfc', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SKIN TEMPERATURE" - call ESMF_FieldScatter(skin_temp_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('cnwat', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID CANOPY MOISTURE CONTENT." - call ESMF_FieldScatter(canopy_mc_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('sfcr', tile, idim_input, jdim_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID Z0." - call ESMF_FieldScatter(z0_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - enddo TILE_LOOP - - deallocate(data_one_tile, data_one_tile_3d) - - end subroutine read_input_sfc_netcdf_file - -!> Read input grid surface data from a grib2 file. -!! -!! @param[in] localpet ESMF local persistent execution thread -!! @author Larissa Reames - subroutine read_input_sfc_grib2_file(localpet) - - use wgrib2api - use program_setup, only : vgtyp_from_climo, sotyp_from_climo - use model_grid, only : input_grid_type - use search_util - - - implicit none - - integer, intent(in) :: localpet - - character(len=250) :: the_file - character(len=250) :: geo_file - character(len=20) :: vname, vname_file,slev - character(len=50) :: method - character(len=20) :: to_upper - - integer :: rc, varnum, iret, i, j,k - integer :: ncid2d, varid, varsize - - logical :: exist, rap_latlon - - real(esmf_kind_r4) :: value - - real(esmf_kind_r4), allocatable :: dummy2d(:,:),icec_save(:,:) - real(esmf_kind_r4), allocatable :: dummy1d(:) - real(esmf_kind_r8), allocatable :: dummy2d_8(:,:),dummy2d_82(:,:),tsk_save(:,:) - real(esmf_kind_r8), allocatable :: dummy3d(:,:,:), dummy3d_stype(:,:,:) - integer(esmf_kind_i4), allocatable :: slmsk_save(:,:) - integer(esmf_kind_i8), allocatable :: dummy2d_i(:,:) - - - rap_latlon = trim(to_upper(external_model))=="RAP" .and. trim(input_grid_type) == "rotated_latlon" - - the_file = trim(data_dir_input_grid) // "/" // trim(grib2_file_input_grid) - geo_file = trim(geogrid_file_input_grid) - - - print*,"- READ SFC DATA FROM GRIB2 FILE: ", trim(the_file) - inquire(file=the_file,exist=exist) - if (.not.exist) then - iret = 1 - call error_handler("OPENING GRIB2 FILE.", iret) - end if - - lsoil_input = grb2_inq(the_file, inv_file, ':TSOIL:',' below ground:') - print*, "- FILE HAS ", lsoil_input, " SOIL LEVELS" - if (lsoil_input <= 0) call error_handler("COUNTING SOIL LEVELS.", rc) - - !We need to recreate the soil fields if we have something other than 4 levels - if (lsoil_input /= 4) then - - call ESMF_FieldDestroy(soil_temp_input_grid, rc=rc) - call ESMF_FieldDestroy(soilm_tot_input_grid, rc=rc) - call ESMF_FieldDestroy(soilm_liq_input_grid, rc=rc) - - print*,"- CALL FieldCreate FOR INPUT SOIL TEMPERATURE." - soil_temp_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, & - ungriddedLBound=(/1/), & - ungriddedUBound=(/lsoil_input/), rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT TOTAL SOIL MOISTURE." - soilm_tot_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, & - ungriddedLBound=(/1/), & - ungriddedUBound=(/lsoil_input/), rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - print*,"- CALL FieldCreate FOR INPUT LIQUID SOIL MOISTURE." - soilm_liq_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, & - ungriddedLBound=(/1/), & - ungriddedUBound=(/lsoil_input/), rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", rc) - - endif - - if (localpet == 0) then - allocate(dummy2d(i_input,j_input)) - allocate(slmsk_save(i_input,j_input)) - allocate(dummy2d_i(i_input,j_input)) - allocate(tsk_save(i_input,j_input)) - allocate(icec_save(i_input,j_input)) - allocate(dummy2d_8(i_input,j_input)) - allocate(dummy2d_82(i_input,j_input)) - allocate(dummy3d(i_input,j_input,lsoil_input)) - allocate(dummy3d_stype(i_input,j_input,16)) - allocate(dummy1d(16)) - else - allocate(dummy3d(0,0,0)) - allocate(dummy2d_8(0,0)) - allocate(dummy2d_82(0,0)) - allocate(dummy2d(0,0)) - - endif - - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - ! These variables are always in grib files, or are required, so no need to check for them - ! in the varmap table. If they can't be found in the input file, then stop the program. - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - if (localpet == 0) then - print*,"- READ TERRAIN." - rc = grb2_inq(the_file, inv_file, ':HGT:',':surface:', data2=dummy2d) - if (rc /= 1) call error_handler("READING TERRAIN.", rc) - print*,'orog ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT TERRAIN." - call ESMF_FieldScatter(terrain_input_grid, real(dummy2d,esmf_kind_r8),rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - -if (localpet == 0) then - print*,"- READ SEAICE FRACTION." - rc = grb2_inq(the_file, inv_file, ':ICEC:',':surface:', data2=dummy2d) - if (rc /= 1) call error_handler("READING SEAICE FRACTION.", rc) - !dummy2d = dummy2d(i_input:1:-1,j_input:1:-1) - print*,'icec ',maxval(dummy2d),minval(dummy2d) - icec_save = dummy2d - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SEAICE FRACTION." - call ESMF_FieldScatter(seaice_fract_input_grid,real(dummy2d,esmf_kind_r8),rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - -!---------------------------------------------------------------------------------- -! GFS v14 and v15.2 grib data has two land masks. LANDN is created by -! nearest neighbor interpolation. LAND is created by bilinear interpolation. -! LANDN matches the bitmap. So use it first. For other GFS versions or other models, -! use LAND. Mask in grib file is '1' (land), '0' (not land). Add sea/lake ice category -! '2' based on ice concentration. -!---------------------------------------------------------------------------------- - - if (localpet == 0) then - print*,"- READ LANDSEA MASK." - rc = grb2_inq(the_file, inv_file, ':LANDN:',':surface:', data2=dummy2d) - - if (rc /= 1) then - rc = grb2_inq(the_file, inv_file, ':LAND:',':surface:', data2=dummy2d) - if (rc /= 1) call error_handler("READING LANDSEA MASK.", rc) - endif - - do j = 1, j_input - do i = 1, i_input - if(dummy2d(i,j) < 0.5_esmf_kind_r4) dummy2d(i,j)=0.0_esmf_kind_r4 - if(icec_save(i,j) > 0.15_esmf_kind_r4) then - !if (dummy2d(i,j) == 0.0_esmf_kind_r4) print*, "CONVERTING WATER TO SEA/LAKE ICE AT ", i, j - dummy2d(i,j) = 2.0_esmf_kind_r4 - endif - enddo - enddo - - slmsk_save = nint(dummy2d) - - deallocate(icec_save) - endif - - print*,"- CALL FieldScatter FOR INPUT LANDSEA MASK." - call ESMF_FieldScatter(landsea_mask_input_grid,real(dummy2d,esmf_kind_r8),rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ SEAICE SKIN TEMPERATURE." - rc = grb2_inq(the_file, inv_file, ':TMP:',':surface:', data2=dummy2d) - if (rc /= 1) call error_handler("READING SEAICE SKIN TEMP.", rc) - print*,'ti ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SEAICE SKIN TEMPERATURE." - call ESMF_FieldScatter(seaice_skin_temp_input_grid,real(dummy2d,esmf_kind_r8),rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - -!---------------------------------------------------------------------------------- -! Read snow fields. Zero out at non-land points and undefined points (points -! removed using the bitmap). Program expects depth and liquid equivalent -! in mm. -!---------------------------------------------------------------------------------- - - if (localpet == 0) then - print*,"- READ SNOW LIQUID EQUIVALENT." - rc = grb2_inq(the_file, inv_file, ':WEASD:',':surface:',':anl:',data2=dummy2d) - if (rc /= 1) then - rc = grb2_inq(the_file, inv_file, ':WEASD:',':surface:','hour fcst:',data2=dummy2d) - if (rc /= 1) call error_handler("READING SNOW LIQUID EQUIVALENT.", rc) - endif - do j = 1, j_input - do i = 1, i_input - if(slmsk_save(i,j) == 0) dummy2d(i,j) = 0.0_esmf_kind_r4 - if(dummy2d(i,j) == grb2_UNDEFINED) dummy2d(i,j) = 0.0_esmf_kind_r4 - enddo - enddo - print*,'weasd ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SNOW LIQUID EQUIVALENT." - call ESMF_FieldScatter(snow_liq_equiv_input_grid,real(dummy2d,esmf_kind_r8),rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ SNOW DEPTH." - rc = grb2_inq(the_file, inv_file, ':SNOD:',':surface:', data2=dummy2d) - if (rc /= 1) call error_handler("READING SNOW DEPTH.", rc) - where(dummy2d == grb2_UNDEFINED) dummy2d = 0.0_esmf_kind_r4 - dummy2d = dummy2d*1000.0 ! Grib2 files have snow depth in (m), fv3 expects it in mm - where(slmsk_save == 0) dummy2d = 0.0_esmf_kind_r4 - print*,'snod ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SNOW DEPTH." - call ESMF_FieldScatter(snow_depth_input_grid,real(dummy2d,esmf_kind_r8),rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ T2M." - rc = grb2_inq(the_file, inv_file, ':TMP:',':2 m above ground:',data2=dummy2d) - if (rc <= 0) call error_handler("READING T2M.", rc) - - print*,'t2m ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID T2M." - call ESMF_FieldScatter(t2m_input_grid,real(dummy2d,esmf_kind_r8), rootpet=0,rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ Q2M." - rc = grb2_inq(the_file, inv_file, ':SPFH:',':2 m above ground:',data2=dummy2d) - if (rc <=0) call error_handler("READING Q2M.", rc) - print*,'q2m ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID Q2M." - call ESMF_FieldScatter(q2m_input_grid,real(dummy2d,esmf_kind_r8), rootpet=0,rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ SKIN TEMPERATURE." - rc = grb2_inq(the_file, inv_file, ':TMP:',':surface:', data2=dummy2d) - if (rc <= 0 ) call error_handler("READING SKIN TEMPERATURE.", rc) - tsk_save(:,:) = real(dummy2d,esmf_kind_r8) - dummy2d_8 = real(dummy2d,esmf_kind_r8) - do j = 1, j_input - do i = 1, i_input - if(slmsk_save(i,j) == 0 .and. dummy2d(i,j) < 271.2) then -! print*,'too cool SST ',i,j,dummy2d(i,j) - dummy2d(i,j) = 271.2 - endif - if(slmsk_save(i,j) == 0 .and. dummy2d(i,j) > 310.) then -! print*,'too hot SST ',i,j,dummy2d(i,j) - dummy2d(i,j) = 310.0 - endif - enddo - enddo - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SKIN TEMPERATURE" - call ESMF_FieldScatter(skin_temp_input_grid,real(dummy2d,esmf_kind_r8),rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) dummy2d = 0.0 - - print*,"- CALL FieldScatter FOR INPUT GRID SRFLAG" - call ESMF_FieldScatter(srflag_input_grid,real(dummy2d,esmf_kind_r8), rootpet=0,rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ SOIL TYPE." - slev=":surface:" - vname=":SOTYP:" - rc = grb2_inq(the_file, inv_file, vname,slev, data2=dummy2d) - !failed => rc = 0 - if (rc <= 0 .and. (trim(to_upper(external_model))=="HRRR" .or. rap_latlon) .and. geo_file .ne. "NULL") then - ! Some HRRR and RAP files don't have dominant soil type in the output, but the geogrid files - ! do, so this gives users the option to provide the geogrid file and use input soil - ! type - print*, "OPEN GEOGRID FILE ", trim(geo_file) - rc = nf90_open(geo_file,NF90_NOWRITE,ncid2d) - call netcdf_err(rc,"READING GEOGRID FILE") - - print*, "INQURE ABOUT DIM IDS" - rc = nf90_inq_dimid(ncid2d,"west_east",varid) - call netcdf_err(rc,"READING west_east DIMENSION FROM GEOGRID FILE") - - rc = nf90_inquire_dimension(ncid2d,varid,len=varsize) - call netcdf_err(rc,"READING west_east DIMENSION SIZE") - if (varsize .ne. i_input) call error_handler ("GEOGRID FILE GRID SIZE DIFFERS FROM INPUT DATA.", -1) - - print*, "INQUIRE ABOUT SOIL TYPE FROM GEOGRID FILE" - rc = nf90_inq_varid(ncid2d,"SCT_DOM",varid) - call netcdf_err(rc,"FINDING SCT_DOM IN GEOGRID FILE") - - print*, "READ SOIL TYPE FROM GEOGRID FILE " - rc = nf90_get_var(ncid2d,varid,dummy2d) - call netcdf_err(rc,"READING SCT_DOM FROM FILE") - - print*, "INQUIRE ABOUT SOIL TYPE FRACTIONS FROM GEOGRID FILE" - rc = nf90_inq_varid(ncid2d,"SOILCTOP",varid) - call netcdf_err(rc,"FINDING SOILCTOP IN GEOGRID FILE") - - print*, "READ SOIL TYPE FRACTIONS FROM GEOGRID FILE " - rc = nf90_get_var(ncid2d,varid,dummy3d_stype) - call netcdf_err(rc,"READING SCT_DOM FROM FILE") - - print*, "CLOSE GEOGRID FILE " - iret = nf90_close(ncid2d) - - - ! There's an issue with the geogrid file containing soil type water at land points. - ! This correction replaces the soil type at these points with the soil type with - ! the next highest fractional coverage. - do j = 1, j_input - do i = 1, i_input - if(dummy2d(i,j) == 14.0_esmf_kind_r4 .and. slmsk_save(i,j) == 1) then - dummy1d(:) = dummy3d_stype(i,j,:) - dummy1d(14) = 0.0_esmf_kind_r4 - dummy2d(i,j) = real(MAXLOC(dummy1d, 1),esmf_kind_r4) - endif - enddo - enddo - endif - - if ((rc <= 0 .and. trim(to_upper(external_model)) /= "HRRR" .and. .not. rap_latlon) & - .or. (rc < 0 .and. (trim(to_upper(external_model)) == "HRRR" .or. rap_latlon))) then - if (.not. sotyp_from_climo) then - call error_handler("COULD NOT FIND SOIL TYPE IN FILE. PLEASE SET SOTYP_FROM_CLIMO=.TRUE. . EXITING", rc) - else - vname = "sotyp" - call get_var_cond(vname,this_miss_var_method=method, this_miss_var_value=value, & - loc=varnum) - call handle_grib_error(vname, slev ,method,value,varnum,rc, var= dummy2d) - if (rc == 1) then ! missing_var_method == skip or no entry in varmap table - print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. WILL NOT "//& - "SCALE SOIL MOISTURE FOR DIFFERENCES IN SOIL TYPE. " - dummy2d(:,:) = -99999.0_esmf_kind_r4 - endif - endif - endif - - ! In the event that the soil type on the input grid still contains mismatches between - ! soil type and landmask, this correction is a last-ditch effort to replace these points - ! with soil type from a nearby land point. - if (.not. sotyp_from_climo) then - do j = 1, j_input - do i = 1, i_input - if(dummy2d(i,j) == 14.0_esmf_kind_r4 .and. slmsk_save(i,j) == 1) dummy2d(i,j) = -99999.9 - enddo - enddo - - dummy2d_8 = real(dummy2d,esmf_kind_r8) - dummy2d_i(:,:) = 0 - where(slmsk_save == 1) dummy2d_i = 1 - - call search(dummy2d_8,dummy2d_i,i_input,j_input,1,230) - else - dummy2d_8=real(dummy2d,esmf_kind_r8) - endif - - print*,'sotype ',maxval(dummy2d_8),minval(dummy2d_8) - deallocate(dummy2d_i) - deallocate(dummy3d_stype) - endif - - - print*,"- CALL FieldScatter FOR INPUT GRID SOIL TYPE." - call ESMF_FieldScatter(soil_type_input_grid,dummy2d_8, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - ! Begin variables whose presence in grib2 files varies, but no climatological - ! data is available, so we have to account for values in the varmap table - !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - - if (.not. vgfrc_from_climo) then - if (localpet == 0) then - print*,"- READ VEG FRACTION." - vname="vfrac" - slev=":surface:" - call get_var_cond(vname,this_miss_var_method=method, this_miss_var_value=value, & - loc=varnum) - !! Changing these for GSD internal runs using new HRRR files - vname=":VEG:" - rc= grb2_inq(the_file, inv_file, vname,slev, data2=dummy2d) - - if (rc > 1) then - rc= grb2_inq(the_file, inv_file, vname,slev,'n=1105:', data2=dummy2d) - if (rc <= 0) then - rc= grb2_inq(the_file, inv_file, vname,slev,'n=1101:', data2=dummy2d) - if (rc <= 0) then - rc= grb2_inq(the_file, inv_file, vname,slev,'n=1151:', data2=dummy2d) - if (rc <= 0) call error_handler("COULD NOT DETERMINE VEGETATION FRACTION IN FILE. & - RECORD NUMBERS MAY HAVE CHANGED. PLEASE SET VGFRC_FROM_CLIMO=.TRUE. EXITING", rc) - endif - endif - elseif (rc <= 0) then - call error_handler("COULD NOT FIND VEGETATION FRACTION IN FILE. & - PLEASE SET VGFRC_FROM_CLIMO=.TRUE. EXITING", rc) - endif - if(maxval(dummy2d) > 2.0) dummy2d = dummy2d / 100.0_esmf_kind_r4 - print*,'vfrac ',maxval(dummy2d),minval(dummy2d) - endif - - - print*,"- CALL FieldScatter FOR INPUT GRID VEG GREENNESS." - call ESMF_FieldScatter(veg_greenness_input_grid,real(dummy2d,esmf_kind_r8), rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - endif - - if (.not. minmax_vgfrc_from_climo) then - if (localpet == 0) then - print*,"- READ MIN VEG FRACTION." - vname="vfrac_min" - slev=":surface:" - call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & - loc=varnum) - vname=":VEG:" - rc= grb2_inq(the_file, inv_file, vname,slev,'n=1106:',data2=dummy2d) - - if (rc <= 0) then - rc= grb2_inq(the_file, inv_file, vname,slev,'n=1102:',data2=dummy2d) - if (rc <= 0) then - rc= grb2_inq(the_file, inv_file, vname,slev,'n=1152:',data2=dummy2d) - if (rc<=0) call error_handler("COULD NOT FIND MIN VEGETATION FRACTION IN FILE. & - PLEASE SET MINMAX_VGFRC_FROM_CLIMO=.TRUE. . EXITING",rc) - endif - endif - if(maxval(dummy2d) > 2.0) dummy2d = dummy2d / 100.0_esmf_kind_r4 - print*,'vfrac min',maxval(dummy2d),minval(dummy2d) - - endif - - print*,"- CALL FieldScatter FOR INPUT GRID MIN VEG GREENNESS." - call ESMF_FieldScatter(min_veg_greenness_input_grid,real(dummy2d,esmf_kind_r8), rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ MAX VEG FRACTION." - vname="vfrac_max" - slev=":surface:" - call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & - loc=varnum) - - vname=":VEG:" - rc= grb2_inq(the_file, inv_file, vname,slev,'n=1107:',data2=dummy2d) - if (rc <=0) then - rc= grb2_inq(the_file, inv_file, vname,slev,'n=1103:',data2=dummy2d) - if (rc <=0) then - rc= grb2_inq(the_file, inv_file, vname,slev,'n=1153:',data2=dummy2d) - if (rc <= 0) call error_handler("COULD NOT FIND MAX VEGETATION FRACTION IN FILE. & - PLEASE SET MINMAX_VGFRC_FROM_CLIMO=.TRUE. . EXITING",rc) - endif - endif - if(maxval(dummy2d) > 2.0) dummy2d = dummy2d / 100.0_esmf_kind_r4 - print*,'vfrac max',maxval(dummy2d),minval(dummy2d) - - endif !localpet==0 - - print*,"- CALL FieldScatter FOR INPUT GRID MAX VEG GREENNESS." - call ESMF_FieldScatter(max_veg_greenness_input_grid,real(dummy2d,esmf_kind_r8),rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - endif !minmax_vgfrc_from_climo - - if (.not. lai_from_climo) then - if (localpet == 0) then - print*,"- READ LAI." - vname="lai" - slev=":surface:" - call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & - loc=varnum) - vname=":var0_7_198:" - rc= grb2_inq(the_file, inv_file, vname,slev,':n=1108:',data2=dummy2d) - if (rc <=0) then - rc= grb2_inq(the_file, inv_file, vname,slev,':n=1104:',data2=dummy2d) - if (rc <=0) then - rc= grb2_inq(the_file, inv_file, vname,slev,':n=1154:',data2=dummy2d) - if (rc <= 0) call error_handler("COULD NOT FIND LAI IN FILE. & - PLEASE SET LAI_FROM_CLIMO=.TRUE. . EXITING",rc) - endif - endif - print*,'lai',maxval(dummy2d),minval(dummy2d) - endif !localpet==0 - - print*,"- CALL FieldScatter FOR INPUT GRID LAI." - call ESMF_FieldScatter(lai_input_grid,real(dummy2d,esmf_kind_r8),rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - - endif - if (localpet == 0) then - print*,"- READ SEAICE DEPTH." - vname="hice" - slev=":surface:" - call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & - loc=varnum) - vname=":ICETK:" - rc= grb2_inq(the_file, inv_file, vname,slev, data2=dummy2d) - if (rc <= 0) then - call handle_grib_error(vname, slev ,method,value,varnum,rc, var= dummy2d) - if (rc==1) then ! missing_var_method == skip or no entry in varmap table - print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. THIS FIELD WILL BE"//& - " REPLACED WITH CLIMO. SET A FILL "// & - "VALUE IN THE VARMAP TABLE IF THIS IS NOT DESIRABLE." - dummy2d(:,:) = 0.0_esmf_kind_r4 - endif - endif - dummy2d_8= real(dummy2d,esmf_kind_r8) - print*,'hice ',maxval(dummy2d),minval(dummy2d) - - endif - - print*,"- CALL FieldScatter FOR INPUT GRID SEAICE DEPTH." - call ESMF_FieldScatter(seaice_depth_input_grid,dummy2d_8, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ TPRCP." - vname="tprcp" - slev=":surface:" - call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & - loc=varnum) - vname=":TPRCP:" - rc= grb2_inq(the_file, inv_file, vname,slev, data2=dummy2d) - if (rc <= 0) then - call handle_grib_error(vname, slev ,method,value,varnum,rc, var= dummy2d) - if (rc==1) then ! missing_var_method == skip or no entry in varmap table - print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. THIS FIELD WILL NOT"//& - " BE WRITTEN TO THE INPUT FILE. SET A FILL "// & - "VALUE IN THE VARMAP TABLE IF THIS IS NOT DESIRABLE." - dummy2d(:,:) = 0.0_esmf_kind_r4 - endif - endif - dummy2d_8= real(dummy2d,esmf_kind_r8) - print*,'tprcp ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID TPRCP." - call ESMF_FieldScatter(tprcp_input_grid,dummy2d_8, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ FFMM." - vname="ffmm" - slev=":surface:" - call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & - loc=varnum) - vname=":FFMM:" - rc= grb2_inq(the_file, inv_file, vname,slev, data2=dummy2d) - if (rc <= 0) then - call handle_grib_error(vname, slev ,method,value,varnum,rc, var= dummy2d) - if (rc==1) then ! missing_var_method == skip or no entry in varmap table - print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. THIS FIELD WILL NOT"//& - " BE WRITTEN TO THE INPUT FILE. SET A FILL "// & - "VALUE IN THE VARMAP TABLE IF THIS IS NOT DESIRABLE." - dummy2d(:,:) = 0.0_esmf_kind_r4 - endif - endif - dummy2d_8= real(dummy2d,esmf_kind_r8) - print*,'ffmm ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID FFMM" - call ESMF_FieldScatter(ffmm_input_grid,dummy2d_8, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ USTAR." - vname="fricv" - slev=":surface:" - call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & - loc=varnum) - vname=":FRICV:" - rc= grb2_inq(the_file, inv_file, vname,slev, data2=dummy2d) - if (rc <= 0) then - call handle_grib_error(vname, slev ,method,value,varnum,rc, var= dummy2d) - if (rc==1) then ! missing_var_method == skip or no entry in varmap table - print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. THIS FIELD WILL "//& - "REPLACED WITH CLIMO. SET A FILL "// & - "VALUE IN THE VARMAP TABLE IF THIS IS NOT DESIRABLE." - dummy2d(:,:) = 0.0_esmf_kind_r4 - endif - endif - dummy2d_8= real(dummy2d,esmf_kind_r8) - print*,'fricv ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID USTAR" - call ESMF_FieldScatter(ustar_input_grid,dummy2d_8, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ F10M." - vname="f10m" - slev=":10 m above ground:" - call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & - loc=varnum) - vname=":F10M:" - rc= grb2_inq(the_file, inv_file, vname,slev, data2=dummy2d) - if (rc <= 0) then - call handle_grib_error(vname, slev ,method,value,varnum,rc, var= dummy2d) - if (rc==1) then ! missing_var_method == skip or no entry in varmap table - print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. THIS FIELD WILL NOT"//& - " BE WRITTEN TO THE INPUT FILE. SET A FILL "// & - "VALUE IN THE VARMAP TABLE IF THIS IS NOT DESIRABLE." - dummy2d(:,:) = 0.0_esmf_kind_r4 - endif - endif - dummy2d_8= real(dummy2d,esmf_kind_r8) - print*,'f10m ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID F10M." - call ESMF_FieldScatter(f10m_input_grid,dummy2d_8, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ CANOPY MOISTURE CONTENT." - vname="cnwat" - slev=":surface:" - call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & - loc=varnum) - vname=":CNWAT:" - rc= grb2_inq(the_file, inv_file, vname,slev, data2=dummy2d) - if (rc <= 0) then - call handle_grib_error(vname, slev ,method,value,varnum,rc, var= dummy2d) - if (rc==1) then ! missing_var_method == skip or no entry in varmap table - print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. THIS FIELD WILL"//& - " REPLACED WITH CLIMO. SET A FILL "// & - "VALUE IN THE VARMAP TABLE IF THIS IS NOT DESIRABLE." - dummy2d(:,:) = 0.0_esmf_kind_r4 - endif - endif - call check_cnwat(dummy2d) - dummy2d_8= real(dummy2d,esmf_kind_r8) - print*,'cnwat ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT GRID CANOPY MOISTURE CONTENT." - call ESMF_FieldScatter(canopy_mc_input_grid,dummy2d_8, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ Z0." - vname="sfcr" - slev=":surface:" - call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & - loc=varnum) - vname=":SFCR:" - rc= grb2_inq(the_file, inv_file, vname,slev, data2=dummy2d) - if (rc <= 0) then - call handle_grib_error(vname, slev ,method,value,varnum,rc, var= dummy2d) - if (rc==1) then ! missing_var_method == skip or no entry in varmap table - print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. THIS FIELD WILL BE"//& - " REPLACED WITH CLIMO. SET A FILL "// & - "VALUE IN THE VARMAP TABLE IF THIS IS NOT DESIRABLE." - dummy2d(:,:) = 0.0_esmf_kind_r4 - endif - else - ! Grib files have z0 (m), but fv3 expects z0(cm) - dummy2d(:,:) = dummy2d(:,:)*10.0 - endif - dummy2d_8= real(dummy2d,esmf_kind_r8) - print*,'sfcr ',maxval(dummy2d),minval(dummy2d) - - endif - - print*,"- CALL FieldScatter FOR INPUT GRID Z0." - call ESMF_FieldScatter(z0_input_grid,dummy2d_8, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - - - if (localpet == 0) then - print*,"- READ LIQUID SOIL MOISTURE." - vname = "soill" - vname_file = ":SOILL:" - call read_grib_soil(the_file,inv_file,vname,vname_file,dummy3d,rc) !!! NEEDTO HANDLE - !!! SOIL LEVELS - print*,'soill ',maxval(dummy3d),minval(dummy3d) - endif - - print*,"- CALL FieldScatter FOR INPUT LIQUID SOIL MOISTURE." - call ESMF_FieldScatter(soilm_liq_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ TOTAL SOIL MOISTURE." - vname = "soilw" - !vname_file = "var2_2_1_7_0_192" !Some files don't recognize this as soilw,so use - vname_file = "var2_2_1_" ! the var number instead - call read_grib_soil(the_file,inv_file,vname,vname_file,dummy3d,rc) - print*,'soilm ',maxval(dummy3d),minval(dummy3d) - endif - - print*,"- CALL FieldScatter FOR INPUT TOTAL SOIL MOISTURE." - call ESMF_FieldScatter(soilm_tot_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - -!---------------------------------------------------------------------------------------- -! Vegetation type is not available in some files. However, it is needed to identify -! permanent land ice points. At land ice, the total soil moisture is a flag value of -! '1'. Use this flag as a temporary solution. -!---------------------------------------------------------------------------------------- - - print*, "- CALL FieldGather for INPUT SOIL TYPE." - call ESMF_FieldGather(soil_type_input_grid, dummy2d_82, rootPet=0, tile=1, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - if (localpet == 0) then - print*,"- READ VEG TYPE." - vname="vtype" - slev=":surface:" - call get_var_cond(vname,this_miss_var_method=method, this_miss_var_value=value, & - loc=varnum) - !Note: sometimes the grib files don't have this one named. Searching for this string - ! ensures that the data is found when it exists - - vname="var2_2" - rc= grb2_inq(the_file, inv_file, vname,"_0_198:",slev,' hour fcst:', data2=dummy2d) - if (rc <= 0) then - rc= grb2_inq(the_file, inv_file, vname,"_0_198:",slev,':anl:', data2=dummy2d) - if (rc <= 0) then - if (.not. vgtyp_from_climo) then - call error_handler("COULD NOT FIND VEGETATION TYPE IN FILE. PLEASE SET VGTYP_FROM_CLIMO=.TRUE. . EXITING", rc) - else - do j = 1, j_input - do i = 1, i_input - dummy2d(i,j) = 0.0_esmf_kind_r4 - if(slmsk_save(i,j) == 1 .and. dummy3d(i,j,1) > 0.99) & - dummy2d(i,j) = real(veg_type_landice_input,esmf_kind_r4) - enddo - enddo - endif ! replace_vgtyp - endif !not find :anl: - endif !not find hour fcst: - - if (trim(external_model) .ne. "GFS") then - do j = 1, j_input - do i = 1,i_input - if (dummy2d(i,j) == 15.0_esmf_kind_r4 .and. slmsk_save(i,j) == 1) then - if (dummy3d(i,j,1) < 0.6) then - dummy2d(i,j) = real(veg_type_landice_input,esmf_kind_r4) - elseif (dummy3d(i,j,1) > 0.99) then - slmsk_save(i,j) = 0 - dummy2d(i,j) = 0.0_esmf_kind_r4 - dummy2d_82(i,j) = 0.0_esmf_kind_r8 - endif - elseif (dummy2d(i,j) == 17.0_esmf_kind_r4 .and. slmsk_save(i,j)==0) then - dummy2d(i,j) = 0.0_esmf_kind_r4 - endif - enddo - enddo - endif - dummy2d_8= real(dummy2d,esmf_kind_r8) - print*,'vgtyp ',maxval(dummy2d),minval(dummy2d) - endif !localpet - deallocate(dummy2d) - print*,"- CALL FieldScatter FOR INPUT VEG TYPE." - call ESMF_FieldScatter(veg_type_input_grid, dummy2d_8, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - - print*,"- CALL FieldScatter FOR INPUT VEG TYPE." - call ESMF_FieldScatter(soil_type_input_grid, dummy2d_82, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - - print*,"- CALL FieldScatter FOR INPUT LANDSEA MASK." - call ESMF_FieldScatter(landsea_mask_input_grid,real(slmsk_save,esmf_kind_r8),rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - -!--------------------------------------------------------------------------------- -! At open water (slmsk==0), the soil temperature array is not used and set -! to the filler value of SST. At lake/sea ice points (slmsk=2), the soil -! temperature array holds ice column temperature. This field is not available -! in the grib data, so set to a default value. -!--------------------------------------------------------------------------------- - - if (localpet == 0) then - print*,"- READ SOIL TEMPERATURE." - vname = "soilt" - vname_file = ":TSOIL:" - call read_grib_soil(the_file,inv_file,vname,vname_file,dummy3d,rc) - call check_soilt(dummy3d,slmsk_save,tsk_save) - print*,'soilt ',maxval(dummy3d),minval(dummy3d) - - deallocate(tsk_save, slmsk_save) - endif - - print*,"- CALL FieldScatter FOR INPUT SOIL TEMPERATURE." - call ESMF_FieldScatter(soil_temp_input_grid, dummy3d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - - deallocate(dummy3d) - deallocate(dummy2d_8) - - end subroutine read_input_sfc_grib2_file - -!> Read nst data from these netcdf formatted fv3 files: tiled history, -!! tiled warm restart, and gaussian history. -!! -!! @param[in] localpet ESMF local persistent execution thread -!! @author George Gayno NCEP/EMC - subroutine read_input_nst_netcdf_file(localpet) - - implicit none - - integer, intent(in) :: localpet - - character(len=10) :: field - - integer :: rc, tile - - real(esmf_kind_r8), allocatable :: data_one_tile(:,:) - - if (localpet == 0) then - allocate(data_one_tile(i_input,j_input)) - else - allocate(data_one_tile(0,0)) - endif - - TILE_LOOP : do tile = 1, num_tiles_input_grid - -! c_d - - if (localpet == 0) then - if (trim(input_type) == "restart") then - field='c_d' - else - field='cd' - endif - call read_fv3_grid_data_netcdf(trim(field), tile, i_input, j_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT C_D" - call ESMF_FieldScatter(c_d_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! c_0 - - if (localpet == 0) then - if (trim(input_type) == "restart") then - field='c_0' - else - field='c0' - endif - call read_fv3_grid_data_netcdf(trim(field), tile, i_input, j_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT C_0" - call ESMF_FieldScatter(c_0_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! d_conv - - if (localpet == 0) then - if (trim(input_type) == "restart") then - field='d_conv' - else - field='dconv' - endif - call read_fv3_grid_data_netcdf(trim(field), tile, i_input, j_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT D_CONV." - call ESMF_FieldScatter(d_conv_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! dt_cool - - if (localpet == 0) then - if (trim(input_type) == "restart") then - field='dt_cool' - else - field='dtcool' - endif - call read_fv3_grid_data_netcdf(trim(field), tile, i_input, j_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT DT_COOL." - call ESMF_FieldScatter(dt_cool_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! ifd - xu li said initialize to '1'. - - if (localpet == 0) then - data_one_tile = 1.0 - endif - - print*,"- CALL FieldScatter FOR INPUT IFD." - call ESMF_FieldScatter(ifd_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! qrain - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('qrain', tile, i_input, j_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT QRAIN." - call ESMF_FieldScatter(qrain_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! tref - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('tref', tile, i_input, j_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT TREF" - call ESMF_FieldScatter(tref_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! w_d - - if (localpet == 0) then - if (trim(input_type) == "restart") then - field='w_d' - else - field='wd' - endif - call read_fv3_grid_data_netcdf(trim(field), tile, i_input, j_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT W_D" - call ESMF_FieldScatter(w_d_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! w_0 - - if (localpet == 0) then - if (trim(input_type) == "restart") then - field='w_0' - else - field='w0' - endif - call read_fv3_grid_data_netcdf(trim(field), tile, i_input, j_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT W_0" - call ESMF_FieldScatter(w_0_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! xs - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('xs', tile, i_input, j_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT XS" - call ESMF_FieldScatter(xs_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! xt - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('xt', tile, i_input, j_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT XT" - call ESMF_FieldScatter(xt_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! xu - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('xu', tile, i_input, j_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT XU" - call ESMF_FieldScatter(xu_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! xv - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('xv', tile, i_input, j_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT XV" - call ESMF_FieldScatter(xv_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! xz - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('xz', tile, i_input, j_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT XZ" - call ESMF_FieldScatter(xz_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! xtts - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('xtts', tile, i_input, j_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT XTTS" - call ESMF_FieldScatter(xtts_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! xzts - - if (localpet == 0) then - call read_fv3_grid_data_netcdf('xzts', tile, i_input, j_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT XZTS" - call ESMF_FieldScatter(xzts_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! z_c - - if (localpet == 0) then - if (trim(input_type) == "restart") then - field='z_c' - else - field='zc' - endif - call read_fv3_grid_data_netcdf(trim(field), tile, i_input, j_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT Z_C" - call ESMF_FieldScatter(z_c_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! zm - Not used yet. Xu li said set to '0'. - - if (localpet == 0) then - field='zm' - call read_fv3_grid_data_netcdf(trim(field), tile, i_input, j_input, & - lsoil_input, sfcdata=data_one_tile) - endif - - print*,"- CALL FieldScatter FOR INPUT ZM" - call ESMF_FieldScatter(zm_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - enddo TILE_LOOP - - deallocate(data_one_tile) - - end subroutine read_input_nst_netcdf_file - -!> Read input grid nst data from fv3 gaussian nemsio history file or -!! spectral GFS nemsio file. -!! -!! @note The spectral GFS nst data is in a separate file from -!! the surface data. The fv3 surface and nst data are in a -!! single file. -!! -!! @param[in] localpet ESMF local persistent execution thread -!! @author George Gayno NCEP/EMC - subroutine read_input_nst_nemsio_file(localpet) - - implicit none - - integer, intent(in) :: localpet - - character(len=300) :: the_file - - integer :: rc - - real(nemsio_realkind), allocatable :: dummy(:) - real(esmf_kind_r8), allocatable :: dummy2d(:,:) - - type(nemsio_gfile) :: gfile - - if (trim(input_type) == "gfs_gaussian_nemsio") then ! spectral gfs nemsio in - ! separate file. - the_file = trim(data_dir_input_grid) // "/" // trim(nst_files_input_grid) - else - the_file = trim(data_dir_input_grid) // "/" // trim(sfc_files_input_grid(1)) - endif - - print*,"- READ NST DATA FROM: ", trim(the_file) - - if (localpet == 0) then - allocate(dummy(i_input*j_input)) - allocate(dummy2d(i_input,j_input)) - call nemsio_open(gfile, the_file, "read", iret=rc) - else - allocate(dummy(0)) - allocate(dummy2d(0,0)) - endif - - if (localpet == 0) then - print*,"- READ TREF" - call nemsio_readrecv(gfile, "tref", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING TREF.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'tref ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT TREF." - call ESMF_FieldScatter(tref_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ CD" - call nemsio_readrecv(gfile, "cd", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING CD.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'cd ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT C_D." - call ESMF_FieldScatter(c_d_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ C0" - call nemsio_readrecv(gfile, "c0", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING C0.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'c0 ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT C_0." - call ESMF_FieldScatter(c_0_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ DCONV" - call nemsio_readrecv(gfile, "dconv", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING DCONV.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'dconv ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT D_CONV." - call ESMF_FieldScatter(d_conv_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ DTCOOL" - call nemsio_readrecv(gfile, "dtcool", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING DTCOOL.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'dtcool ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT DT_COOL." - call ESMF_FieldScatter(dt_cool_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - dummy2d = 1.0 ! IFD not in file. Set to '1' per Xu Li. - endif - - print*,"- CALL FieldScatter FOR INPUT IFD." - call ESMF_FieldScatter(ifd_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ QRAIN" - call nemsio_readrecv(gfile, "qrain", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING QRAIN.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'qrain ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT QRAIN." - call ESMF_FieldScatter(qrain_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ WD" - call nemsio_readrecv(gfile, "wd", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING WD.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'wd ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT WD." - call ESMF_FieldScatter(w_d_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ W0" - call nemsio_readrecv(gfile, "w0", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING W0.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'w0 ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT W0." - call ESMF_FieldScatter(w_0_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ XS" - call nemsio_readrecv(gfile, "xs", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING XS.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'xs ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT XS." - call ESMF_FieldScatter(xs_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ XT" - call nemsio_readrecv(gfile, "xt", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING XT.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'xt ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT XT." - call ESMF_FieldScatter(xt_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ XU" - call nemsio_readrecv(gfile, "xu", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING XU.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'xu ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT XU." - call ESMF_FieldScatter(xu_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ XV" - call nemsio_readrecv(gfile, "xv", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING XV.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'xv ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT XV." - call ESMF_FieldScatter(xv_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ XZ" - call nemsio_readrecv(gfile, "xz", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING XZ.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'xz ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT XZ." - call ESMF_FieldScatter(xz_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ XTTS" - call nemsio_readrecv(gfile, "xtts", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING XTTS.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'xtts ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT XTTS." - call ESMF_FieldScatter(xtts_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ XZTS" - call nemsio_readrecv(gfile, "xzts", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING XZTS.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'xzts ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT XZTS." - call ESMF_FieldScatter(xzts_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - print*,"- READ ZC" - call nemsio_readrecv(gfile, "zc", "sfc", 1, dummy, 0, iret=rc) - if (rc /= 0) call error_handler("READING ZC.", rc) - dummy2d = reshape(dummy, (/i_input,j_input/)) - print*,'zc ',maxval(dummy2d),minval(dummy2d) - endif - - print*,"- CALL FieldScatter FOR INPUT Z_C." - call ESMF_FieldScatter(z_c_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (localpet == 0) then - dummy2d = 0.0 ! zm not used yet. Set to zero per Xu Li. - endif - - print*,"- CALL FieldScatter FOR INPUT ZM." - call ESMF_FieldScatter(zm_input_grid, dummy2d, rootpet=0, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - deallocate(dummy, dummy2d) - - if (localpet == 0) call nemsio_close(gfile) - - end subroutine read_input_nst_nemsio_file - -!> Read a record from a netcdf file -!! -!! @param [in] field name of field to be read -!! @param [in] tile_num grid tile number -!! @param [in] imo i-dimension of field -!! @param [in] jmo j-dimension of field -!! @param [in] lmo number of vertical levels of field -!! @param [out] sfcdata 1-d array containing field data -!! @param [out] sfcdata_3d 3-d array containing field data -!! @author George Gayno NCEP/EMC - SUBROUTINE READ_FV3_GRID_DATA_NETCDF(FIELD,TILE_NUM,IMO,JMO,LMO, & - SFCDATA, SFCDATA_3D) - - IMPLICIT NONE - - CHARACTER(LEN=*),INTENT(IN) :: FIELD - - INTEGER, INTENT(IN) :: IMO, JMO, LMO, TILE_NUM - - REAL(ESMF_KIND_R8), INTENT(OUT), OPTIONAL :: SFCDATA(IMO,JMO) - REAL(ESMF_KIND_R8), INTENT(OUT), OPTIONAL :: SFCDATA_3D(IMO,JMO,LMO) - - CHARACTER(LEN=256) :: TILEFILE - - INTEGER :: ERROR, NCID, ID_VAR - - TILEFILE = TRIM(DATA_DIR_INPUT_GRID) // "/" // TRIM(SFC_FILES_INPUT_GRID(TILE_NUM)) - - PRINT*,'WILL READ ',TRIM(FIELD), ' FROM: ', TRIM(TILEFILE) - - ERROR=NF90_OPEN(TRIM(TILEFILE),NF90_NOWRITE,NCID) - CALL NETCDF_ERR(ERROR, 'OPENING: '//TRIM(TILEFILE) ) - - ERROR=NF90_INQ_VARID(NCID, FIELD, ID_VAR) - CALL NETCDF_ERR(ERROR, 'READING FIELD ID' ) - - IF (PRESENT(SFCDATA_3D)) THEN - ERROR=NF90_GET_VAR(NCID, ID_VAR, SFCDATA_3D) - CALL NETCDF_ERR(ERROR, 'READING FIELD' ) - ELSE - ERROR=NF90_GET_VAR(NCID, ID_VAR, SFCDATA) - CALL NETCDF_ERR(ERROR, 'READING FIELD' ) - ENDIF - - ERROR = NF90_CLOSE(NCID) - - END SUBROUTINE READ_FV3_GRID_DATA_NETCDF - -!> Read winds from a grib2 file. Rotate winds -!! to be earth relative if necessary. -!! -!! @param [in] file grib2 file to be read -!! @param [in] inv grib2 inventory file -!! @param [inout] u u-component wind -!! @param [inout] v v-component wind -!! @param[in] localpet ESMF local persistent execution thread -!! @author Larissa Reames - subroutine read_winds(file,inv,u,v,localpet) - - use wgrib2api - use netcdf - use program_setup, only : get_var_cond, fix_dir_input_grid - use model_grid, only : input_grid_type - implicit none - - character(len=250), intent(in) :: file - character(len=10), intent(in) :: inv - integer, intent(in) :: localpet - real(esmf_kind_r8), intent(inout), allocatable :: u(:,:,:),v(:,:,:) - - real(esmf_kind_r4), dimension(i_input,j_input) :: alpha - real(esmf_kind_r8), dimension(i_input,j_input) :: lon, lat - real(esmf_kind_r4), allocatable :: u_tmp(:,:),v_tmp(:,:) - real(esmf_kind_r4), dimension(i_input,j_input) :: ws,wd - real(esmf_kind_r4) :: value_u, value_v,lov,latin1,latin2 - real(esmf_kind_r8) :: d2r - - integer :: varnum_u, varnum_v, vlev, & !ncid, id_var, & - error, iret, istr - - character(len=20) :: vname - character(len=50) :: method_u, method_v - character(len=250) :: file_coord - character(len=10000) :: temp_msg - - d2r=acos(-1.0_esmf_kind_r8) / 180.0_esmf_kind_r8 - if (localpet==0) then - allocate(u(i_input,j_input,lev_input)) - allocate(v(i_input,j_input,lev_input)) - else - allocate(u(0,0,0)) - allocate(v(0,0,0)) - endif - - file_coord = trim(fix_dir_input_grid)//"/latlon_grid3.32769.nc" - - vname = "u" - call get_var_cond(vname,this_miss_var_method=method_u, this_miss_var_value=value_u, & - loc=varnum_u) - vname = "v" - call get_var_cond(vname,this_miss_var_method=method_v, this_miss_var_value=value_v, & - loc=varnum_v) - - if (trim(input_grid_type)=="rotated_latlon") then - print*,"- CALL FieldGather FOR INPUT GRID LONGITUDE" - call ESMF_FieldGather(longitude_input_grid, lon, rootPet=0, tile=1, rc=error) - if(ESMF_logFoundError(rcToCheck=error,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", error) - print*,"- CALL FieldGather FOR INPUT GRID LATITUDE" - call ESMF_FieldGather(latitude_input_grid, lat, rootPet=0, tile=1, rc=error) - if(ESMF_logFoundError(rcToCheck=error,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", error) - - if (localpet==0) then - print*,"- CALCULATE ROTATION ANGLE FOR ROTATED_LATLON INPUT GRID" - error = grb2_inq(file, inv,grid_desc=temp_msg) - !1:0:grid_template=32769:winds(grid): - ! I am not an Arakawa E-grid. - ! I am rotated but have no rotation angle. - ! I am staggered. What am I? - ! (953 x 834) units 1e-06 input WE:SN output WE:SN res 56 - ! lat0 -10.590603 lat-center 54.000000 dlat 121.813000 - ! lon0 220.914154 lon-center 254.000000 dlon 121.813000 #points=794802 - - istr = index(temp_msg, "lat-center ") + len("lat_center ") - read(temp_msg(istr:istr+9),"(F8.5)") latin1 - istr = index(temp_msg, "lon-center ") + len("lon-center ") - read(temp_msg(istr:istr+10),"(F9.6)") lov - - print*, "- CALL CALCALPHA_ROTLATLON with center lat,lon = ",latin1,lov - call calcalpha_rotlatlon(lat,lon,latin1,lov,alpha) - print*, " alpha min/max = ",MINVAL(alpha),MAXVAL(alpha) - endif - elseif (trim(input_grid_type) == "lambert") then - !# NG this has been edited to correctly calculate gridrot for Lambert grids - ! Previously was incorrectly using polar-stereographic formation - print*,"- CALL FieldGather FOR INPUT GRID LONGITUDE" - call ESMF_FieldGather(longitude_input_grid, lon, rootPet=0, tile=1, rc=error) - if(ESMF_logFoundError(rcToCheck=error,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", error) - - if (localpet==0) then - error = grb2_inq(file, inv,grid_desc=temp_msg) - !1:0:grid_template=30:winds(grid): - ! Lambert Conformal: (1799 x 1059) input WE:SN output WE:SN res 8 - ! Lat1 21.138123 Lon1 237.280472 LoV 262.500000 - ! LatD 38.500000 Latin1 38.500000 Latin2 38.500000 - ! LatSP 0.000000 LonSP 0.000000 - ! North Pole (1799 x 1059) Dx 3000.000000 m Dy 3000.000000 m mode 8 - - istr = index(temp_msg, "LoV ") + len("LoV ") - read(temp_msg(istr:istr+10),"(F9.6)") lov - istr = index(temp_msg, "Latin1 ") + len("Latin1 ") - read(temp_msg(istr:istr+9),"(F8.5)") latin1 - istr = index(temp_msg, "Latin2 ") + len("Latin2 ") - read(temp_msg(istr:istr+9),"(F8.5)") latin2 - - print*, "- CALL GRIDROT for LC grid with lov,latin1/2 = ",lov,latin1,latin2 - call gridrot(lov,latin1,latin2,lon,alpha) - print*, " alpha min/max = ",MINVAL(alpha),MAXVAL(alpha) - endif - endif - - if (localpet==0) then - do vlev = 1, lev_input - - vname = ":UGRD:" - iret = grb2_inq(file,inv,vname,slevs(vlev),data2=u_tmp) - if (iret <= 0) then - call handle_grib_error(vname, slevs(vlev),method_u,value_u,varnum_u,iret,var=u_tmp) - if (iret==1) then ! missing_var_method == skip - call error_handler("READING IN U AT LEVEL "//trim(slevs(vlev))//". SET A FILL "// & - "VALUE IN THE VARMAP TABLE IF THIS ERROR IS NOT DESIRABLE.",iret) - endif - endif - - vname = ":VGRD:" - iret = grb2_inq(file,inv,vname,slevs(vlev),data2=v_tmp) - if (iret <= 0) then - call handle_grib_error(vname, slevs(vlev),method_v,value_v,varnum_v,iret,var=v_tmp) - if (iret==1) then ! missing_var_method == skip - call error_handler("READING IN V AT LEVEL "//trim(slevs(vlev))//". SET A FILL "// & - "VALUE IN THE VARMAP TABLE IF THIS ERROR IS NOT DESIRABLE.",iret) - endif - endif - - if (trim(input_grid_type) == "latlon") then - if (external_model == 'UKMET') then - u(:,:,vlev) = u_tmp - v(:,:,vlev) = (v_tmp(:,2:jp1_input) + v_tmp(:,1:j_input))/2 - else - u(:,:,vlev) = u_tmp - v(:,:,vlev) = v_tmp - endif - else if (trim(input_grid_type) == "rotated_latlon") then - ws = sqrt(u_tmp**2 + v_tmp**2) - wd = atan2(-u_tmp,-v_tmp) / d2r ! calculate grid-relative wind direction - wd = wd + alpha + 180.0 ! Rotate from grid- to earth-relative direction - wd = 270.0 - wd ! Convert from meteorological (true N) to mathematical direction - u(:,:,vlev) = -ws*cos(wd*d2r) - v(:,:,vlev) = -ws*sin(wd*d2r) - else - u(:,:,vlev) = real(u_tmp * cos(alpha) + v_tmp * sin(alpha),esmf_kind_r8) - v(:,:,vlev) = real(v_tmp * cos(alpha) - u_tmp * sin(alpha),esmf_kind_r8) - endif - - print*, 'max, min U ', minval(u(:,:,vlev)), maxval(u(:,:,vlev)) - print*, 'max, min V ', minval(v(:,:,vlev)), maxval(v(:,:,vlev)) - enddo - endif - -end subroutine read_winds - -!> Convert winds from 2-d to 3-d components. -!! -!! @author George Gayno NCEP/EMC - subroutine convert_winds - - implicit none - - integer :: clb(4), cub(4) - integer :: i, j, k, rc - - real(esmf_kind_r8) :: latrad, lonrad - real(esmf_kind_r8), pointer :: windptr(:,:,:,:) - real(esmf_kind_r8), pointer :: uptr(:,:,:) - real(esmf_kind_r8), pointer :: vptr(:,:,:) - real(esmf_kind_r8), pointer :: latptr(:,:) - real(esmf_kind_r8), pointer :: lonptr(:,:) - - print*,"- CALL FieldGet FOR 3-D WIND." - call ESMF_FieldGet(wind_input_grid, & - computationalLBound=clb, & - computationalUBound=cub, & - farrayPtr=windptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR U." - call ESMF_FieldGet(u_input_grid, & - farrayPtr=uptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR V." - call ESMF_FieldGet(v_input_grid, & - farrayPtr=vptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR LATITUDE." - call ESMF_FieldGet(latitude_input_grid, & - farrayPtr=latptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR LONGITUDE." - call ESMF_FieldGet(longitude_input_grid, & - farrayPtr=lonptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - do i = clb(1), cub(1) - do j = clb(2), cub(2) - latrad = latptr(i,j) * acos(-1.) / 180.0 - lonrad = lonptr(i,j) * acos(-1.) / 180.0 - do k = clb(3), cub(3) - windptr(i,j,k,1) = uptr(i,j,k) * cos(lonrad) - vptr(i,j,k) * sin(latrad) * sin(lonrad) - windptr(i,j,k,2) = uptr(i,j,k) * sin(lonrad) + vptr(i,j,k) * sin(latrad) * cos(lonrad) - windptr(i,j,k,3) = vptr(i,j,k) * cos(latrad) - enddo - enddo - enddo - - call ESMF_FieldDestroy(u_input_grid, rc=rc) - call ESMF_FieldDestroy(v_input_grid, rc=rc) - - end subroutine convert_winds - -!> Compute grid rotation angle for non-latlon grids. -!! -!! @note The original gridrot subroutine was specific to polar -!! stereographic grids. We need to compute it for Lambert Conformal -!! grids. So we need lat1,lat2. This follows the ncl_ncarg source -!! code: ncl_ncarg-6.6.2/ni/src/ncl/GetGrids.c -!! -!! @param [in] lov orientation angle -!! @param [in] latin1 first tangent latitude -!! @param [in] latin2 second tangent latitude -!! @param [in] lon longitude -!! @param [inout] rot rotation angle -!! @author Larissa Reames -subroutine gridrot(lov,latin1,latin2,lon,rot) - - use model_grid, only : i_input,j_input - implicit none - - - real(esmf_kind_r4), intent(in) :: lov,latin1,latin2 - real(esmf_kind_r4), intent(inout) :: rot(i_input,j_input) - real(esmf_kind_r8), intent(in) :: lon(i_input,j_input) - - real(esmf_kind_r4) :: trot(i_input,j_input), tlon(i_input,j_input) - real(esmf_kind_r4) :: dtor = 3.14159265359/180.0_esmf_kind_r4 - real(esmf_kind_r4) :: an - !trot_tmp = real(lon,esmf_kind_r4)-lov - !trot = trot_tmp - !where(trot_tmp > 180.0) trot = trot-360.0_esmf_kind_r4 - !where(trot_tmp < -180.0) trot = trot-360.0_esmf_kind_r4 - - if ( (latin1 - latin2) .lt. 0.000001 ) then - an = sin(latin1*dtor) - else - an = log( cos(latin1*dtor) / cos(latin2*dtor) ) / & - log( tan(dtor*(90.0-latin1)/2.) / tan(dtor*(90.0-latin2)/2.)) - end if - - tlon = mod(lon - lov + 180. + 3600., 360.) - 180. - trot = an * tlon - - rot = trot * dtor - -end subroutine gridrot - -!> Calculate rotation angle for rotated latlon grids. -!! Needed to convert to earth-relative winds. -!! -!! @param [in] latgrid grid latitudes -!! @param [in] longrid grid longitudes -!! @param [in] cenlat center latitude -!! @param [in] cenlon center longitude -!! @param [out] alpha grid rotation angle -!! @author Larissa Reames -subroutine calcalpha_rotlatlon(latgrid,longrid,cenlat,cenlon,alpha) - - use model_grid, only : i_input,j_input - implicit none - - real(esmf_kind_r8), intent(in) :: latgrid(i_input,j_input), & - longrid(i_input,j_input) - real(esmf_kind_r4), intent(in) :: cenlat, cenlon - real(esmf_kind_r4), intent(out) :: alpha(i_input,j_input) - - ! Variables local to subroutine - real(esmf_kind_r8) :: D2R,lon0_r,lat0_r,sphi0,cphi0 - real(esmf_kind_r8), DIMENSION(i_input,j_input) :: tlat,tlon,tph,sinalpha - - D2R = acos(-1.0_esmf_kind_r8) / 180.0_esmf_kind_r8 - if (cenlon .lt. 0) then - lon0_r = (cenlon + 360.0)*D2R - else - lon0_r = cenlon*D2R - end if - lat0_r=cenlat*D2R - sphi0=sin(lat0_r) - cphi0=cos(lat0_r) - - ! deal with input lat/lon - tlat = latgrid * D2R - tlon = longrid * D2R - - ! Calculate alpha (rotation angle) - tlon = -tlon + lon0_r - tph = asin(cphi0*sin(tlat) - sphi0*cos(tlat)*cos(tlon)) - sinalpha = sphi0 * sin(tlon) / cos(tph) - alpha = -asin(sinalpha)/D2R - ! returns alpha in degrees -end subroutine calcalpha_rotlatlon - -!> Handle GRIB2 read error based on the user selected -!! method in the varmap file. -!! -!! @param [in] vname grib2 variable name -!! @param [in] lev grib2 variable level -!! @param [in] method how missing data is handled -!! @param [in] value fill value for missing data -!! @param [in] varnum grib2 variable number -!! @param [inout] iret return status code -!! @param [inout] var 4-byte array of corrected data -!! @param [inout] var8 8-byte array of corrected data -!! @param [inout] var3d 3-d array of corrected data -!! @author Larissa Reames -subroutine handle_grib_error(vname,lev,method,value,varnum, iret,var,var8,var3d) - - use, intrinsic :: ieee_arithmetic - - implicit none - - real(esmf_kind_r4), intent(in) :: value - real(esmf_kind_r4), intent(inout), optional :: var(:,:) - real(esmf_kind_r8), intent(inout), optional :: var8(:,:) - real(esmf_kind_r8), intent(inout), optional :: var3d(:,:,:) - - character(len=20), intent(in) :: vname, lev, method - - integer, intent(in) :: varnum - integer, intent(inout) :: iret - - iret = 0 - if (varnum == 9999) then - print*, "WARNING: ", trim(vname), " NOT FOUND AT LEVEL ", lev, " IN EXTERNAL FILE ", & - "AND NO ENTRY EXISTS IN VARMAP TABLE. VARIABLE WILL NOT BE USED." - iret = 1 - - return - endif - - if (trim(method) == "skip" ) then - print*, "WARNING: SKIPPING ", trim(vname), " IN FILE" - read_from_input(varnum) = .false. - iret = 1 - elseif (trim(method) == "set_to_fill") then - print*, "WARNING: ,", trim(vname), " NOT AVILABLE AT LEVEL ", trim(lev), & - ". SETTING EQUAL TO FILL VALUE OF ", value - if(present(var)) var(:,:) = value - if(present(var8)) var8(:,:) = value - if(present(var3d)) var3d(:,:,:) = value - elseif (trim(method) == "set_to_NaN") then - print*, "WARNING: ,", trim(vname), " NOT AVILABLE AT LEVEL ", trim(lev), & - ". SETTING EQUAL TO NaNs" - if(present(var)) var(:,:) = ieee_value(var,IEEE_QUIET_NAN) - if(present(var8)) var8(:,:) = ieee_value(var8,IEEE_QUIET_NAN) - if(present(var3d)) var3d(:,:,:) = ieee_value(var3d,IEEE_QUIET_NAN) - elseif (trim(method) == "stop") then - call error_handler("READING "//trim(vname)// " at level "//lev//". TO MAKE THIS NON- & - FATAL, CHANGE STOP TO SKIP FOR THIS VARIABLE IN YOUR VARMAP & - FILE.", iret) - elseif (trim(method) == "intrp") then - print*, "WARNING: ,"//trim(vname)//" NOT AVAILABLE AT LEVEL "//trim(lev)// & - ". WILL INTERPOLATE INTERSPERSED MISSING LEVELS AND/OR FILL MISSING"//& - " LEVELS AT EDGES." - else - call error_handler("ERROR USING MISSING_VAR_METHOD. PLEASE SET VALUES IN" // & - " VARMAP TABLE TO ONE OF: set_to_fill, set_to_NaN,"// & - " , skip, or stop.", 1) - endif - -end subroutine handle_grib_error - -!> Read soil temperature and soil moisture fields from a GRIB2 file. -!! -!! @param [in] the_file grib2 file name -!! @param [in] inv_file grib2 inventory file name -!! @param [in] vname variable name in varmap table -!! @param [in] vname_file variable name in grib2 file -!! @param [inout] dummy3d array of soil data -!! @param [out] rc read error status code -!! @author George Gayno NCEP/EMC -subroutine read_grib_soil(the_file,inv_file,vname,vname_file,dummy3d,rc) - - use wgrib2api - implicit none - - character(len=*), intent(in) :: the_file, inv_file - character(len=20), intent(in) :: vname,vname_file - - integer, intent(out) :: rc - - real(esmf_kind_r8), intent(inout) :: dummy3d(:,:,:) - - real(esmf_kind_r4), allocatable :: dummy2d(:,:) - real(esmf_kind_r4) :: value - integer :: varnum,i - character(len=50) :: slevs(lsoil_input) - character(len=50) :: method - - allocate(dummy2d(i_input,j_input)) - - if(lsoil_input == 4) then - slevs = (/character(24)::':0-0.1 m below ground:', ':0.1-0.4 m below ground:', & - ':0.4-1 m below ground:', ':1-2 m below ground:'/) - elseif(lsoil_input == 9) then - slevs = (/character(26)::':0-0 m below ground',':0.01-0.01 m below ground:',':0.04-0.04 m below ground:', & - ':0.1-0.1 m below ground:',':0.3-0.3 m below ground:',':0.6-0.6 m below ground:', & - ':1-1 m below ground:',':1.6-1.6 m below ground:',':3-3 m below ground:'/) - else - rc = -1 - call error_handler("reading soil levels. File must have 4 or 9 soil levels.", rc) - endif - - call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & - loc=varnum) - do i = 1,lsoil_input - if (vname_file=="var2_2_1_") then - rc = grb2_inq(the_file,inv_file,vname_file,"_0_192:",slevs(i),data2=dummy2d) - else - rc = grb2_inq(the_file,inv_file,vname_file,slevs(i),data2=dummy2d) - endif - if (rc <= 0) then - call handle_grib_error(vname_file, slevs(i),method,value,varnum,rc,var=dummy2d) - if (rc==1 .and. trim(vname) /= "soill") then - ! missing_var_method == skip or no entry in varmap table - call error_handler("READING IN "//trim(vname)//". SET A FILL "// & - "VALUE IN THE VARMAP TABLE IF THIS ERROR IS NOT DESIRABLE.",rc) - elseif (rc==1) then - dummy3d(:,:,:) = 0.0_esmf_kind_r8 - exit - endif - endif - - dummy3d(:,:,i) = real(dummy2d,esmf_kind_r8) - end do - - deallocate(dummy2d) - - end subroutine read_grib_soil - -!> Free up memory associated with atm data. -!! -!! @author George Gayno NCEP/EMC - subroutine cleanup_input_atm_data - - implicit none - - integer :: rc, n - - print*,'- DESTROY ATMOSPHERIC INPUT DATA.' - - call ESMF_FieldDestroy(terrain_input_grid, rc=rc) - call ESMF_FieldDestroy(pres_input_grid, rc=rc) - call ESMF_FieldDestroy(dzdt_input_grid, rc=rc) - call ESMF_FieldDestroy(temp_input_grid, rc=rc) - call ESMF_FieldDestroy(wind_input_grid, rc=rc) - call ESMF_FieldDestroy(ps_input_grid, rc=rc) - - do n = 1, num_tracers_input - call ESMF_FieldDestroy(tracers_input_grid(n), rc=rc) - enddo - deallocate(tracers_input_grid) - - end subroutine cleanup_input_atm_data - -!> Free up memory associated with nst data. -!! -!! @author George Gayno NCEP/EMC - subroutine cleanup_input_nst_data - - implicit none - - integer :: rc - - print*,'- DESTROY NST INPUT DATA.' - - call ESMF_FieldDestroy(landsea_mask_input_grid, rc=rc) - call ESMF_FieldDestroy(c_d_input_grid, rc=rc) - call ESMF_FieldDestroy(c_0_input_grid, rc=rc) - call ESMF_FieldDestroy(d_conv_input_grid, rc=rc) - call ESMF_FieldDestroy(dt_cool_input_grid, rc=rc) - call ESMF_FieldDestroy(ifd_input_grid, rc=rc) - call ESMF_FieldDestroy(qrain_input_grid, rc=rc) - call ESMF_FieldDestroy(tref_input_grid, rc=rc) - call ESMF_FieldDestroy(w_d_input_grid, rc=rc) - call ESMF_FieldDestroy(w_0_input_grid, rc=rc) - call ESMF_FieldDestroy(xs_input_grid, rc=rc) - call ESMF_FieldDestroy(xt_input_grid, rc=rc) - call ESMF_FieldDestroy(xu_input_grid, rc=rc) - call ESMF_FieldDestroy(xv_input_grid, rc=rc) - call ESMF_FieldDestroy(xz_input_grid, rc=rc) - call ESMF_FieldDestroy(xtts_input_grid, rc=rc) - call ESMF_FieldDestroy(xzts_input_grid, rc=rc) - call ESMF_FieldDestroy(z_c_input_grid, rc=rc) - call ESMF_FieldDestroy(zm_input_grid, rc=rc) - - end subroutine cleanup_input_nst_data - -!> Free up memory associated with sfc data. -!! -!! @author George Gayno NCEP/EMC - subroutine cleanup_input_sfc_data - - implicit none - - integer :: rc - - print*,"- CALL FieldDestroy FOR INPUT GRID FIELDS." - - call ESMF_FieldDestroy(canopy_mc_input_grid, rc=rc) - call ESMF_FieldDestroy(f10m_input_grid, rc=rc) - call ESMF_FieldDestroy(ffmm_input_grid, rc=rc) - if (.not. convert_nst) then - call ESMF_FieldDestroy(landsea_mask_input_grid, rc=rc) - endif - call ESMF_FieldDestroy(q2m_input_grid, rc=rc) - call ESMF_FieldDestroy(seaice_depth_input_grid, rc=rc) - call ESMF_FieldDestroy(seaice_fract_input_grid, rc=rc) - call ESMF_FieldDestroy(seaice_skin_temp_input_grid, rc=rc) - call ESMF_FieldDestroy(skin_temp_input_grid, rc=rc) - call ESMF_FieldDestroy(snow_depth_input_grid, rc=rc) - call ESMF_FieldDestroy(snow_liq_equiv_input_grid, rc=rc) - call ESMF_FieldDestroy(soil_temp_input_grid, rc=rc) - call ESMF_FieldDestroy(soil_type_input_grid, rc=rc) - call ESMF_FieldDestroy(soilm_liq_input_grid, rc=rc) - call ESMF_FieldDestroy(soilm_tot_input_grid, rc=rc) - call ESMF_FieldDestroy(srflag_input_grid, rc=rc) - call ESMF_FieldDestroy(t2m_input_grid, rc=rc) - call ESMF_FieldDestroy(tprcp_input_grid, rc=rc) - call ESMF_FieldDestroy(ustar_input_grid, rc=rc) - call ESMF_FieldDestroy(veg_type_input_grid, rc=rc) - call ESMF_FieldDestroy(z0_input_grid, rc=rc) - call ESMF_FieldDestroy(terrain_input_grid, rc=rc) - if (.not. vgfrc_from_climo) then - call ESMF_FieldDestroy(veg_greenness_input_grid, rc=rc) - endif - if (.not. minmax_vgfrc_from_climo) then - call ESMF_FieldDestroy(min_veg_greenness_input_grid, rc=rc) - call ESMF_FieldDestroy(max_veg_greenness_input_grid, rc=rc) - endif - if (.not. lai_from_climo) then - call ESMF_FieldDestroy(lai_input_grid, rc=rc) - endif - - end subroutine cleanup_input_sfc_data - -!> Sort an array of values. -!! -!! @param a the sorted array -!! @param first the first value of sorted array -!! @param last the last value of sorted array -!! @author Jili Dong NOAA/EMC -recursive subroutine quicksort(a, first, last) - implicit none - real*8 a(*), x, t - integer first, last - integer i, j - - x = a( (first+last) / 2 ) - i = first - j = last - do - do while (a(i) < x) - i=i+1 - end do - do while (x < a(j)) - j=j-1 - end do - if (i >= j) exit - t = a(i); a(i) = a(j); a(j) = t - i=i+1 - j=j-1 - end do - if (first < i-1) call quicksort(a, first, i-1) - if (j+1 < last) call quicksort(a, j+1, last) -end subroutine quicksort - -!> Check for and replace certain values in soil temperature. -!> At open water points (landmask=0) use skin temperature as -!> a filler value. At land points (landmask=1) with excessive -!> soil temperature, replace soil temperature with skin temperature. -!> In GEFSv12.0 data there are some erroneous missing values at -!> land points which this corrects. At sea ice points (landmask=2), -!> store a default ice column temperature because grib2 files do not -!> have ice column temperature which FV3 expects at these points. -!! -!! @param soilt [inout] 3-dimensional soil temperature arrray -!! @param landmask [in] landmask of the input grid -!! @param skint [in] 2-dimensional skin temperature array -!! @author Larissa Reames CIMMS/NSSL - -subroutine check_soilt(soilt, landmask, skint) - implicit none - real(esmf_kind_r8), intent(inout) :: soilt(i_input,j_input,lsoil_input) - real(esmf_kind_r8), intent(in) :: skint(i_input,j_input) - integer(esmf_kind_i4), intent(in) :: landmask(i_input,j_input) - - integer :: i, j, k - - do k=1,lsoil_input - do j = 1, j_input - do i = 1, i_input - if (landmask(i,j) == 0_esmf_kind_i4 ) then - soilt(i,j,k) = skint(i,j) - else if (landmask(i,j) == 1_esmf_kind_i4 .and. soilt(i,j,k) > 350.0_esmf_kind_r8) then - soilt(i,j,k) = skint(i,j) - else if (landmask(i,j) == 2_esmf_kind_i4 ) then - soilt(i,j,k) = ICET_DEFAULT - endif - enddo - enddo - enddo -end subroutine check_soilt - -!> When using GEFS data, some points on the target grid have -!> unreasonable canpy moisture content, so zero out any -!> locations with unrealistic canopy moisture values (>0.5). -!! -!! @param cnwat [input] 2-dimensional canopy moisture content -!! @author Larissa Reames CIMMS/NSSL - -subroutine check_cnwat(cnwat) - implicit none - real(esmf_kind_r4), intent(inout) :: cnwat(i_input,j_input) - - real(esmf_kind_r4) :: max_cnwat = 0.5 - - integer :: i, j - - do i = 1,i_input - do j = 1,j_input - if (cnwat(i,j) .gt. max_cnwat) cnwat(i,j) = 0.0_esmf_kind_r4 - enddo - enddo -end subroutine check_cnwat - - - - -!> Pressure to presure vertical interpolation for tracers with linear or lnP -!> interpolation. Input tracers on pres levels are interpolated -!> to the target output pressure levels. The matching levels of input and -!> output will keep the same. Extrapolation is also allowed but needs -!> caution. The routine is mostly for GFSV16 combined grib2 input when spfh has -!> missing levels in low and mid troposphere from U/T/HGT/DZDT. -!! -!! @param [in] ppin 1d input pres levs -!! @param [in] xxin 1d input tracer -!! @param [in] npin number of input levs -!! @param [in] ppout 1d target pres levs -!! @param [out] xxout 1d interpolated tracer -!! @param [in] npout number of target levs -!! @param [in] linlog interp method.1:linear;not 1:log;neg:extrp allowed -!! @param [in] xmsg fill values of missing levels (-999.0) -!! @param [out] ier error status. non 0: failed interpolation -!! @author Jili Dong NCEP/EMC -!! @date 2021/07/30 - -SUBROUTINE DINT2P(PPIN,XXIN,NPIN,PPOUT,XXOUT,NPOUT & - ,LINLOG,XMSG,IER) - IMPLICIT NONE - -! NCL code for pressure level interpolation -! -! This code was designed for one simple task. It has since -! been mangled and abused for assorted reasons. For example, -! early gfortran compilers had some issues with automatic arrays. -! Hence, the C-Wrapper was used to create 'work' arrays which -! were then passed to this code. The original focused (non-NCL) -! task was to handle PPIN & PPOUT that had the same 'monotonicity.' -! Extra code was added to handle the more general case. -! Blah-Blah: Punch line: it is embarrassingly convoluted!!! -! -! ! input types - INTEGER NPIN,NPOUT,LINLOG,IER - real*8 PPIN(NPIN),XXIN(NPIN),PPOUT(NPOUT),XMSG - ! output - real*8 XXOUT(NPOUT) - ! work - real*8 PIN(NPIN),XIN(NPIN),P(NPIN),X(NPIN) - real*8 POUT(NPOUT),XOUT(NPOUT) - -! local - INTEGER J1,NP,NL,NIN,NLMAX,NPLVL,NLSAVE,NP1,NO1,N1,N2,LOGLIN, & - NLSTRT - real*8 SLOPE,PA,PB,PC - - LOGLIN = ABS(LINLOG) - -! error check: enough points: pressures consistency? - - IER = 0 - IF (NPOUT.GT.0) THEN - DO NP = 1,NPOUT - XXOUT(NP) = XMSG - END DO - END IF -! Jili Dong input levels have to be the same as output levels: -! we only interpolate for levels with missing variables -! IF (.not. all(PPIN .eq. PPOUT)) IER = IER+1 - - IF (NPIN.LT.2 .OR. NPOUT.LT.1) IER = IER + 1 - - IF (IER.NE.0) THEN -! PRINT *,'INT2P: error exit: ier=',IER - RETURN - END IF - -! should *input arrays* be reordered? want p(1) > p(2) > p(3) etc -! so that it will match order for which code was originally designed -! copy to 'work' arrays - - NP1 = 0 - NO1 = 0 - IF (PPIN(1).LT.PPIN(2)) THEN - NP1 = NPIN + 1 - END IF - IF (PPOUT(1).LT.PPOUT(2)) THEN - NO1 = NPOUT + 1 - END IF - - DO NP = 1,NPIN - PIN(NP) = PPIN(ABS(NP1-NP)) - XIN(NP) = XXIN(ABS(NP1-NP)) - END DO - - DO NP = 1,NPOUT - POUT(NP) = PPOUT(ABS(NO1-NP)) - END DO - -! eliminate XIN levels with missing data. -! . This can happen with observational data. - - NL = 0 - DO NP = 1,NPIN - IF (XIN(NP).NE.XMSG .AND. PIN(NP).NE.XMSG) THEN - NL = NL + 1 - P(NL) = PIN(NP) - X(NL) = XIN(NP) - END IF - END DO - NLMAX = NL - - ! all missing data - IF (NLMAX.LT.2) THEN - IER = IER + 1000 - PRINT *,'INT2P: ier=',IER - RETURN - END IF - -! ===============> pressure in decreasing order <================ -! perform the interpolation [pin(1)>pin(2)>...>pin(npin)] -! ( p ,x) -! ------------------------- p(nl+1), x(nl+1) example (200,5) -! . -! ------------------------- pout(np), xout(np) (250,?) -! . -! ------------------------- p(nl) , x(nl) (300,10) - - -! exact p-level matches - NLSTRT = 1 - NLSAVE = 1 - DO NP = 1,NPOUT - XOUT(NP) = XMSG - DO NL = NLSTRT,NLMAX - IF (POUT(NP).EQ.P(NL)) THEN - XOUT(NP) = X(NL) - NLSAVE = NL + 1 - GO TO 10 - END IF - END DO - 10 NLSTRT = NLSAVE - END DO - - IF (LOGLIN.EQ.1) THEN - DO NP = 1,NPOUT - DO NL = 1,NLMAX - 1 - IF (POUT(NP).LT.P(NL) .AND. POUT(NP).GT.P(NL+1)) THEN - SLOPE = (X(NL)-X(NL+1))/ (P(NL)-P(NL+1)) - XOUT(NP) = X(NL+1) + SLOPE* (POUT(NP)-P(NL+1)) - END IF - END DO - END DO - ELSE - DO NP = 1,NPOUT - DO NL = 1,NLMAX - 1 - IF (POUT(NP).LT.P(NL) .AND. POUT(NP).GT.P(NL+1)) THEN - PA = LOG(P(NL)) - PB = LOG(POUT(NP)) -! special case: In case someome inadvertently enter p=0. - if (p(nl+1).gt.0.d0) then - PC = LOG(P(NL+1)) - else - PC = LOG(1.d-4) - end if - - SLOPE = (X(NL)-X(NL+1))/ (PA-PC) - XOUT(NP) = X(NL+1) + SLOPE* (PB-PC) - END IF - END DO - END DO - END IF - -! extrapolate? -! . use the 'last' valid slope for extrapolating - - IF (LINLOG.LT.0) THEN - DO NP = 1,NPOUT - DO NL = 1,NLMAX - IF (POUT(NP).GT.P(1)) THEN - IF (LOGLIN.EQ.1) THEN - SLOPE = (X(2)-X(1))/ (P(2)-P(1)) - XOUT(NP) = X(1) + SLOPE* (POUT(NP)-P(1)) - ELSE - PA = LOG(P(2)) - PB = LOG(POUT(NP)) - PC = LOG(P(1)) - SLOPE = (X(2)-X(1))/ (PA-PC) - XOUT(NP) = X(1) + SLOPE* (PB-PC) - END IF - ELSE IF (POUT(NP).LT.P(NLMAX)) THEN - N1 = NLMAX - N2 = NLMAX - 1 - IF (LOGLIN.EQ.1) THEN - SLOPE = (X(N1)-X(N2))/ (P(N1)-P(N2)) - XOUT(NP) = X(N1) + SLOPE* (POUT(NP)-P(N1)) - ELSE - PA = LOG(P(N1)) - PB = LOG(POUT(NP)) - PC = LOG(P(N2)) - SLOPE = (X(N1)-X(N2))/ (PA-PC) - !XOUT(NP) = X(N1) + SLOPE* (PB-PC) !bug fixed below - XOUT(NP) = X(N1) + SLOPE* (PB-PA) - END IF - END IF - END DO - END DO - END IF - -! place results in the return array; -! . possibly .... reverse to original order - - if (NO1.GT.0) THEN - DO NP = 1,NPOUT - n1 = ABS(NO1-NP) - PPOUT(NP) = POUT(n1) - XXOUT(NP) = XOUT(n1) - END DO - ELSE - DO NP = 1,NPOUT - PPOUT(NP) = POUT(NP) - XXOUT(NP) = XOUT(NP) - END DO - END IF - - - RETURN - END SUBROUTINE DINT2P - - - end module input_data diff --git a/sorc/chgres_cube.fd/model_grid.F90 b/sorc/chgres_cube.fd/model_grid.F90 index 844a7f1fa..eba73b922 100644 --- a/sorc/chgres_cube.fd/model_grid.F90 +++ b/sorc/chgres_cube.fd/model_grid.F90 @@ -11,14 +11,13 @@ module model_grid use esmf use ESMF_LogPublicMod + use utilities, only : error_handler, netcdf_err implicit none private character(len=5), allocatable, public :: tiles_target_grid(:) !< Tile names of target grid. - character(len=10), public :: inv_file = "chgres.inv" - !< wgrib2 inventory file character(len=50), public :: input_grid_type = "latlon" !< map projection of input grid @@ -118,7 +117,7 @@ module model_grid !! @author George Gayno NCEP/EMC subroutine define_input_grid(localpet, npets) - use program_setup, only : input_type, external_model + use program_setup, only : input_type implicit none @@ -128,11 +127,9 @@ subroutine define_input_grid(localpet, npets) trim(input_type) == "gfs_gaussian_nemsio" .or. & trim(input_type) == "gfs_sigio" .or. & trim(input_type) == "gaussian_netcdf") then - call define_input_grid_gaussian(localpet, npets) - elseif (trim(external_model) == "GFS" .and. trim(input_type) == "grib2") then - call define_input_grid_gfs_grib2(localpet,npets) + call define_input_grid_gaussian(npets) elseif (trim(input_type) == "grib2") then - call define_input_grid_grib2(localpet,npets) + call define_input_grid_grib2(npets) else call define_input_grid_mosaic(localpet, npets) endif @@ -147,10 +144,9 @@ end subroutine define_input_grid !! - spectral gfs sigio (prior to July 19, 2017) !! - spectral gfs sfcio (prior to July 19, 2017) !! -!! @param [in] localpet ESMF local persistent execution thread !! @param [in] npets Number of persistent execution threads. !! @author George Gayno NCEP/EMC - subroutine define_input_grid_gaussian(localpet, npets) + subroutine define_input_grid_gaussian(npets) use nemsio_module @@ -166,7 +162,7 @@ subroutine define_input_grid_gaussian(localpet, npets) implicit none - integer, intent(in) :: localpet, npets + integer, intent(in) :: npets character(len=250) :: the_file @@ -611,64 +607,143 @@ subroutine define_input_grid_mosaic(localpet, npets) end subroutine define_input_grid_mosaic -!> Define input grid object for GFS grib2 data. Only works for data on -!! global lat/lon or gaussian grids. +!> Define input grid object for grib2 input data. !! -!! @param [in] localpet ESMF local persistent execution thread !! @param [in] npets Number of persistent execution threads -!! @author George Gayno NCEP/EMC - subroutine define_input_grid_gfs_grib2(localpet, npets) +!! @author Larissa Reames +!! @author Jeff Beck +!! @author George Gayno + subroutine define_input_grid_grib2(npets) - use wgrib2api - use mpi - use program_setup, only : data_dir_input_grid, & - grib2_file_input_grid + use grib_mod + use gdswzd_mod + use program_setup, only : grib2_file_input_grid, data_dir_input_grid implicit none - integer, intent(in) :: localpet, npets + integer, intent(in) :: npets - character(len=250) :: the_file + character(len=500) :: the_file - integer :: i, j, rc, clb(2), cub(2) - integer :: ierr + integer :: i, j, k, jdisc, jgdtn, jpdtn, lugb, lugi + integer :: jids(200), jgdt(200), jpdt(200), rc + integer :: kgds(200), nret, clb(2), cub(2) + logical :: unpack + + real :: res + real, allocatable :: rlon(:,:),rlat(:,:),xpts(:,:),ypts(:,:) + real, allocatable :: rlon_corner(:,:),rlat_corner(:,:) + real, allocatable :: rlon_diff(:,:),rlat_diff(:,:) + real, allocatable :: xpts_corner(:,:),ypts_corner(:,:) real(esmf_kind_r8), allocatable :: latitude(:,:) real(esmf_kind_r8), allocatable :: longitude(:,:) - real(esmf_kind_r4), allocatable :: lat4(:,:), lon4(:,:) + real(esmf_kind_r8), allocatable :: latitude_corner(:,:) + real(esmf_kind_r8), allocatable :: longitude_corner(:,:) real(esmf_kind_r8), pointer :: lat_src_ptr(:,:) - real(esmf_kind_r8), pointer :: lon_src_ptr(:,:) real(esmf_kind_r8), pointer :: lat_corner_src_ptr(:,:) + real(esmf_kind_r8), pointer :: lon_src_ptr(:,:) real(esmf_kind_r8), pointer :: lon_corner_src_ptr(:,:) - real(esmf_kind_r8) :: deltalon type(esmf_polekind_flag) :: polekindflag(2) - print*,"- DEFINE INPUT GRID OBJECT FOR INPUT GRIB2 DATA." - - num_tiles_input_grid = 1 + type(gribfield) :: gfld the_file = trim(data_dir_input_grid) // "/" // grib2_file_input_grid - if (localpet == 0) then - print*,'- OPEN AND INVENTORY GRIB2 FILE: ',trim(the_file) - rc=grb2_mk_inv(the_file,inv_file) - if (rc /=0) call error_handler("OPENING GRIB2 FILE",rc) - endif -! Wait for localpet 0 to create inventory - call mpi_barrier(mpi_comm_world, ierr) + lugb=12 + + print*,"- OPEN AND READ INPUT DATA GRIB2 FILE: ", trim(the_file) + call baopenr(lugb,the_file,rc) + if (rc /= 0) call error_handler("OPENING FILE", rc) + +! Read the first record and get the grid definition template. + + j = 0 ! Search at beginning of file + lugi = 0 ! No grib index file + jdisc = -1 ! Search for any discipline + jpdtn = -1 ! Search for any product definition template number + jgdtn = -1 ! Search for any grid definition template number + jids = -9999 ! Array of values in identification section, set to wildcard. + jgdt = -9999 ! Array of values in grid definition template, set to wildcard. + jpdt = -9999 ! Array of values in product definition template, set to wildcard. + unpack = .false. ! unpack data + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + if (rc /= 0) call error_handler("DEGRIBBING INPUT FILE.", rc) + + call baclose(lugb,rc) + + if (gfld%igdtnum == 0) then + print*,"- INPUT DATA ON LAT/LON GRID." + input_grid_type = 'latlon' + elseif (gfld%igdtnum == 30) then + print*,"- INPUT DATA ON LAMBERT CONFORMAL GRID." + input_grid_type = 'lambert' + elseif (gfld%igdtnum == 32769) then + print*,"- INPUT DATA ON ROTATED LAT/LON GRID." + input_grid_type = 'rotated_latlon' + else + call error_handler("INPUT GRID TEMPLATE NOT SUPPORTED.", 2) + endif - rc = grb2_inq(the_file,inv_file,':PRES:',':surface:',nx=i_input, ny=j_input, & - lat=lat4, lon=lon4) - if (rc /= 1) call error_handler("READING GRIB2 FILE", rc) + kgds = 0 + call gdt_to_gds(gfld%igdtnum, gfld%igdtmpl, gfld%igdtlen, kgds, i_input, j_input, res) ip1_input = i_input + 1 jp1_input = j_input + 1 - polekindflag(1:2) = ESMF_POLEKIND_MONOPOLE + allocate(rlat(i_input,j_input)) + allocate(rlon(i_input,j_input)) + allocate(rlat_diff(i_input,j_input)) + allocate(rlon_diff(i_input,j_input)) + allocate(xpts(i_input,j_input)) + allocate(ypts(i_input,j_input)) + allocate(rlat_corner(ip1_input,jp1_input)) + allocate(rlon_corner(ip1_input,jp1_input)) + allocate(xpts_corner(ip1_input,jp1_input)) + allocate(ypts_corner(ip1_input,jp1_input)) + + do j = 1, j_input + do i = 1, i_input + xpts(i,j) = float(i) + ypts(i,j) = float(j) + enddo + enddo - print*,"- CALL GridCreate1PeriDim FOR INPUT GRID." - input_grid = ESMF_GridCreate1PeriDim(minIndex=(/1,1/), & + print*,"- COMPUTE GRID CELL CENTER COORDINATES." + call gdswzd(kgds,1,(i_input*j_input),-9999.,xpts,ypts,rlon,rlat,nret) + + if (nret /= (i_input*j_input)) then + call error_handler("GDSWZD RETURNED WRONG NUMBER OF POINTS.", 2) + endif + + deallocate(xpts, ypts) + + do j = 1, jp1_input + do i = 1, ip1_input + xpts_corner(i,j) = float(i) - 0.5 + ypts_corner(i,j) = float(j) - 0.5 + enddo + enddo + + print*,"- COMPUTE GRID CELL CORNER COORDINATES." + call gdswzd(kgds,1,(ip1_input*jp1_input),-9999.,xpts_corner,ypts_corner,rlon_corner,rlat_corner,nret) + + if (nret /= (ip1_input*jp1_input)) then + call error_handler("GDSWZD RETURNED WRONG NUMBER OF POINTS.", 2) + endif + + deallocate(xpts_corner, ypts_corner) + + if (gfld%igdtnum == 0) then ! gfs lat/lon data + + print*,"- CALL GridCreate1PeriDim FOR INPUT GRID." + + polekindflag(1:2) = ESMF_POLEKIND_MONOPOLE + + input_grid = ESMF_GridCreate1PeriDim(minIndex=(/1,1/), & maxIndex=(/i_input,j_input/), & polekindflag=polekindflag, & periodicDim=1, & @@ -676,6 +751,17 @@ subroutine define_input_grid_gfs_grib2(localpet, npets) coordSys=ESMF_COORDSYS_SPH_DEG, & regDecomp=(/1,npets/), & indexflag=ESMF_INDEX_GLOBAL, rc=rc) + + else + + print*,"- CALL GridCreateNoPeriDim FOR INPUT GRID." + + input_grid = ESMF_GridCreateNoPeriDim(maxIndex=(/i_input,j_input/), & + indexflag=ESMF_INDEX_GLOBAL, & + rc=rc) + + endif + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN GridCreate1PeriDim", rc) @@ -694,22 +780,15 @@ subroutine define_input_grid_gfs_grib2(localpet, npets) name="input_grid_longitude", rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) - - allocate(longitude(i_input,j_input)) + allocate(latitude(i_input,j_input)) - - do i = 1, i_input - longitude(i,:) = real(lon4(i,:),kind=esmf_kind_r8) - enddo + allocate(longitude(i_input,j_input)) - do i = 1, j_input - latitude(:,i) = real(lat4(:,i),kind=esmf_kind_r8) - enddo + latitude = rlat + longitude = rlon - deallocate(lat4, lon4) + deallocate (rlat, rlon) - deltalon = abs(longitude(2,1)-longitude(1,1)) - print*,"- CALL FieldScatter FOR INPUT GRID LONGITUDE." call ESMF_FieldScatter(longitude_input_grid, longitude, rootpet=0, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & @@ -754,6 +833,16 @@ subroutine define_input_grid_gfs_grib2(localpet, npets) enddo enddo + deallocate(latitude, longitude) + + allocate(latitude_corner(ip1_input,jp1_input)) + allocate(longitude_corner(ip1_input,jp1_input)) + + latitude_corner = rlat_corner + longitude_corner = rlon_corner + + deallocate (rlat_corner, rlon_corner) + print*,"- CALL GridAddCoord FOR INPUT GRID." call ESMF_GridAddCoord(input_grid, & staggerloc=ESMF_STAGGERLOC_CORNER, rc=rc) @@ -782,323 +871,16 @@ subroutine define_input_grid_gfs_grib2(localpet, npets) do j = clb(2), cub(2) do i = clb(1), cub(1) - lon_corner_src_ptr(i,j) = longitude(i,1) - (0.5_esmf_kind_r8*deltalon) + lon_corner_src_ptr(i,j) = longitude_corner(i,j) if (lon_corner_src_ptr(i,j) > 360.0_esmf_kind_r8) lon_corner_src_ptr(i,j) = lon_corner_src_ptr(i,j) - 360.0_esmf_kind_r8 - if (j == 1) then - lat_corner_src_ptr(i,j) = -90.0_esmf_kind_r8 - cycle - endif - if (j == jp1_input) then - lat_corner_src_ptr(i,j) = +90.0_esmf_kind_r8 - cycle - endif - lat_corner_src_ptr(i,j) = 0.5_esmf_kind_r8 * (latitude(i,j-1)+ latitude(i,j)) + lat_corner_src_ptr(i,j) = latitude_corner(i,j) enddo enddo - deallocate(latitude,longitude) - - end subroutine define_input_grid_gfs_grib2 - -!> Define input grid object for non-GFS grib2 data. -!! -!! @param [in] localpet ESMF local persistent execution thread -!! @param [in] npets Number of persistent execution threads -!! @author Larissa Reames -!! @author Jeff Beck - subroutine define_input_grid_grib2(localpet, npets) - - use mpi - use netcdf - use wgrib2api - use program_setup, only : grib2_file_input_grid, data_dir_input_grid, & - fix_dir_input_grid - implicit none - - character(len=500) :: the_file, temp_file - - integer, intent(in) :: localpet, npets - - integer :: error, extra, i, j, clb(2), cub(2) - - real(esmf_kind_r4), allocatable :: latitude_one_tile(:,:), lat_corners(:,:) - real(esmf_kind_r4), allocatable :: longitude_one_tile(:,:), lon_corners(:,:) - real(esmf_kind_r8) :: lat_target(i_target,j_target), & - lon_target(i_target,j_target) - real(esmf_kind_r8) :: deltalon, dx - integer :: ncid,id_var, id_dim - real(esmf_kind_r8), pointer :: lat_src_ptr(:,:), lon_src_ptr(:,:) - character(len=10000) :: temp_msg - character(len=10) :: temp_num = 'NA' - - num_tiles_input_grid = 1 - - !inv_file = "chgres.inv" - the_file = trim(data_dir_input_grid) // "/" // grib2_file_input_grid - temp_file = trim(fix_dir_input_grid)//"/latlon_grid3.32769.nc" - - call ESMF_FieldGather(latitude_target_grid, lat_target, rootPet=0, tile=1, rc=error) - if(ESMF_logFoundError(rcToCheck=error,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", error) - call ESMF_FieldGather(longitude_target_grid, lon_target, rootPet=0, tile=1, rc=error) - if(ESMF_logFoundError(rcToCheck=error,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", error) - - if (localpet==0) then - print*,'- OPEN AND INVENTORY GRIB2 FILE: ',trim(the_file) - error=grb2_mk_inv(the_file,inv_file) - if (error /=0) call error_handler("OPENING GRIB2 FILE",error) - error = grb2_inq(the_file, inv_file,grid_desc=temp_msg) - i = index(temp_msg, "grid_template=") + len("grid_template=") - j = index(temp_msg,":winds(") - temp_num=temp_msg(i:j-1) - endif - call MPI_BARRIER(MPI_COMM_WORLD, error) - call MPI_BCAST(temp_num,10,MPI_CHAR,0,MPI_COMM_WORLD,error) - - ! Wgrib2 can't properly read the lat/lon arrays of data on NCEP rotated lat/lon - ! grids, so read in lat/lon from fixed coordinate file - if (trim(temp_num)=="3.32769" .or. trim(temp_num)=="32769") then - - input_grid_type = "rotated_latlon" - - error=nf90_open(trim(temp_file),nf90_nowrite,ncid) - call netcdf_err(error, 'opening: '//trim(temp_file)) - - error=nf90_inq_dimid(ncid, 'nx', id_dim) - call netcdf_err(error, 'reading nx id' ) - error=nf90_inquire_dimension(ncid,id_dim,len=i_input) - call netcdf_err(error, 'reading nx value' ) - - error=nf90_inq_dimid(ncid, 'ny', id_dim) - call netcdf_err(error, 'reading ny id' ) - error=nf90_inquire_dimension(ncid,id_dim,len=j_input) - call netcdf_err(error, 'reading ny value' ) - - allocate(longitude_one_tile(i_input,j_input)) - allocate(latitude_one_tile(i_input,j_input)) - - error=nf90_inq_varid(ncid, 'gridlat', id_var) - call netcdf_err(error, 'reading field id' ) - error=nf90_get_var(ncid, id_var, latitude_one_tile) - call netcdf_err(error, 'reading field' ) - - error=nf90_inq_varid(ncid, 'gridlon', id_var) - call netcdf_err(error, 'reading field id' ) - error=nf90_get_var(ncid, id_var, longitude_one_tile) - call netcdf_err(error, 'reading field' ) - - elseif (temp_num == "3.0" .or. temp_num == "3.30" .or. temp_num=="30" .or. temp_num == "0") then - - if (temp_num =="3.0" .or. temp_num == "0") input_grid_type = "latlon" - if (temp_num =="3.30" .or. temp_num=='30') input_grid_type = "lambert" - - error = grb2_inq(the_file,inv_file,':PRES:',':surface:',nx=i_input, ny=j_input, & - lat=latitude_one_tile, lon=longitude_one_tile) - if (error /= 1) call error_handler("READING FILE", error) - - - if (localpet==0) print*, "from file lon(1:10,1) = ", longitude_one_tile(1:10,1) - if (localpet==0) print*, "from file lat(1,1:10) = ", latitude_one_tile(1,1:10) - elseif (temp_num=="NA") then - error = 0 - call error_handler("Grid template number cannot be read from the input file. Please " //& - "check that the wgrib2 executable is in your path.", error) - else - error = 0 - call error_handler("Unknown input file grid template number. Must be one of: " //& - "3, 3.30, 3.32769", error) - endif - - print*,"- I/J DIMENSIONS OF THE INPUT GRID TILES ", i_input, j_input - - ip1_input = i_input + 1 - jp1_input = j_input + 1 - -!----------------------------------------------------------------------- -! Create ESMF grid object for the model grid. -!----------------------------------------------------------------------- - - extra = npets / num_tiles_input_grid - - print*,"- CALL GridCreateNoPeriDim FOR INPUT MODEL GRID" - input_grid = ESMF_GridCreateNoPeriDim(maxIndex=(/i_input,j_input/), & - indexflag=ESMF_INDEX_GLOBAL, & - rc=error) - if(ESMF_logFoundError(rcToCheck=error,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN GridCreateNoPeriDim", error) - - -!----------------------------------------------------------------------- -! Read the mask and lat/lons. -!----------------------------------------------------------------------- - - print*,"- CALL FieldCreate FOR INPUT GRID LATITUDE." - latitude_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, & - name="input_grid_latitude", & - rc=error) - if(ESMF_logFoundError(rcToCheck=error,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", error) - - print*,"- CALL FieldCreate FOR INPUT GRID LONGITUDE." - longitude_input_grid = ESMF_FieldCreate(input_grid, & - typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, & - name="input_grid_longitude", & - rc=error) - if(ESMF_logFoundError(rcToCheck=error,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldCreate", error) - - print*,"- CALL FieldScatter FOR INPUT GRID LATITUDE. " - call ESMF_FieldScatter(latitude_input_grid, real(latitude_one_tile,esmf_kind_r8), rootpet=0, rc=error) - if(ESMF_logFoundError(rcToCheck=error,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", error) - -print*,"- CALL FieldScatter FOR INPUT GRID LONGITUDE." - call ESMF_FieldScatter(longitude_input_grid, real(longitude_one_tile,esmf_kind_r8), rootpet=0, rc=error) - if(ESMF_logFoundError(rcToCheck=error,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", error) - - - print*,"- CALL GridAddCoord FOR INPUT GRID." - call ESMF_GridAddCoord(input_grid, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=error) - if(ESMF_logFoundError(rcToCheck=error,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN GridAddCoord", error) - - - print*,"- CALL GridGetCoord FOR INPUT GRID X-COORD." - nullify(lon_src_ptr) - call ESMF_GridGetCoord(input_grid, & - staggerLoc=ESMF_STAGGERLOC_CENTER, & - coordDim=1, & - farrayPtr=lon_src_ptr, rc=error) - if(ESMF_logFoundError(rcToCheck=error,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN GridGetCoord", error) - - print*,"- CALL GridGetCoord FOR INPUT GRID Y-COORD." - nullify(lat_src_ptr) - call ESMF_GridGetCoord(input_grid, & - staggerLoc=ESMF_STAGGERLOC_CENTER, & - coordDim=2, & - computationalLBound=clb, & - computationalUBound=cub, & - farrayPtr=lat_src_ptr, rc=error) - if(ESMF_logFoundError(rcToCheck=error,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN GridGetCoord", error) - - do j = clb(2),cub(2) - do i = clb(1), cub(1) - lon_src_ptr(i,j)=real(longitude_one_tile(i,j),esmf_kind_r8) - lat_src_ptr(i,j)=real(latitude_one_tile(i,j),esmf_kind_r8) - enddo - enddo - - print*,"- CALL GridAddCoord FOR INPUT GRID." - call ESMF_GridAddCoord(input_grid, & - staggerloc=ESMF_STAGGERLOC_CORNER, rc=error) - if(ESMF_logFoundError(rcToCheck=error,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN GridAddCoord", error) - - print*,"- CALL GridGetCoord FOR INPUT GRID X-COORD." - nullify(lon_src_ptr) - call ESMF_GridGetCoord(input_grid, & - staggerLoc=ESMF_STAGGERLOC_CORNER, & - coordDim=1, & - farrayPtr=lon_src_ptr, rc=error) - if(ESMF_logFoundError(rcToCheck=error,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN GridGetCoord", error) - - print*,"- CALL GridGetCoord FOR INPUT GRID Y-COORD." - nullify(lat_src_ptr) - call ESMF_GridGetCoord(input_grid, & - staggerLoc=ESMF_STAGGERLOC_CORNER, & - coordDim=2, & - computationalLBound=clb, & - computationalUBound=cub, & - farrayPtr=lat_src_ptr, rc=error) - if(ESMF_logFoundError(rcToCheck=error,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN GridGetCoord", error) - - - ! If we have data on a lat/lon or lambert grid, create staggered coordinates - if(trim(input_grid_type)=="latlon" .or. trim(input_grid_type) == "lambert") then - if (trim(input_grid_type) == "latlon") then - - deltalon = abs(longitude_one_tile(2,1)-longitude_one_tile(1,1)) - do j = clb(2), cub(2) - do i = clb(1), cub(1) - - if (i == ip1_input) then - lon_src_ptr(i,j) = longitude_one_tile(i_input,1) + (0.5_esmf_kind_r8*deltalon) - else - lon_src_ptr(i,j) = longitude_one_tile(i,1) - (0.5_esmf_kind_r8*deltalon) - endif - - if (j == jp1_input) then - lat_src_ptr(i,j) = latitude_one_tile(1,j_input) + (0.5_esmf_kind_r8*deltalon) - else - lat_src_ptr(i,j) = latitude_one_tile(1,j) - (0.5_esmf_kind_r8*deltalon) - endif - - enddo - enddo - else - if (localpet==0) then - !cmdline_msg = "wgrib2 "//trim(the_file)//" -d 1 -grid &> temp2.out" - !call system(cmdline_msg) - !open(4,file="temp2.out") - !do i = 1,6 - ! read(4,"(A)") temp_msg2 - !enddo - !close(4) - print*, trim(temp_msg) - i = index(temp_msg, "Dx ") + len("Dx ") - j = index(temp_msg," m Dy") - read(temp_msg(i:j-1),"(F9.6)") dx - endif - call MPI_BARRIER(MPI_COMM_WORLD,error) - call MPI_BCAST(dx,1,MPI_REAL8,0,MPI_COMM_WORLD,error) - - call get_cell_corners(real(latitude_one_tile,esmf_kind_r8), & - real(longitude_one_tile, esmf_kind_r8), & - lat_src_ptr, lon_src_ptr, dx, clb, cub) - endif - elseif (trim(input_grid_type) == "rotated_latlon") then !Read the corner coords from file - - allocate(lon_corners(ip1_input,jp1_input)) - allocate(lat_corners(ip1_input,jp1_input)) - - error=nf90_inq_varid(ncid, 'gridlon_corners', id_var) - call netcdf_err(error, 'reading field id' ) - error=nf90_get_var(ncid, id_var, lon_corners) - call netcdf_err(error, 'reading field' ) - - error=nf90_inq_varid(ncid, 'gridlat_corners', id_var) - call netcdf_err(error, 'reading field id' ) - error=nf90_get_var(ncid, id_var, lat_corners) - call netcdf_err(error, 'reading field' ) - - do j = clb(2),cub(2) - do i = clb(1), cub(1) - lon_src_ptr(i,j)=real(lon_corners(i,j),esmf_kind_r8) - lat_src_ptr(i,j)=real(lat_corners(i,j),esmf_kind_r8) - enddo - enddo - - error= nf90_close(ncid) - endif - - nullify(lon_src_ptr) - nullify(lat_src_ptr) - - deallocate(longitude_one_tile) - deallocate(latitude_one_tile) + deallocate(latitude_corner, longitude_corner) end subroutine define_input_grid_grib2 - + !> Setup the esmf grid object for the target grid. !! !! @param [in] localpet ESMF local persistent execution thread @@ -1456,7 +1238,7 @@ subroutine get_model_latlons(mosaic_file, orog_dir, num_tiles, tile, & real(esmf_kind_r8), optional, intent(out) :: latitude_corner(ip1_tile, jp1_tile) real(esmf_kind_r8), optional, intent(out) :: longitude_corner(ip1_tile, jp1_tile) - character(len=25) :: grid_files(num_tiles) + character(len=50) :: grid_files(num_tiles) character(len=255) :: grid_file integer :: error, id_var, ncid @@ -1596,91 +1378,6 @@ subroutine get_model_latlons(mosaic_file, orog_dir, num_tiles, tile, & end subroutine get_model_latlons -!> For grids with equal cell sizes (e.g., lambert conformal), get -!! latitude and longitude of the grid cell corners. -!! -!! @param [in] latitude grid box center latitude -!! @param [in] longitude grid box center longitude -!! @param [inout] latitude_sw latitude of the 'southwest' corner of grid box -!! @param [inout] longitude_sw longitude of the 'southwest' corner of grid box -!! @param [in] dx grid cell side size in meters -!! @param [in] clb lower bounds of indices processed by this mpi task -!! @param [in] cub upper bounds of indices processed by this mpi task -!! @author Larissa Reames -!! @author Jeff Beck - subroutine get_cell_corners( latitude, longitude, latitude_sw, longitude_sw, dx,clb,cub) - implicit none - - real(esmf_kind_r8), intent(in) :: latitude(i_input,j_input) - real(esmf_kind_r8), intent(inout), pointer :: latitude_sw(:,:) - real(esmf_kind_r8), intent(in) :: longitude(i_input, j_input) - real(esmf_kind_r8), intent(inout), pointer :: longitude_sw(:,:) - real(esmf_kind_r8), intent(in) :: dx - - integer, intent(in) :: clb(2), cub(2) - - real(esmf_kind_r8) :: lat1, lon1, lat2, lon2, d, brng - - - real(esmf_kind_r8), parameter :: pi = 3.14159265359 - real(esmf_kind_r8), parameter :: R = 6371200.0 - real(esmf_kind_r8), parameter :: bearingInDegrees = 135.0 - - integer :: i, j - - d = sqrt((dx**2.0_esmf_kind_r8)/2.0_esmf_kind_r8) - - do j = clb(2),cub(2) - do i = clb(1), cub(1) - - if (j == jp1_input .and. i == ip1_input) then - lat1 = latitude(i_input,j_input) * ( pi / 180.0_esmf_kind_r8 ) - lon1 = longitude(i_input,j_input) * ( pi / 180.0_esmf_kind_r8 ) - brng = 315.0_esmf_kind_r8 * pi / 180.0_esmf_kind_r8 - lat2 = asin( sin( lat1 ) * cos( d / R ) + cos( lat1 ) * sin( d / R ) * cos( brng ) ); - lon2= lon1 + atan2( sin( brng ) * sin( d / R ) * cos( lat1 ), cos( d / R ) - sin( lat1 ) * sin( lat2 ) ); - latitude_sw(ip1_input,jp1_input) = lat2 * 180.0_esmf_kind_r8 / pi - longitude_sw(ip1_input,jp1_input) = lon2 * 180.0_esmf_kind_r8 / pi - cycle - endif - - if (i == ip1_input) then - brng = 225.0_esmf_kind_r8 * pi / 180.0_esmf_kind_r8 - lat1 = latitude(i_input,j) * ( pi / 180.0_esmf_kind_r8 ) - lon1 = longitude(i_input,j) * ( pi / 180.0_esmf_kind_r8 ) - lat2 = asin( sin( lat1 ) * cos( d / R ) + cos( lat1 ) * sin( d / R ) * cos( brng ) ); - lon2= lon1 + atan2( sin( brng ) * sin( d / R ) * cos( lat1 ), cos( d / R ) - sin( lat1 ) * sin( lat2 ) ); - latitude_sw(ip1_input,j) = lat2 * 180.0_esmf_kind_r8 / pi - longitude_sw(ip1_input,j) = lon2 * 180.0_esmf_kind_r8 / pi - cycle - endif - - if (j == jp1_input) then - brng = 45.0_esmf_kind_r8 * pi / 180.0_esmf_kind_r8 - lat1 = latitude(i,j_input) * ( pi / 180.0_esmf_kind_r8 ) - lon1 = longitude(i,j_input) * ( pi / 180.0_esmf_kind_r8 ) - lat2 = asin( sin( lat1 ) * cos( d / R ) + cos( lat1 ) * sin( d / R ) * cos( brng ) ); - lon2= lon1 + atan2( sin( brng ) * sin( d / R ) * cos( lat1 ), cos( d / R ) - sin( lat1 ) * sin( lat2 ) ); - latitude_sw(i,jp1_input) = lat2 * 180.0_esmf_kind_r8 / pi - longitude_sw(i,jp1_input) = lon2 * 180.0_esmf_kind_r8 / pi - cycle - endif - - lat1 = latitude(i,j) * ( pi / 180.0_esmf_kind_r8 ) - lon1 = longitude(i,j) * ( pi / 180.0_esmf_kind_r8 ) - - brng = bearingInDegrees * ( pi / 180.0_esmf_kind_r8 ); - lat2 = asin( sin( lat1 ) * cos( d / R ) + cos( lat1 ) * sin( d / R ) * cos( brng ) ); - lon2= lon1 + atan2( sin( brng ) * sin( d / R ) * cos( lat1 ), cos( d / R ) - sin( lat1 ) * sin( lat2 ) ); - - latitude_sw(i,j) = lat2 * 180.0_esmf_kind_r8 / pi - longitude_sw(i,j) = lon2 * 180.0_esmf_kind_r8 / pi - - enddo - enddo - - end subroutine get_cell_corners - !> Read the model land mask and terrain for a single tile !! from the orography file. !! @@ -1802,4 +1499,143 @@ subroutine cleanup_input_target_grid_data end subroutine cleanup_input_target_grid_data +!> Convert the GRIB2 grid description template to +!! to the GRIB1 grid description section. +!! +!! @param [in] igdtnum GRIB2 grid description template number. +!! @param [in] igdstmpl Length of grib2 grid description template. +!! @param [in] igdtlen Array of GRIB2 grid description template octets. +!! @param [out] kgds Array of GRIB1 grid description octets. +!! @param [out] ni I-dimension of grid. +!! @param [out] nj J-dimension of grid. +!! @param [out] res Resolution of grid in km. +!! @author George Gayno NCEP/EMC + subroutine gdt_to_gds(igdtnum, igdstmpl, igdtlen, kgds, ni, nj, res) + + implicit none + + integer, intent(in ) :: igdtnum, igdtlen, igdstmpl(igdtlen) + integer, intent( out) :: kgds(200), ni, nj + integer :: iscale + + real, intent( out) :: res + + kgds=0 + + if (igdtnum.eq.32769) then ! rot lat/lon b grid + + iscale=igdstmpl(10)*igdstmpl(11) + if (iscale == 0) iscale = 1e6 + kgds(1)=205 ! oct 6, rotated lat/lon for Non-E + ! Stagger grid + kgds(2)=igdstmpl(8) ! octs 7-8, Ni + ni = kgds(2) + kgds(3)=igdstmpl(9) ! octs 9-10, Nj + nj = kgds(3) + kgds(4)=nint(float(igdstmpl(12))/float(iscale)*1000.) ! octs 11-13, Lat of + ! 1st grid point + kgds(5)=nint(float(igdstmpl(13))/float(iscale)*1000.) ! octs 14-16, Lon of + ! 1st grid point + + kgds(6)=0 ! oct 17, resolution and component flags + if (igdstmpl(1)==2 ) kgds(6)=64 + if ( btest(igdstmpl(14),4).OR.btest(igdstmpl(14),5) ) kgds(6)=kgds(6)+128 + if ( btest(igdstmpl(14),3) ) kgds(6)=kgds(6)+8 + + kgds(7)=nint(float(igdstmpl(15))/float(iscale)*1000.) ! octs 18-20, + ! Lat of cent of rotation + kgds(8)=nint(float(igdstmpl(16))/float(iscale)*1000.) ! octs 21-23, + ! Lon of cent of rotation + kgds(9)=nint(float(igdstmpl(17))/float(iscale)*1000.) ! octs 24-25, + ! Di + kgds(10)=nint(float(igdstmpl(18))/float(iscale)*1000.) ! octs 26-27, + ! Dj + + kgds(11) = 0 ! oct 28, scan mode + if (btest(igdstmpl(19),7)) kgds(11) = 128 + if (btest(igdstmpl(19),6)) kgds(11) = kgds(11) + 64 + if (btest(igdstmpl(19),5)) kgds(11) = kgds(11) + 32 + + kgds(12)=nint(float(igdstmpl(20))/float(iscale)*1000.) ! octs 29-31, Lat of + ! last grid point + kgds(13)=nint(float(igdstmpl(21))/float(iscale)*1000.) ! octs 32-34, Lon of + ! last grid point + + kgds(19)=0 ! oct 4, # vert coordinate parameters + kgds(20)=255 ! oct 5, used for thinned grids, set to 255 + + res = ((float(kgds(9)) / 1000.0) + (float(kgds(10)) / 1000.0)) & + * 0.5 * 111.0 + + elseif(igdtnum==30) then + + kgds(1)=3 ! oct 6, lambert conformal + kgds(2)=igdstmpl(8) ! octs 7-8, Ni + ni = kgds(2) + kgds(3)=igdstmpl(9) ! octs 9-10, Nj + nj = kgds(3) + + iscale = 1e6 + kgds(4) = nint(float(igdstmpl(10))/1000.0) + kgds(5) = nint(float(igdstmpl(11))/1000.0) + + kgds(6)=0 ! oct 17, resolution and component flags + if (igdstmpl(1)==2 ) kgds(6)=64 + if ( btest(igdstmpl(12),4).OR.btest(igdstmpl(12),5) ) kgds(6)=kgds(6)+128 + if ( btest(igdstmpl(12),3) ) kgds(6)=kgds(6)+8 + + kgds(7) = nint(float(igdstmpl(14))/1000.0) + kgds(8) = nint(float(igdstmpl(15))/1000.0) + kgds(9) = nint(float(igdstmpl(16))/1000.0) + kgds(10) = 0 + + kgds(11) = 0 ! oct 28, scan mode + if (btest(igdstmpl(18),7)) kgds(11) = 128 + if (btest(igdstmpl(18),6)) kgds(11) = kgds(11) + 64 + if (btest(igdstmpl(18),5)) kgds(11) = kgds(11) + 32 + + kgds(12) = nint(float(igdstmpl(19))/1000.0) + kgds(13) = nint(float(igdstmpl(20))/1000.0) + kgds(14) = -90 + kgds(15) = 0 + + elseif(igdtnum==0) then ! lat/lon grid + + iscale=igdstmpl(10)*igdstmpl(11) + if (iscale == 0) iscale = 1e6 + kgds(1)=0 ! oct 6, data representation type. + kgds(2)=igdstmpl(8) ! octs 7-8, Ni + ni = kgds(2) + kgds(3)=igdstmpl(9) ! octs 9-10, Nj + nj = kgds(3) + kgds(4)=nint(float(igdstmpl(12))/float(iscale)*1000.) ! octs 11-13, Lat of 1st grid point + kgds(5)=nint(float(igdstmpl(13))/float(iscale)*1000.) ! octs 14-16, Lon of 1st grid point + + kgds(6)=0 ! oct 17, resolution and component flags + if (igdstmpl(1)==2 ) kgds(6)=64 + if ( btest(igdstmpl(14),4).OR.btest(igdstmpl(14),5) ) kgds(6)=kgds(6)+128 + if ( btest(igdstmpl(14),3) ) kgds(6)=kgds(6)+8 + + kgds(7)=nint(float(igdstmpl(15))/float(iscale)*1000.) ! octs 18-20, Lat of last grid point + kgds(8)=nint(float(igdstmpl(16))/float(iscale)*1000.) ! octs 21-23, Lon of last grid point + kgds(9)=nint(float(igdstmpl(17))/float(iscale)*1000.) ! octs 24-25, "i" resolution. + kgds(10)=nint(float(igdstmpl(18))/float(iscale)*1000.) ! octs 26-27, "j" resolution. + + kgds(11) = 0 ! oct 28, scan mode + if (btest(igdstmpl(19),7)) kgds(11) = 128 + if (btest(igdstmpl(19),6)) kgds(11) = kgds(11) + 64 + if (btest(igdstmpl(19),5)) kgds(11) = kgds(11) + 32 + + kgds(12)=0 ! octs 29-32, reserved + kgds(19)=0 ! oct 4, # vert coordinate parameters + kgds(20)=255 ! oct 5, used for thinned grids, set to 255 + + else + + call error_handler("UNRECOGNIZED INPUT GRID TYPE ", 1) + + endif + + end subroutine gdt_to_gds + end module model_grid diff --git a/sorc/chgres_cube.fd/msis2.1.fd/CMakeLists.txt b/sorc/chgres_cube.fd/msis2.1.fd/CMakeLists.txt new file mode 100644 index 000000000..1eb2dc7be --- /dev/null +++ b/sorc/chgres_cube.fd/msis2.1.fd/CMakeLists.txt @@ -0,0 +1,26 @@ +include(FetchContent) +include(CheckFortranCompilerFlag) + +add_library(msis2 + msis_utils.F90 + msis_constants.F90 + msis_init.F90 + msis_gfn.F90 + msis_tfn.F90 + msis_dfn.F90 + msis_calc.F90 + msis_gtd8d.F90) + +set_target_properties(msis2 PROPERTIES Fortran_MODULE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/include) + +target_include_directories(msis2 INTERFACE ${CMAKE_CURRENT_BINARY_DIR}/include) + +if(CMAKE_Fortran_COMPILER_ID STREQUAL GNU) + # msis_calc:bspline has argument mismatch on nodes variable + target_compile_options(msis2 PRIVATE -std=legacy) +endif() + +target_link_libraries( + msis2 + PUBLIC + MPI::MPI_Fortran) diff --git a/sorc/chgres_cube.fd/msis2.1.fd/msis_calc.F90 b/sorc/chgres_cube.fd/msis2.1.fd/msis_calc.F90 new file mode 100644 index 000000000..61a63226e --- /dev/null +++ b/sorc/chgres_cube.fd/msis2.1.fd/msis_calc.F90 @@ -0,0 +1,223 @@ +!####################################################################### +! MSIS� (NRL-SOF-014-1) SOFTWARE +! NRLMSIS� empirical atmospheric model software. Use is governed by the +! Open Source Academic Research License Agreement contained in the file +! nrlmsis2.1_license.txt, which is part of this software package. BY +! USING OR MODIFYING THIS SOFTWARE, YOU ARE AGREEING TO THE TERMS AND +! CONDITIONS OF THE LICENSE. +!####################################################################### + +!!! =========================================================================== +!!! NRLMSIS 2.1: +!!! Neutral atmosphere empirical model from the surface to lower exosphere +!!! =========================================================================== +!!! +!!! MSISCALC: Interface with re-ordered input arguments and output arrays. +! +! PREREQUISITES: +! Must first run MSISINIT to load parameters and set switches. The +! MSISCALC subroutine checks for initialization and does a default +! initialization if necessary. This self-initialization will be removed +! in future versions. +! +! CALLING SEQUENCE: +! CALL MSISCALC(DAY, UTSEC, Z, LAT, LON, SFLUXAVG, SFLUX, AP, TN, DN, [TEX]) +! +! INPUT VARIABLES: +! DAY Day of year (1.0 to 365.0 or 366.0) +! UTSEC Universal time (seconds) +! Z Geodetic altitude (km) (default) or Geopotential height (km) +! LAT Geodetic latitude (deg) +! LON Geodetic longitude (deg) +! SFLUXAVG 81 day average, centered on input time, of F10.7 solar +! activity index +! SFLUX Daily F10.7 for previous day +! AP Geomagnetic activity index array: +! (1) Daily Ap +! (2) 3 hr ap index for current time +! (3) 3 hr ap index for 3 hrs before current time +! (4) 3 hr ap index for 6 hrs before current time +! (5) 3 hr ap index for 9 hrs before current time +! (6) Average of eight 3 hr ap indices from 12 to 33 hrs +! prior to current time +! (7) Average of eight 3 hr ap indices from 36 to 57 hrs +! prior to current time +! AP(2:7) are only used when switch_legacy(9) = -1.0 in MSISINIT +! +! NOTES ON INPUT VARIABLES: +! - The day-of-year dependence of the model only uses the DAY argument. If +! a continuous day-of-year dependence is desired, this argument should +! include the fractional day (e.g., DAY = + UTSEC/86400.0 +! - If lzalt_type = .true. (default) in the MSISINIT call, then Z is +! treated as geodetic altitude. +! If lzalt_type = .false., then Z is treated as geopotential height. +! - F107 and F107A values are the 10.7 cm radio flux at the Sun-Earth +! distance, not the radio flux at 1 AU. +! +! OUTPUT VARIABLES: +! TN Temperature at altitude (K) +! DN(1) Total mass density (kg/m3) +! DN(2) N2 number density (m-3) +! DN(3) O2 number density (m-3) +! DN(4) O number density (m-3) +! DN(5) He number density (m-3) +! DN(6) H number density (m-3) +! DN(7) Ar number density (m-3) +! DN(8) N number density (m-3) +! DN(9) Anomalous oxygen number density (m-3) +! DN(10) NO number density (m-3) +! TEX Exospheric temperature (K) (optional argument) +! +! NOTES ON OUTPUT VARIABLES: +! - Missing density values are returned as 9.999e-38 +! - Species included in mass density calculation are set in MSISINIT +! +!!! ========================================================================= + +!************************************************************************************************** +! MSIS_CALC Module: Contains main MSIS entry point +!************************************************************************************************** +module msis_calc + +contains + + !================================================================================================== + ! MSISCALC: The main MSIS subroutine entry point + !================================================================================================== + subroutine msiscalc(day,utsec,z,lat,lon,sfluxavg,sflux,ap,tn,dn,tex) + + use msis_constants, only : rp, dmissing, lnp0, Mbarg0divkB, kB, nspec, nodesTN, nd, zetaF, zetaB, & + Hgamma, zetagamma, maxnbf + use msis_init, only : msisinit, initflag, zaltflag, specflag, massflag, masswgt, etaTN + use msis_gfn, only : globe + use msis_tfn, only : tnparm, tfnparm, tfnx + use msis_dfn, only : dnparm, dfnparm, dfnx + use msis_utils, only : alt2gph, bspline, dilog + + implicit none + + real(kind=rp), intent(in) :: day + real(kind=rp), intent(in) :: utsec + real(kind=rp), intent(in) :: z + real(kind=rp), intent(in) :: lat + real(kind=rp), intent(in) :: lon + real(kind=rp), intent(in) :: sfluxavg,sflux,ap(1:7) + real(kind=rp), intent(out) :: tn, dn(1:10) + real(kind=rp), intent(out), optional :: tex + + real(kind=rp), save :: lastday = -9999.0 + real(kind=rp), save :: lastutsec = -9999.0 + real(kind=rp), save :: lastlat = -9999.0 + real(kind=rp), save :: lastlon = -9999.0 + real(kind=rp), save :: lastz = -9999.0 + real(kind=rp), save :: lastsflux = -9999.0 + real(kind=rp), save :: lastsfluxavg = -9999.0 + real(kind=rp), save :: lastap(1:7) = -9999.0 + real(kind=rp), save :: gf(0:maxnbf-1) + real(kind=rp), save :: Sz(-5:0,2:6) + integer, save :: iz + type(tnparm), save :: tpro + type(dnparm), save :: dpro(1:nspec-1) + + real(8) :: zaltd, latd + real(kind=rp) :: zeta, lndtotz, Vz, Wz, HRfact, lnPz, delz + integer :: i, j, kmax, ispec + + ! Check if model has been initialized; if not, perform default initialization + if (.not. initflag) call msisinit() + + ! Calculate geopotential height, if necessary + if(zaltflag) then + zaltd = dble(z) + latd = dble(lat) + zeta = alt2gph(latd,zaltd) + else + zeta = z + endif + + ! If only altitude changes then update the local spline weights + if (zeta .lt. zetaB) then + if (zeta .ne. lastz) then + if (zeta .lt. zetaF) then + kmax = 5 + else + kmax = 6 + endif + call bspline(zeta,nodesTN,nd+2,kmax,etaTN,Sz,iz) + lastz = zeta + endif + endif + + ! If location, time, or solar/geomagnetic conditions change then recompute the profile parameters + if ((day .ne. lastday) .or. (utsec .ne. lastutsec) .or. & + (lat .ne. lastlat) .or. (lon .ne. lastlon) .or. & + (sflux .ne. lastsflux) .or. (sfluxavg .ne. lastsfluxavg) .or. & + any(ap .ne. lastap)) then + call globe(day,utsec,lat,lon,sfluxavg,sflux,ap,gf) + call tfnparm(gf,tpro) + do ispec = 2, nspec-1 + if (specflag(ispec)) call dfnparm(ispec,gf,tpro,dpro(ispec)) + enddo + lastday = day + lastutsec = utsec + lastlat = lat + lastlon = lon + lastsflux = sflux + lastsfluxavg = sfluxavg + lastap = ap + endif + + ! Exospheric temperature + if (present(tex)) then + tex = tpro%tex + endif + + ! Temperature at altitude + tn = tfnx(zeta,iz,Sz(-3:0,4),tpro) + + ! Temperature integration terms at altitude, total number density + delz = zeta - zetaB + if (zeta .lt. zetaF) then + i = max(iz-4,0) + if (iz .lt. 4) then + j = -iz + else + j = -4 + endif + Vz = dot_product(tpro%beta(i:iz),Sz(j:0,5)) + tpro%cVS + Wz = 0.0_rp + lnPz = lnP0 - Mbarg0divkB*(Vz - tpro%Vzeta0) + lndtotz = lnPz - log(kB*tn) + else + if (zeta .lt. zetaB) then + Vz = dot_product(tpro%beta(iz-4:iz),Sz(-4:0,5)) + tpro%cVS + Wz = dot_product(tpro%gamma(iz-5:iz),Sz(-5:0,6)) + tpro%cVS*delz + tpro%cWS + else + Vz = (delz + log(tn/tpro%tex)/tpro%sigma)/tpro%tex + tpro%cVB + Wz = (0.5_rp*delz*delz + dilog(tpro%b*exp(-tpro%sigma*delz))/tpro%sigmasq)/tpro%tex & + + tpro%cVB*delz + tpro%cWB + endif + endif + + ! Species number densities at altitude + HRfact = 0.5_rp * (1.0_rp + tanh(Hgamma*(zeta - zetagamma))) !Reduction factor for chemical/dynamical correction scale height below zetagamma + do ispec = 2, nspec-1 + if (specflag(ispec)) then + dn(ispec) = dfnx(zeta,tn,lndtotz,Vz,Wz,HRfact,tpro,dpro(ispec)) + else + dn(ispec) = dmissing + endif + enddo + + ! Mass density + if (specflag(1)) then + dn(1) = dot_product(dn,masswgt) + else + dn(1) = dmissing + endif + + return + + end subroutine msiscalc + +end module msis_calc diff --git a/sorc/chgres_cube.fd/msis2.1.fd/msis_constants.F90 b/sorc/chgres_cube.fd/msis2.1.fd/msis_constants.F90 new file mode 100644 index 000000000..29c5355a5 --- /dev/null +++ b/sorc/chgres_cube.fd/msis2.1.fd/msis_constants.F90 @@ -0,0 +1,196 @@ +!####################################################################### +! MSIS� (NRL-SOF-014-1) SOFTWARE +! NRLMSIS� empirical atmospheric model software. Use is governed by the +! Open Source Academic Research License Agreement contained in the file +! nrlmsis2.1_license.txt, which is part of this software package. BY +! USING OR MODIFYING THIS SOFTWARE, YOU ARE AGREEING TO THE TERMS AND +! CONDITIONS OF THE LICENSE. +!####################################################################### + +!!! =========================================================================== +!!! NRLMSIS 2.1: +!!! Neutral atmosphere empirical model from the surface to lower exosphere +!!! =========================================================================== + +!************************************************************************************************** +! MSIS_CONSTANTS Module: Contains constants and hardwired parameters +!************************************************************************************************** +module msis_constants + + implicit none + + ! Floating Point Precision +#ifdef DBLE + integer, parameter :: rp = 8 +#else + integer, parameter :: rp = 4 +#endif + + ! Missing density value + real(kind=rp),parameter :: dmissing = 9.999e-38_rp + + ! Trigonometric constants + real(kind=rp), parameter :: pi = 3.1415926535897932384626433832795_rp + real(kind=rp), parameter :: deg2rad = pi / 180.0_rp + real(kind=rp), parameter :: doy2rad = 2.0_rp*pi / 365.0_rp + real(kind=rp), parameter :: lst2rad = pi / 12.0_rp + !real(kind=rp), parameter :: tanh1 = 0.761594155955765485_rp ! tanh(1.0) + real(kind=rp), parameter :: tanh1 = tanh(1.0_rp) + + ! Thermodynamic constants + ! Boltzmann constant (CODATA 2018) (J/kg) + real(kind=rp), parameter :: kB = 1.380649e-23_rp + ! Avogadro constant (CODATA 2018) + real(kind=rp), parameter :: NA = 6.02214076e23_rp + ! Reference gravity (CIMO Guide 2014) (m/s^2) (specified separately in alt2gph, in msis_utils.F90) + real(kind=rp), parameter :: g0 = 9.80665_rp + ! Species molecular masses (kg/molecule) (CIPM 2007) + real(kind=rp), parameter :: specmass(1:10) = (/ 0.0_rp, & ! Mass density (dummy value) + 28.0134_rp, & ! N2 + 31.9988_rp, & ! O2 + 31.9988_rp/2.0_rp, & ! O + 4.0_rp, & ! He + 1.0_rp, & ! H + 39.948_rp, & ! Ar + 28.0134_rp/2.0_rp, & ! N + 31.9988_rp/2.0_rp, & ! Anomalous O + (28.0134_rp+31.9988_rp)/2.0_rp /) & ! NO + / (1.0e3_rp * NA) ! Convert from g/mol to kg/molecule + ! Dry air mean mass in fully mixed atmosphere (CIPM 2007) (includes CO2 and other trace species that are not yet in MSIS) + real(kind=rp), parameter :: Mbar = 28.96546_rp / (1.0e3_rp * NA) ! kg/molecule + ! Dry air log volume mixing ratios (CIPM 2007) + real(kind=rp), parameter :: lnvmr(1:10) = log( (/ 1.0_rp, & ! Mass density (dummy value) + 0.780848_rp, & ! N2 + 0.209390_rp, & ! O2 + 1.0_rp, & ! O (dummy value) + 0.0000052_rp, & ! He + 1.0_rp, & ! H (dummy value) + 0.009332_rp, & ! Ar + 1.0_rp, & ! N (dummy value) + 1.0_rp, & ! Anomalous O (dummy value) + 1.0_rp /) ) ! NO (dummy value) + ! Natural log of global average surface pressure (Pa) + !real(kind=rp), parameter :: lnP0 = 11.5080482 !+ 0.00759597 After calibration with MERRA2 + real(kind=rp), parameter :: lnP0 = 11.515614 + ! Derived constants + real(kind=rp), parameter :: g0divkB = g0/kB * 1.0e3_rp ! K/(kg km) + real(kind=rp), parameter :: Mbarg0divkB = Mbar*g0/kB * 1.0e3_rp ! K/km + ! References: + ! CODATA Internationally recommended 2018 values of the fundamental physical constants. + ! https://pml.nist.gov/cuu/Constants/; https://pml.nist.gov/cuu/pdf/wallet_2018.pdf + ! Picard, A., Davis, R. S., Glaeser, M., and Fujii, K. (2007). Revised formula for the density of + ! air (CIPM 2007). Metrologia 45, 149�155. doi:10.1088/0026-1394/45/2/004 + ! World Meteorological Organization (2014). WMO guide to meteorological instruments and methods of observation + ! (the CIMO Guide). Part I, Chapter 12. https://www.wmo.int/pages/prog/www/IMOP/CIMO-Guide.html + + ! Vertical profile parameters + integer, parameter :: nspec = 11 !Number of species including temperature + integer, parameter :: nd = 27 !Number of temperature profile nodes + integer, parameter :: p = 4 !Spline order + integer, parameter :: nl = nd - p !Last temperature profile level index + integer, parameter :: nls = 9 !Last parameter index for each species (excluding O, NO splines) + real(kind=rp), parameter :: bwalt = 122.5_rp ! Reference geopotential height for Bates Profile + real(kind=rp), parameter :: zetaF = 70.0_rp ! Fully mixed below this, uses constant mixing ratios + real(kind=rp), parameter :: zetaB = bwalt ! Bates Profile above this altitude + real(kind=rp), parameter :: zetaA = 85.0_rp ! Default reference height for active minor species + real(kind=rp), parameter :: zetagamma = 100.0_rp ! Reference height of tanh taper of chemical/dynamical correction scale height + real(kind=rp), parameter :: Hgamma = 1.0_rp/30.0_rp ! Inverse scale height of tanh taper of chemical/dynamical correction scale height + real(kind=rp), parameter :: nodesTN(0:nd+2) = & !Nodes for temperature profile splines + (/ -15., -10., -5., 0., 5., 10., 15., 20., 25., 30., 35., 40., 45., 50., & + 55., 60., 65., 70., 75., 80., 85., 92.5, 102.5, 112.5, 122.5, 132.5, 142.5, & + 152.5, 162.5, 172.5/) + integer, parameter :: izfmx = 13 ! fully mixed below this spline index + integer, parameter :: izfx = 14 ! Spline index at zetaF + integer, parameter :: izax = 17 ! Spline index at zetaA + integer, parameter :: itex = nl ! Index of Bates exospheric temperature + integer, parameter :: itgb0 = nl - 1 ! Index of Bates temperature gradient at lower boundary + integer, parameter :: itb0 = nl - 2 ! Index of Bates temperature at lower boundary + ! O1 Spline parameters + integer, parameter :: ndO1 = 13 + integer, parameter :: nsplO1 = ndO1-5 !Number of unconstrained spline parameters for O1 (there are 2 additional C1-constrained splines) + real(kind=rp), parameter :: nodesO1(0:ndO1) = & !Nodes for O1 splines (Domain 50-85 km) + (/ 35., 40., 45., 50., 55., 60., 65., 70., 75., 80., 85., 92.5, 102.5, 112.5/) + real(kind=rp), parameter :: zetarefO1 = zetaA !Joining height for O1 splines, and reference height for O1 density + ! NO Spline parameters + integer, parameter :: ndNO = 13 + integer, parameter :: nsplNO = ndNO-5 !Number of unconstrained spline parameters for NO (there are 2 additional C1-constrained splines) + real(kind=rp), parameter :: nodesNO(0:ndNO) = & !Nodes for NO splines (Domain 70-122.5 km) + (/ 47.5, 55., 62.5, 70., 77.5, 85., 92.5, 100., 107.5, 115., 122.5, 130., 137.5, 145./) + real(kind=rp), parameter :: zetarefNO = zetaB !Joining height for NO splines, and reference height for NO density + !C2 Continuity matrix for temperature; Last 3 splines are constrained (must be recomputed if nodes change) + real(kind=rp), parameter :: c2tn(3,3) = reshape((/1.0_rp, -10.0_rp, 33.333333333333336_rp, & + 1.0_rp, 0.0_rp, -16.666666666666668_rp, & + 1.0_rp, 10.0_rp, 33.333333333333336_rp/), & + (/3,3/)) + !C1 Continuity for O1; Last 2 splines are constrained (must be recomputed if nodes change) + real(kind=rp), parameter :: c1o1(2,2) = reshape((/ 1.75_rp, -2.916666573405061_rp, & + -1.624999900076852_rp, 21.458332647194382_rp /), & + (/2,2/)) + real(kind=rp), parameter :: c1o1adj(2) = (/0.257142857142857_rp, -0.102857142686844_rp/) !Weights for coefficents on 3rd to last spline; product to be subtracted from RHS of continuity equation + !C1 Continuity for NO; Last 2 splines are constrained (must be recomputed if nodes change) + real(kind=rp), parameter :: c1NO(2,2) = reshape((/ 1.5_rp, -3.75_rp, & + 0.0_rp, 15.0_rp /), & + (/2,2/)) + real(kind=rp), parameter :: c1NOadj(2) = (/0.166666666666667_rp, -0.066666666666667_rp/) !Weights for coefficents on 3rd to last spline; product to be subtracted from RHS of continuity equation + ! Anomalous Oxygen parameters (legacy profile from NRLMSISE-00) + real(kind=rp),parameter :: zetarefOA = zetaB !Reference height for anomalous oxygen density + real(kind=rp),parameter :: TOA = 4000. !Temperature of anomalous oxygen density (K) + real(kind=rp),parameter :: HOA = (kB * TOA) / ( (16.0_rp/(1.0e3_rp*NA)) * g0 ) * 1.0e-3_rp !Hydrostatic scale height of anomalous oxygen density (km) + + ! Horizontal and time-dependent basis function (gfn) parameters + integer, parameter :: maxnbf = 512 ! Number of basis functions to be allocated + integer, parameter :: maxn = 6 ! Maximum latitude (Legendre) spectral degree + integer, parameter :: maxl = 3 ! Maximum local time (tidal) spectral order + integer, parameter :: maxm = 2 ! Maximum longitude (stationary planetary wave) order + integer, parameter :: maxs = 2 ! Maximimum day of year (intra-annual) Fourier order + integer, parameter :: amaxn = 6 ! Maximum Legendre degree used in time independent and intra-annual zonal mean terms + integer, parameter :: amaxs = 2 ! Maximum intra-annual order used in zonal mean terms + integer, parameter :: tmaxl = 3 ! Maximum tidal order used + integer, parameter :: tmaxn = 6 ! Maximum Legendre degree coupled with tides + integer, parameter :: tmaxs = 2 ! Maximum intra-annual order coupled with tides + integer, parameter :: pmaxm = 2 ! Maximum stationary planetary wave order used + integer, parameter :: pmaxn = 6 ! Maximum Legendre degree coupled with SPW + integer, parameter :: pmaxs = 2 ! Maximum intra-annual order coupled with SPW + integer, parameter :: nsfx = 5 ! Number of linear solar flux terms + integer, parameter :: nsfxmod = 5 ! Number of nonlinear modulating solar flux terms (legacy NRLMSISE-00 terms) + integer, parameter :: nmag = 54 ! Number of terms in NRLMSISE-00 legacy geomagnetic parameterization + integer, parameter :: nut = 12 ! Number of terms in NRLMSISE-00 legacy UT parameterization + integer, parameter :: ctimeind = 0 ! Starting index of time-independent terms + integer, parameter :: cintann = ctimeind + (amaxn+1) ! Starting index of zonal mean intra-annual terms + integer, parameter :: ctide = cintann + ((amaxn+1)*2*amaxs) ! Starting index of zonal mean intra-annual terms + integer, parameter :: cspw = ctide + (4*tmaxs+2)*(tmaxl*(tmaxn+1)-(tmaxl*(tmaxl+1))/2) ! Starting index of SPW terms + integer, parameter :: csfx = cspw + (4*pmaxs+2)*(pmaxm*(pmaxn+1)-(pmaxm*(pmaxm+1))/2) ! Starting index of linear solar flux terms + integer, parameter :: cextra = csfx + nsfx ! Starting index of time-independent terms + integer, parameter :: mbf = 383 ! Last index of linear terms + integer, parameter :: cnonlin = mbf + 1 ! Starting index of nonlinear terms + integer, parameter :: csfxmod = cnonlin ! Starting index of modulating solar flux terms + integer, parameter :: cmag = csfxmod + nsfxmod ! Starting index of daily geomagnetic terms + integer, parameter :: cut = cmag + nmag ! Starting index of UT terms + + ! Weights for calculation log pressure spline coefficients from temperature coefficients (must be recalcuated if nodes change) + real(kind=rp), parameter :: gwht(0:3) = (/ 5.0_rp/24.0_rp, 55.0_rp/24.0_rp, 55.0_rp/24.0_rp, 5.0_rp/24.0_rp /) + + ! Constants needed for analytical integration by parts of hydrostatic piecewise effective mass profile + real(kind=rp), parameter :: wbeta(0:nl) = (nodesTN(4:nd) - nodesTN(0:nl)) / 4.0_rp !Weights for 1st spline integration + real(kind=rp), parameter :: wgamma(0:nl) = (nodesTN(5:nd+1)- nodesTN(0:nl)) / 5.0_rp !Weights for 2nd spline integration + ! Non-zero bspline values at zetaB (5th and 6th order) (must be recalcuated if nodes change) + real(kind=rp), parameter :: S5zetaB(0:3) = (/0.041666666666667_rp, 0.458333333333333_rp, 0.458333333333333_rp, & + 0.041666666666667_rp/) + real(kind=rp), parameter :: S6zetaB(0:4) = (/0.008771929824561_rp, 0.216228070175439_rp, 0.550000000000000_rp, & + 0.216666666666667_rp, 0.008333333333333_rp/) + !Weights for calculating temperature gradient at zetaA (must be recalcuated if nodes change) + real(kind=rp), parameter :: wghtAxdz(0:2) = (/-0.102857142857_rp, 0.0495238095238_rp, 0.053333333333_rp/) + !Non-zero bspline values at zetaA (4th, 5th and 6th order) (must be recalcuated if nodes change) + real(kind=rp), parameter :: S4zetaA(0:2) = (/0.257142857142857_rp, 0.653968253968254_rp, 0.088888888888889_rp/) + real(kind=rp), parameter :: S5zetaA(0:3) = (/0.085714285714286_rp, 0.587590187590188_rp, 0.313020313020313_rp, & + 0.013675213675214_rp/) + real(kind=rp), parameter :: S6zetaA(0:4) = (/0.023376623376623_rp, 0.378732378732379_rp, 0.500743700743701_rp, & + 0.095538448479625_rp, 0.001608848667672_rp/) + !Non-zero bspline values at zetaF (4th and 5th order) (must be recalcuated if nodes change) + real(kind=rp), parameter :: S4zetaF(0:2) = (/0.166666666666667_rp, 0.666666666666667_rp, 0.166666666666667_rp/) + real(kind=rp), parameter :: S5zetaF(0:3) = (/0.041666666666667_rp, 0.458333333333333_rp, 0.458333333333333_rp, & + 0.041666666666667_rp/) + !Non-zero bspline values at zeta=0 (5th order) (must be recalcuated if nodes change) + real(kind=rp), parameter :: S5zeta0(0:2) = (/0.458333333333333_rp, 0.458333333333333_rp, 0.041666666666667_rp/) + +end module msis_constants diff --git a/sorc/chgres_cube.fd/msis2.1.fd/msis_dfn.F90 b/sorc/chgres_cube.fd/msis2.1.fd/msis_dfn.F90 new file mode 100644 index 000000000..566d125b9 --- /dev/null +++ b/sorc/chgres_cube.fd/msis2.1.fd/msis_dfn.F90 @@ -0,0 +1,539 @@ +!####################################################################### +! MSIS� (NRL-SOF-014-1) SOFTWARE +! NRLMSIS� empirical atmospheric model software. Use is governed by the +! Open Source Academic Research License Agreement contained in the file +! nrlmsis2.1_license.txt, which is part of this software package. BY +! USING OR MODIFYING THIS SOFTWARE, YOU ARE AGREEING TO THE TERMS AND +! CONDITIONS OF THE LICENSE. +!####################################################################### + +!!! =========================================================================== +!!! NRLMSIS 2.1: +!!! Neutral atmosphere empirical model from the surface to lower exosphere +!!! =========================================================================== + +!************************************************************************************************** +! MSIS_DFN Module: Contains vertical species density profile parameters and subroutines +!************************************************************************************************** +module msis_dfn + + use msis_constants, only : rp, nl, nsplO1, nsplNO + use msis_utils, only : bspline, dilog + + type dnparm + sequence + real(kind=rp) :: lnPhiF ! (Except O, H) Natural log of mixing ratio at zetaF (70 km), before chemical and dynamical corrections are applied (ln m^-3) (global term only) + real(kind=rp) :: lndref ! Natural log of number density at reference height + real(kind=rp) :: zetaM ! "Turbopause Height": Height of midpoint of effective mass transition (km) + real(kind=rp) :: HML ! Scale height of lower portion of effective mass profile (km) + real(kind=rp) :: HMU ! Scale height of upper portion of effective mass profile (km) + real(kind=rp) :: C ! Chapman term coefficient + real(kind=rp) :: zetaC ! Chapman term reference height (km) + real(kind=rp) :: HC ! Chapman term scale height (km) + real(kind=rp) :: R ! Chemical/dynamical term coefficient + real(kind=rp) :: zetaR ! Chemical/dynamical term reference height (km) + real(kind=rp) :: HR ! Chemical/dynamical term scale height (km) + real(kind=rp) :: cf(0:nsplO1+1) ! Merged spline coefficients (for chemistry-dominated region of O1, NO, and (eventually), H, N) + real(kind=rp) :: zref ! Reference height for hydrostatic integral and ideal gas terms + real(kind=rp) :: Mi(0:4) ! Effective mass at nodes of piecewise mass profile (derived from zetaM, HML, HMU) + real(kind=rp) :: zetaMi(0:4) ! Height of nodes of piecewise mass profile (derived from zetaM, HML, HMU) + real(kind=rp) :: aMi(0:4) = 0.0_rp ! Slopes of piecewise mass profile segments (derived from zetaM, HML, HMU) + real(kind=rp) :: WMi(0:4) = 0.0_rp ! 2nd indefinite integral of 1/T at mass profile nodes + real(kind=rp) :: XMi(0:4) = 0.0_rp ! Cumulative adjustment to M/T integral due to changing effective mass + real(kind=rp) :: Izref ! Indefinite hydrostatic integral at reference height + real(kind=rp) :: Tref ! Temperature at reference height (for ideal gas law term) + real(kind=rp) :: zmin ! Minimum height of profile (missing values below) + real(kind=rp) :: zhyd ! Hydrostatic terms needed above this height + integer(kind=rp) :: ispec ! Species index + end type dnparm + + contains + + !================================================================================================== + ! DFNPARM: Compute the species density profile parameters + !================================================================================================== + subroutine dfnparm(ispec,gf,tpro,dpro) + + use msis_constants, only : tanh1, specmass, lnvmr, Mbar, g0divkB, & + nd, zetaF, zetaB, zetaA, nodesTN, & + nodesO1, zetarefO1, c1o1, c1o1adj, & + nodesNO, zetarefNO, c1NO, c1NOadj, & + zetarefOA, & + maxnbf, mbf, nmag, nut, cmag, cut + use msis_init, only : etaTN, TN,PR,N2,O2,O1,HE,H1,AR,N1,OA,NO, N2Rflag, & + HRfactO1ref, dHRfactO1ref, HRfactNOref, dHRfactNOref + use msis_gfn, only : sfluxmod, geomag, utdep + use msis_tfn, only : tnparm + + implicit none + + integer, intent(in) :: ispec ! Species index + real(kind=rp), intent(in) :: gf(0:maxnbf-1) ! Array of horizontal and temporal basis function terms + type(tnparm), intent(in) :: tpro ! Structure containing temperature vertical profile parameters + type(dnparm), intent(out) :: dpro ! Output structure containing density vertical profile parameters + + integer :: izf, i, i1, iz + real(kind=rp) :: Cterm, Rterm0, Rterm + real(kind=rp) :: bc(2) + real(kind=rp) :: hbetaL,hbetaU + real(kind=rp) :: delM, delz + real(kind=rp) :: Wi ! 2nd indefinite integral at a piecewise mass profile node + real(kind=rp) :: Si(-5:0,2:6) ! Array of b-spline values at a mass profile node + real(kind=rp) :: Mzref ! Effective mass at reference altitude + + dpro%ispec = ispec + + select case(ispec) + + ! Molecular Nitrogen ---------------------- + case(2) + ! Mixing ratio and reference number density + dpro%lnPhiF = lnvmr(ispec) + dpro%lndref = tpro%lndtotF + dpro%lnPhiF + dpro%zref = zetaF + dpro%zmin = -1.0_rp + dpro%zhyd = zetaF + ! Effective mass + dpro%zetaM = dot_product(N2%beta(0:mbf,1),gf(0:mbf)) + dpro%HML = N2%beta(0,2) + dpro%HMU = N2%beta(0,3) + ! Photochemical correction + dpro%R = 0.0_rp + if (N2Rflag) dpro%R = dot_product(N2%beta(0:mbf,7),gf(0:mbf)) + dpro%zetaR = N2%beta(0,8) + dpro%HR = N2%beta(0,9) + + ! Molecular Oxygen ------------------------ + case(3) + ! Mixing ratio and reference number density + dpro%lnPhiF = lnvmr(ispec) + dpro%lndref = tpro%lndtotF + dpro%lnPhiF + dpro%zref = zetaF + dpro%zmin = -1.0_rp + dpro%zhyd = zetaF + ! Effective mass + dpro%zetaM = O2%beta(0,1) + dpro%HML = O2%beta(0,2) + dpro%HMU = O2%beta(0,3) + ! Photochemical correction + dpro%R = dot_product(O2%beta(0:mbf,7),gf(0:mbf)) + dpro%R = dpro%R + geomag(O2%beta(cmag:cmag+nmag-1,7),gf(cmag:cmag+12),gf(cmag+13:cmag+26)) + dpro%zetaR = O2%beta(0,8) + dpro%HR = O2%beta(0,9) + + ! Atomic Oxygen -------------------------- + case(4) + ! Reference number density + dpro%lnPhiF = 0.0_rp + dpro%lndref = dot_product(O1%beta(0:mbf,0),gf(0:mbf)) + dpro%zref = zetarefO1 + dpro%zmin = nodesO1(3) + dpro%zhyd = zetarefO1 + ! Effective mass + dpro%zetaM = O1%beta(0,1) + dpro%HML = O1%beta(0,2) + dpro%HMU = O1%beta(0,3) + ! Chapman correction + dpro%C = dot_product(O1%beta(0:mbf,4),gf(0:mbf)) + dpro%zetaC = O1%beta(0,5) + dpro%HC = O1%beta(0,6) + ! Dynamical correction + dpro%R = dot_product(O1%beta(0:mbf,7),gf(0:mbf)) + dpro%R = dpro%R + sfluxmod(7,gf,O1,0.0_rp) + dpro%R = dpro%R + geomag(O1%beta(cmag:cmag+nmag-1,7),gf(cmag:cmag+12),gf(cmag+13:cmag+26)) + dpro%R = dpro%R + utdep(O1%beta(cut:cut+nut-1,7),gf(cut:cut+8)) + dpro%zetaR = O1%beta(0,8) + dpro%HR = O1%beta(0,9) + ! Unconstrained splines + do izf = 0, nsplO1-1 + dpro%cf(izf) = dot_product(O1%beta(0:mbf,izf+10),gf(0:mbf)) + enddo + ! Constrained splines calculated after case statement + + ! Helium ---------------------- + case(5) + ! Mixing ratio and reference number density + dpro%lnPhiF = lnvmr(ispec) + dpro%lndref = tpro%lndtotF + dpro%lnPhiF + dpro%zref = zetaF + dpro%zmin = -1.0_rp + dpro%zhyd = zetaF + ! Effective mass + dpro%zetaM = HE%beta(0,1) + dpro%HML = HE%beta(0,2) + dpro%HMU = HE%beta(0,3) + ! Dynamical correction + dpro%R = dot_product(HE%beta(0:mbf,7),gf(0:mbf)) + dpro%R = dpro%R + sfluxmod(7,gf,HE,1.0_rp) + dpro%R = dpro%R + geomag(HE%beta(cmag:cmag+nmag-1,7),gf(cmag:cmag+12),gf(cmag+13:cmag+26)) + dpro%R = dpro%R + utdep(HE%beta(cut:cut+nut-1,7),gf(cut:cut+8)) + dpro%zetaR = HE%beta(0,8) + dpro%HR = HE%beta(0,9) + + ! Atomic Hydrogen ---------------------- + case(6) + ! Reference number density + dpro%lnPhiF = 0.0_rp + dpro%lndref = dot_product(H1%beta(0:mbf,0),gf(0:mbf)) + dpro%zref = zetaA + dpro%zmin = 75.0_rp + dpro%zhyd = zetaF + ! Effective mass + dpro%zetaM = H1%beta(0,1) + dpro%HML = H1%beta(0,2) + dpro%HMU = H1%beta(0,3) + ! Chapman correction + dpro%C = dot_product(H1%beta(0:mbf,4),gf(0:mbf)) + dpro%zetaC = dot_product(H1%beta(0:mbf,5),gf(0:mbf)) + dpro%HC = H1%beta(0,6) + ! Dynamical correction + dpro%R = dot_product(H1%beta(0:mbf,7),gf(0:mbf)) + dpro%R = dpro%R + sfluxmod(7,gf,H1,0.0_rp) + dpro%R = dpro%R + geomag(H1%beta(cmag:cmag+nmag-1,7),gf(cmag:cmag+12),gf(cmag+13:cmag+26)) + dpro%R = dpro%R + utdep(H1%beta(cut:cut+nut-1,7),gf(cut:cut+8)) + dpro%zetaR = H1%beta(0,8) + dpro%HR = H1%beta(0,9) + + ! Argon ---------------------- + case(7) + ! Mixing ratio and reference number density + dpro%lnPhiF = lnvmr(ispec) + dpro%lndref = tpro%lndtotF + dpro%lnPhiF + dpro%zref = zetaF + dpro%zmin = -1.0_rp + dpro%zhyd = zetaF + ! Effective mass + dpro%zetaM = AR%beta(0,1) + dpro%HML = AR%beta(0,2) + dpro%HMU = AR%beta(0,3) + ! Dynamical correction + dpro%R = dot_product(AR%beta(0:mbf,7),gf(0:mbf)) + dpro%R = dpro%R + geomag(AR%beta(cmag:cmag+nmag-1,7),gf(cmag:cmag+12),gf(cmag+13:cmag+26)) + dpro%R = dpro%R + utdep(AR%beta(cut:cut+nut-1,7),gf(cut:cut+8)) + dpro%zetaR = AR%beta(0,8) + dpro%HR = AR%beta(0,9) + + ! Atomic Nitrogen ---------------------- + case(8) + ! Reference number density + dpro%lnPhiF = 0.0_rp + dpro%lndref = dot_product(N1%beta(0:mbf,0),gf(0:mbf)) + dpro%lndref = dpro%lndref + sfluxmod(0,gf,N1,0.0_rp) + dpro%lndref = dpro%lndref + geomag(N1%beta(cmag:cmag+nmag-1,0),gf(cmag:cmag+12),gf(cmag+13:cmag+26)) + dpro%lndref = dpro%lndref + utdep(N1%beta(cut:cut+nut-1,0),gf(cut:cut+8)) + dpro%zref = zetaB + dpro%zmin = 90.0_rp + dpro%zhyd = zetaF + ! Effective mass + dpro%zetaM = N1%beta(0,1) + dpro%HML = N1%beta(0,2) + dpro%HMU = N1%beta(0,3) + ! Chapman correction + dpro%C = N1%beta(0,4) + dpro%zetaC = N1%beta(0,5) + dpro%HC = N1%beta(0,6) + ! Dynamical correction + dpro%R = dot_product(N1%beta(0:mbf,7),gf(0:mbf)) + dpro%zetaR = N1%beta(0,8) + dpro%HR = N1%beta(0,9) + + ! Anomalous Oxygen ---------------------- + case(9) + dpro%lndref = dot_product(OA%beta(0:mbf,0),gf(0:mbf)) + dpro%lndref = dpro%lndref + geomag(OA%beta(cmag:cmag+nmag-1,0),gf(cmag:cmag+12),gf(cmag+13:cmag+26)) + dpro%zref = zetarefOA + dpro%zmin = 120.0_rp + dpro%zhyd = 0.0_rp + dpro%C = OA%beta(0,4) + dpro%zetaC = OA%beta(0,5) + dpro%HC = OA%beta(0,6) + return !No further parameters needed for legacy anomalous oxygen profile + + ! Nitic Oxide ---------------------- + ! Added geomag dependence 2/18/21 + case(10) + ! Skip if parameters are not defined + if (NO%beta(0,0) .eq. 0.0_rp) then + dpro%lndref = 0.0_rp + return + endif + ! Reference number density + dpro%lnPhiF = 0.0_rp + dpro%lndref = dot_product(NO%beta(0:mbf,0),gf(0:mbf)) + dpro%lndref = dpro%lndref + geomag(NO%beta(cmag:cmag+nmag-1,0),gf(cmag:cmag+12),gf(cmag+13:cmag+26)) + dpro%zref = zetarefNO + !dpro%zmin = nodesNO(3) + dpro%zmin = 72.5 !JTE 1/18/22 Cut off profile below 72.5 km, due to possible spline artefacts at edge of domain (70 km) + dpro%zhyd = zetarefNO + ! Effective mass + dpro%zetaM = dot_product(NO%beta(0:mbf,1),gf(0:mbf)) + dpro%HML = dot_product(NO%beta(0:mbf,2),gf(0:mbf)) + dpro%HMU = dot_product(NO%beta(0:mbf,3),gf(0:mbf)) + ! Chapman correction + dpro%C = dot_product(NO%beta(0:mbf,4),gf(0:mbf)) + dpro%C = dpro%C + geomag(NO%beta(cmag:cmag+nmag-1,4),gf(cmag:cmag+12),gf(cmag+13:cmag+26)) + dpro%zetaC = dot_product(NO%beta(0:mbf,5),gf(0:mbf)) + dpro%HC = dot_product(NO%beta(0:mbf,6),gf(0:mbf)) + ! Dynamical correction + dpro%R = dot_product(NO%beta(0:mbf,7),gf(0:mbf)) + dpro%zetaR = dot_product(NO%beta(0:mbf,8),gf(0:mbf)) + dpro%HR = dot_product(NO%beta(0:mbf,9),gf(0:mbf)) + ! Unconstrained splines + do izf = 0,nsplNO-1 + dpro%cf(izf) = dot_product(NO%beta(0:mbf,izf+10),gf(0:mbf)) + dpro%cf(izf) = dpro%cf(izf) + geomag(NO%beta(cmag:cmag+nmag-1,izf+10),gf(cmag:cmag+12),gf(cmag+13:cmag+26)) + enddo + ! Constrained splines calculated after case statement + +! Failsafe ----- --------------------------- + case default + stop 'Species not yet implemented' + + endselect + + ! Compute piecewise mass profile values and integration terms + dpro%zetaMi(0) = dpro%zetaM - 2.0_rp*dpro%HML + dpro%zetaMi(1) = dpro%zetaM - dpro%HML + dpro%zetaMi(2) = dpro%zetaM + dpro%zetaMi(3) = dpro%zetaM + dpro%HMU + dpro%zetaMi(4) = dpro%zetaM + 2.0_rp*dpro%HMU + dpro%Mi(0) = Mbar + dpro%Mi(4) = specmass(ispec) + dpro%Mi(2) = (dpro%Mi(0) + dpro%Mi(4)) / 2.0_rp + delM = tanh1 * (dpro%Mi(4) - dpro%Mi(0)) / 2.0_rp + dpro%Mi(1) = dpro%Mi(2) - delM + dpro%Mi(3) = dpro%Mi(2) + delM + do i = 0, 3 + dpro%aMi(i) = (dpro%Mi(i+1) - dpro%Mi(i)) / (dpro%zetaMi(i+1) - dpro%zetaMi(i)) + enddo + do i = 0, 4 + delz = dpro%zetaMi(i) - zetaB + if (dpro%zetaMi(i) .lt. zetaB) then + call bspline(dpro%zetaMi(i),nodesTN,nd+2,6,etaTN,Si,iz) + dpro%WMi(i) = dot_product(tpro%gamma(iz-5:iz),Si(:,6)) + tpro%cVS*delz + tpro%cWS + else + dpro%WMi(i) = (0.5_rp*delz*delz + dilog(tpro%b*exp(-tpro%sigma*delz))/tpro%sigmasq)/tpro%tex & + + tpro%cVB*delz + tpro%cWB + endif + end do + dpro%XMi(0) = -dpro%aMi(0) * dpro%WMi(0) + do i = 1, 3 + dpro%XMi(i) = dpro%XMi(i-1) - dpro%WMi(i) * (dpro%aMi(i) - dpro%aMi(i-1)) + end do + dpro%XMi(4) = dpro%XMi(3) + dpro%WMi(4) * dpro%aMi(3) + + ! Calculate hydrostatic integral at reference height, and copy temperature + if (dpro%zref .eq. zetaF) then + Mzref = Mbar + dpro%Tref = tpro%TzetaF + dpro%Izref = Mbar * tpro%VzetaF + else if (dpro%zref .eq. zetaB) then + Mzref = pwmp(dpro%zref,dpro%zetaMi,dpro%Mi,dpro%aMi) + dpro%Tref = tpro%Tb0 + dpro%Izref = 0.0_rp + if ((zetaB .gt. dpro%zetaMi(0)) .and. (zetaB .lt. dpro%zetaMi(4))) then + i = 0 + do i1 = 1, 3 + if (zetaB .lt. dpro%zetaMi(i1)) then + exit + else + i = i1 + endif + enddo + dpro%Izref = dpro%Izref - dpro%XMi(i) + else + dpro%Izref = dpro%Izref - dpro%XMi(4) + endif + else if (dpro%zref .eq. zetaA) then + Mzref = pwmp(dpro%zref,dpro%zetaMi,dpro%Mi,dpro%aMi) + dpro%Tref = tpro%TzetaA + dpro%Izref = Mzref * tpro%VzetaA + if ((zetaA .gt. dpro%zetaMi(0)) .and. (zetaA .lt. dpro%zetaMi(4))) then + i = 0 + do i1 = 1, 3 + if (zetaA .lt. dpro%zetaMi(i1)) then + exit + else + i = i1 + endif + enddo + dpro%Izref = dpro%Izref - (dpro%aMi(i)*tpro%WzetaA + dpro%XMi(i)) + else + dpro%Izref = dpro%Izref - dpro%XMi(4) + endif + else + stop 'Integrals at reference height not available' + endif + + ! C1 constraint for O1 at 85 km + if (ispec .eq. 4) then + Cterm = dpro%C*exp(-(dpro%zref-dpro%zetaC)/dpro%HC) + Rterm0 = tanh((dpro%zref-dpro%zetaR)/(HRfactO1ref*dpro%HR)) + Rterm = dpro%R*(1+Rterm0) + bc(1) = dpro%lndref - Cterm + Rterm - dpro%cf(7)*c1o1adj(1) !Reference density, Chapman term, logistic term, and subtraction of last unconstrained spline(7) + bc(2) = -Mzref*g0divkB/tpro%tzetaA & !Gradient of hydrostatic term + -tpro%dlntdzA & !Gradient of ideal gas law term + +Cterm/dpro%HC & !Gradient of Chapman term + +Rterm*(1-Rterm0)/dpro%HR*dHrfactO1ref & !Gradient of tapered logistic term + -dpro%cf(7)*c1o1adj(2) !Subtraction of gradient of last unconstrained spline(7) + ! Compute coefficients for constrained splines + dpro%cf(8:9) = matmul(bc,c1o1) + endif + + ! C1 constraint for NO at 122.5 km + if (ispec .eq. 10) then + Cterm = dpro%C*exp(-(dpro%zref - dpro%zetaC)/dpro%HC) + Rterm0 = tanh((dpro%zref-dpro%zetaR)/(HRfactNOref*dpro%HR)) + Rterm = dpro%R*(1+Rterm0) + bc(1) = dpro%lndref - Cterm + Rterm - dpro%cf(7)*c1noadj(1) !Reference density, Chapman term, logistic term, and subtraction of last unconstrained spline(7) + bc(2) = -Mzref*g0divkB/tpro%tb0 & !Gradient of hydrostatic term + -tpro%tgb0/tpro%tb0 & !Gradient of ideal gas law term + +Cterm/dpro%HC & !Gradient of Chapman term + +Rterm*(1-Rterm0)/dpro%HR*dHrfactNOref & !Gradient of tapered logistic term + -dpro%cf(7)*c1noadj(2) !Subtraction of gradient of last unconstrained spline(7) + ! Compute coefficients for constrained splines + dpro%cf(8:9) = matmul(bc,c1no) + endif + + return + + end subroutine dfnparm + + !================================================================================================== + ! DFNX: Compute a species density at specified geopotential height + !================================================================================================== + real(kind=rp) function dfnx(z,tnz,lndtotz,Vz,Wz,HRfact,tpro,dpro) + + use msis_constants, only : dmissing, g0divkB, ndO1, nodesO1, ndNO, nodesNO, HOA + use msis_init, only : etaO1, etaNO + use msis_tfn, only : tnparm + + implicit none + + real(kind=rp), intent(in) :: z ! Geopotential height + real(kind=rp), intent(in) :: tnz, lndtotz ! Temperature, total number density at input z + real(kind=rp), intent(in) :: Vz, Wz ! First and second indefinite integrals of 1/T at z + real(kind=rp), intent(in) :: HRfact ! Reduction factor for chemical/dynamical correction scale height below zetaF + type(tnparm), intent(in) :: tpro ! Structure containing temperature vertical profile parameters + type(dnparm), intent(in) :: dpro ! Structure containing density vertical profile parameters + + integer(4) :: i, i1, iz + real(kind=rp) :: Mz + real(kind=rp) :: Sz(-5:0,2:6) + real(kind=rp) :: Ihyd ! Hydrostatic definite integral + real(kind=rp) :: ccor ! Chapman and logistical corrections + + ! Below minimum height of profile + if (z .lt. dpro%zmin) then + dfnx = dmissing + return + endif + + ! Anomalous Oxygen (legacy MSISE-00 formulation) + if (dpro%ispec .eq. 9) then + dfnx = dpro%lndref - (z - dpro%zref)/HOA - dpro%C*exp(-(z-dpro%zetaC)/dpro%HC) + dfnx = exp(dfnx) + return !No further calculation needed for anomalous oxygen + endif + + ! Nitric Oxide: Skip if parameters are not defined + if (dpro%ispec .eq. 10) then + if (dpro%lndref .eq. 0.0_rp) then + dfnx = dmissing + return + endif + endif + + ! Chapman and logistic corrections + select case(dpro%ispec) + case(2,3,5,7) !For N2, O2, He, and Ar: logistic correction only + ccor = dpro%R*(1+tanh((z-dpro%zetaR)/(HRfact*dpro%HR))) + case(4,6,8,10) !For O, H, N, and NO: Chapman and logistic corrections + ccor = - dpro%C*exp(-(z-dpro%zetaC)/dpro%HC) & + + dpro%R*(1+tanh((z-dpro%zetaR)/(HRfact*dpro%HR))) + endselect + + ! Below height where hydrostatic terms are needed + if (z .lt. dpro%zhyd) then + select case(dpro%ispec) + case(2,3,5,7) !For N2, O2, He, and Ar, apply mixing ratios and exit + dfnx = exp(lndtotz + dpro%lnPhiF + ccor) + return + case(4) !For O, evaluate splines + call bspline(z,nodesO1,ndO1,4,etaO1,Sz,iz) + dfnx = exp(dot_product(dpro%cf(iz-3:iz),Sz(-3:0,4))) + return + case(10) !For NO, evaluate splines + call bspline(z,nodesNO,ndNO,4,etaNO,Sz,iz) + dfnx = exp(dot_product(dpro%cf(iz-3:iz),Sz(-3:0,4))) + return + endselect + endif + + ! Calculate hydrostatic term and apply to reference density + Mz = pwmp(z,dpro%zetaMi,dpro%Mi,dpro%aMi) + Ihyd = Mz * Vz - dpro%Izref + if ((z .gt. dpro%zetaMi(0)) .and. (z .lt. dpro%zetaMi(4))) then + i = 0 + do i1 = 1, 3 + if (z .lt. dpro%zetaMi(i1)) then + exit + else + i = i1 + endif + enddo + Ihyd = Ihyd - (dpro%aMi(i)*Wz + dpro%XMi(i)) + else if (z .ge. dpro%zetaMi(4)) then + Ihyd = Ihyd - dpro%XMi(4) + endif + dfnx = dpro%lndref - Ihyd * g0divkB + ccor + + ! Apply ideal gas law + dfnx = exp(dfnx) * dpro%Tref/tnz + + return + + end function dfnx + + !================================================================================================== + ! PWMP: Piecewise effective mass profile interpolation + !================================================================================================== + real(kind=rp) function pwmp(z,zm,m,dmdz) + + use msis_constants, only : rp + + real(kind=rp), intent(in) :: z + real(kind=rp), intent(in) :: zm(0:4) + real(kind=rp), intent(in) :: m(0:4) + real(kind=rp), intent(in) :: dmdz(0:3) + + integer :: irng !Index of piecwise interval + integer :: inode + + ! Most probable case + if (z .ge. zm(4)) then + pwmp = m(4) + return + endif + + ! Second most probable case + if (z .le. zm(0)) then + pwmp = m(0) + return + endif + + ! None of the above + do inode = 0,3 + if (z .lt. zm(inode+1)) then + pwmp = m(inode) + dmdz(inode)*(z - zm(inode)) + return + endif + enddo + + ! If we are here this is a problem + stop 'Error in pwmp' + + end function pwmp + +end module msis_dfn + diff --git a/sorc/chgres_cube.fd/msis2.1.fd/msis_gfn.F90 b/sorc/chgres_cube.fd/msis2.1.fd/msis_gfn.F90 new file mode 100644 index 000000000..f15f8aecd --- /dev/null +++ b/sorc/chgres_cube.fd/msis2.1.fd/msis_gfn.F90 @@ -0,0 +1,540 @@ +!####################################################################### +! MSIS� (NRL-SOF-014-1) SOFTWARE +! NRLMSIS� empirical atmospheric model software. Use is governed by the +! Open Source Academic Research License Agreement contained in the file +! nrlmsis2.1_license.txt, which is part of this software package. BY +! USING OR MODIFYING THIS SOFTWARE, YOU ARE AGREEING TO THE TERMS AND +! CONDITIONS OF THE LICENSE. +!####################################################################### + +!!! =========================================================================== +!!! NRLMSIS 2.1: +!!! Neutral atmosphere empirical model from the surface to lower exosphere +!!! =========================================================================== + +!************************************************************************************************** +! MSIS_GFN Module: Contains subroutines to calculate global (horizontal and time-dependent) model +! basis functions +!************************************************************************************************** +module msis_gfn + + use msis_constants, only : rp, maxn + use msis_init, only : TN,PR,N2,O2,O1,HE,H1,AR,N1,OA,NO, swg + + implicit none + + real(kind=rp) :: plg(0:maxn,0:maxn) + real(kind=rp) :: cdoy(2), sdoy(2) + real(kind=rp) :: clst(3), slst(3) + real(kind=rp) :: clon(2), slon(2) + real(kind=rp) :: sfluxavgref = 150.0 ! Reference F10.7 value (=150 in NRLMSISE-00) + real(kind=rp) :: sfluxavg_quad_cutoff = 150.0 ! Cutoff F10.7 for truncated quadratic F10.7a function + real(kind=rp) :: lastlat = -999.9 + real(kind=rp) :: lastdoy = -999.9 + real(kind=rp) :: lastlst = -999.9 + real(kind=rp) :: lastlon = -999.9 + +contains + + !================================================================================================== + ! GLOBE: Calculate horizontal and time-dependent basis functions + ! (Same purpose as NRLMSISE-00 "GLOBE7" subroutine) + !================================================================================================== + subroutine globe(doy,utsec,lat,lon,sfluxavg,sflux,ap,bf) + + use msis_constants, only : deg2rad, doy2rad, lst2rad, & + maxnbf, mbf, maxn, amaxn, amaxs, tmaxl, tmaxn, tmaxs, pmaxm, pmaxn, pmaxs, & + nsfx, nsfxmod, ctimeind, cintann, ctide, cspw, csfx, cextra, cnonlin, csfxmod, cmag, cut + implicit none + + real(kind=rp), intent(in) :: doy ! Day of year + real(kind=rp), intent(in) :: utsec ! Universal time in seconds + real(kind=rp), intent(in) :: lat ! Latitude + real(kind=rp), intent(in) :: lon ! Longitdue + real(kind=rp), intent(in) :: sfluxavg ! 81-day average F10.7 + real(kind=rp), intent(in) :: sflux ! Daily F10.7 + real(kind=rp), intent(in) :: ap(1:7) ! Ap geomagnetic activity index history array + real(kind=rp), intent(out) :: bf(0:maxnbf-1) ! Output array of basis function terms + + real(kind=rp) :: lst + real(kind=rp) :: slat, clat, clat2, clat4, slat2 + real(kind=rp) :: cosdoy, sindoy + real(kind=rp) :: coslon, sinlon + real(kind=rp) :: pl + real(kind=rp) :: coslst, sinlst + real(kind=rp) :: dfa, df + real(kind=rp) :: theta + real(kind=rp) :: sza + integer :: n, m, l, s, c + + ! Associated Legendre polynomials + if (lat .ne. lastlat) then + clat = sin(lat*deg2rad) ! clat <=> sin, Legendre polyomial defined in colat + slat = cos(lat*deg2rad) ! slat <=> cos, Legendre polyomial defined in colat + clat2 = clat*clat + clat4 = clat2*clat2 + slat2 = slat*slat + + plg(0,0) = 1.0_rp + plg(1,0) = clat + plg(2,0) = 0.5_rp * (3.0_rp * clat2 - 1.0_rp) + plg(3,0) = 0.5_rp * (5.0_rp * clat * clat2 - 3.0_rp * clat) + plg(4,0) = (35.0_rp * clat4 - 30.0_rp * clat2 + 3.0_rp)/8.0_rp + plg(5,0) = (63.0_rp * clat2 * clat2 * clat - 70.0_rp * clat2 * clat + 15.0_rp * clat)/8.0_rp + plg(6,0) = (11.0_rp * clat * plg(5, 0) - 5.0_rp * plg(4, 0))/6.0_rp + + plg(1,1) = slat + plg(2,1) = 3.0_rp * clat * slat + plg(3,1) = 1.5_rp * (5.0_rp * clat2 - 1.0_rp) * slat + plg(4,1) = 2.5_rp * (7.0_rp * clat2 * clat - 3.0_rp * clat) * slat + plg(5,1) = 1.875_rp * (21.0_rp * clat4 - 14.0_rp * clat2 + 1.0_rp) * slat + plg(6,1) = (11.0_rp * clat * plg(5, 1) - 6.0_rp * plg(4, 1))/5.0_rp + + plg(2,2) = 3.0_rp * slat2 + plg(3,2) = 15.0_rp * slat2 * clat + plg(4,2) = 7.5_rp * (7.0_rp * clat2 - 1.0_rp) * slat2 + plg(5,2) = 3.0_rp * clat * plg(4, 2) - 2.0_rp * plg(3, 2) + plg(6,2) = (11.0_rp * clat * plg(5, 2) - 7.0_rp * plg(4, 2))/4.0_rp + + plg(3,3) = 15.0_rp * slat2 * slat + plg(4,3) = 105.0_rp * slat2 * slat * clat + plg(5,3) = (9.0_rp * clat * plg(4, 3) - 7.0_rp * plg(3, 3))/2.0_rp + plg(6,3) = (11.0_rp * clat * plg(5, 3) - 8.0_rp * plg(4, 3))/3.0_rp + + lastlat = lat + endif + + ! Fourier harmonics of day of year + if (doy .ne. lastdoy) then + cdoy(1) = cos(doy2rad*doy) + sdoy(1) = sin(doy2rad*doy) + cdoy(2) = cos(doy2rad*doy*2.0_rp) + sdoy(2) = sin(doy2rad*doy*2.0_rp) + lastdoy = doy + endif + + ! Fourier harmonics of local time + lst = mod(utsec/3600.0_rp + lon/15.0_rp + 24.0_rp, 24.0_rp) + if (lst .ne. lastlst) then + clst(1) = cos(lst2rad*lst) + slst(1) = sin(lst2rad*lst) + clst(2) = cos(lst2rad*lst*2.0_rp) + slst(2) = sin(lst2rad*lst*2.0_rp) + clst(3) = cos(lst2rad*lst*3.0_rp) + slst(3) = sin(lst2rad*lst*3.0_rp) + lastlst = lst + endif + + ! Fourier harmonics of longitude + if (lon .ne. lastlon) then + clon(1) = cos(deg2rad*lon) + slon(1) = sin(deg2rad*lon) + clon(2) = cos(deg2rad*lon*2.0_rp) + slon(2) = sin(deg2rad*lon*2.0_rp) + lastlon = lon + endif + + !--------------------------------------------- + ! Coupled Linear Terms + !--------------------------------------------- + + ! Reset basis functions + bf(:) = 0.0_rp + + ! Time-independent (pure latitude dependence) + c = ctimeind + do n = 0, amaxn + bf(c) = plg(n,0) + c = c + 1 + enddo + + ! Intra-annual (annual and semiannual) + if (c .ne. cintann) stop 'problem with basis definitions' + do s = 1, amaxs + cosdoy = cdoy(s) + sindoy = sdoy(s) + do n = 0, amaxn + pl = plg(n,0) + bf(c) = pl*cosdoy + bf(c+1) = pl*sindoy + c = c + 2 + enddo + enddo + + ! Migrating Tides (local time dependence) + if (c .ne. ctide) stop 'problem with basis definitions' + do l = 1, tmaxl + coslst = clst(l) + sinlst = slst(l) + do n = l, tmaxn + pl = plg(n,l) + bf(c) = pl*coslst + bf(c+1) = pl*sinlst + c = c + 2 + enddo + ! Intra-annual modulation of tides + do s = 1, tmaxs + cosdoy = cdoy(s) + sindoy = sdoy(s) + do n = l, tmaxn + pl = plg(n,l) + bf(c) = pl*coslst*cosdoy + bf(c+1) = pl*sinlst*cosdoy + bf(c+2) = pl*coslst*sindoy + bf(c+3) = pl*sinlst*sindoy + c = c + 4 + enddo + enddo + enddo + + ! Stationary Planetary Waves (longitude dependence) + if (c .ne. cspw) stop 'problem with basis definitions' + do m = 1, pmaxm + coslon = clon(m) + sinlon = slon(m) + do n = m, pmaxn + pl = plg(n,m) + bf(c) = pl*coslon + bf(c+1) = pl*sinlon + c = c + 2 + enddo + ! Intra-annual modulation of SPWs + do s = 1, pmaxs + cosdoy = cdoy(s) + sindoy = sdoy(s) + do n = m, pmaxn + pl = plg(n,m) + bf(c) = pl*coslon*cosdoy + bf(c+1) = pl*sinlon*cosdoy + bf(c+2) = pl*coslon*sindoy + bf(c+3) = pl*sinlon*sindoy + c = c + 4 + enddo + enddo + enddo + + ! Linear solar flux terms + if (c .ne. csfx) stop 'problem with basis definitions' + dfa = sfluxavg - sfluxavgref + df = sflux - sfluxavg + bf(c) = dfa + bf(c+1) = dfa*dfa + bf(c+2) = df + bf(c+3) = df*df + bf(c+4) = df*dfa + c = c + nsfx + + ! Additional linear terms + if (c .ne. cextra) stop 'problem with basis definitions' + sza = solzen(doy,lst,lat,lon) + bf(c) = -0.5_rp*tanh((sza-98.0_rp)/6.0_rp) !Solar zenith angle logistic function for O, H (transition width 3 deg, transition sza for horizon at ~65 km altitude) + bf(c+1) = -0.5_rp*tanh((sza-101.5_rp)/20.0_rp) !Solar zenith angle logistic function for NO (transition width 10 deg, transition sza for horizon at ~130 km altitude) + bf(c+2) = dfa*bf(c) !Solar flux modulation of logistic sza term + bf(c+3) = dfa*bf(c+1) !Solar flux modulation of logistic sza term + bf(c+4) = dfa*plg(2,0) !Solar flux modulation of P(2,0) term + bf(c+5) = dfa*plg(4,0) !Solar flux modulation of P(4,0) term + bf(c+6) = dfa*plg(0,0)*cdoy(1) !Solar flux modulation of global AO + bf(c+7) = dfa*plg(0,0)*sdoy(1) !Solar flux modulation of global AO + bf(c+8) = dfa*plg(0,0)*cdoy(2) !Solar flux modulation of global SAO + bf(c+9) = dfa*plg(0,0)*sdoy(2) !Solar flux modulation of global SAO + if (sfluxavg .le. sfluxavg_quad_cutoff) then !Quadratic F10.7a function with cutoff of quadratic term (for robust extrapolation) + bf(c+10) = dfa*dfa + else + bf(c+10) = (sfluxavg_quad_cutoff-sfluxavgref)*(2.0_rp*dfa - (sfluxavg_quad_cutoff-sfluxavgref)) + endif + bf(c+11) = bf(c+10)*plg(2,0) !P(2,0) modulation of truncated quadratic F10.7a term + bf(c+12) = bf(c+10)*plg(4,0) !P(4,0) modulation of truncated quadratic F10.7a term + bf(c+13) = df*plg(2,0) !P(2,0) modulation of df --> (F10.7 - F10.7a) + bf(c+14) = df*plg(4,0) !P(4,0) modulation of df --> (F10.7 - F10.7a) + + !--------------------------------------------- + ! Nonlinear Terms + !--------------------------------------------- + + c = cnonlin + + ! Solar flux modulation terms + if (c .ne. csfxmod) stop 'problem with basis definitions' + bf(c) = dfa + bf(c+1) = dfa*dfa + bf(c+2) = df + bf(c+3) = df*df + bf(c+4) = df*dfa + c = c + nsfxmod + + ! Terms needed for legacy geomagnetic activity dependence + if (c .ne. cmag) stop 'problem with basis set' + bf(c:c+6) = ap - 4.0 + bf(c+8) = doy2rad*doy + bf(c+9) = lst2rad*lst + bf(c+10) = deg2rad*lon + bf(c+11) = lst2rad*utsec/3600.0 + bf(c+12) = abs(lat) + c = c + 13 + do m = 0,1 + do n = 0,amaxn + bf(c) = plg(n,m) + c = c + 1 + enddo + enddo + + ! Terms needed for legacy UT dependence + c = cut + bf(c) = lst2rad*utsec/3600.0 + bf(c+1) = doy2rad*doy + bf(c+2) = dfa + bf(c+3) = deg2rad*lon + bf(c+4) = plg(1,0) + bf(c+5) = plg(3,0) + bf(c+6) = plg(5,0) + bf(c+7) = plg(3,2) + bf(c+8) = plg(5,2) + + !--------------------------------------------- + ! Apply Switches + !--------------------------------------------- + where(.not. swg(0:mbf)) bf(0:mbf) = 0.0_rp + + return + + end subroutine globe + + !================================================================================================== + ! SOLZEN: Calculate solar zenith angle (adapted from IRI subroutine) + !================================================================================================== + real(kind=rp) function solzen(ddd,lst,lat,lon) + + use msis_constants, only : pi, deg2rad + + implicit none + + real(kind=rp), intent(in) :: ddd + real(kind=rp), intent(in) :: lst + real(kind=rp), intent(in) :: lat + real(kind=rp), intent(in) :: lon + + real(kind=rp) :: wlon,dec + real(kind=rp) :: teqnx,tf,teqt + real(kind=rp) :: rlat,phi,cosx + real(kind=rp), parameter :: humr = pi/12.0_rp + real(kind=rp), parameter :: dumr = pi/182.5_rp + real(kind=rp), parameter :: p(5) = (/0.017203534,0.034407068,0.051610602,0.068814136,0.103221204/) + + wlon = 360.0 - lon + teqnx = ddd + (lst + wlon / 15.0_rp) / 24.0_rp + 0.9369_rp + teqnx = ddd + 0.9369_rp + + ! Solar declination + dec = 23.256_rp * sin(p(1) * (teqnx - 82.242_rp)) + 0.381_rp * sin(p(2)*(teqnx - 44.855_rp)) & + + 0.167_rp * sin(p(3) * (teqnx - 23.355_rp)) - 0.013_rp * sin(p(4)*(teqnx + 11.97_rp)) & + + 0.011_rp * sin(p(5) * (teqnx - 10.410_rp)) + 0.339137_rp + dec = dec * deg2rad + + ! Equation of time + tf = teqnx - 0.5_rp + teqt = -7.38_rp * sin(p(1) * (tf - 4.0_rp)) - 9.87_rp * sin(p(2) * (tf + 9.0_rp)) & + + 0.27_rp * sin(p(3) * (tf - 53.0_rp)) - 0.2_rp * cos(p(4) * (tf - 17.0_rp)) + + phi = humr * (lst - 12.0_rp) + teqt * deg2rad / 4.0_rp + rlat = lat * deg2rad + + ! Cosine of solar zenith angle + cosx = sin(rlat) * sin(dec) + cos(rlat) * cos(dec) * cos(phi) + if (abs(cosx) .gt. 1.0_rp) cosx = sign(1.0_rp,cosx) + + solzen = acos(cosx) / deg2rad + + return + + end function solzen + + !================================================================================================== + ! SFLUXMOD: Legacy nonlinear modulation of intra-annual, tide, and SPW terms + !================================================================================================== + real(kind=rp) function sfluxmod(iz,gf,parmset,dffact) + + use msis_constants, only : maxnbf, mbf, csfx, csfxmod + use msis_init, only : basissubset, zsfx, tsfx, psfx + + implicit none + + integer, intent(in) :: iz + real(kind=rp), intent(in) :: gf(0:maxnbf-1) + type(basissubset), intent(in) :: parmset + real(kind=rp), intent(in) :: dffact !Turns on or adjusts the delta-F terms added to F1 and F2 (eqns. A22b and A22c in Hedin (1987)). + + real(kind=rp) :: f1, f2, f3, sum + integer :: j + + ! Intra-annual modulation factor + if (swg(csfxmod)) then + f1 = parmset%beta(csfxmod,iz) * gf(csfxmod) & + + (parmset%beta(csfx+2,iz) * gf(csfxmod+2) + parmset%beta(csfx+3,iz) * gf(csfxmod+3) ) * dffact + else + f1 = 0.0_rp + endif + + ! Migrating tide (local time) modulation factor + if (swg(csfxmod+1)) then + f2 = parmset%beta(csfxmod+1,iz) * gf(csfxmod) & + + (parmset%beta(csfx+2,iz) * gf(csfxmod+2) + parmset%beta(csfx+3,iz) * gf(csfxmod+3) ) * dffact + else + f2 = 0.0_rp + endif + + ! SPW (longitude) modulation factor + if (swg(csfxmod+2)) then + f3 = parmset%beta(csfxmod+2,iz) * gf(csfxmod) + else + f3 = 0.0_rp + endif + + sum = 0.0 + do j = 0, mbf + ! Apply intra-annual modulation + if (zsfx(j)) then + sum = sum + parmset%beta(j,iz)*gf(j)*f1 + cycle + endif + ! Apply migrating tide modulation + if (tsfx(j)) then + sum = sum + parmset%beta(j,iz)*gf(j)*f2 + cycle + endif + ! Apply SPW modulation + if (psfx(j)) then + sum = sum + parmset%beta(j,iz)*gf(j)*f3 + cycle + endif + enddo + + sfluxmod = sum + + return + + end function sfluxmod + + !================================================================================================== + ! GEOMAG: Legacy nonlinear ap dependence (daily ap mode and ap history mode), including mixed + ! ap/UT/Longitude terms. + ! Master switch control is as follows: + ! swg(cmag) .nor. swg(cmag+1) Do nothing: Return zero + ! swg(cmag) .and. swg(cmag+1) Daily Ap mode + ! swg(cmag) .neqv. swg(cmag+1) 3-hour ap history mode + !================================================================================================== + real(kind=rp) function geomag(p0,bf,plg) + + use msis_constants, only : nmag, cmag + + implicit none + + real(kind=rp), intent(in) :: p0(0:nmag-1) + real(kind=rp), intent(in) :: bf(0:12) + real(kind=rp), intent(in) :: plg(0:6,0:1) + + logical :: swg1(0:nmag-1) !Copy of switches + real(kind=rp) :: p(0:nmag-1) !Copy of parameters used to apply switches + real(kind=rp) :: delA, gbeta, ex, sumex, G(1:6) + integer(4) :: i + + ! Return zero if both master switches are off + if (.not. (swg(cmag) .or. swg(cmag+1))) then + geomag = 0.0_rp + return + endif + + ! Copy parameters + p = p0 + swg1 = swg(cmag:cmag+nmag-1) + + ! Calculate function + if (swg1(0) .eqv. swg1(1)) then + ! Daily Ap mode + if (p(1) .eq. 0) then !If k00s is zero, then cannot compute function + geomag = 0.0_rp + return + endif + where(.not. swg1(2:25)) p(2:25) = 0.0_rp !Apply switches + p(8) = p0(8) !Need doy phase term + delA = G0fn(bf(0),p(0),p(1)) + geomag = ( p(2)*plg(0,0) + p(3)*plg(2,0) + p(4)*plg(4,0) & ! time independent + + (p(5)*plg(1,0) + p(6)*plg(3,0) + p(7)*plg(5,0)) * cos(bf(8) - p(8)) & ! doy modulation + + (p(9)*plg(1,1) + p(10)*plg(3,1) + p(11)*plg(5,1)) * cos(bf(9) - p(12)) & ! local time modulation + + (1.0_rp + p(13)*plg(1,0)) * & + (p(14)*plg(2,1) + p(15)*plg(4,1) + p(16)*plg(6,1)) * cos(bf(10) - p(17)) & ! longitude effect + + (p(18)*plg(1,1) + p(19)*plg(3,1) + p(20)*plg(5,1)) * cos(bf(10) - p(21)) * & + cos(bf(8) - p(8)) & ! longitude with doy modulaiton + + (p(22)*plg(1,0) + p(23)*plg(3,0) + p(24)*plg(5,0)) * cos(bf(11) - p(25)) ) & ! universal time + *delA + else + ! 3-hour ap history mode + if (p(28) .eq. 0) then !If beta00 is zero, then cannot compute function + geomag = 0.0 + return + endif + where(.not. swg1(30:)) p(30:) = 0.0 !Apply switches + p(36) = p0(36) !Need doy phase term + gbeta = p(28)/(1 + p(29)*(45.0_rp - bf(12))) + ex = exp(-10800.0_rp*gbeta) + sumex = 1 + (1 - ex**19.0_rp) * ex**(0.5_rp) / (1 - ex) + do i = 1, 6 + G(i) = G0fn(bf(i),p(26),p(27)) + enddo + delA = ( G(1) & + + ( G(2)*ex + G(3)*ex*ex + G(4)*ex**3.0_rp & + +(G(5)*ex**4.0_rp + G(6)*ex**12.0_rp)*(1-ex**8.0_rp)/(1-ex) ) ) / sumex + geomag = ( p(30)*plg(0,0) + p(31)*plg(2,0) + p(32)*plg(4,0) & ! time independent + + (p(33)*plg(1,0) + p(34)*plg(3,0) + p(35)*plg(5,0)) * cos(bf(8) - p(36)) & ! doy modulation + + (p(37)*plg(1,1) + p(38)*plg(3,1) + p(39)*plg(5,1)) * cos(bf(9) - p(40)) & ! local time modulation + + (1.0_rp + p(41)*plg(1,0)) * & + (p(42)*plg(2,1) + p(43)*plg(4,1) + p(44)*plg(6,1)) * cos(bf(10) - p(45)) & ! longitude effect + + (p(46)*plg(1,1) + p(47)*plg(3,1) + p(48)*plg(5,1)) * cos(bf(10) - p(49)) * & + cos(bf(8) - p(36)) & ! longitude with doy modulaiton + + (p(50)*plg(1,0) + p(51)*plg(3,0) + p(52)*plg(5,0)) * cos(bf(11) - p(53)) ) & ! universal time + *delA + endif + + return + + contains + + real(kind=rp) function G0fn(a,k00r,k00s) + real(kind=rp),intent(in) :: a, k00r, k00s + G0fn = a + (k00r - 1.0_rp) * (a + (exp(-a*k00s) - 1.0_rp)/k00s) + return + end function G0fn + + end function geomag + + !================================================================================================== + ! UTDEP: Legacy nonlinear UT dependence + !================================================================================================== + real(kind=rp) function utdep(p0,bf) + + use msis_constants, only : nut, cut + + implicit none + + real(kind=rp), intent(in) :: p0(0:nut-1) + real(kind=rp), intent(in) :: bf(0:8) + + real(kind=rp) :: p(0:nut-1) !Copy of parameters used to apply switches + logical :: swg1(0:nut-1) !Copy of switches + + !Copy parameters + p = p0 + swg1 = swg(cut:cut+nut-1) + where(.not. swg1(3:nut-1)) p(3:nut-1) = 0.0 !Apply switches + + ! Calculate function + utdep = cos(bf(0)-p(0)) * & + (1 + p(3)*bf(4)*cos(bf(1)-p(1))) * & + (1 + p(4)*bf(2)) * (1 + p(5)*bf(4)) * & + (p(6)*bf(4) + p(7)*bf(5) + p(8)*bf(6)) + & + cos(bf(0)-p(2)+2*bf(3)) * (p(9)*bf(7) + p(10)*bf(8)) * (1 + p(11)*bf(2)) + + return + + end function utdep + +end module msis_gfn diff --git a/sorc/chgres_cube.fd/msis2.1.fd/msis_gtd8d.F90 b/sorc/chgres_cube.fd/msis2.1.fd/msis_gtd8d.F90 new file mode 100644 index 000000000..1955a3cad --- /dev/null +++ b/sorc/chgres_cube.fd/msis2.1.fd/msis_gtd8d.F90 @@ -0,0 +1,147 @@ +!####################################################################### +! MSIS� (NRL-SOF-014-1) SOFTWARE +! NRLMSIS� empirical atmospheric model software. Use is governed by the +! Open Source Academic Research License Agreement contained in the file +! nrlmsis2.1_license.txt, which is part of this software package. BY +! USING OR MODIFYING THIS SOFTWARE, YOU ARE AGREEING TO THE TERMS AND +! CONDITIONS OF THE LICENSE. +!####################################################################### + +!!! =========================================================================== +!!! NRLMSIS 2.1: +!!! Neutral atmosphere empirical model from the surface to lower exosphere +!!! =========================================================================== +!!! +!!! GTD8D: Legacy wrapper with input and output arguments used in NRLMSISE-00 +! +! PREREQUISITES: +! Must first run MSISINIT to load parameters and set switches. The +! MSISCALC subroutine (called by this wrapper) checks for initialization +! and does a default initialization if necessary. This self-initialization +! will be removed in future versions. +! +! CALLING SEQUENCE: +! CALL GTD8D(IYD, SEC, ALT, GLAT, GLONG, STL, F107A, F107, AP, MASS, D, T) +! +! INPUT VARIABLES: +! IYD Year and day as YYDDD (day of year from 1 to 365 (or 366)) +! (Year is ignored in current model) +! SEC Universal time (seconds) +! ALT Geodetic altitude (km) +! GLAT Geodetic latitude (deg) +! GLONG Geodetic longitude (deg) +! STL Local solar time (Ignored; calculated from SEC and GLONG) +! F107A 81 day average, centered on input time, of F10.7 solar activity +! index +! F107 Daily F10.7 for previous day +! AP Geomagnetic activity index array: +! (1) Daily Ap +! (2) 3 hr ap index for current time +! (3) 3 hr ap index for 3 hrs before current time +! (4) 3 hr ap index for 6 hrs before current time +! (5) 3 hr ap index for 9 hrs before current time +! (6) Average of eight 3 hr ap indices from 12 to 33 hrs +! prior to current time +! (7) Average of eight 3 hr ap indices from 36 to 57 hrs +! prior to current time +! AP(2:7) are only used when switch_legacy(9) = -1.0 in MSISINIT +! MASS Mass number (Ignored in 2.0) +! +! NOTES ON INPUT VARIABLES: +! - If lzalt_type = .false. in the MSISINIT call, then the ALT input +! argument is treated as geopotential height. +! - The STL input argument is ignored in NRLMSIS 2.0. Instead, local time +! is computed from universal time and longitude. +! - F107 and F107A values are the 10.7 cm radio flux at the Sun-Earth +! distance, not the radio flux at 1 AU. +! - The MASS input argument is ignored in NRLMSIS 2.0; species to be +! calculated are set in MSISINIT. +! +! OUTPUT VARIABLES: +! D(1) He number density (cm-3) +! D(2) O number density (cm-3) +! D(3) N2 number density (cm-3) +! D(4) O2 number density (cm-3) +! D(5) Ar number density (cm-3) +! D(6) Total mass density (g/cm3) +! D(7) H number density (cm-3) +! D(8) N number density (cm-3) +! D(9) Anomalous oxygen number density (cm-3) +! D(10) NO number density (cm-3) +! T(1) Exospheric temperature (K) +! T(2) Temperature at altitude (K) +! +! NOTES ON OUTPUT VARIABLES: +! - Missing density values are returned as 9.999e-38 +! - Species included in mass density calculation are set in MSISINIT +! +!!! ========================================================================= + +!================================================================================================== +! GTD8D: Legacy wrapper +!================================================================================================== +subroutine gtd8d(iyd,sec,alt,glat,glong,stl,f107a,f107,ap,mass,d,t) + + use msis_constants, only : rp, dmissing + use msis_init, only : msisinit + use msis_calc, only : msiscalc + + implicit none + + ! MSIS Legacy subroutine arguments + integer, intent(in) :: iyd + real(4), intent(in) :: sec + real(4), intent(in) :: alt + real(4), intent(in) :: glat + real(4), intent(in) :: glong + real(4), intent(in) :: stl + real(4), intent(in) :: f107a + real(4), intent(in) :: f107 + real(4), intent(in) :: ap(7) + integer, intent(in) :: mass + real(4), intent(out) :: d(10), t(2) + + ! MSIS 1.97 subroutine arguments + real(kind=rp) :: xday + real(kind=rp) :: xutsec + real(kind=rp) :: xalt + real(kind=rp) :: xlat + real(kind=rp) :: xlon + real(kind=rp) :: xsfluxavg, xsflux + real(kind=rp) :: xap(1:7) + real(kind=rp) :: xtn + real(kind=rp) :: xdn(1:10) + real(kind=rp) :: xtex + + ! Convert the legacy input arguments to the new interface values and precision + xday = mod(iyd,1000) + xutsec = sec + xalt = alt + xlat = glat + xlon = glong + xsfluxavg = f107a + xsflux = f107 + xap = ap + + ! Call the new subroutine + call msiscalc(xday,xutsec,xalt,xlat,xlon,xsfluxavg,xsflux,xap,xtn,xdn,tex=xtex) + + ! Convert the output arguments to the legacy format (mks to cgs, re-order species) + t(1) = sngl(xtex) ! Expospheric temperature + t(2) = sngl(xtn) ! Temperature at altitude + where (xdn .ne. dmissing) xdn = xdn*1d-6 + if (xdn(1) .ne. dmissing) xdn(1) = xdn(1)*1e3_rp + d(1) = sngl(xdn(5)) ! [He] + d(2) = sngl(xdn(4)) ! [O] + d(3) = sngl(xdn(2)) ! [N2] + d(4) = sngl(xdn(3)) ! [O2] + d(5) = sngl(xdn(7)) ! [Ar] + d(6) = sngl(xdn(1)) ! Mass density + d(7) = sngl(xdn(6)) ! [H] + d(8) = sngl(xdn(8)) ! [N] + d(9) = sngl(xdn(9)) ! [Anomalous O] + d(10) = sngl(xdn(10)) ! [NO] + + return + +end subroutine gtd8d \ No newline at end of file diff --git a/sorc/chgres_cube.fd/msis2.1.fd/msis_init.F90 b/sorc/chgres_cube.fd/msis2.1.fd/msis_init.F90 new file mode 100644 index 000000000..e6dd54b25 --- /dev/null +++ b/sorc/chgres_cube.fd/msis2.1.fd/msis_init.F90 @@ -0,0 +1,638 @@ +!####################################################################### +! MSIS� (NRL-SOF-014-1) SOFTWARE +! NRLMSIS� empirical atmospheric model software. Use is governed by the +! Open Source Academic Research License Agreement contained in the file +! nrlmsis2.1_license.txt, which is part of this software package. BY +! USING OR MODIFYING THIS SOFTWARE, YOU ARE AGREEING TO THE TERMS AND +! CONDITIONS OF THE LICENSE. +!####################################################################### + +!!! =========================================================================== +!!! NRLMSIS 2.1: +!!! Neutral atmosphere empirical model from the surface to lower exosphere +!!! =========================================================================== +!!! +!!! MSISINIT: Initialization of MSIS parameters, switches, and options. +! +! PREREQUISITES: +! MSIS binary parameter file (msis207.parm) +! +! CALLING SEQUENCE: +! CALL MSISINIT([OPTIONAL ARGUMENTS]) +! +! OPTIONAL ARGUMENTS: +! parmpath File path pointing to the MSIS parameter file. +! Default: Null string (current directory) +! parmfile Name of MSIS parameter file. +! Default: 'msis21.parm' +! iun File unit number for reading parameter file. +! Default: 67 +! switch_gfn Logical array of 512 swtiches for individual terms. For +! advanced users. +! Default values: True (all switches on) +! switch_legacy Floating point array (1:25) of legacy switches that +! control groups of terms: +! 1 - F10.7 +! 2 - Time independent +! 3 - Symmetrical annual +! 4 - Symmetrical semiannual +! 5 - Asymmetrical annual +! 6 - Asymmetrical semiannual +! 7 - Diurnal +! 8 - Semidiurnal +! 9 - Geomagnetic activity: +! 1.0 = Daily Ap mode +! -1.0 = Storm-time ap mode +! 10 - All UT/long effects +! 11 - Longitudinal +! 12 - UT and mixed UT/long +! 13 - Mixed Ap/UT/long +! 14 - Terdiurnal +! 15-25 - Not used in NRLMSIS 2.07 +! For all switches: +! 0.0 = Off +! 1.0 = On +! 2.0 = Main effects off, cross terms on +! Default values: 1.0 +! lzalt_type Logical flag for altitude input type: +! True = Geodetic altitude (km) +! False = Geopotential height (km) +! Default: True (Geodetic altitude) +! lspec_select Logical array (1:10) flagging which densities to +! calculate. +! True = Calculate, False = Do not calculate +! 1 - Mass density +! 2 - N2 +! 3 - O2 +! 4 - O +! 5 - He +! 6 - H +! 7 - Ar +! 8 - N +! 9 - Anomalous O +! 10 - NO +! Default values: True +! lmass_include Logical array (1:10) flagging which species to include +! in mass density calculation. Same ordering as +! lspec_select. +! Default values: True +! lN2_msis00 Logical flag for retrieving NRLMSISE-00 upper +! thermospheric N2 variation. See paper for details. +! False: Thermospheric N2 determined entirely by +! temperature profile and the constant mixing ratio +! of N2 in the lower atmosphere. +! True: Upper thermospheric N2 relaxes to NRLMSISE-00 +! Values. +! Default: False +! +! NOTES: +! - The switch_legacy optional argument performs the same function as +! TSELEC(SW) in NRLSMSISE-00, except that switches 15-25 are not used in +! NRLMSIS 2.07. The change in the switch-setting call is illustrated as +! follows, where SW is the 25-element array of switches: +! NRLMSISE-00: CALL TSELEC(SW) +! NRLMSIS 2.07: call msisinit(switch_legacy=SW) +! +!!! =========================================================================== + +!************************************************************************************************** +! MSIS_INIT Module: Contains initialization subroutines, model options, and model parameters +!************************************************************************************************** +module msis_init + + use msis_constants, only : rp, nspec, nl, maxnbf, mbf + + implicit none + + !Model flags + logical :: initflag = .false. !Flags whether model has been initialized + logical :: haveparmspace = .false. !Flags whether parameter space has been initialized and allocated + logical :: zaltflag = .true. !true: height input is geometric, false: height input is geopotential + logical :: specflag(1:nspec-1) = .true. !Array flagging which species densities are required + logical :: massflag(1:nspec-1) = .true. !Array flagging which species should be included in mass density + logical :: N2Rflag = .false. !Flag for retrieving NRLMSISE-00 thermospheric N2 variations + logical :: zsfx(0:mbf) = .false. !Flags zonal mean terms to be modulated by F1 (MSISE-00 legacy multiplier) + logical :: tsfx(0:mbf) = .false. !Flags tide terms to be modulated by F2 (MSISE-00 legacy multiplier) + logical :: psfx(0:mbf) = .false. !Flags SPW terms to be modulated by F3 (MSISE-00 legacy multiplier) + logical :: smod(0:nl) = .false. !Flags which temperature levels get solar flux modulation; loadparmset turns flags on based on parameter values + logical :: swg(0:maxnbf-1) = .true. !Switch array for globe subroutine. + real(kind=rp) :: masswgt(1:nspec-1) = 0.0_rp !Weights for calculating mass density + real(4) :: swleg(1:25)=1.0, swc(1:25), sav(1:25) !Legacy switch arrays + + ! Model parameter arrays + type basissubset + sequence + character(8) :: name + integer :: bl,nl + real(kind=rp), allocatable :: beta(:,:) + logical, allocatable :: active(:,:) + integer, allocatable :: fitb(:,:) + end type basissubset + type (basissubset) :: TN + type (basissubset) :: PR + type (basissubset) :: N2 + type (basissubset) :: O2 + type (basissubset) :: O1 + type (basissubset) :: HE + type (basissubset) :: H1 + type (basissubset) :: AR + type (basissubset) :: N1 + type (basissubset) :: OA !Anomalous O + type (basissubset) :: NO + integer :: nvertparm + + ! Reciprocal node difference arrays (constant values needed for B-spline calculations) + real(kind=rp) :: etaTN(0:30,2:6) = 0.0_rp + real(kind=rp) :: etaO1(0:30,2:6) = 0.0_rp + real(kind=rp) :: etaNO(0:30,2:6) = 0.0_rp + + ! C1 constraint terms for O and NO related to the tapered logistic correction + real(kind=rp) :: HRfactO1ref, dHRfactO1ref, HRfactNOref, dHRfactNOref + +contains + + !================================================================================================== + ! MSISINIT: Entry point for initializing model and loading parameters + !================================================================================================== + subroutine msisinit(parmpath,parmfile,iun,switch_gfn,switch_legacy, & + lzalt_type,lspec_select,lmass_include,lN2_msis00) + + use msis_constants, only : specmass, nspec, maxnbf + + implicit none + + character(len=*), intent(in), optional :: parmpath !Path to parameter file + character(len=*), intent(in), optional :: parmfile !Parameter file name + integer, intent(in), optional :: iun !File unit number for reading parameter file + logical, intent(in), optional :: switch_gfn(0:maxnbf-1) !Switch array for globe subroutine. + real(4), intent(in), optional :: switch_legacy(1:25) !Legacy switch array + logical, intent(in), optional :: lzalt_type !true: height input is geometric, false: height input is geopotential + logical, intent(in), optional :: lspec_select(1:nspec-1) !Array flagging which species densities are required + logical, intent(in), optional :: lmass_include(1:nspec-1) !Array flagging which species should be included in mass density + logical, intent(in), optional :: lN2_msis00 !Flag for retrieving NRLMSISE-00 thermospheric N2 variations + + character(len=128) :: parmpath1 + character(len=300) :: parmfile1 + integer :: iun1 + + ! Path to parameter file + if (present(parmpath)) then + parmpath1 = parmpath + else + parmpath1 = '' + endif + + ! Parameter file name + if (present(parmfile)) then + parmfile1 = parmfile + else + parmfile1 = 'msis21.parm' + endif + + ! Initialize model parameter space + if (.not. haveparmspace) call initparmspace() + + ! Load parameter set + if (present(iun)) then + iun1 = iun + else + iun1 = 67 + endif + call loadparmset(trim(parmpath1)//trim(parmfile1),iun1) + + ! Set switches + swg(:) = .true. + swleg(:) = 1.0 + if (present(switch_gfn)) then + swg = switch_gfn + else + if (present(switch_legacy)) then + swleg = switch_legacy + call tselec(swleg) + endif + endif + + ! Input altitude type flag + if (present(lzalt_type)) then + zaltflag = lzalt_type + else + zaltflag = .true. + endif + + ! Species flags for number density and mass density + if (present(lspec_select)) then + specflag = lspec_select + else + specflag(:) = .true. + endif + if (specflag(1)) then + if (present(lmass_include)) then + massflag = lmass_include + else + massflag(:) = .true. + endif + else + massflag(:) = .false. + endif + where(massflag) specflag = .true. + masswgt(:) = 0.0_rp + where(massflag) masswgt = 1.0_rp + masswgt(1) = 0.0_rp + masswgt = masswgt * specmass + masswgt(10) = 0.0_rp + + ! Flag for retrieving NRLMSISE-00 thermospheric N2 variations + if (present(lN2_msis00)) then + N2Rflag = lN2_msis00 + else + N2Rflag = .false. + endif + + ! Set model initialization flag + initflag = .true. + + return + + end subroutine msisinit + + !================================================================================================== + ! INITPARMSPACE: Initialize and allocate the model parameter space + !================================================================================================== + subroutine initparmspace() + + use msis_constants, only : nl, nls, nodesTN, ndO1, nsplO1, nodesO1, nsplNO, ndNO, nodesNO, & + zetagamma, Hgamma, zetarefO1, zetarefNO, maxnbf, ctide, cspw + + implicit none + + integer :: n, m, j, k + real(kind=rp) :: gammaterm0 + + ! Vertical parameter counter (number of vertical parameters in the parmeter file) + nvertparm = 0 + + ! Model formulation parameter subsets + call initsubset(TN,0,nl, maxnbf,'TN') + call initsubset(PR,0,nl, maxnbf,'PR') + call initsubset(N2,0,nls, maxnbf,'N2') + call initsubset(O2,0,nls, maxnbf,'O2') + call initsubset(O1,0,nls+nsplO1,maxnbf,'O1') + call initsubset(HE,0,nls, maxnbf,'HE') + call initsubset(H1,0,nls, maxnbf,'H1') + call initsubset(AR,0,nls, maxnbf,'AR') + call initsubset(N1,0,nls, maxnbf,'N1') + call initsubset(OA,0,nls, maxnbf,'OA') + call initsubset(NO,0,nls+nsplNO,maxnbf,'NO') + + ! Add the surface pressure parameter to the vertical parameter counter + nvertparm = nvertparm + 1 + + ! Set solar flux modulation flags + zsfx(:) = .false. + tsfx(:) = .false. + psfx(:) = .false. + ! F1, solar flux modulation of the zonal mean asymmetric annual terms + zsfx(9:10) = .true. !Pl(1,0) annual terms + zsfx(13:14) = .true. !Pl(3,0) annual terms + zsfx(17:18) = .true. !Pl(5,0) annual terms + ! F2, solar sflux modulation of the tides + tsfx(ctide:cspw-1) = .true. + ! F3, solar sflux modulation of stationary planetary wave 1 + psfx(cspw:cspw+59) = .true. + + ! Calculate reciprocal node difference arrays + do k = 2, 6 + do j = 0, nl + etaTN(j,k) = 1.0_rp / (nodesTN(j+k-1) - nodesTN(j)) + enddo + enddo + do k = 2, 4 + do j = 0, ndO1-k+1 + etaO1(j,k) = 1.0_rp / (nodesO1(j+k-1) - nodesO1(j)) + enddo + do j = 0, ndNO-k+1 + etaNO(j,k) = 1.0_rp / (nodesNO(j+k-1) - nodesNO(j)) + enddo + enddo + + ! Calculate C1 constraint terms for O and NO related to the tapered logistic correction + gammaterm0 = tanh((zetarefO1 - zetagamma)*Hgamma) + HRfactO1ref = 0.5_rp * (1.0_rp + gammaterm0) + dHRfactO1ref = (1.0_rp - (zetarefO1 - zetagamma)*(1.0_rp - gammaterm0)*Hgamma) / HRfactO1ref + gammaterm0 = tanh((zetarefNO - zetagamma)*Hgamma) + HRfactNOref = 0.5_rp * (1.0_rp + gammaterm0) + dHRfactNOref = (1.0_rp - (zetarefNO - zetagamma)*(1.0_rp - gammaterm0)*Hgamma) / HRfactNOref + + ! Set parameter space initialization flag + haveparmspace = .true. + + return + + contains + + !-------------------------------------------------------------------------------------------------- + ! INITSUBSET: Initialize and allocate a parameter subset + !-------------------------------------------------------------------------------------------------- + subroutine initsubset(subset,bl,nl,maxnbf,name) + + implicit none + + type (basissubset), intent(inout) :: subset + integer, intent(in) :: bl + integer, intent(in) :: nl + integer, intent(in) :: maxnbf + character(2), intent(in) :: name + + integer :: iz + + ! Allocate and initialize subset structure + subset%name = name + subset%bl = bl + subset%nl = nl + allocate(subset%beta(0:maxnbf-1,bl:nl), & + subset%active(0:maxnbf-1,bl:nl), & + subset%fitb(0:maxnbf-1,bl:nl)) + subset%beta = 0.0_rp + subset%active = .false. + subset%fitb = 0 + + ! Increment vertical parameter counter except for pressure + if (name .ne. 'PR') nvertparm = nvertparm + nl - bl + 1 + + return + + end subroutine initsubset + + end subroutine initparmspace + + !================================================================================================== + ! LOADPARMSET: Read in a parameter file + !================================================================================================== + subroutine loadparmset(name,iun) + + use mpi + + use msis_constants, only : maxnbf, csfxmod + + implicit none + + character(len=*), intent(in) :: name + integer, intent(in) :: iun + + integer :: i0, i1 + integer :: ierr + logical :: havefile + real(8), allocatable :: parmin(:,:) + + ! Check if file exists + inquire(file=trim(name),exist=havefile) + if (havefile) then + open(unit=iun,file=trim(name),status='old',access='stream',convert='little_endian') + else + print *,"FATAL ERROR: MSIS parameter set ",trim(name)," not found. Stopping." + call mpi_abort(mpi_comm_world, 999, ierr) + endif + + ! Read in parameter values into temporary double-precision array + allocate(parmin(0:maxnbf-1,0:nvertparm-1)) + read(iun) parmin + close(iun) + + ! Transfer parameters to structures + i0 = 0 + i1 = TN%nl - TN%bl + TN%beta = parmin(:,i0:i1) + i0 = i1 + 1 + i1 = i0 + PR%beta(:,0) = parmin(:,i0) + i0 = i1 + 1 + i1 = i0 + N2%nl - N2%bl + N2%beta = parmin(:,i0:i1) + i0 = i1 + 1 + i1 = i0 + O2%nl - O2%bl + O2%beta = parmin(:,i0:i1) + i0 = i1 + 1 + i1 = i0 + O1%nl - O1%bl + O1%beta = parmin(:,i0:i1) + i0 = i1 + 1 + i1 = i0 + HE%nl - HE%bl + HE%beta = parmin(:,i0:i1) + i0 = i1 + 1 + i1 = i0 + H1%nl - H1%bl + H1%beta = parmin(:,i0:i1) + i0 = i1 + 1 + i1 = i0 + AR%nl - AR%bl + AR%beta = parmin(:,i0:i1) + i0 = i1 + 1 + i1 = i0 + N1%nl - N1%bl + N1%beta = parmin(:,i0:i1) + i0 = i1 + 1 + i1 = i0 + OA%nl - OA%bl + OA%beta = parmin(:,i0:i1) + i0 = i1 + 1 + i1 = i0 + NO%nl - NO%bl + NO%beta = parmin(:,i0:i1) + + !Set solar flux modulation flags; if on for a given vertical parameter, then sfluxmod is called by tfnparm + smod(:) = .false. + where((Tn%beta(csfxmod+0,:) .ne. 0) .or. & + (Tn%beta(csfxmod+1,:) .ne. 0) .or. & + (Tn%beta(csfxmod+2,:) .ne. 0)) smod = .true. + + ! Compute log pressure spline coefficients from temperature spline coeffcients + call pressparm() + + return + + end subroutine loadparmset + + !================================================================================================== + ! PRESSPARM: Compute log pressure spline coefficients from temperature spline coeffcients + !================================================================================================== + subroutine pressparm() + + use msis_constants, only : Mbarg0divkB, izfmx, mbf, gwht + + implicit none + + integer :: j, b, iz + real(kind=rp) :: lnz + + !Integrate pressure on nodes up to the last fully mixed level + do j = 0, mbf + lnz = 0.0 + do b = 0, 3 + lnz = lnz + TN%beta(j,b)*gwht(b)*Mbarg0divkB + enddo + PR%beta(j,1) = -lnz + do iz = 1, izfmx + lnz = 0.0 + do b = 0, 3 + lnz = lnz + TN%beta(j,iz+b)*gwht(b)*Mbarg0divkB + enddo + PR%beta(j,iz+1) = PR%beta(j,iz) - lnz + enddo + enddo + + return + + end subroutine pressparm + + !================================================================================================== + ! TSELEC: Legacy switches and mapping to new switches + !================================================================================================== + subroutine tselec(sv) + + use msis_constants, only : nsfx, nsfxmod, nut, cspw, csfx, csfxmod, cmag, cut + + implicit none + + real(4), intent(in) :: sv(1:25) + + integer :: i + + !Set cross-terms flags + do i = 1, 25 + sav(i) = sv(i) + swleg(i) = amod(sv(i), 2.0) + if(abs(sv(i)) .eq. 1.0 .or. abs(sv(i)) .eq. 2.0) then + swc(i) = 1.0 + else + swc(i) = 0.0 + endif + enddo + + !Main effects + swg(0) = .true. !Global term must be on + swg(csfx:csfx+nsfx-1) = (swleg(1) .eq. 1.0) !Solar flux + swg(310) = (swleg(1) .eq. 1.0) !Solar flux (truncated quadratic F10.7a function) + swg(1:6) = (swleg(2) .eq. 1.0) !Time independent + swg(304:305) = (swleg(2) .eq. 1.0) !Time independent (extra, F10.7a modulated terms) + swg(311:312) = (swleg(2) .eq. 1.0) !Time independent (extra, truncated quadratic F10.7a modulated terms) + swg(313:314) = (swleg(2) .eq. 1.0) !Time independent (extra, dF10.7 modulated terms) + swg((/7,8,11,12,15,16,19,20/)) = (swleg(3) .eq. 1.0) !Symmetric annual + swg(306:307) = (swleg(3) .eq. 1.0) !Global AO (extra, solar-flux modulated terms) + swg((/21,22,25,26,29,30,33,34/)) = (swleg(4) .eq. 1.0) !Symmetric semiannual + swg(308:309) = (swleg(4) .eq. 1.0) !Global SAO (extra, solar-flux modulated terms) + swg((/9,10,13,14,17,18/)) = (swleg(5) .eq. 1.0) !Asymmetric annual + swg((/23,24,27,28,31,32/)) = (swleg(6) .eq. 1.0) !Asymmetric semiannual + swg(35:94) = (swleg(7) .eq. 1.0) !Diurnal + swg(300:303) = (swleg(7) .eq. 1.0) !Solar zenith angle + swg(95:144) = (swleg(8) .eq. 1.0) !Semidiurnal + swg(145:184) = (swleg(14) .eq. 1.0) !Terdiurnal + swg(cmag:cmag+1) = .false. !Geomagnetic activity mode master switch + if((swleg(9) .gt. 0) .or. (swleg(13) .eq. 1)) swg(cmag:cmag+1) = (/.true.,.true./) !Daily mode master switch + if(swleg(9) .lt. 0) swg(cmag:cmag+1) = (/.false.,.true./) !Storm-time mode master switch + swg(cmag+2:cmag+12) = (swleg(9) .eq. 1.0) !Daily geomagnetic activity terms + swg(cmag+28:cmag+40) = (swleg(9) .eq. -1.0) !Storm-time geomagnetic activity terms + swg(cspw:csfx-1) = ((swleg(11) .eq. 1.0) .and. (swleg(10) .eq. 1.0)) !Longitudinal + swg(cut:cut+nut-1) = ((swleg(12) .eq. 1.0) .and. (swleg(10) .eq. 1.0)) !UT/Lon + swg(cmag+13:cmag+25) = ((swleg(13) .eq. 1.0) .and. (swleg(10) .eq. 1.0)) !Mixed UT/Lon/Geomag (Daily mode terms) + swg(cmag+41:cmag+53) = ((swleg(13) .eq. 1.0) .and. (swleg(10) .eq. 1.0)) !Mixed UT/Lon/Geomag (Storm-time mode terms) + + !Cross terms + swg(csfxmod:csfxmod+nsfxmod-1) = (swc(1) .eq. 1.0) !Solar activity modulation + if (swc(1) .eq. 0) then !Solar activity modulation + swg(302:303) = .false. !Solar zenith angle + swg(304:305) = .false. !Time independent + swg(306:307) = .false. !Global AO + swg(308:309) = .false. !Global SAO + swg(311:314) = .false. !Time independent + swg(447) = .false. !UT/Lon + swg(454) = .false. !UT/Lon + endif + if (swc(2) .eq. 0) then !Time independent (latitude terms) (in MSISE-00, SWC(2) is not used - latitude modulations are always on) + swg(9:20) = .false. !AO + swg(23:34) = .false. !SAO + swg(35:184) = .false. !All tides + swg(185:294) = .false. !All SPW + swg(392:414) = .false. !Daily geomagnetic activity + swg(420:442) = .false. !Storm-time geomagnetic activity + swg(449:453) = .false. !UT/Lon + endif + if (swc(3) .eq. 0) then !Symmetric annual + swg(201:204) = .false. !SPW1 (2,1) + swg(209:212) = .false. !SPW1 (4,1) + swg(217:220) = .false. !SPW1 (6,1) + swg(255:258) = .false. !SPW2 (2,2) + swg(263:266) = .false. !SPW2 (4,2) + swg(271:274) = .false. !SPW2 (6,2) + swg(306:307) = .false. !Global AO solar flux modulation + endif + if (swc(4) .eq. 0) then !Symmetric semiannual + swg(225:228) = .false. !SPW1 (2,1) + swg(233:236) = .false. !SPW1 (4,1) + swg(241:244) = .false. !SPW1 (6,1) + swg(275:278) = .false. !SPW2 (2,2) + swg(283:286) = .false. !SPW2 (4,2) + swg(291:294) = .false. !SPW2 (6,2) + swg(308:309) = .false. !Global SAO solar flux modulation + endif + if (swc(5) .eq. 0) then !Asymmetric annual + swg(47:50) = .false. !Diurnal (1,1) + swg(51:54) = .false. !Diurnal (2,1) !In MSISE-00, swc(5) is applied to all annual modulated tides + swg(55:58) = .false. !Diurnal (3,1) + swg(59:62) = .false. !Diurnal (4,1) + swg(63:66) = .false. !Diurnal (5,1) + swg(67:70) = .false. !Diurnal (6,1) + swg(105:108) = .false. !Semidiurnal (2,2) + swg(109:112) = .false. !Semidiurnal (3,2) + swg(113:116) = .false. !Semidiurnal (4,2) + swg(117:120) = .false. !Semidiurnal (5,2) + swg(121:124) = .false. !Semidiurnal (6,2) + swg(153:156) = .false. !Terdiurnal (3,3) + swg(157:160) = .false. !Terdiurnal (4,3) + swg(161:164) = .false. !Terdiurnal (5,3) + swg(165:168) = .false. !Terdiurnal (6,3) + swg(197:200) = .false. !SPW1 (1,1) + swg(205:208) = .false. !SPW1 (3,1) + swg(213:216) = .false. !SPW1 (5,1) + swg(259:262) = .false. !SPW2 (3,2) + swg(267:270) = .false. !SPW2 (5,2) + swg(394:397) = .false. !Geomag (Daily mode terms) + swg(407:410) = .false. !Mixed UT/Lon/Geomag (Daily mode terms) + swg(422:425) = .false. !Geomag (Storm-time mode terms) + swg(435:438) = .false. !Mixed UT/Lon/Geomag (Storm-time mode terms) + swg(446) = .false. !UT/Lon + endif + if (swc(6) .eq. 0) then !Asymmetric semiannual + swg(221:224) = .false. !SPW1 (1,1) + swg(229:232) = .false. !SPW1 (3,1) + swg(237:240) = .false. !SPW1 (5,1) + swg(279:282) = .false. !SPW2 (3,2) + swg(287:290) = .false. !SPW2 (5,2) + endif + if (swc(7) .eq. 0) then !Diurnal + swg(398:401) = .false. !Geomag (Daily mode terms) + swg(426:429) = .false. !Geomag (Storm-time mode terms) + endif + if (swc(11) .eq. 0) then !Longitude + swg(402:410) = .false. !Mixed UT/Lon/Geomag (Daily mode terms) + swg(430:438) = .false. !Mixed UT/Lon/Geomag (Storm-time mode terms) + swg(452:453) = .false. !UT/Lon + endif + if (swc(12) .eq. 0) then !UT/Lon + swg(411:414) = .false. !Mixed UT/Lon/Geomag (Daily mode terms) + swg(439:440) = .false. !Mixed UT/Lon/Geomag (Storm-time mode terms) + endif + + end subroutine tselec + + !================================================================================================== + ! TRETRV: Legacy routine for retrieving switch settings + !================================================================================================== + subroutine tretrv(svv) + + implicit none + + real(4), intent(out) :: svv(1:25) + + integer :: i + + do i = 1, 25 + svv(i) = sav(i) + enddo + + end subroutine tretrv + +end module msis_init diff --git a/sorc/chgres_cube.fd/msis2.1.fd/msis_tfn.F90 b/sorc/chgres_cube.fd/msis2.1.fd/msis_tfn.F90 new file mode 100644 index 000000000..6f601799b --- /dev/null +++ b/sorc/chgres_cube.fd/msis2.1.fd/msis_tfn.F90 @@ -0,0 +1,176 @@ +!####################################################################### +! MSIS� (NRL-SOF-014-1) SOFTWARE +! NRLMSIS� empirical atmospheric model software. Use is governed by the +! Open Source Academic Research License Agreement contained in the file +! nrlmsis2.1_license.txt, which is part of this software package. BY +! USING OR MODIFYING THIS SOFTWARE, YOU ARE AGREEING TO THE TERMS AND +! CONDITIONS OF THE LICENSE. +!####################################################################### + +!!! =========================================================================== +!!! NRLMSIS 2.1: +!!! Neutral atmosphere empirical model from the surface to lower exosphere +!!! =========================================================================== + +!************************************************************************************************** +! MSIS_TFN Module: Contains vertical temperature profile parameters and subroutines, including +! temperature integration terms. +!************************************************************************************************** +module msis_tfn + + use msis_constants, only : rp, nl + + type tnparm + sequence + real(kind=rp) :: cf(0:nl) ! Spline coefficients + real(kind=rp) :: tzetaF ! Tn at zetaF + real(kind=rp) :: tzetaA ! Tn at zetaA (reference altitude for O1, H1) + real(kind=rp) :: dlntdzA ! log-temperature gradient at zetaA (km^-1) + real(kind=rp) :: lndtotF ! ln total number density at zetaF (m^-3) + real(kind=rp) :: tex + real(kind=rp) :: tgb0 + real(kind=rp) :: tb0 + real(kind=rp) :: sigma + real(kind=rp) :: sigmasq + real(kind=rp) :: b ! b = 1-tb0/tex + real(kind=rp) :: beta(0:nl) ! 1st integration coefficients on k=5 splines + real(kind=rp) :: gamma(0:nl) ! 2nd integration coefficients on k=6 splines + real(kind=rp) :: cVs ! 1st integration constant (spline portion) + real(kind=rp) :: cVb ! 1st integration constant (Bates portion) + real(kind=rp) :: cWs ! 2nd integration constant (spline portion) + real(kind=rp) :: cWb ! 2nd integration constant (Bates portion) + real(kind=rp) :: VzetaF ! 1st indefinite integral at zetaF + real(kind=rp) :: VzetaA ! 1st indefinite integral at zetaA + real(kind=rp) :: WzetaA ! 2nd indefinite integral at zetaA + real(kind=rp) :: Vzeta0 ! 1st indefinite integral at zeta=0 (needed for pressure calculation) + end type tnparm + + contains + + !================================================================================================== + ! TFNPARM: Compute the vertical temperature and species-independent profile parameters + !================================================================================================== + subroutine tfnparm(gf,tpro) + + use msis_constants, only : kB, lnP0, Mbarg0divkB, zetaB, zetaA, izfx, izax, itex, itgb0, itb0, c2tn, & + maxnbf, mbf, nmag, nut, cmag, cut, & + wbeta, wgamma, S5zetaB, S6zetaB, wghtAxdz, S4zetaA, S5zetaA, S6zetaA, & + S4zetaF, S5zetaF, S5zeta0 + use msis_init, only : smod, TN, PR + use msis_gfn, only : sfluxmod, geomag, utdep + use msis_utils, only : dilog + + implicit none + + real(kind=rp), intent(in) :: gf(0:maxnbf-1) ! Array of horizontal and temporal basis function terms + type(tnparm), intent(out) :: tpro ! Output structure containing temperature vertical profile parameters + + integer(4) :: ix + real(kind=rp) :: bc(3) + + ! Unconstrained spline coefficients + do ix = 0, itb0-1 + tpro%cf(ix) = dot_product(TN%beta(0:mbf,ix),gf(0:mbf)) + enddo + do ix = 0, itb0-1 + if (smod(ix)) then + tpro%cf(ix) = tpro%cf(ix) + sfluxmod(ix,gf,TN,1.0_rp/TN%beta(0,ix)) !sfluxmod adds F10.7 modulation of tides + endif + enddo + + ! Exospheric temperature + tpro%tex = dot_product(TN%beta(0:mbf,itex),gf(0:mbf)) + tpro%tex = tpro%tex + sfluxmod(itex,gf,TN,1.0_rp/TN%beta(0,itex)) + tpro%tex = tpro%tex + geomag(TN%beta(cmag:cmag+nmag-1,itex),gf(cmag:cmag+12),gf(cmag+13:cmag+26)) + tpro%tex = tpro%tex + utdep(TN%beta(cut:cut+nut-1,itex),gf(cut:cut+8)) + + ! Temperature gradient at zetaB (122.5 km) + tpro%tgb0 = dot_product(TN%beta(0:mbf,itgb0),gf(0:mbf)) + if (smod(itgb0)) tpro%tgb0 = tpro%tgb0 + sfluxmod(itgb0,gf,TN,1.0_rp/TN%beta(0,itgb0)) + tpro%tgb0 = tpro%tgb0 + geomag(TN%beta(cmag:cmag+nmag-1,itgb0),gf(cmag:cmag+12),gf(cmag+13:cmag+26)) + + ! Temperature at zetaB (122.5 km) + tpro%tb0 = dot_product(TN%beta(0:mbf,itb0),gf(0:mbf)) + if (smod(itb0)) tpro%tb0 = tpro%tb0 + sfluxmod(itb0,gf,TN,1.0_rp/TN%beta(0,itb0)) + tpro%tb0 = tpro%tb0 + geomag(TN%beta(cmag:cmag+nmag-1,itb0),gf(cmag:cmag+12),gf(cmag+13:cmag+26)) + + ! Shape factor + tpro%sigma = tpro%tgb0/(tpro%tex-tpro%tb0) + + ! Constrain top three spline coefficients for C2 continuity + bc(1) = 1.0_rp/tpro%tb0 + bc(2) = -tpro%tgb0/(tpro%tb0*tpro%tb0) + bc(3) = -bc(2)*(tpro%sigma + 2.0_rp*tpro%tgb0/tpro%tb0) + tpro%cf(itb0:itex) = matmul(bc, c2tn) + + ! Reference temperature at zetaF (70 km) + tpro%tzetaF = 1.0_rp / dot_product(tpro%cf(izFx:izFx+2),S4zetaF) + + ! Reference temperature and gradient at zetaA (85 km) + tpro%tzetaA = 1.0_rp / dot_product(tpro%cf(izAx:izAx+2),S4zetaA) + tpro%dlntdzA = -dot_product(tpro%cf(izAx:izAx+2),wghtAxdz) * tpro%tzetaA + + ! Calculate spline coefficients for first and second 1/T integrals + tpro%beta(0) = tpro%cf(0)*wbeta(0) + do ix = 1, nl + tpro%beta(ix) = tpro%beta(ix-1) + tpro%cf(ix)*wbeta(ix) + enddo + tpro%gamma(0) = tpro%beta(0)*wgamma(0) + do ix = 1, nl + tpro%gamma(ix) = tpro%gamma(ix-1) + tpro%beta(ix)*wgamma(ix) + enddo + + ! Integration terms and constants + tpro%b = 1 - tpro%tb0 / tpro%tex + tpro%sigmasq = tpro%sigma * tpro%sigma + tpro%cVS = -dot_product(tpro%beta(itb0-1:itb0+2),S5zetaB) + tpro%cWS = -dot_product(tpro%gamma(itb0-2:itb0+2),S6zetaB) + tpro%cVB = -log(1-tpro%b) / (tpro%sigma * tpro%tex) + tpro%cWB = -dilog(tpro%b) / (tpro%sigmasq * tpro%tex) + tpro%VzetaF = dot_product(tpro%beta(izfx-1:izfx+2),S5zetaF) + tpro%cVS + tpro%VzetaA = dot_product(tpro%beta(izax-1:izax+2),S5zetaA) + tpro%cVS + tpro%WzetaA = dot_product(tpro%gamma(izax-2:izax+2),S6zetaA) + tpro%cVS*(zetaA-zetaB) + tpro%cWS + tpro%Vzeta0 = dot_product(tpro%beta(0:2),S5zeta0) + tpro%cVS + + ! Compute total number density at zetaF + tpro%lndtotF = lnP0 - Mbarg0divkB*(tpro%VzetaF - tpro%Vzeta0) - log(kB*tpro%TzetaF) + + return + + end subroutine tfnparm + + !================================================================================================== + ! TFNX: Compute the temperature at specified geopotential height + !================================================================================================== + real(kind=rp) function tfnx(z,iz,wght,tpro) + + use msis_constants, only : zetaB + + implicit none + + real(kind=rp), intent(in) :: z ! Geopotential height + integer, intent(in) :: iz ! Bspline reference index + real(kind=rp), intent(in) :: wght(-3:0) ! Bspline weights + type(tnparm), intent(in) :: tpro ! Structure containing temperature vertical profile parameters + + integer :: i, j + + if (z .lt. zetaB) then + ! Spline region + i = max(iz-3,0) + if (iz .lt. 3) then + j = -iz + else + j = -3 + endif + tfnx = 1.0_rp / dot_product(tpro%cf(i:iz),wght(j:0)) + else + ! Bates profile region + tfnx = tpro%tex - (tpro%tex - tpro%tb0)*exp(-tpro%sigma * (z - zetaB)) + endif + + return + + end function tfnx + +end module msis_tfn diff --git a/sorc/chgres_cube.fd/msis2.1.fd/msis_utils.F90 b/sorc/chgres_cube.fd/msis2.1.fd/msis_utils.F90 new file mode 100644 index 000000000..522dcd769 --- /dev/null +++ b/sorc/chgres_cube.fd/msis2.1.fd/msis_utils.F90 @@ -0,0 +1,282 @@ +!####################################################################### +! MSIS� (NRL-SOF-014-1) SOFTWARE +! NRLMSIS� empirical atmospheric model software. Use is governed by the +! Open Source Academic Research License Agreement contained in the file +! nrlmsis2.1_license.txt, which is part of this software package. BY +! USING OR MODIFYING THIS SOFTWARE, YOU ARE AGREEING TO THE TERMS AND +! CONDITIONS OF THE LICENSE. +!####################################################################### + +!!! =========================================================================== +!!! NRLMSIS 2.1: +!!! Neutral atmosphere empirical model from the surface to lower exosphere +!!! =========================================================================== + +!************************************************************************************************** +! MSIS_UTILS Module: Contains the following auxiliary subroutines: +! alt2gph: Converts geodetic altitude to geopotential height +! gph2alt: Converts geopotential height to geodetic altitude +! bspline: Computes B-splines using input nodes and up to specified order +! dilog: Computes dilogarithm function (expansion truncated at order 3, error < 1E-5) +!************************************************************************************************** + +module msis_utils + +contains + + !================================================================================================== + ! ALT2GPH: Altitude to Geopotential Height + ! References: + ! DMA Technical Report TR8350.2 (1987), + ! http://earth-info.nga.mil/GandG/publications/historic/historic.html + ! Featherstone, W. E., and S. J. Claessens (2008), Closed-form transformation between + ! geodetic and ellipsoidal coordinates, Studia Geophysica et Geodaetica, 52, 1-18 + ! Jekeli, C. (2009), Potential theory and static gravity field of the Earth, in + ! Treatise on Geophysics, ed. T. Herring, vol 3, 11-42 + ! NIMA Technical Report TR8350.2 (2000, 3rd edition, Amendment1), + ! http://earth-info.nga.mil/GandG/publications/tr8350.2/tr8350_2.html + !================================================================================================== + real(8) function alt2gph(lat,alt) + + implicit none + + ! Input variables + real(8), intent(in) :: lat !Geodetic latitude (deg) + real(8), intent(in) :: alt !Geodetic altitude (km) + + real(8), parameter :: deg2rad = 0.017453292519943295d0 + + ! WGS84 Defining parameters + real(8), parameter :: a = 6378.1370d0 * 1d3 !Semi-major axis of reference ellipsoid (m) + real(8), parameter :: finv = 298.257223563d0 ! 1/f = Reciprocal of flattening + real(8), parameter :: w = 7292115d-11 !Angular velocity of Earth rotation (rad/s) + real(8), parameter :: GM = 398600.4418 * 1d9 !Gravitational constant x Earth mass (m^3/s^2) + + ! WGS84 Derived parameters + real(8), parameter :: asq = a*a + real(8), parameter :: wsq = w*w + real(8), parameter :: f = 1.0d0 / finv + real(8), parameter :: esq = 2*f - f*f + real(8), parameter :: e = sqrt(esq) !Ellipsoid eccentricity + real(8), parameter :: Elin = a*e !Linear eccentricity of ellipsoid + real(8), parameter :: Elinsq = Elin*Elin + real(8), parameter :: epr = e / (1-f) !Second eccentricity + real(8), parameter :: q0 = ((1.0d0 + 3.0d0/(epr*epr))*atan(epr) - 3.0d0/epr)/2.0d0 !DMA Technical Report tr8350.2, Eq. 3-25 + real(8), parameter :: U0 = -GM*atan(epr)/Elin - wsq*asq/3d0 !Theoretical potential of reference ellipsoid (m^2/s^2) + real(8), parameter :: g0 = 9.80665d0 !Standard gravity (m/s^2), CGPM 1901; WMO + real(8), parameter :: GMdivElin = GM / Elin + + ! Parameters for centrifugal potential taper + real(8), parameter :: x0sq = 2d7**2 !Axial distance squared at which tapering begins (m^2) + real(8), parameter :: Hsq = 1.2d7**2 !Relaxation scale length of taper (m^2) + + ! Working variables + real(8) :: altm, sinsqlat, v, xsq, zsq + real(8) :: rsqminElinsq, usq, cossqdelta, epru, atanepru, q, U, Vc + + ! Compute Cartesian and ellipsoidal coordinates + altm = alt * 1000.0d0 + sinsqlat = sin(lat*deg2rad)**2 + v = a / sqrt(1-esq*sinsqlat) !Radius of curvature of the reference ellipsoid, Featherstone eq. 4 + xsq = (v + altm)**2 * (1 - sinsqlat) !Squared x-coordinate of geocentric system, Featherstone eq. 1 + zsq = (v*(1-esq) + altm)**2 * sinsqlat !Squared z-coordinate of geocentric system, Featherstone eq. 3 + rsqminElinsq = xsq + zsq - Elinsq + usq = rsqminElinsq/2.0d0 + sqrt(rsqminElinsq**2 / 4.0d0 + Elinsq*zsq) !Ellipsoidal distance coordinate, Featherstone eq. 19 + cossqdelta = zsq / usq !Ellipsoidal polar angle, Featherstone eq. 21 + + ! Compute gravitational potential + epru = Elin / sqrt(usq) !Second eccentricity at ellipsoidal coordinate u + atanepru = atan(epru) + q = ((1+3.0d0/(epru*epru))*atanepru - 3.0d0/epru)/2.0d0 !Jekeli, eq. 114 + U = -GMdivElin * atanepru - wsq * ( asq * q * (cossqdelta - 1/3.0d0) / q0 ) / 2.0d0 !Jekeli, eq. 113 + + ! Compute centrifugal potential and adjust total potential + if (xsq .le. x0sq) then + Vc = (wsq/2.0d0) * xsq + else + Vc = (wsq/2.0d0) * (Hsq*tanh((xsq-x0sq)/Hsq) + x0sq) !Centrifugal potential taper + endif + U = U - Vc + + ! Compute geopotential height + alt2gph = (U - U0) / g0 / 1000.0d0 + + return + + end function alt2gph + + !================================================================================================== + ! GPH2ALT: Geopotential Height to Altitude + !================================================================================================== + real(8) function gph2alt(theta,gph) + + implicit none + + real(8), intent(in) :: theta + real(8), intent(in) :: gph + + integer, parameter :: maxn = 10 + real(8), parameter :: epsilon = 0.0005 + + real(8) :: x,dx,y,dydz + integer :: n + + x = gph + n = 0 + dx = epsilon + epsilon + do while ((abs(dx) .gt. epsilon) .and. (n .lt. 10)) + y = alt2gph(theta,x) + dydz = (alt2gph(theta,x+dx) - y)/dx + dx = (gph - y)/dydz + x = x + dx + n = n + 1 + end do + + gph2alt = x + + end function gph2alt + + !================================================================================================== + ! BSPLINE: Returns array of nonzero b-spline values, for all orders up to specified order (max 6) + !================================================================================================== + subroutine bspline(x,nodes,nd,kmax,eta,S,i) + + use msis_constants, only: rp + + implicit none + + ! Input variables + real(kind=rp), intent(in) :: x !Location at which splines are to be evaluated + real(kind=rp),dimension(0:),intent(in) :: nodes !Spline node locations + integer, intent(in) :: nd !Number of spline nodes minus one (0:nd) + integer, intent(in) :: kmax !Maximum order (up to 6 allowed) of evaluated splines + real(kind=rp), intent(in) :: eta(0:30,2:6) !Precomputed weights for recursion (reciprocals of node differences) + ! Ouput variables + real(kind=rp), intent(out) :: S(-5:0,2:6) !b-spline values (spline index relative to i (-5:0), spline order (2:6)) + integer, intent(out) :: i !Index of last nonzero b-spline + + ! Working variables + integer :: j, k, l + integer :: low, high + real(kind=rp) :: w(-4:0) !Weights for recursion relation + + ! Initialize to zero + S(:,:) = 0.0_rp + + ! Find index of last (rightmost) nonzero spline + if (x .ge. nodes(nd)) then + i = nd + return + endif + if (x .le. nodes(0)) then + i = -1 + return + endif + low = 0 + high = nd + i = (low + high)/2 + do while (x .lt. nodes(i) .or. x .ge. nodes(i + 1)) + if (x .lt. nodes(i)) then + high = i + else + low = i + endif + i = (low + high)/2 + end do + + ! Initialize with linear splines + S(0,2) = (x - nodes(i)) * eta(i,2) + if (i .gt. 0) S(-1,2) = 1 - S(0,2) + if (i .ge. nd-1) S(0,2) = 0.0_rp !Reset out-of-bounds spline to zero + + ! k = 3 (quadratic splines) + w(:) = 0.0_rp + w(0) = (x - nodes(i)) * eta(i,3) + if (i .ne. 0) w(-1) = (x - nodes(i-1)) * eta(i-1,3) + if (i .lt. (nd-2)) S(0,3) = w(0)*S(0,2) + if ( ((i-1) .ge. 0) .and. ((i-1) .lt. (nd-2)) ) & + S(-1,3) = w(-1) * S(-1,2) + (1.0_rp - w(0))*S(0,2) + if ((i-2) .ge. 0) S(-2,3) = (1.0_rp - w(-1))*S(-1,2) + + ! k = 4 (cubic splines) + do l = 0, -2, -1 + j = i + l + if (j .lt. 0) exit !Skip out-of-bounds splines + w(l) = (x - nodes(j)) * eta(j,4) + enddo + if (i .lt. (nd-3)) S(0,4) = w(0)*S(0,3) + do l = -1, -2, -1 + if ( ((i+l) .ge. 0) .and. ((i+l) .lt. (nd-3)) ) & + S(l,4) = w(l)*S(l,3) + (1.0_rp - w(l+1))*S(l+1,3) + enddo + if ((i-3) .ge. 0) S(-3,4) = (1.0_rp - w(-2))*S(-2,3) + + ! k = 5 + do l = 0, -3, -1 + j = i + l + if (j .lt. 0) exit !Skip out-of-bounds splines + w(l) = (x - nodes(j)) * eta(j,5) + enddo + if (i .lt. (nd-4)) S(0,5) = w(0)*S(0,4) + do l = -1, -3, -1 + if ( ((i+l) .ge. 0) .and. ((i+l) .lt. (nd-4)) ) & + S(l,5) = w(l)*S(l,4) + (1.0_rp - w(l+1))*S(l+1,4) + enddo + if ((i-4) .ge. 0) S(-4,5) = (1.0_rp - w(-3))*S(-3,4) + if (kmax .eq. 5) return !Exit if only 5th order spline is needed + + ! k = 6 + do l = 0, -4, -1 + j = i + l + if (j .lt. 0) exit !Skip out-of-bounds splines + w(l) = (x - nodes(j)) * eta(j,6) + enddo + if (i .lt. (nd-5)) S(0,6) = w(0)*S(0,5) + do l = -1, -4, -1 + if ( ((i+l) .ge. 0) .and. ((i+l) .lt. (nd-5)) ) & + S(l,6) = w(l)*S(l,5) + (1.0_rp - w(l+1))*S(l+1,5) + enddo + if ((i-5) .ge. 0) S(-5,6) = (1.0_rp - w(-4))*S(-4,5) + + return + + end subroutine bspline + + !================================================================================================== + ! DILOG: Calculate dilogarithm in the domain [0,1) + ! Retains terms up to order 3 in the expansion, which results in relative errors less than 1E-5. + ! Reference: + ! Ginsberg, E. S., and D. Zaborowski (1975), The Dilogarithm function of a real argument, + ! Commun. ACM, 18, 200�202. + !================================================================================================== + real(kind=rp) function dilog(x0) + + use msis_constants, only : rp, pi + + implicit none + + real(kind=rp), intent(in) :: x0 + real(kind=rp), parameter :: pi2_6 = pi*pi / 6.0_rp + real(kind=rp) :: x, xx, x4, lnx + + x = x0 + if (x .gt. 0.5_rp) then + lnx = log(x) + x = 1.0_rp - x !Reflect argument into [0,0.5] range + xx = x*x + x4 = 4.0_rp*x + dilog = pi2_6 - lnx*log(x) & + - (4.0_rp*xx*(23.0_rp/16.0_rp + x/36.0_rp + xx/576.0_rp + xx*x/3600.0_rp) & + + x4 + 3.0_rp*(1.0_rp - xx)*lnx) / (1.0_rp + x4 + xx) + else + xx = x*x + x4 = 4.0_rp*x + dilog = (4.0_rp*xx*(23.0_rp/16.0_rp + x/36.0_rp + xx/576.0_rp + xx*x/3600.0_rp) & + + x4 + 3.0_rp*(1.0_rp - xx)*log(1.0_rp - x)) / (1.0_rp + x4 + xx) + endif + + return + + end function dilog + +end module msis_utils \ No newline at end of file diff --git a/sorc/chgres_cube.fd/msis2.1.fd/nrlmsis2.1_license.txt b/sorc/chgres_cube.fd/msis2.1.fd/nrlmsis2.1_license.txt new file mode 100644 index 000000000..244ab1922 --- /dev/null +++ b/sorc/chgres_cube.fd/msis2.1.fd/nrlmsis2.1_license.txt @@ -0,0 +1,71 @@ +MSIS� (NRL-SOF-014-1) SOFTWARE +OPEN SOURCE ACADEMIC RESEARCH LICENSE AGREEMENT + +1. Agreement. The MSIS� empirical atmospheric model software (hereinafter +�Software�) is property of The Government of the United States of America. This +software is being made available under the following terms and conditions. By +using, modifying, reproducing, or preparing a derivative work of this Software, +you agree to abide by the terms and conditions herein. + +2. License. In accordance with federal law, authorization is given to use, +reproduce, and modify the Software solely for research, academic, and non-profit +purposes and only in accordance with the terms and conditions in this Agreement. +Any commercial use is prohibited. No other rights or permissions are provided. + +3. Basis. The Software was written by employees of the U.S. Naval Research +Laboratory (NRL) and is property of the United States Government, as represented +by the Secretary of the Navy. MSIS� is a registered trademark of the Government +of the United States of America, as represented by the Secretary of the Navy. +Unauthorized use of the trademark is prohibited. + +4. Restrictions and Use. + +a. Sales. A user of the Software shall not sell, or license, or transfer for a +fee the Software or portion thereof, or any derivative work of the Software, or +any data products generated by the Software, without first obtaining the written +consent of IP Counsel for the Naval Research Laboratory. + +b. Modifications. All modifications to the Software and derivative works of the +Software (including translations to other programming languages) shall carry +prominent notices stating how the files were changed and the date of the change. +Any party who modifies the Software shall deliver the modified portion of the +Software to authors or NRL Code 7630, U.S. Naval Research Laboratory. Any +reproductions, modified versions of the Software, or derivative works shall be +made available to the public as open source software. A party who modifies the +Software or creates a derivative work of the Software hereby grants the +Government of the United States of America a non-exclusive, irrevocable, fully +paid-up license to such modifications and derivative works, and shall deliver +such derivative works, including any source code, data, or information that +pertains to such derivatives works, to Code 7630, U.S. Naval Research +Laboratory. If any modifications to the Software substantially change the model +output (including, but not limited to, alterations of the model formulation or +model parameter values), then the modified Software shall not be identified +�MSIS� without first obtaining the written consent of Counsel, Office of Naval +Research, Department of the Navy. In such cases, the MSIS acronym shall +nonetheless still appear in the individual files in order to document the +provenance of the modified Software. + +c. Notices. Each copy of the Software, any modified Software, or derivative +work shall include a file containing this Agreement. Any software package that +incorporates the MSIS� Software or derivative work shall include the following +statement: "This software incorporates the MSIS� empirical atmospheric model +software designed and provided by NRL. Use is governed by the Open Source +Academic Research License Agreement contained in the file +nrlmsis2.1_license.txt." + +5. Disclaimer of Warranty and Liability: As the owner of the MSIS� software, the +Government of the United States of America: (1) Disclaims any warranties, +express, or implied, including but not limited to any implied warranties of +merchantability, fitness for a particular purpose, title or non-infringement, +(2) Does not assume any legal liability or responsibility for the accuracy, +completeness, or usefulness of the software, (3) Does not represent that use of +the software would not infringe privately owned rights, (4) Does not warrant +that the software will function uninterrupted, that is error-free or that any +errors will be corrected. + +6. No Support. The Software is provided without any support or maintenance, and +without any obligation to provide modifications, improvements, enhancements, or +updates of the Software. No oral or written information or advice given by the +NRL authors shall create a warranty or in any way modify this agreement. Should +the Software prove defective, the user (and not NRL or any NRL representative) +assume the cost of all necessary correction. diff --git a/sorc/chgres_cube.fd/msis2.1.fd/readme.txt b/sorc/chgres_cube.fd/msis2.1.fd/readme.txt new file mode 100644 index 000000000..3cd759b41 --- /dev/null +++ b/sorc/chgres_cube.fd/msis2.1.fd/readme.txt @@ -0,0 +1,104 @@ +####################################################################### + MSIS® (NRL-SOF-014-1) SOFTWARE + NRLMSIS® empirical atmospheric model software. Use is governed by the + Open Source Academic Research License Agreement contained in the file + nrlmsis2.1_license.txt, which is part of this software package. BY + USING OR MODIFYING THIS SOFTWARE, YOU ARE AGREEING TO THE TERMS AND + CONDITIONS OF THE LICENSE. +####################################################################### + +NRLMSIS 2.1 Whole-Atmosphere Empirical Model of Temperature and Neutral Species + Densities + +VERSION HISTORY + 08 MAR 19 Version 1.97 (Beta version) + 26 MAY 20 Version 2.0 (Release version) + 04 APR 22 Version 2.1 (Release version with NO density) + +AUTHORS + John Emmert (john.emmert@nrl.navy.mil) + Douglas Drob (douglas.drob@nrl.navy.mil) + McArthur Jones Jr. (mcarthur.jones@nrl.navy.mil) + +REFERENCE FOR NRLMSIS 2.0 + Emmert, J. T., Drob, D. P., Picone, J. M., Siskind, D. E., Jones, M. Jr., + Mlynczak, M. G., et al. (2021). NRLMSIS 2.0: A whole-atmosphere empirical model + of temperature and neutral species densities. Earth and Space Science, 8, + e2020EA001321. https://doi.org/10.1029/2020EA001321 + +PACKAGE CONTENTS + readme.txt This file + nrlmsis2.1_license.txt Open Source Academic Research License Agreement + msis2.1_test.F90 Test program + msis_init.F90 Subroutines to initialize the model, set switches and + options, and load parameter file + msis_gtd8d.F90 Subroutine to evaluate the model using the legacy + interface + msis_calc.F90 Subroutine for evaluating the model using the new + interface + msis_constants.F90 Module containing model constants + msis_gfn.F90 Subroutines to calculate horizontal expansion + functions + msis_tfn.F90 Subroutines to calculate the vertical temperature + profile + msis_dfn.F90 Subroutines to calculate vertical density profiles + msis_utils.F90 Subroutines to convert between geodetic height and + geopotential height, and other support subroutines + msis21.parm Binary data file containing model parameters + msis2.1_test_in.txt ASCII file containing input for test program. + msis2.1_test_ref_dp.txt ASCII file containing expected output of test program + (double-precision internally) + +RELEASE NOTES: MODEL FORMULATION + Minor changes to the NRLMSIS 2.0 formulation include: + - Addition of new terms to support fitting of NO densities. + - Reorganization of support subroutines (alt2gph, gph2alt, bspline, dilog) + into msis_utils module. + +RELEASE NOTES: PARAMETER ESTIMATION + - NO density parameters were tuned to six NO data sets (ENVISAT/MIPAS, SNOE, + ACE/FTS, AIM/SOFIE, UARS/HALOE, and Odin/SMR). + - Temperature and all other species densities are the same as in NRLMSIS 2.0. + +COMPILING THE MODEL CODE + The model package was tested on Windows, Linux, and Mac systems using the + following Fortran compilers and compile statements: + gfortran 4.8.5, 7.5.0, 9.3.0 + gfortran -O3 -cpp -o msis2.1_test.exe msis_constants.F90 msis_utils.F90 + msis_init.F90 msis_gfn.F90 msis_tfn.F90 msis_dfn.F90 msis_calc.F90 + msis_gtd8d.F90 msis2.1_test.F90 + NOTES: + - The following optimization flags may improve performance: + -march=native -ffast-math + Intel 2017.2.163, 18.0.1.156, 2021.1 + ifort -O2 -fpp -o msis2.1_test.exe msis_constants.F90 msis_utils.F90 + msis_init.F90 msis_gfn.F90 msis_tfn.F90 msis_dfn.F90 msis_calc.F90 + msis_gtd8d.F90 msis2.1_test.F90 + NOTES: + - The following optimization flags may improve performance: + Windows: -Qipo -QxHost + Linux/macOS: -ipo -xHost + For double precision, add the flag -DDBLE. Double precision is not necessary + for most applications, but for testing purposes it ensures that the test + output exactly matches the expected output in msis2.1_test_ref_dp.txt, + regardless of the compiler or compiler settings. + +INITIALIZING AND RUNNING THE MODEL + - The model must be initialized using the MSISINIT subroutine, which sets + switches and options and loads the model parameter values from a file. + - The switch_legacy optional argument to MSISINIT performs the same function + as TSELEC(SW) in NRLSMSISE-00, except that switches 15-25 are not used in + NRLMSIS 2.1. The change in the switch-setting call is illustrated as + follows, where SW is the 25-element array of switches: + NRLMSISE-00: CALL TSELEC(SW) + NRLMSIS 2.1: call msisinit(switch_legacy=SW) + - The MSISCALC subroutine checks for initialization and does a default + initialization if necessary. This self-initialization will be removed in + future versions. + - The model can be called using either the legacy interface (subroutine + GTD8D) or the new interface (subroutine MSISCALC). + - Details of the input and output arguments of MSISINIT, GTD8D, and MSISCALC + are provided in the headers of the respective source code files. + +ACKNOWLEDGEMENTS + This work was supported by the Office of Naval Research and NASA. \ No newline at end of file diff --git a/sorc/chgres_cube.fd/nst_input_data.F90 b/sorc/chgres_cube.fd/nst_input_data.F90 new file mode 100644 index 000000000..027e7aa6c --- /dev/null +++ b/sorc/chgres_cube.fd/nst_input_data.F90 @@ -0,0 +1,820 @@ +module nst_input_data +!> @file +!! @brief Read NST surface data from NEMSIO and NetCDF files. +!! @author George Gayno NCEP/EMC + +!> Read nst data on the input grid. +!! Supported formats include fv3 tiled 'restart' files, fv3 tiled +!! 'history' files, fv3 gaussian history files, and spectral gfs +!! gaussian nemsio files. +!! +!! Public variables are defined below: "input" indicates field +!! associated with the input grid. +!! +!! @author George Gayno NCEP/EMC + use esmf + use netcdf + use nemsio_module + + use program_setup, only : data_dir_input_grid, & + sfc_files_input_grid, & + nst_files_input_grid, & + input_type + + use model_grid, only : input_grid, & + i_input, j_input, & + ip1_input, jp1_input, & + num_tiles_input_grid + + use sfc_input_data, only : lsoil_input, & + read_fv3_grid_data_netcdf, & + landsea_mask_input_grid + + use utilities, only : error_handler + implicit none + +! Fields associated with the nst model. + + type(esmf_field), public :: c_d_input_grid !< Coefficient 2 to calculate d(tz)/d(ts) + type(esmf_field), public :: c_0_input_grid !< Coefficient 1 to calculate d(tz)/d(ts) + type(esmf_field), public :: d_conv_input_grid !< Thickness of free convectionlayer + type(esmf_field), public :: dt_cool_input_grid !< Sub-layer cooling amount + type(esmf_field), public :: ifd_input_grid !< Model mode index. 0-diurnalmodel not + !< started; 1-diurnal model + !started. + type(esmf_field), public :: qrain_input_grid !< Sensible heat flux due torainfall + type(esmf_field), public :: tref_input_grid !< Reference temperature + type(esmf_field), public :: w_d_input_grid !< Coefficient 4 to calculated(tz)/d(ts) + type(esmf_field), public :: w_0_input_grid !< Coefficient 3 to calculated(tz)/d(ts) + type(esmf_field), public :: xs_input_grid !< Salinity content in diurnalthermocline layer + type(esmf_field), public :: xt_input_grid !< Heat content in diurnalthermocline layer + type(esmf_field), public :: xu_input_grid !< u-current content in diurnalthermocline layer + type(esmf_field), public :: xv_input_grid !< v-current content in diurnalthermocline layer + type(esmf_field), public :: xz_input_grid !< Diurnal thermocline layerthickness + type(esmf_field), public :: xtts_input_grid !< d(xt)/d(ts) + type(esmf_field), public :: xzts_input_grid !< d(xz)/d(ts) + type(esmf_field), public :: z_c_input_grid !< Sub-layer cooling thickness + type(esmf_field), public :: zm_input_grid !< Oceanic mixed layer depth + + public :: read_input_nst_data + public :: cleanup_input_nst_data + + contains +!> Driver to read input grid nst data. +!! +!! @param[in] localpet ESMF local persistent execution thread +!! @author George Gayno NCEP/EMC + subroutine read_input_nst_data(localpet) + + implicit none + + integer, intent(in) :: localpet + + integer :: rc + + print*,"- READ INPUT GRID NST DATA." + + print*,"- CALL FieldCreate FOR INPUT GRID C_D." + c_d_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID C_0." + c_0_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID D_CONV." + d_conv_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID DT_COOL." + dt_cool_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID IFD." + ifd_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID QRAIN." + qrain_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID TREF." + tref_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID W_D." + w_d_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID W_0." + w_0_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID XS." + xs_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID XT." + xt_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID XU." + xu_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID XV." + xv_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID XZ." + xz_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID XTTS." + xtts_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID XZTS." + xzts_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID Z_C." + z_c_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID ZM." + zm_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + +!-------------------------------------------------------------------------- +! Read input grid nst data from a fv3 gaussian nemsio history file or +! spectral GFS nemsio file. +!-------------------------------------------------------------------------- + + if (trim(input_type) == "gaussian_nemsio" .or. trim(input_type) == "gfs_gaussian_nemsio") then + + call read_input_nst_nemsio_file(localpet) + +!--------------------------------------------------------------------------- +! Read nst data from these netcdf formatted fv3 files: tiled history, +! tiled warm restart, and gaussian history. +!--------------------------------------------------------------------------- + + else + + call read_input_nst_netcdf_file(localpet) + + endif + + end subroutine read_input_nst_data + + !> Read nst data from these netcdf formatted fv3 files: tiled history, +!! tiled warm restart, and gaussian history. +!! +!! @param[in] localpet ESMF local persistent execution thread +!! @author George Gayno NCEP/EMC + subroutine read_input_nst_netcdf_file(localpet) + + implicit none + + integer, intent(in) :: localpet + + character(len=10) :: field + + integer :: rc, tile + + real(esmf_kind_r8), allocatable :: data_one_tile(:,:) + + if (localpet == 0) then + allocate(data_one_tile(i_input,j_input)) + else + allocate(data_one_tile(0,0)) + endif + + TILE_LOOP : do tile = 1, num_tiles_input_grid + +! c_d + + if (localpet == 0) then + if (trim(input_type) == "restart") then + field='c_d' + else + field='cd' + endif + call read_fv3_grid_data_netcdf(trim(field), tile, i_input, j_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT C_D" + call ESMF_FieldScatter(c_d_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! c_0 + + if (localpet == 0) then + if (trim(input_type) == "restart") then + field='c_0' + else + field='c0' + endif + call read_fv3_grid_data_netcdf(trim(field), tile, i_input, j_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT C_0" + call ESMF_FieldScatter(c_0_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! d_conv + + if (localpet == 0) then + if (trim(input_type) == "restart") then + field='d_conv' + else + field='dconv' + endif + call read_fv3_grid_data_netcdf(trim(field), tile, i_input, j_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT D_CONV." + call ESMF_FieldScatter(d_conv_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! dt_cool + + if (localpet == 0) then + if (trim(input_type) == "restart") then + field='dt_cool' + else + field='dtcool' + endif + call read_fv3_grid_data_netcdf(trim(field), tile, i_input, j_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT DT_COOL." + call ESMF_FieldScatter(dt_cool_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! ifd - xu li said initialize to '1'. + + if (localpet == 0) then + data_one_tile = 1.0 + endif + + print*,"- CALL FieldScatter FOR INPUT IFD." + call ESMF_FieldScatter(ifd_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! qrain + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('qrain', tile, i_input, j_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT QRAIN." + call ESMF_FieldScatter(qrain_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! tref + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('tref', tile, i_input, j_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT TREF" + call ESMF_FieldScatter(tref_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! w_d + + if (localpet == 0) then + if (trim(input_type) == "restart") then + field='w_d' + else + field='wd' + endif + call read_fv3_grid_data_netcdf(trim(field), tile, i_input, j_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT W_D" + call ESMF_FieldScatter(w_d_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! w_0 + + if (localpet == 0) then + if (trim(input_type) == "restart") then + field='w_0' + else + field='w0' + endif + call read_fv3_grid_data_netcdf(trim(field), tile, i_input, j_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT W_0" + call ESMF_FieldScatter(w_0_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! xs + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('xs', tile, i_input, j_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT XS" + call ESMF_FieldScatter(xs_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! xt + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('xt', tile, i_input, j_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT XT" + call ESMF_FieldScatter(xt_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! xu + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('xu', tile, i_input, j_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT XU" + call ESMF_FieldScatter(xu_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! xv + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('xv', tile, i_input, j_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT XV" + call ESMF_FieldScatter(xv_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! xz + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('xz', tile, i_input, j_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT XZ" + call ESMF_FieldScatter(xz_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! xtts + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('xtts', tile, i_input, j_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT XTTS" + call ESMF_FieldScatter(xtts_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! xzts + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('xzts', tile, i_input, j_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT XZTS" + call ESMF_FieldScatter(xzts_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! z_c + + if (localpet == 0) then + if (trim(input_type) == "restart") then + field='z_c' + else + field='zc' + endif + call read_fv3_grid_data_netcdf(trim(field), tile, i_input, j_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT Z_C" + call ESMF_FieldScatter(z_c_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! zm - Not used yet. Xu li said set to '0'. + + if (localpet == 0) then +! Do not set zm to 0 for warm restart files - AMG + if (trim(input_type) == "restart") then + print*,"- Do not set zm to 0 for warm restart files" + call read_fv3_grid_data_netcdf('zm', tile, i_input, j_input, & + lsoil_input, sfcdata=data_one_tile) +! print*,'zm max/min ',maxval(data_one_tile),minval(data_one_tile) + else + data_one_tile = 0.0 + endif + endif + + print*,"- CALL FieldScatter FOR INPUT ZM" + call ESMF_FieldScatter(zm_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + enddo TILE_LOOP + + deallocate(data_one_tile) + + end subroutine read_input_nst_netcdf_file + +!> Read input grid nst data from fv3 gaussian nemsio history file or +!! spectral GFS nemsio file. +!! +!! @note The spectral GFS nst data is in a separate file from +!! the surface data. The fv3 surface and nst data are in a +!! single file. +!! +!! @param[in] localpet ESMF local persistent execution thread +!! @author George Gayno NCEP/EMC + subroutine read_input_nst_nemsio_file(localpet) + + implicit none + + integer, intent(in) :: localpet + + character(len=300) :: the_file + + integer :: rc + + real(nemsio_realkind), allocatable :: dummy(:) + real(esmf_kind_r8), allocatable :: dummy2d(:,:) + + type(nemsio_gfile) :: gfile + + if (trim(input_type) == "gfs_gaussian_nemsio") then ! spectral gfs nemsio in + ! separate file. + the_file = trim(data_dir_input_grid) // "/" // trim(nst_files_input_grid) + else + the_file = trim(data_dir_input_grid) // "/" // trim(sfc_files_input_grid(1)) + endif + + print*,"- READ NST DATA FROM: ", trim(the_file) + + if (localpet == 0) then + allocate(dummy(i_input*j_input)) + allocate(dummy2d(i_input,j_input)) + call nemsio_open(gfile, the_file, "read", iret=rc) + else + allocate(dummy(0)) + allocate(dummy2d(0,0)) + endif + + if (localpet == 0) then + print*,"- READ TREF" + call nemsio_readrecv(gfile, "tref", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING TREF.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'tref ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT TREF." + call ESMF_FieldScatter(tref_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ CD" + call nemsio_readrecv(gfile, "cd", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING CD.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'cd ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT C_D." + call ESMF_FieldScatter(c_d_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ C0" + call nemsio_readrecv(gfile, "c0", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING C0.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'c0 ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT C_0." + call ESMF_FieldScatter(c_0_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ DCONV" + call nemsio_readrecv(gfile, "dconv", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING DCONV.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'dconv ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT D_CONV." + call ESMF_FieldScatter(d_conv_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ DTCOOL" + call nemsio_readrecv(gfile, "dtcool", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING DTCOOL.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'dtcool ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT DT_COOL." + call ESMF_FieldScatter(dt_cool_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + dummy2d = 1.0 ! IFD not in file. Set to '1' per Xu Li. + endif + + print*,"- CALL FieldScatter FOR INPUT IFD." + call ESMF_FieldScatter(ifd_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ QRAIN" + call nemsio_readrecv(gfile, "qrain", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING QRAIN.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'qrain ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT QRAIN." + call ESMF_FieldScatter(qrain_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ WD" + call nemsio_readrecv(gfile, "wd", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING WD.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'wd ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT WD." + call ESMF_FieldScatter(w_d_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ W0" + call nemsio_readrecv(gfile, "w0", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING W0.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'w0 ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT W0." + call ESMF_FieldScatter(w_0_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ XS" + call nemsio_readrecv(gfile, "xs", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING XS.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'xs ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT XS." + call ESMF_FieldScatter(xs_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ XT" + call nemsio_readrecv(gfile, "xt", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING XT.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'xt ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT XT." + call ESMF_FieldScatter(xt_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ XU" + call nemsio_readrecv(gfile, "xu", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING XU.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'xu ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT XU." + call ESMF_FieldScatter(xu_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ XV" + call nemsio_readrecv(gfile, "xv", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING XV.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'xv ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT XV." + call ESMF_FieldScatter(xv_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ XZ" + call nemsio_readrecv(gfile, "xz", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING XZ.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'xz ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT XZ." + call ESMF_FieldScatter(xz_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ XTTS" + call nemsio_readrecv(gfile, "xtts", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING XTTS.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'xtts ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT XTTS." + call ESMF_FieldScatter(xtts_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ XZTS" + call nemsio_readrecv(gfile, "xzts", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING XZTS.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'xzts ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT XZTS." + call ESMF_FieldScatter(xzts_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ ZC" + call nemsio_readrecv(gfile, "zc", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING ZC.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'zc ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT Z_C." + call ESMF_FieldScatter(z_c_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + dummy2d = 0.0 ! zm not used yet. Set to zero per Xu Li. + endif + + print*,"- CALL FieldScatter FOR INPUT ZM." + call ESMF_FieldScatter(zm_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + deallocate(dummy, dummy2d) + + if (localpet == 0) call nemsio_close(gfile) + + end subroutine read_input_nst_nemsio_file + + !> Free up memory associated with nst data. +!! +!! @author George Gayno NCEP/EMC + subroutine cleanup_input_nst_data + + implicit none + + integer :: rc + + print*,'- DESTROY NST INPUT DATA.' + + call ESMF_FieldDestroy(landsea_mask_input_grid, rc=rc) + call ESMF_FieldDestroy(c_d_input_grid, rc=rc) + call ESMF_FieldDestroy(c_0_input_grid, rc=rc) + call ESMF_FieldDestroy(d_conv_input_grid, rc=rc) + call ESMF_FieldDestroy(dt_cool_input_grid, rc=rc) + call ESMF_FieldDestroy(ifd_input_grid, rc=rc) + call ESMF_FieldDestroy(qrain_input_grid, rc=rc) + call ESMF_FieldDestroy(tref_input_grid, rc=rc) + call ESMF_FieldDestroy(w_d_input_grid, rc=rc) + call ESMF_FieldDestroy(w_0_input_grid, rc=rc) + call ESMF_FieldDestroy(xs_input_grid, rc=rc) + call ESMF_FieldDestroy(xt_input_grid, rc=rc) + call ESMF_FieldDestroy(xu_input_grid, rc=rc) + call ESMF_FieldDestroy(xv_input_grid, rc=rc) + call ESMF_FieldDestroy(xz_input_grid, rc=rc) + call ESMF_FieldDestroy(xtts_input_grid, rc=rc) + call ESMF_FieldDestroy(xzts_input_grid, rc=rc) + call ESMF_FieldDestroy(z_c_input_grid, rc=rc) + call ESMF_FieldDestroy(zm_input_grid, rc=rc) + + end subroutine cleanup_input_nst_data + + end module nst_input_data diff --git a/sorc/chgres_cube.fd/program_setup.F90 b/sorc/chgres_cube.fd/program_setup.F90 index 5e854a2c3..4be7940a6 100644 --- a/sorc/chgres_cube.fd/program_setup.F90 +++ b/sorc/chgres_cube.fd/program_setup.F90 @@ -8,6 +8,9 @@ !! @author George Gayno NCEP/EMC module program_setup + use esmf + use utilities, only : error_handler, to_lower + implicit none private @@ -53,10 +56,6 @@ module program_setup !! gfs sigio/sfcio files. character(len=20), public :: external_model="GFS" !< The model that the input data is derived from. Current supported options are: "GFS", "HRRR", "NAM", "RAP". Default: "GFS" - character(len=500), public :: fix_dir_input_grid = "NULL" !< Directory containing files of latitude and - !! and longitude for certain GRIB2 input data. - - integer, parameter, public :: max_tracers=100 !< Maximum number of atmospheric tracers processed. integer, public :: num_tracers !< Number of atmospheric tracers to be processed. integer, public :: num_tracers_input !< Number of atmospheric tracers in input file. @@ -81,6 +80,7 @@ module program_setup !! by this program. character(len=20), allocatable, public :: field_var_names(:) !< The GRIB2 variable name in the varmap table. + character(len=500), public :: wam_parm_file="msis21.parm" !< Full path to msis21.parm for WAM initialization integer, public :: cycle_year = -999 !< Cycle year. integer, public :: cycle_mon = -999 !< Cycle month. @@ -135,10 +135,9 @@ module program_setup real, allocatable, public :: wltsmc_target(:) !< Plant wilting point soil moisture content target grid. real, allocatable, public :: bb_target(:) !< Soil 'b' parameter, target grid real, allocatable, public :: satpsi_target(:) !< Saturated soil potential, target grid - real, allocatable, public :: missing_var_values(:) !< If input GRIB2 record is missing, the variable - !! is set to this value. + real(kind=esmf_kind_r4), allocatable, public :: missing_var_values(:) !< If input GRIB2 record is missing, the variable + !! is set to this value. - public :: read_setup_namelist public :: calc_soil_params_driver public :: read_varmap @@ -148,15 +147,14 @@ module program_setup !> Reads program configuration namelist. !! -!! @param filename the name of the configuration file (defaults to +!! @param filename The name of the configuration file (defaults to !! ./fort.41). !! @author George Gayno NCEP/EMC subroutine read_setup_namelist(filename) implicit none character(len=*), intent(in), optional :: filename - character(:), allocatable :: filename_to_use - + character(len=250), allocatable :: filename_to_use integer :: is, ie, ierr @@ -189,23 +187,23 @@ subroutine read_setup_namelist(filename) lai_from_climo, tg3_from_soil, & regional, input_type, & external_model, & + wam_parm_file, & atm_weight_file, tracers, & tracers_input, & halo_bndy, & halo_blend, & - fix_dir_input_grid, & nsoill_out, & thomp_mp_climo_file print*,"- READ SETUP NAMELIST" if (present(filename)) then - filename_to_use = filename + filename_to_use = filename else - filename_to_use = "./fort.41" + filename_to_use = "./fort.41" endif - open(41, file=filename_to_use, iostat=ierr) + open(41, file=trim(filename_to_use), iostat=ierr) if (ierr /= 0) call error_handler("OPENING SETUP NAMELIST.", ierr) read(41, nml=config, iostat=ierr) if (ierr /= 0) call error_handler("READING SETUP NAMELIST.", ierr) @@ -309,9 +307,9 @@ subroutine read_setup_namelist(filename) !------------------------------------------------------------------------- if (trim(input_type) == "grib2") then - if (trim(grib2_file_input_grid) == "NULL" .or. trim(grib2_file_input_grid) == "") then - call error_handler("FOR GRIB2 DATA, PLEASE PROVIDE GRIB2_FILE_INPUT_GRID", 1) - endif + if (trim(grib2_file_input_grid) == "NULL" .or. trim(grib2_file_input_grid) == "") then + call error_handler("FOR GRIB2 DATA, PLEASE PROVIDE GRIB2_FILE_INPUT_GRID", 1) + endif endif !------------------------------------------------------------------------- @@ -319,14 +317,14 @@ subroutine read_setup_namelist(filename) !------------------------------------------------------------------------- if (trim(input_type) == "grib2") then - if (.not. any((/character(4)::"GFS","NAM","RAP","HRRR"/)==trim(external_model))) then - call error_handler( "KNOWN SUPPORTED external_model INPUTS ARE GFS, NAM, RAP, AND HRRR. " // & - "IF YOU WISH TO PROCESS GRIB2 DATA FROM ANOTHER MODEL, YOU MAY ATTEMPT TO DO SO AT YOUR OWN RISK. " // & - "ONE WAY TO DO THIS IS PROVIDE NAM FOR external_model AS IT IS A RELATIVELY STRAIGHT-" // & - "FORWARD REGIONAL GRIB2 FILE. YOU MAY ALSO COMMENT OUT THIS ERROR MESSAGE IN " // & - "program_setup.f90 LINE 389. NO GUARANTEE IS PROVIDED THAT THE CODE WILL WORK OR "// & - "THAT THE RESULTING DATA WILL BE CORRECT OR WORK WITH THE ATMOSPHERIC MODEL.", 1) - endif + if (.not. any((/character(4)::"GFS","NAM","RAP","HRRR"/)==trim(external_model))) then + call error_handler( "KNOWN SUPPORTED external_model INPUTS ARE GFS, NAM, RAP, AND HRRR. " // & + "IF YOU WISH TO PROCESS GRIB2 DATA FROM ANOTHER MODEL, YOU MAY ATTEMPT TO DO SO AT YOUR OWN RISK. " // & + "ONE WAY TO DO THIS IS PROVIDE NAM FOR external_model AS IT IS A RELATIVELY STRAIGHT-" // & + "FORWARD REGIONAL GRIB2 FILE. YOU MAY ALSO COMMENT OUT THIS ERROR MESSAGE IN " // & + "program_setup.f90 LINE 389. NO GUARANTEE IS PROVIDED THAT THE CODE WILL WORK OR "// & + "THAT THE RESULTING DATA WILL BE CORRECT OR WORK WITH THE ATMOSPHERIC MODEL.", 1) + endif endif !------------------------------------------------------------------------- @@ -335,11 +333,10 @@ subroutine read_setup_namelist(filename) !------------------------------------------------------------------------- if (trim(input_type) == "grib2" .and. trim(external_model)=="HRRR") then - if (trim(geogrid_file_input_grid) == "NULL" .or. trim(grib2_file_input_grid) == "") then - print*, "HRRR DATA DOES NOT CONTAIN SOIL TYPE INFORMATION. WITHOUT & - GEOGRID_FILE_INPUT_GRID SPECIFIED, SOIL MOISTURE INTERPOLATION MAY BE LESS & - ACCURATE. " - endif + if (trim(geogrid_file_input_grid) == "NULL" .or. trim(grib2_file_input_grid) == "") then + print*, "HRRR DATA DOES NOT CONTAIN SOIL TYPE INFORMATION. WITHOUT" + print*, "GEOGRID_FILE_INPUT_GRID SPECIFIED, SOIL MOISTURE INTERPOLATION MAY BE LESS ACCURATE." + endif endif if (trim(thomp_mp_climo_file) /= "NULL") then @@ -447,7 +444,6 @@ end subroutine read_varmap !! @author Jeff Beck subroutine get_var_cond(var_name,this_miss_var_method,this_miss_var_value, & this_field_var_name, loc) - use esmf implicit none character(len=20), intent(in) :: var_name diff --git a/sorc/chgres_cube.fd/search_util.F90 b/sorc/chgres_cube.fd/search_util.F90 index e4d3d314f..fbab5e209 100644 --- a/sorc/chgres_cube.fd/search_util.F90 +++ b/sorc/chgres_cube.fd/search_util.F90 @@ -220,7 +220,7 @@ end subroutine search !> Set default Sea Surface Temperature (SST) based on latitude. !! !! Based loosely on the average annual SST -!! values from ./fix_am/cfs_oi2sst1x1monclim19822001.grb +!! values from ./am/cfs_oi2sst1x1monclim19822001.grb !! !! The temperature in the polar and tropical regions !! is set to 273.16 and 300.0 Kelvin respectively. Polar diff --git a/sorc/chgres_cube.fd/sfc_input_data.F90 b/sorc/chgres_cube.fd/sfc_input_data.F90 new file mode 100644 index 000000000..47e050e1b --- /dev/null +++ b/sorc/chgres_cube.fd/sfc_input_data.F90 @@ -0,0 +1,3370 @@ +module sfc_input_data +!> @file +!! @brief Read atmospheric and surface data from GRIB2, NEMSIO and NetCDF files. +!! @author George Gayno NCEP/EMC + +!> Read atmospheric, surface and nst data on the input grid. +!! Supported formats include fv3 tiled 'restart' files, fv3 tiled +!! 'history' files, fv3 gaussian history files, spectral gfs +!! gaussian nemsio files, and spectral gfs sigio/sfcio files. +!! +!! Public variables are defined below: "input" indicates field +!! associated with the input grid. +!! +!! @author George Gayno NCEP/EMC + use esmf + use netcdf + use nemsio_module + + use program_setup, only : data_dir_input_grid, & + sfc_files_input_grid, & + grib2_file_input_grid, & + convert_nst, & + orog_dir_input_grid, & + orog_files_input_grid, & + input_type, & + get_var_cond, & + geogrid_file_input_grid, & + external_model, & + vgfrc_from_climo, & + minmax_vgfrc_from_climo, & + lai_from_climo,& + read_from_input + + use model_grid, only : input_grid, & + i_input, j_input, & + ip1_input, jp1_input, & + num_tiles_input_grid + use atm_input_data, only : terrain_input_grid + + use utilities, only : error_handler, & + netcdf_err, & + handle_grib_error, & + to_upper, & + check_soilt, & + check_cnwat + +! Fields associated with the land-surface model. + + integer, public :: veg_type_landice_input = 15 !< NOAH land ice option + !< defined at this veg type. + !< Default is igbp. + real :: ICET_DEFAULT = 265.0 !< Default value of soil and skin + !< temperature (K) over ice. + type(esmf_field), public :: canopy_mc_input_grid !< canopy moist content + type(esmf_field), public :: f10m_input_grid !< log((z0+10)*1/z0) + type(esmf_field), public :: ffhh_input_grid !< log((ztmax+z1)*1/ztmax) + !! See sfc_diff.f for details. + type(esmf_field), public :: ffmm_input_grid !< log((z0+z1)*1/z0) + !! See sfc_diff.f for details. + type(esmf_field), public :: landsea_mask_input_grid !< land sea mask; + !! 0-water, 1-land, 2-ice + type(esmf_field), public :: q2m_input_grid !< 2-m spec hum + type(esmf_field), public :: seaice_depth_input_grid !< sea ice depth + type(esmf_field), public :: seaice_fract_input_grid !< sea ice fraction + type(esmf_field), public :: seaice_skin_temp_input_grid !< sea ice skin temp + type(esmf_field), public :: skin_temp_input_grid !< skin temp/sst + type(esmf_field), public :: snow_depth_input_grid !< snow dpeth + type(esmf_field), public :: snow_liq_equiv_input_grid !< snow liq equiv depth + type(esmf_field), public :: soil_temp_input_grid !< 3-d soil temp + type(esmf_field), public :: soil_type_input_grid !< soil type + type(esmf_field), public :: soilm_liq_input_grid !< 3-d liquid soil moisture + type(esmf_field), public :: soilm_tot_input_grid !< 3-d total soil moisture + type(esmf_field), public :: srflag_input_grid !< snow/rain flag + type(esmf_field), public :: t2m_input_grid !< 2-m temperature + type(esmf_field), public :: tprcp_input_grid !< precip + type(esmf_field), public :: ustar_input_grid !< fric velocity + type(esmf_field), public :: veg_type_input_grid !< vegetation type + type(esmf_field), public :: z0_input_grid !< roughness length + type(esmf_field), public :: veg_greenness_input_grid !< vegetation fraction + type(esmf_field), public :: lai_input_grid !< leaf area index + type(esmf_field), public :: max_veg_greenness_input_grid !< shdmax + type(esmf_field), public :: min_veg_greenness_input_grid !< shdmin + + integer, public :: lsoil_input=4 !< number of soil layers, no longer hardwired to allow + !! for 7 layers of soil for the RUC LSM + + public :: read_input_sfc_data + public :: cleanup_input_sfc_data + public :: init_sfc_esmf_fields + + contains + + !> Driver to read input grid surface data. +!! +!! @param[in] localpet ESMF local persistent execution thread +!! @author George Gayno NCEP/EMC + subroutine read_input_sfc_data(localpet) + + implicit none + + integer, intent(in) :: localpet + + call init_sfc_esmf_fields() + +!------------------------------------------------------------------------------- +! Read the tiled 'warm' restart files. +!------------------------------------------------------------------------------- + + if (trim(input_type) == "restart") then + + call read_input_sfc_restart_file(localpet) + +!------------------------------------------------------------------------------- +! Read the tiled or gaussian history files in netcdf format. +!------------------------------------------------------------------------------- + + elseif (trim(input_type) == "history" .or. trim(input_type) == & + "gaussian_netcdf") then + + call read_input_sfc_netcdf_file(localpet) + +!------------------------------------------------------------------------------- +! Read the gaussian history files in nemsio format. +!------------------------------------------------------------------------------- + + elseif (trim(input_type) == "gaussian_nemsio") then + + call read_input_sfc_gaussian_nemsio_file(localpet) + +!------------------------------------------------------------------------------- +! Read the spectral gfs gaussian history files in nemsio format. +!------------------------------------------------------------------------------- + + elseif (trim(input_type) == "gfs_gaussian_nemsio") then + + call read_input_sfc_gfs_gaussian_nemsio_file(localpet) + +!------------------------------------------------------------------------------- +! Read the spectral gfs gaussian history files in sfcio format. +!------------------------------------------------------------------------------- + + elseif (trim(input_type) == "gfs_sigio") then + + call read_input_sfc_gfs_sfcio_file(localpet) + +!------------------------------------------------------------------------------- +! Read fv3gfs surface data in grib2 format. +!------------------------------------------------------------------------------- + + elseif (trim(input_type) == "grib2") then + + call read_input_sfc_grib2_file(localpet) + + endif + + end subroutine read_input_sfc_data + + !> Read input grid surface data from a spectral gfs gaussian sfcio +!! file. +!! +!! @note Prior to July 19, 2017. +!! +!! @param[in] localpet ESMF local persistent execution thread +!! @author George Gayno NCEP/EMC + subroutine read_input_sfc_gfs_sfcio_file(localpet) + + use sfcio_module + + implicit none + + integer, intent(in) :: localpet + + character(len=300) :: the_file + + integer(sfcio_intkind) :: iret + integer :: rc + + real(esmf_kind_r8), allocatable :: dummy2d(:,:) + real(esmf_kind_r8), allocatable :: dummy3d(:,:,:) + + type(sfcio_head) :: sfchead + type(sfcio_dbta) :: sfcdata + + the_file = trim(data_dir_input_grid) // "/" // trim(sfc_files_input_grid(1)) + + print*,"- READ SURFACE DATA IN SFCIO FORMAT." + print*,"- OPEN AND READ: ",trim(the_file) + call sfcio_sropen(23, trim(the_file), iret) + if (iret /= 0) then + rc=iret + call error_handler("OPENING FILE", rc) + endif + + call sfcio_srhead(23, sfchead, iret) + if (iret /= 0) then + rc=iret + call error_handler("READING HEADER", rc) + endif + + if (localpet == 0) then + call sfcio_aldbta(sfchead, sfcdata, iret) + if (iret /= 0) then + rc=iret + call error_handler("ALLOCATING DATA.", rc) + endif + call sfcio_srdbta(23, sfchead, sfcdata, iret) + if (iret /= 0) then + rc=iret + call error_handler("READING DATA.", rc) + endif + allocate(dummy2d(i_input,j_input)) + allocate(dummy3d(i_input,j_input,lsoil_input)) + else + allocate(dummy2d(0,0)) + allocate(dummy3d(0,0,0)) + endif + + if (localpet == 0) dummy2d = sfcdata%slmsk + + print*,"- CALL FieldScatter FOR INPUT LANDSEA MASK." + call ESMF_FieldScatter(landsea_mask_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) dummy2d = sfcdata%zorl + + print*,"- CALL FieldScatter FOR INPUT Z0." + call ESMF_FieldScatter(z0_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) dummy2d = nint(sfcdata%vtype) + + print*,"- CALL FieldScatter FOR INPUT VEG TYPE." + call ESMF_FieldScatter(veg_type_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! Prior to July, 2017, gfs used zobler soil types. '13' indicates permanent land ice. + veg_type_landice_input = 13 + + if (localpet == 0) dummy2d = sfcdata%canopy + + print*,"- CALL FieldScatter FOR INPUT CANOPY MC." + call ESMF_FieldScatter(canopy_mc_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) dummy2d = sfcdata%fice + + print*,"- CALL FieldScatter FOR INPUT ICE FRACTION." + call ESMF_FieldScatter(seaice_fract_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) dummy2d = sfcdata%hice + + print*,"- CALL FieldScatter FOR INPUT ICE DEPTH." + call ESMF_FieldScatter(seaice_depth_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) dummy2d = sfcdata%tisfc + + print*,"- CALL FieldScatter FOR INPUT ICE SKIN TEMP." + call ESMF_FieldScatter(seaice_skin_temp_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) dummy2d = sfcdata%snwdph ! mm (expected by program) + + print*,"- CALL FieldScatter FOR INPUT SNOW DEPTH." + call ESMF_FieldScatter(snow_depth_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) dummy2d = sfcdata%sheleg + + print*,"- CALL FieldScatter FOR INPUT SNOW LIQUID EQUIV." + call ESMF_FieldScatter(snow_liq_equiv_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) dummy2d = sfcdata%t2m + + print*,"- CALL FieldScatter FOR INPUT T2M." + call ESMF_FieldScatter(t2m_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) dummy2d = sfcdata%q2m + + print*,"- CALL FieldScatter FOR INPUT Q2M." + call ESMF_FieldScatter(q2m_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) dummy2d = sfcdata%tprcp + + print*,"- CALL FieldScatter FOR INPUT TPRCP." + call ESMF_FieldScatter(tprcp_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) dummy2d = sfcdata%f10m + + print*,"- CALL FieldScatter FOR INPUT F10M." + call ESMF_FieldScatter(f10m_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) dummy2d = sfcdata%uustar + + print*,"- CALL FieldScatter FOR INPUT USTAR." + call ESMF_FieldScatter(ustar_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) dummy2d = sfcdata%ffmm + + print*,"- CALL FieldScatter FOR INPUT FFMM." + call ESMF_FieldScatter(ffmm_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) dummy2d = sfcdata%srflag + + print*,"- CALL FieldScatter FOR INPUT SRFLAG." + call ESMF_FieldScatter(srflag_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) dummy2d = sfcdata%tsea + + print*,"- CALL FieldScatter FOR INPUT SKIN TEMP." + call ESMF_FieldScatter(skin_temp_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) dummy2d = nint(sfcdata%stype) + + print*,"- CALL FieldScatter FOR INPUT SOIL TYPE." + call ESMF_FieldScatter(soil_type_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) dummy2d = sfcdata%orog + + print*,"- CALL FieldScatter FOR INPUT TERRAIN." + call ESMF_FieldScatter(terrain_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) dummy3d = sfcdata%slc + + print*,"- CALL FieldScatter FOR INPUT LIQUID SOIL MOISTURE." + call ESMF_FieldScatter(soilm_liq_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) dummy3d = sfcdata%smc + + print*,"- CALL FieldScatter FOR INPUT TOTAL SOIL MOISTURE." + call ESMF_FieldScatter(soilm_tot_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) dummy3d = sfcdata%stc + + print*,"- CALL FieldScatter FOR INPUT SOIL TEMPERATURE." + call ESMF_FieldScatter(soil_temp_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + deallocate(dummy2d, dummy3d) + call sfcio_axdbta(sfcdata, iret) + + call sfcio_sclose(23, iret) + + end subroutine read_input_sfc_gfs_sfcio_file + +!> Read input grid surface data from a spectral gfs gaussian nemsio +!! file. +!! +!! @note Format used by gfs starting July 19, 2017. +!! +!! @param[in] localpet ESMF local persistent execution thread +!! @author George Gayno NCEP/EMC + subroutine read_input_sfc_gfs_gaussian_nemsio_file(localpet) + + implicit none + + integer, intent(in) :: localpet + + character(len=300) :: the_file + + integer :: rc + + real(nemsio_realkind), allocatable :: dummy(:) + real(esmf_kind_r8), allocatable :: dummy2d(:,:) + real(esmf_kind_r8), allocatable :: dummy3d(:,:,:) + + type(nemsio_gfile) :: gfile + + the_file = trim(data_dir_input_grid) // "/" // trim(sfc_files_input_grid(1)) + + if (localpet == 0) then + allocate(dummy3d(i_input,j_input,lsoil_input)) + allocate(dummy2d(i_input,j_input)) + allocate(dummy(i_input*j_input)) + print*,"- OPEN FILE ", trim(the_file) + call nemsio_open(gfile, the_file, "read", iret=rc) + if (rc /= 0) call error_handler("OPENING FILE.", rc) + else + allocate(dummy3d(0,0,0)) + allocate(dummy2d(0,0)) + allocate(dummy(0)) + endif + + if (localpet == 0) then + print*,"- READ TERRAIN." + call nemsio_readrecv(gfile, "orog", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING TERRAIN.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'orog ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT TERRAIN." + call ESMF_FieldScatter(terrain_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ LANDSEA MASK." + call nemsio_readrecv(gfile, "land", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING LANDSEA MASK.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'landmask ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT LANDSEA MASK." + call ESMF_FieldScatter(landsea_mask_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ SEAICE FRACTION." + call nemsio_readrecv(gfile, "icec", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING SEAICE FRACTION.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'icec ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SEAICE FRACTION." + call ESMF_FieldScatter(seaice_fract_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ SEAICE DEPTH." + call nemsio_readrecv(gfile, "icetk", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING SEAICE DEPTH.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'icetk ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SEAICE DEPTH." + call ESMF_FieldScatter(seaice_depth_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ SEAICE SKIN TEMPERATURE." + call nemsio_readrecv(gfile, "tisfc", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING SEAICE SKIN TEMP.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'ti ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SEAICE SKIN TEMPERATURE." + call ESMF_FieldScatter(seaice_skin_temp_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ SNOW LIQUID EQUIVALENT." + call nemsio_readrecv(gfile, "weasd", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING SNOW LIQUID EQUIVALENT.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'weasd ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SNOW LIQUID EQUIVALENT." + call ESMF_FieldScatter(snow_liq_equiv_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ SNOW DEPTH." + call nemsio_readrecv(gfile, "snod", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING SNOW DEPTH.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'snod ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SNOW DEPTH." + call ESMF_FieldScatter(snow_depth_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ VEG TYPE." + call nemsio_readrecv(gfile, "vtype", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING VEG TYPE", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'vtype ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID VEG TYPE." + call ESMF_FieldScatter(veg_type_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ SOIL TYPE." + call nemsio_readrecv(gfile, "sotyp", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING SOIL TYPE.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'sotype ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SOIL TYPE." + call ESMF_FieldScatter(soil_type_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ T2M." + call nemsio_readrecv(gfile, "tmp", "2 m above gnd", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING T2M.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'t2m ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID T2M." + call ESMF_FieldScatter(t2m_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ Q2M." + call nemsio_readrecv(gfile, "spfh", "2 m above gnd", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING Q2M.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'q2m ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID Q2M." + call ESMF_FieldScatter(q2m_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ TPRCP." + call nemsio_readrecv(gfile, "tprcp", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING TPRCP.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'tprcp ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID TPRCP." + call ESMF_FieldScatter(tprcp_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ FFMM." + call nemsio_readrecv(gfile, "ffmm", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING FFMM.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'ffmm ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID FFMM" + call ESMF_FieldScatter(ffmm_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ USTAR." + call nemsio_readrecv(gfile, "fricv", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING USTAR.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'fricv ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID USTAR" + call ESMF_FieldScatter(ustar_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) dummy2d = 0.0 + print*,"- CALL FieldScatter FOR INPUT GRID SRFLAG" + call ESMF_FieldScatter(srflag_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ SKIN TEMPERATURE." + call nemsio_readrecv(gfile, "tmp", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING SKIN TEMPERATURE.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'tmp ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SKIN TEMPERATURE" + call ESMF_FieldScatter(skin_temp_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ F10M." + call nemsio_readrecv(gfile, "f10m", "10 m above gnd", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING F10M.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'f10m ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID F10M." + call ESMF_FieldScatter(f10m_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ CANOPY MOISTURE CONTENT." + call nemsio_readrecv(gfile, "cnwat", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING CANOPY MOISTURE CONTENT.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'cnwat ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID CANOPY MOISTURE CONTENT." + call ESMF_FieldScatter(canopy_mc_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ Z0." + call nemsio_readrecv(gfile, "sfcr", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING Z0.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'sfcr ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID Z0." + call ESMF_FieldScatter(z0_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + deallocate(dummy2d) + + if (localpet == 0) then + print*,"- READ LIQUID SOIL MOISTURE." + call nemsio_readrecv(gfile, "slc", "soil layer", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING LAYER 1 LIQUID SOIL MOIST.", rc) + dummy3d(:,:,1) = reshape(dummy, (/i_input,j_input/)) + call nemsio_readrecv(gfile, "slc", "soil layer", 2, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING LAYER 2 LIQUID SOIL MOIST.", rc) + dummy3d(:,:,2) = reshape(dummy, (/i_input,j_input/)) + call nemsio_readrecv(gfile, "slc", "soil layer", 3, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING LAYER 3 LIQUID SOIL MOIST.", rc) + dummy3d(:,:,3) = reshape(dummy, (/i_input,j_input/)) + call nemsio_readrecv(gfile, "slc", "soil layer", 4, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING LAYER 4 LIQUID SOIL MOIST.", rc) + dummy3d(:,:,4) = reshape(dummy, (/i_input,j_input/)) + print*,'slc ',maxval(dummy3d),minval(dummy3d) + endif + + print*,"- CALL FieldScatter FOR INPUT LIQUID SOIL MOISTURE." + call ESMF_FieldScatter(soilm_liq_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ TOTAL SOIL MOISTURE." + call nemsio_readrecv(gfile, "smc", "soil layer", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING LAYER 1 TOTAL SOIL MOIST.", rc) + dummy3d(:,:,1) = reshape(dummy, (/i_input,j_input/)) + call nemsio_readrecv(gfile, "smc", "soil layer", 2, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING LAYER 2 TOTAL SOIL MOIST.", rc) + dummy3d(:,:,2) = reshape(dummy, (/i_input,j_input/)) + call nemsio_readrecv(gfile, "smc", "soil layer", 3, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING LAYER 3 TOTAL SOIL MOIST.", rc) + dummy3d(:,:,3) = reshape(dummy, (/i_input,j_input/)) + call nemsio_readrecv(gfile, "smc", "soil layer", 4, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING LAYER 4 TOTAL SOIL MOIST.", rc) + dummy3d(:,:,4) = reshape(dummy, (/i_input,j_input/)) + print*,'smc ',maxval(dummy3d),minval(dummy3d) + endif + + print*,"- CALL FieldScatter FOR INPUT TOTAL SOIL MOISTURE." + call ESMF_FieldScatter(soilm_tot_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ SOIL TEMPERATURE." + call nemsio_readrecv(gfile, "stc", "soil layer", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING LAYER 1 SOIL TEMP.", rc) + dummy3d(:,:,1) = reshape(dummy, (/i_input,j_input/)) + call nemsio_readrecv(gfile, "stc", "soil layer", 2, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING LAYER 2 SOIL TEMP.", rc) + dummy3d(:,:,2) = reshape(dummy, (/i_input,j_input/)) + call nemsio_readrecv(gfile, "stc", "soil layer", 3, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING LAYER 3 SOIL TEMP.", rc) + dummy3d(:,:,3) = reshape(dummy, (/i_input,j_input/)) + call nemsio_readrecv(gfile, "stc", "soil layer", 4, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING LAYER 4 SOIL TEMP.", rc) + dummy3d(:,:,4) = reshape(dummy, (/i_input,j_input/)) + print*,'stc ',maxval(dummy3d),minval(dummy3d) + endif + + print*,"- CALL FieldScatter FOR INPUT SOIL TEMPERATURE." + call ESMF_FieldScatter(soil_temp_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + deallocate(dummy3d, dummy) + + if (localpet == 0) call nemsio_close(gfile) + + end subroutine read_input_sfc_gfs_gaussian_nemsio_file + +!> Read input grid surface data from an fv3 gaussian nemsio file. +!! +!! @param[in] localpet ESMF local persistent execution thread +!! @author George Gayno NCEP/EMC + subroutine read_input_sfc_gaussian_nemsio_file(localpet) + + implicit none + + integer, intent(in) :: localpet + + character(len=250) :: the_file + + integer :: rc + + real(nemsio_realkind), allocatable :: dummy(:) + real(esmf_kind_r8), allocatable :: dummy2d(:,:) + real(esmf_kind_r8), allocatable :: dummy3d(:,:,:) + + type(nemsio_gfile) :: gfile + + the_file = trim(data_dir_input_grid) // "/" // trim(sfc_files_input_grid(1)) + + if (localpet == 0) then + allocate(dummy3d(i_input,j_input,lsoil_input)) + allocate(dummy2d(i_input,j_input)) + allocate(dummy(i_input*j_input)) + print*,"- OPEN FILE ", trim(the_file) + call nemsio_open(gfile, the_file, "read", iret=rc) + if (rc /= 0) call error_handler("OPENING FILE.", rc) + else + allocate(dummy3d(0,0,0)) + allocate(dummy2d(0,0)) + allocate(dummy(0)) + endif + + if (localpet == 0) then + print*,"- READ TERRAIN." + call nemsio_readrecv(gfile, "orog", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING TERRAIN.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'orog ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT TERRAIN." + call ESMF_FieldScatter(terrain_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ LANDSEA MASK." + call nemsio_readrecv(gfile, "land", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING LANDSEA MASK.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'landmask ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT LANDSEA MASK." + call ESMF_FieldScatter(landsea_mask_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ SEAICE FRACTION." + call nemsio_readrecv(gfile, "icec", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING SEAICE FRACTION.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'icec ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SEAICE FRACTION." + call ESMF_FieldScatter(seaice_fract_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ SEAICE DEPTH." + call nemsio_readrecv(gfile, "icetk", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING SEAICE DEPTH.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'icetk ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SEAICE DEPTH." + call ESMF_FieldScatter(seaice_depth_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ SEAICE SKIN TEMPERATURE." + call nemsio_readrecv(gfile, "ti", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING SEAICE SKIN TEMP.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'ti ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SEAICE SKIN TEMPERATURE." + call ESMF_FieldScatter(seaice_skin_temp_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ SNOW LIQUID EQUIVALENT." + call nemsio_readrecv(gfile, "weasd", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING SNOW LIQUID EQUIVALENT.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'weasd ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SNOW LIQUID EQUIVALENT." + call ESMF_FieldScatter(snow_liq_equiv_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ SNOW DEPTH." + call nemsio_readrecv(gfile, "snod", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING SNOW DEPTH.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) * 1000.0_8 + print*,'snod ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SNOW DEPTH." + call ESMF_FieldScatter(snow_depth_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ VEG TYPE." + call nemsio_readrecv(gfile, "vtype", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING VEG TYPE", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'vtype ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID VEG TYPE." + call ESMF_FieldScatter(veg_type_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ SOIL TYPE." + call nemsio_readrecv(gfile, "sotyp", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING SOIL TYPE.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'sotype ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SOIL TYPE." + call ESMF_FieldScatter(soil_type_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ T2M." + call nemsio_readrecv(gfile, "tmp", "2 m above gnd", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING T2M.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'t2m ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID T2M." + call ESMF_FieldScatter(t2m_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ Q2M." + call nemsio_readrecv(gfile, "spfh", "2 m above gnd", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING Q2M.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'q2m ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID Q2M." + call ESMF_FieldScatter(q2m_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ TPRCP." + call nemsio_readrecv(gfile, "tprcp", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING TPRCP.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'tprcp ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID TPRCP." + call ESMF_FieldScatter(tprcp_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ FFMM." + call nemsio_readrecv(gfile, "ffmm", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING FFMM.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'ffmm ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID FFMM" + call ESMF_FieldScatter(ffmm_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ USTAR." + call nemsio_readrecv(gfile, "fricv", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING USTAR.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'fricv ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID USTAR" + call ESMF_FieldScatter(ustar_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) dummy2d = 0.0 + print*,"- CALL FieldScatter FOR INPUT GRID SRFLAG" + call ESMF_FieldScatter(srflag_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ SKIN TEMPERATURE." + call nemsio_readrecv(gfile, "tmp", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING SKIN TEMPERATURE.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'tmp ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SKIN TEMPERATURE" + call ESMF_FieldScatter(skin_temp_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ F10M." + call nemsio_readrecv(gfile, "f10m", "10 m above gnd", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING F10M.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'f10m ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID F10M." + call ESMF_FieldScatter(f10m_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ CANOPY MOISTURE CONTENT." + call nemsio_readrecv(gfile, "cnwat", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING CANOPY MOISTURE CONTENT.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) + print*,'cnwat ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID CANOPY MOISTURE CONTENT." + call ESMF_FieldScatter(canopy_mc_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ Z0." + call nemsio_readrecv(gfile, "sfcr", "sfc", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING Z0.", rc) + dummy2d = reshape(dummy, (/i_input,j_input/)) * 100.0_8 ! convert to cm + print*,'sfcr ',maxval(dummy2d),minval(dummy2d) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID Z0." + call ESMF_FieldScatter(z0_input_grid, dummy2d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + deallocate(dummy2d) + + if (localpet == 0) then + print*,"- READ LIQUID SOIL MOISTURE." + call nemsio_readrecv(gfile, "soill", "0-10 cm down", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING LAYER 1 LIQUID SOIL MOIST.", rc) + dummy3d(:,:,1) = reshape(dummy, (/i_input,j_input/)) + call nemsio_readrecv(gfile, "soill", "10-40 cm down", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING LAYER 2 LIQUID SOIL MOIST.", rc) + dummy3d(:,:,2) = reshape(dummy, (/i_input,j_input/)) + call nemsio_readrecv(gfile, "soill", "40-100 cm down", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING LAYER 3 LIQUID SOIL MOIST.", rc) + dummy3d(:,:,3) = reshape(dummy, (/i_input,j_input/)) + call nemsio_readrecv(gfile, "soill", "100-200 cm down", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING LAYER 4 LIQUID SOIL MOIST.", rc) + dummy3d(:,:,4) = reshape(dummy, (/i_input,j_input/)) + print*,'soill ',maxval(dummy3d),minval(dummy3d) + endif + + print*,"- CALL FieldScatter FOR INPUT LIQUID SOIL MOISTURE." + call ESMF_FieldScatter(soilm_liq_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ TOTAL SOIL MOISTURE." + call nemsio_readrecv(gfile, "soilw", "0-10 cm down", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING LAYER 1 TOTAL SOIL MOIST.", rc) + dummy3d(:,:,1) = reshape(dummy, (/i_input,j_input/)) + call nemsio_readrecv(gfile, "soilw", "10-40 cm down", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING LAYER 2 TOTAL SOIL MOIST.", rc) + dummy3d(:,:,2) = reshape(dummy, (/i_input,j_input/)) + call nemsio_readrecv(gfile, "soilw", "40-100 cm down", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING LAYER 3 TOTAL SOIL MOIST.", rc) + dummy3d(:,:,3) = reshape(dummy, (/i_input,j_input/)) + call nemsio_readrecv(gfile, "soilw", "100-200 cm down", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING LAYER 4 TOTAL SOIL MOIST.", rc) + dummy3d(:,:,4) = reshape(dummy, (/i_input,j_input/)) + print*,'soilm ',maxval(dummy3d),minval(dummy3d) + endif + + print*,"- CALL FieldScatter FOR INPUT TOTAL SOIL MOISTURE." + call ESMF_FieldScatter(soilm_tot_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ SOIL TEMPERATURE." + call nemsio_readrecv(gfile, "tmp", "0-10 cm down", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING LAYER 1 SOIL TEMP.", rc) + dummy3d(:,:,1) = reshape(dummy, (/i_input,j_input/)) + call nemsio_readrecv(gfile, "tmp", "10-40 cm down", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING LAYER 2 SOIL TEMP.", rc) + dummy3d(:,:,2) = reshape(dummy, (/i_input,j_input/)) + call nemsio_readrecv(gfile, "tmp", "40-100 cm down", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING LAYER 3 SOIL TEMP.", rc) + dummy3d(:,:,3) = reshape(dummy, (/i_input,j_input/)) + call nemsio_readrecv(gfile, "tmp", "100-200 cm down", 1, dummy, 0, iret=rc) + if (rc /= 0) call error_handler("READING LAYER 4 SOIL TEMP.", rc) + dummy3d(:,:,4) = reshape(dummy, (/i_input,j_input/)) + print*,'soilt ',maxval(dummy3d),minval(dummy3d) + endif + + print*,"- CALL FieldScatter FOR INPUT SOIL TEMPERATURE." + call ESMF_FieldScatter(soil_temp_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + deallocate(dummy3d, dummy) + + if (localpet == 0) call nemsio_close(gfile) + + end subroutine read_input_sfc_gaussian_nemsio_file + +!> Read input grid surface data from fv3 tiled warm 'restart' files. +!! +!! @param[in] localpet ESMF local persistent execution thread +!! @author George Gayno NCEP/EMC + subroutine read_input_sfc_restart_file(localpet) + + implicit none + + integer, intent(in) :: localpet + + character(len=500) :: tilefile + + integer :: error, rc + integer :: id_dim, idim_input, jdim_input + integer :: ncid, tile, id_var + + real(esmf_kind_r8), allocatable :: data_one_tile(:,:) + real(esmf_kind_r8), allocatable :: data_one_tile_3d(:,:,:) + +!--------------------------------------------------------------------------- +! Get i/j dimensions and number of soil layers from first surface file. +! Do dimensions match those from the orography file? +!--------------------------------------------------------------------------- + + tilefile = trim(data_dir_input_grid) // "/" // trim(sfc_files_input_grid(1)) + print*,"- READ GRID DIMENSIONS FROM: ", trim(tilefile) + error=nf90_open(trim(tilefile),nf90_nowrite,ncid) + call netcdf_err(error, 'opening: '//trim(tilefile) ) + + error=nf90_inq_dimid(ncid, 'xaxis_1', id_dim) + call netcdf_err(error, 'reading xaxis_1 id' ) + error=nf90_inquire_dimension(ncid,id_dim,len=idim_input) + call netcdf_err(error, 'reading xaxis_1 value' ) + + error=nf90_inq_dimid(ncid, 'yaxis_1', id_dim) + call netcdf_err(error, 'reading yaxis_1 id' ) + error=nf90_inquire_dimension(ncid,id_dim,len=jdim_input) + call netcdf_err(error, 'reading yaxis_1 value' ) + + if (idim_input /= i_input .or. jdim_input /= j_input) then + call error_handler("DIMENSION MISMATCH BETWEEN SFC AND OROG FILES.", 1) + endif + + error = nf90_close(ncid) + + if (localpet == 0) then + allocate(data_one_tile(idim_input,jdim_input)) + allocate(data_one_tile_3d(idim_input,jdim_input,lsoil_input)) + else + allocate(data_one_tile(0,0)) + allocate(data_one_tile_3d(0,0,0)) + endif + + TERRAIN_LOOP: do tile = 1, num_tiles_input_grid + + if (localpet == 0) then + tilefile = trim(orog_dir_input_grid) // trim(orog_files_input_grid(tile)) + print*,'- OPEN OROGRAPHY FILE: ', trim(tilefile) + error=nf90_open(tilefile,nf90_nowrite,ncid) + call netcdf_err(error, 'OPENING OROGRAPHY FILE' ) + error=nf90_inq_varid(ncid, 'orog_raw', id_var) + call netcdf_err(error, 'READING OROG RECORD ID' ) + error=nf90_get_var(ncid, id_var, data_one_tile) + call netcdf_err(error, 'READING OROG RECORD' ) + print*,'terrain check ',tile, maxval(data_one_tile) + error=nf90_close(ncid) + endif + + print*,"- CALL FieldScatter FOR INPUT TERRAIN." + call ESMF_FieldScatter(terrain_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + enddo TERRAIN_LOOP + + TILE_LOOP : do tile = 1, num_tiles_input_grid + +! liquid soil moisture + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('slc', tile, idim_input, jdim_input, & + lsoil_input, sfcdata_3d=data_one_tile_3d) + endif + + print*,"- CALL FieldScatter FOR INPUT LIQUID SOIL MOISTURE." + call ESMF_FieldScatter(soilm_liq_input_grid, data_one_tile_3d, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('smc', tile, idim_input, jdim_input, & + lsoil_input, sfcdata_3d=data_one_tile_3d) + endif + + print*,"- CALL FieldScatter FOR INPUT TOTAL SOIL MOISTURE." + call ESMF_FieldScatter(soilm_tot_input_grid, data_one_tile_3d, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('stc', tile, idim_input, jdim_input, & + lsoil_input, sfcdata_3d=data_one_tile_3d) + endif + + print*,"- CALL FieldScatter FOR INPUT SOIL TEMPERATURE." + call ESMF_FieldScatter(soil_temp_input_grid, data_one_tile_3d, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! land mask + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('slmsk', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT LANDSEA MASK." + call ESMF_FieldScatter(landsea_mask_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! sea ice fraction + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('fice', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SEAICE FRACTION." + call ESMF_FieldScatter(seaice_fract_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! sea ice depth + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('hice', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SEAICE DEPTH." + call ESMF_FieldScatter(seaice_depth_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! sea ice skin temperature + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('tisfc', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SEAICE SKIN TEMPERATURE." + call ESMF_FieldScatter(seaice_skin_temp_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! liquid equivalent snow depth + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('sheleg', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SNOW LIQUID EQUIVALENT." + call ESMF_FieldScatter(snow_liq_equiv_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! physical snow depth + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('snwdph', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + data_one_tile = data_one_tile + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SNOW DEPTH." + call ESMF_FieldScatter(snow_depth_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! Vegetation type + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('vtype', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID VEG TYPE." + call ESMF_FieldScatter(veg_type_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! Soil type + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('stype', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SOIL TYPE." + call ESMF_FieldScatter(soil_type_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! Two-meter temperature + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('t2m', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID T2M." + call ESMF_FieldScatter(t2m_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! Two-meter q + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('q2m', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID Q2M." + call ESMF_FieldScatter(q2m_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('tprcp', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID TPRCP." + call ESMF_FieldScatter(tprcp_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('f10m', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID F10M" + call ESMF_FieldScatter(f10m_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('ffhh', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID FFHH" + call ESMF_FieldScatter(ffhh_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('ffmm', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID FFMM" + call ESMF_FieldScatter(ffmm_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('uustar', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID USTAR" + call ESMF_FieldScatter(ustar_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('srflag', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SRFLAG" + call ESMF_FieldScatter(srflag_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('tsea', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SKIN TEMPERATURE" + call ESMF_FieldScatter(skin_temp_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('canopy', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID CANOPY MOISTURE CONTENT." + call ESMF_FieldScatter(canopy_mc_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('zorl', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID Z0." + call ESMF_FieldScatter(z0_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + enddo TILE_LOOP + + deallocate(data_one_tile, data_one_tile_3d) + + end subroutine read_input_sfc_restart_file + +!> Read input grid surface data from tiled 'history' files (netcdf) or +!! gaussian netcdf files. +!! +!! @param[in] localpet ESMF local persistent execution thread +!! @author George Gayno NCEP/EMC + subroutine read_input_sfc_netcdf_file(localpet) + + implicit none + + integer, intent(in) :: localpet + + character(len=500) :: tilefile + + integer :: error, id_var + integer :: id_dim, idim_input, jdim_input + integer :: ncid, rc, tile + + real(esmf_kind_r8), allocatable :: data_one_tile(:,:) + real(esmf_kind_r8), allocatable :: data_one_tile_3d(:,:,:) + +!--------------------------------------------------------------------------- +! Get i/j dimensions and number of soil layers from first surface file. +! Do dimensions match those from the orography file? +!--------------------------------------------------------------------------- + + tilefile = trim(data_dir_input_grid) // "/" // trim(sfc_files_input_grid(1)) + print*,"- READ GRID DIMENSIONS FROM: ", trim(tilefile) + error=nf90_open(trim(tilefile),nf90_nowrite,ncid) + call netcdf_err(error, 'opening: '//trim(tilefile) ) + + error=nf90_inq_dimid(ncid, 'grid_xt', id_dim) + call netcdf_err(error, 'reading grid_xt id' ) + error=nf90_inquire_dimension(ncid,id_dim,len=idim_input) + call netcdf_err(error, 'reading grid_xt value' ) + + error=nf90_inq_dimid(ncid, 'grid_yt', id_dim) + call netcdf_err(error, 'reading grid_yt id' ) + error=nf90_inquire_dimension(ncid,id_dim,len=jdim_input) + call netcdf_err(error, 'reading grid_yt value' ) + + if (idim_input /= i_input .or. jdim_input /= j_input) then + call error_handler("DIMENSION MISMATCH BETWEEN SFC AND OROG FILES.", 3) + endif + + error = nf90_close(ncid) + + if (localpet == 0) then + allocate(data_one_tile(idim_input,jdim_input)) + allocate(data_one_tile_3d(idim_input,jdim_input,lsoil_input)) + else + allocate(data_one_tile(0,0)) + allocate(data_one_tile_3d(0,0,0)) + endif + + TERRAIN_LOOP: do tile = 1, num_tiles_input_grid + + if (trim(input_type) == "gaussian_netcdf") then + if (localpet == 0) then + call read_fv3_grid_data_netcdf('orog', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + else + + if (localpet == 0) then + tilefile = trim(orog_dir_input_grid) // trim(orog_files_input_grid(tile)) + print*,'- OPEN OROGRAPHY FILE: ', trim(tilefile) + error=nf90_open(tilefile,nf90_nowrite,ncid) + call netcdf_err(error, 'OPENING OROGRAPHY FILE.' ) + error=nf90_inq_varid(ncid, 'orog_raw', id_var) + call netcdf_err(error, 'READING OROGRAPHY RECORD ID.' ) + error=nf90_get_var(ncid, id_var, data_one_tile) + call netcdf_err(error, 'READING OROGRAPHY RECORD.' ) + print*,'terrain check history ',tile, maxval(data_one_tile) + error=nf90_close(ncid) + endif + + endif + + print*,"- CALL FieldScatter FOR INPUT TERRAIN." + call ESMF_FieldScatter(terrain_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + enddo TERRAIN_LOOP + + TILE_LOOP : do tile = 1, num_tiles_input_grid + +! liquid soil moisture + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('soill1', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + data_one_tile_3d(:,:,1) = data_one_tile + call read_fv3_grid_data_netcdf('soill2', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + data_one_tile_3d(:,:,2) = data_one_tile + call read_fv3_grid_data_netcdf('soill3', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + data_one_tile_3d(:,:,3) = data_one_tile + call read_fv3_grid_data_netcdf('soill4', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + data_one_tile_3d(:,:,4) = data_one_tile + endif + + print*,"- CALL FieldScatter FOR INPUT LIQUID SOIL MOISTURE." + call ESMF_FieldScatter(soilm_liq_input_grid, data_one_tile_3d, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! total soil moisture + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('soilw1', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + data_one_tile_3d(:,:,1) = data_one_tile + call read_fv3_grid_data_netcdf('soilw2', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + data_one_tile_3d(:,:,2) = data_one_tile + call read_fv3_grid_data_netcdf('soilw3', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + data_one_tile_3d(:,:,3) = data_one_tile + call read_fv3_grid_data_netcdf('soilw4', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + data_one_tile_3d(:,:,4) = data_one_tile + endif + + print*,"- CALL FieldScatter FOR INPUT TOTAL SOIL MOISTURE." + call ESMF_FieldScatter(soilm_tot_input_grid, data_one_tile_3d, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! soil tempeature (ice temp at land ice points) + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('soilt1', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + data_one_tile_3d(:,:,1) = data_one_tile + call read_fv3_grid_data_netcdf('soilt2', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + data_one_tile_3d(:,:,2) = data_one_tile + call read_fv3_grid_data_netcdf('soilt3', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + data_one_tile_3d(:,:,3) = data_one_tile + call read_fv3_grid_data_netcdf('soilt4', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + data_one_tile_3d(:,:,4) = data_one_tile + endif + + print*,"- CALL FieldScatter FOR INPUT SOIL TEMPERATURE." + call ESMF_FieldScatter(soil_temp_input_grid, data_one_tile_3d, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! land mask + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('land', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT LANDSEA MASK." + call ESMF_FieldScatter(landsea_mask_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! sea ice fraction + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('icec', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SEAICE FRACTION." + call ESMF_FieldScatter(seaice_fract_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! sea ice depth + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('icetk', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SEAICE DEPTH." + call ESMF_FieldScatter(seaice_depth_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! sea ice skin temperature + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('tisfc', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SEAICE SKIN TEMPERATURE." + call ESMF_FieldScatter(seaice_skin_temp_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! liquid equivalent snow depth + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('weasd', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SNOW LIQUID EQUIVALENT." + call ESMF_FieldScatter(snow_liq_equiv_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! physical snow depth + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('snod', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + data_one_tile = data_one_tile * 1000.0 ! convert from meters to mm. + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SNOW DEPTH." + call ESMF_FieldScatter(snow_depth_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! Vegetation type + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('vtype', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID VEG TYPE." + call ESMF_FieldScatter(veg_type_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! Soil type + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('sotyp', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SOIL TYPE." + call ESMF_FieldScatter(soil_type_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! Two-meter temperature + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('tmp2m', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID T2M." + call ESMF_FieldScatter(t2m_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + +! Two-meter q + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('spfh2m', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID Q2M." + call ESMF_FieldScatter(q2m_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('tprcp', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID TPRCP." + call ESMF_FieldScatter(tprcp_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('f10m', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID F10M" + call ESMF_FieldScatter(f10m_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('ffmm', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID FFMM" + call ESMF_FieldScatter(ffmm_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('fricv', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID USTAR" + call ESMF_FieldScatter(ustar_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then +! call read_fv3_grid_data_netcdf('srflag', tile, idim_input, jdim_input, & +! lsoil_input, sfcdata=data_one_tile) + data_one_tile = 0.0 + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SRFLAG" + call ESMF_FieldScatter(srflag_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('tmpsfc', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SKIN TEMPERATURE" + call ESMF_FieldScatter(skin_temp_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('cnwat', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID CANOPY MOISTURE CONTENT." + call ESMF_FieldScatter(canopy_mc_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + call read_fv3_grid_data_netcdf('sfcr', tile, idim_input, jdim_input, & + lsoil_input, sfcdata=data_one_tile) + endif + + print*,"- CALL FieldScatter FOR INPUT GRID Z0." + call ESMF_FieldScatter(z0_input_grid, data_one_tile, rootpet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + enddo TILE_LOOP + + deallocate(data_one_tile, data_one_tile_3d) + + end subroutine read_input_sfc_netcdf_file + +!> Read input grid surface data from a grib2 file. +!! +!! @param[in] localpet ESMF local persistent execution thread +!! @author Larissa Reames + subroutine read_input_sfc_grib2_file(localpet) + + use mpi + use grib_mod + use program_setup, only : vgtyp_from_climo, sotyp_from_climo + use model_grid, only : input_grid_type + use search_util + + implicit none + + integer, intent(in) :: localpet + + character(len=250) :: the_file + character(len=250) :: geo_file + character(len=200) :: err_msg + character(len=20) :: vname, vname_file, slev + character(len=50) :: method + + integer :: rc, varnum, iret, i, j,k + integer :: ncid2d, varid, varsize + integer :: lugb, lugi + integer :: jdisc, jgdtn, jpdtn, pdt_num + integer :: jids(200), jgdt(200), jpdt(200) + + logical :: rap_latlon, unpack + + real(esmf_kind_r4) :: value + real(esmf_kind_r4), allocatable :: dummy2d(:,:) + real(esmf_kind_r8), allocatable :: icec_save(:,:) + real(esmf_kind_r4), allocatable :: dummy1d(:) + real(esmf_kind_r8), allocatable :: dummy2d_8(:,:),dummy2d_82(:,:),tsk_save(:,:) + real(esmf_kind_r8), allocatable :: dummy3d(:,:,:), dummy3d_stype(:,:,:) + integer(esmf_kind_i4), allocatable :: slmsk_save(:,:) + integer(esmf_kind_i8), allocatable :: dummy2d_i(:,:) + + type(gribfield) :: gfld + + rap_latlon = trim(to_upper(external_model))=="RAP" .and. trim(input_grid_type) == "rotated_latlon" + + the_file = trim(data_dir_input_grid) // "/" // trim(grib2_file_input_grid) + geo_file = trim(geogrid_file_input_grid) + + print*,"- READ SFC DATA FROM GRIB2 FILE: ", trim(the_file) + +! Determine the number of soil layers in file. + + if (localpet == 0) then + + lugb=12 + call baopenr(lugb,the_file,rc) + if (rc /= 0) call error_handler("ERROR OPENING GRIB2 FILE.", rc) + + j = 0 ! search at beginning of file + lugi = 0 ! no grib index file + jdisc = -1 ! search for any discipline + jpdtn = -1 ! search for any product definition template number + jgdtn = -1 ! search for any grid definition template number + jids = -9999 ! array of values in identification section, set to wildcard + jgdt = -9999 ! array of values in grid definition template, set to wildcard + jpdt = -9999 ! array of values in product definition template, set to wildcard + unpack = .false. ! unpack data + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + + if (rc == 0) then + if (gfld%idsect(1) == 7 .and. gfld%idsect(2) == 2) then + print*,'- THIS IS NCEP GEFS DATA.' + pdt_num = 1 + else + pdt_num = 0 + endif + else + if (rc /= 0) call error_handler("ERROR READING GRIB2 FILE.", rc) + endif + + j = 0 + lsoil_input = 0 + + do + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + + if (rc /= 0) exit + + if (gfld%discipline == 2) then ! discipline - land products + if (gfld%ipdtnum == pdt_num) then ! prod template number - analysis or forecast at single level. + if (gfld%ipdtmpl(1) == 0 .and. gfld%ipdtmpl(2) == 2) then ! soil temp + ! Sect4/octs 10 and 11 + if (gfld%ipdtmpl(10) == 106 .and. gfld%ipdtmpl(13) == 106) then ! Sect4/octs 23/29. + ! Layer below ground. + lsoil_input = lsoil_input + 1 + endif + endif + endif + endif + + j = k + + enddo + + print*, "- FILE HAS ", lsoil_input, " SOIL LEVELS." + if (lsoil_input == 0) call error_handler("COUNTING SOIL LEVELS.", rc) + + endif ! localpet == 0 + + call MPI_BARRIER(MPI_COMM_WORLD, rc) + call MPI_BCAST(lsoil_input,1,MPI_INTEGER,0,MPI_COMM_WORLD,rc) + + ! We need to recreate the soil fields if we have something other than 4 levels + + if (lsoil_input /= 4) then + + call ESMF_FieldDestroy(soil_temp_input_grid, rc=rc) + call ESMF_FieldDestroy(soilm_tot_input_grid, rc=rc) + call ESMF_FieldDestroy(soilm_liq_input_grid, rc=rc) + + print*,"- CALL FieldCreate FOR INPUT SOIL TEMPERATURE." + soil_temp_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + ungriddedLBound=(/1/), & + ungriddedUBound=(/lsoil_input/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT TOTAL SOIL MOISTURE." + soilm_tot_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + ungriddedLBound=(/1/), & + ungriddedUBound=(/lsoil_input/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT LIQUID SOIL MOISTURE." + soilm_liq_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + ungriddedLBound=(/1/), & + ungriddedUBound=(/lsoil_input/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + endif + + if (localpet == 0) then + allocate(dummy2d(i_input,j_input)) + allocate(slmsk_save(i_input,j_input)) + allocate(tsk_save(i_input,j_input)) + allocate(icec_save(i_input,j_input)) + allocate(dummy2d_8(i_input,j_input)) + allocate(dummy2d_82(i_input,j_input)) + allocate(dummy3d(i_input,j_input,lsoil_input)) + else + allocate(dummy3d(0,0,0)) + allocate(dummy2d_8(0,0)) + allocate(dummy2d_82(0,0)) + allocate(dummy2d(0,0)) + allocate(slmsk_save(0,0)) + endif + + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + ! These variables are always in grib files, or are required, so no need to check for them + ! in the varmap table. If they can't be found in the input file, then stop the program. + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + if (localpet == 0) then + + print*,"- READ TERRAIN." + + j = 0 + jdisc = 0 ! Search for discipline 0 - meteorological products + jpdt = -9999 ! array of values in product definition template, set to wildcard. + jpdtn = pdt_num ! search for product definition template number 0 - anl or fcst. + jpdt(1) = 3 ! Sec4/oct 10 - param cat - mass field + jpdt(2) = 5 ! Sec4/oct 11 - param number - geopotential height + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + if (rc /= 0) call error_handler("READING TERRAIN.", rc) + + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) +! print*,'orog ', maxval(dummy2d_8),minval(dummy2d_8) + + endif + + print*,"- CALL FieldScatter FOR INPUT TERRAIN." + call ESMF_FieldScatter(terrain_input_grid, dummy2d_8, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + + print*,"- READ SEAICE FRACTION." + + jdisc = 10 ! Search for discipline - ocean products + j = 0 ! Search at beginning of file. + jpdtn = pdt_num ! Search for product def template number 0 - anl or fcst. + jpdt = -9999 ! Array of values in Sec 4 product definition template; + ! Initialize to wildcard. + jpdt(1) = 2 ! Sec4/oct 10 - parameter category - ice + jpdt(2) = 0 ! Sec4/oct 11 - parameter number - ice cover + unpack=.true. + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + if (rc /= 0) call error_handler("READING SEAICE FRACTION.", rc) + + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) +! print*,'icec ', maxval(dummy2d_8),minval(dummy2d_8) + + icec_save = dummy2d_8 + + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SEAICE FRACTION." + call ESMF_FieldScatter(seaice_fract_input_grid, dummy2d_8 ,rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + +!---------------------------------------------------------------------------------- +! GFS v14 and v15.2 grib data has two land masks. LANDN is created by +! nearest neighbor interpolation. LAND is created by bilinear interpolation. +! LANDN matches the bitmap. So use it first. For other GFS versions or other models, +! use LAND. Mask in grib file is '1' (land), '0' (not land). Add sea/lake ice category +! '2' based on ice concentration. +!---------------------------------------------------------------------------------- + + if (localpet == 0) then + + print*,"- READ LANDSEA MASK." + + jdisc = 2 ! Search for discipline - land products + j = 0 ! Search at beginning of file. + jpdtn = pdt_num ! Search for product definition template number 0 - anl or fcst. + jpdt = -9999 ! Initialize array of values in product definition template - Sec 4. + jpdt(1) = 0 ! Sec4/oct 10 - parameter category - veg/biomass + jpdt(2) = 218 ! Sec4/oct 11 - parameter number - land nearest neighbor + unpack=.true. + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + + if (rc == 0) then + + print*,'landnn ', maxval(gfld%fld),minval(gfld%fld) + + else + + jdisc = 2 ! Search for discipline - land products + j = 0 ! Search at beginning of file. + jpdtn = pdt_num ! Search for product def template number 0 - anl or fcst. + jpdt = -9999 ! Initialize array of values in product definition template - Sec 4. + jpdt(1) = 0 ! Sec4/oct 10 - parameter category - veg/biomass + jpdt(2) = 0 ! Sec4/oct 11 - parameter number - land cover (fraction) + unpack=.true. + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + if (rc /= 0) call error_handler("READING LANDSEA MASK.", rc) + +! print*,'land ', maxval(gfld%fld),minval(gfld%fld) + + endif + + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + + do j = 1, j_input + do i = 1, i_input + if(dummy2d_8(i,j) < 0.5_esmf_kind_r8) dummy2d_8(i,j)=0.0 + if(icec_save(i,j) > 0.15_esmf_kind_r8) then + dummy2d_8(i,j) = 2.0_esmf_kind_r8 + endif + enddo + enddo + + slmsk_save = nint(dummy2d_8) + + deallocate(icec_save) + + endif ! read land mask + + print*,"- CALL FieldScatter FOR INPUT LANDSEA MASK." + call ESMF_FieldScatter(landsea_mask_input_grid, dummy2d_8 ,rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + + print*,"- READ SEAICE SKIN TEMPERATURE." + + jdisc = 0 ! Search for discipline - meteorological products + j = 0 ! Search at beginning of file. + jpdtn = pdt_num ! Search for product definition template number 0 - anl or fcst. + jpdt = -9999 ! Initialize array of values in product definition template - Sec4 + jpdt(1) = 0 ! Sec4/oct 10 - parameter category - temperature + jpdt(2) = 0 ! Sec4/oct 11 - parameter number - temperature + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + if (rc /= 0) call error_handler("READING SEAICE SKIN TEMP.", rc) + +! print*,'ti ',maxval(gfld%fld),minval(gfld%fld) + + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SEAICE SKIN TEMPERATURE." + call ESMF_FieldScatter(seaice_skin_temp_input_grid, dummy2d_8 ,rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + +!---------------------------------------------------------------------------------- +! Read snow fields. Zero out at non-land points and undefined points (points +! removed using the bitmap). Program expects depth and liquid equivalent +! in mm. +!---------------------------------------------------------------------------------- + + if (localpet == 0) then + + print*,"- READ SNOW LIQUID EQUIVALENT." + + jdisc = 0 ! Search for discipline - meteorological products + j = 0 ! Search at beginning of file. + jpdtn = pdt_num ! Search for the product definition template number. + jpdt = -9999 ! Initialize array of values in product definition template - Sec4 + jpdt(1) = 1 ! Sec4/oct 10 - parameter category - moisture + jpdt(2) = 13 ! Sec4/oct 11 - parameter number - liquid equiv snow depth + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + if (rc /= 0) call error_handler("READING SNOW LIQUID EQUIVALENT.", rc) + +! print*,'weasd ', maxval(gfld%fld),minval(gfld%fld) + + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + + do j = 1, j_input + do i = 1, i_input + if(slmsk_save(i,j) == 0) dummy2d_8(i,j) = 0.0 + enddo + enddo + + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SNOW LIQUID EQUIVALENT." + call ESMF_FieldScatter(snow_liq_equiv_input_grid, dummy2d_8 ,rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + + print*,"- READ SNOW DEPTH." + + jdisc = 0 ! Search for discipline - meteorological products + j = 0 ! Search at beginning of file. + jpdtn = pdt_num ! Search for the product definition template number. + jpdt = -9999 ! Initialize array of values in product definition template - Sec4 + jpdt(1) = 1 ! Sec4/oct 10 - parameter category - moisture + jpdt(2) = 11 ! Sec4/oct 11 - parameter number - snow depth + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + + if (rc /= 0) then + call error_handler("READING SNOW DEPTH.", rc) + else + gfld%fld = gfld%fld * 1000.0 +! print*,'snod ', maxval(gfld%fld),minval(gfld%fld) + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + endif + + do j = 1, j_input + do i = 1, i_input + if(slmsk_save(i,j) == 0) dummy2d_8(i,j) = 0.0 + enddo + enddo + + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SNOW DEPTH." + call ESMF_FieldScatter(snow_depth_input_grid,dummy2d_8,rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + + print*,"- READ T2M." + + jdisc = 0 ! Search for discipline - meteorological products + j = 0 ! Search at beginning of file. + jpdtn = pdt_num ! Search for the product definition template number. + jpdt = -9999 ! Initialize array of values in product definition template - Sec4 + jpdt(1) = 0 ! Sec4/oct 10 - parameter category - temperature + jpdt(2) = 0 ! Sec4/oct 11 - parameter number - temperature + jpdt(10) = 103 ! Sec4/oct 23 - type of level - height above ground surface + jpdt(12) = 2 ! Sec4/octs 25-28 - 2 meters above ground. + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + + if (rc /= 0) call error_handler("READING T2M.", rc) +! print*,'t2m ', maxval(gfld%fld),minval(gfld%fld) + + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + + endif + + print*,"- CALL FieldScatter FOR INPUT GRID T2M." + call ESMF_FieldScatter(t2m_input_grid, dummy2d_8, rootpet=0,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + + print*,"- READ Q2M." + + jdisc = 0 ! Search for discipline - meteorological products + j = 0 ! Search at beginning of file. + jpdtn = pdt_num ! Search for the product definition template number. + jpdt = -9999 ! Initialize array of values in product definition template - Sec4 + jpdt(1) = 1 ! Sec4/oct 10 - parameter category - moisture + jpdt(2) = 0 ! Sec4/oct 11 - parameter number - specific humidity + jpdt(10) = 103 ! Sec4/oct 23 - type of level - height above ground surface + jpdt(12) = 2 ! Sec4/octs 25-28 - 2 meters above ground. + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + if (rc /=0) call error_handler("READING Q2M.", rc) + +! print*,'q2m ',maxval(gfld%fld),minval(gfld%fld) + + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + + endif + + print*,"- CALL FieldScatter FOR INPUT GRID Q2M." + call ESMF_FieldScatter(q2m_input_grid,dummy2d_8, rootpet=0,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + + print*,"- READ SKIN TEMPERATURE." + + jdisc = 0 ! Search for discipline - meteorological products + j = 0 ! Search at beginning of file. + jpdtn = pdt_num ! Search for the product definition template number. + jpdt = -9999 ! Initialize array of values in product definition template - Sec4 + jpdt(1) = 0 ! Sec4/oct 10 - parameter category - temperature + jpdt(2) = 0 ! Sec4/oct 11 - parameter number - temperature + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + + if (rc /= 0 ) call error_handler("READING SKIN TEMPERATURE.", rc) +! print*,'skint ', maxval(gfld%fld),minval(gfld%fld) + + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + + tsk_save(:,:) = dummy2d_8 + + do j = 1, j_input + do i = 1, i_input + if(slmsk_save(i,j) == 0 .and. dummy2d_8(i,j) < 271.2) then +! print*,'too cool SST ',i,j,dummy2d_8(i,j) + dummy2d_8(i,j) = 271.2 + endif + if(slmsk_save(i,j) == 0 .and. dummy2d_8(i,j) > 310.) then +! print*,'too hot SST ',i,j,dummy2d_8(i,j) + dummy2d_8(i,j) = 310.0 + endif + enddo + enddo + + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SKIN TEMPERATURE" + call ESMF_FieldScatter(skin_temp_input_grid,dummy2d_8,rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + +! srflag not in files. Set to zero. + + if (localpet == 0) dummy2d_8 = 0.0 + + print*,"- CALL FieldScatter FOR INPUT GRID SRFLAG" + call ESMF_FieldScatter(srflag_input_grid,dummy2d_8, rootpet=0,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + + print*,"- READ SOIL TYPE." + + jdisc = 2 ! Search for discipline - land products + j = 0 ! Search at beginning of file + jpdtn = pdt_num ! Search for the product definition template number. + jpdt = -9999 ! Initialize array of values in product definition template - Sec4 + jpdt(1) = 3 ! Sec4/oct 10 - parameter category - soil products + jpdt(2) = 0 ! Sec4/oct 11 - parameter number - soil type + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + + if (rc == 0 ) then +! print*,'soil type ', maxval(gfld%fld),minval(gfld%fld) + dummy2d = reshape(real(gfld%fld,kind=esmf_kind_r4) , (/i_input,j_input/)) + + endif + + if (rc /= 0 .and. (trim(to_upper(external_model))=="HRRR" .or. rap_latlon) .and. geo_file .ne. "NULL") then + ! Some HRRR and RAP files don't have dominant soil type in the output, but the geogrid files + ! do, so this gives users the option to provide the geogrid file and use input soil + ! type + print*, "OPEN GEOGRID FILE ", trim(geo_file) + rc = nf90_open(geo_file,NF90_NOWRITE,ncid2d) + call netcdf_err(rc,"READING GEOGRID FILE") + + print*, "INQURE ABOUT DIM IDS" + rc = nf90_inq_dimid(ncid2d,"west_east",varid) + call netcdf_err(rc,"READING west_east DIMENSION FROM GEOGRID FILE") + + rc = nf90_inquire_dimension(ncid2d,varid,len=varsize) + call netcdf_err(rc,"READING west_east DIMENSION SIZE") + if (varsize .ne. i_input) call error_handler ("GEOGRID FILE GRID SIZE DIFFERS FROM INPUT DATA.", -1) + + print*, "INQUIRE ABOUT SOIL TYPE FROM GEOGRID FILE" + rc = nf90_inq_varid(ncid2d,"SCT_DOM",varid) + call netcdf_err(rc,"FINDING SCT_DOM IN GEOGRID FILE") + + print*, "READ SOIL TYPE FROM GEOGRID FILE " + rc = nf90_get_var(ncid2d,varid,dummy2d) + call netcdf_err(rc,"READING SCT_DOM FROM FILE") + + print*, "INQUIRE ABOUT SOIL TYPE FRACTIONS FROM GEOGRID FILE" + rc = nf90_inq_varid(ncid2d,"SOILCTOP",varid) + call netcdf_err(rc,"FINDING SOILCTOP IN GEOGRID FILE") + + allocate(dummy3d_stype(i_input,j_input,16)) + print*, "READ SOIL TYPE FRACTIONS FROM GEOGRID FILE " + rc = nf90_get_var(ncid2d,varid,dummy3d_stype) + call netcdf_err(rc,"READING SCT_DOM FROM FILE") + + print*, "CLOSE GEOGRID FILE " + iret = nf90_close(ncid2d) + + ! There's an issue with the geogrid file containing soil type water at land points. + ! This correction replaces the soil type at these points with the soil type with + ! the next highest fractional coverage. + allocate(dummy1d(16)) + do j = 1, j_input + do i = 1, i_input + if(dummy2d(i,j) == 14.0_esmf_kind_r4 .and. slmsk_save(i,j) == 1) then + dummy1d(:) = real(dummy3d_stype(i,j,:),kind=esmf_kind_r4) + dummy1d(14) = 0.0_esmf_kind_r4 + dummy2d(i,j) = real(MAXLOC(dummy1d, 1),esmf_kind_r4) + endif + enddo + enddo + deallocate(dummy1d) + deallocate(dummy3d_stype) + endif ! failed + + if ((rc /= 0 .and. trim(to_upper(external_model)) /= "HRRR" .and. .not. rap_latlon) & + .or. (rc /= 0 .and. (trim(to_upper(external_model)) == "HRRR" .or. rap_latlon))) then + if (.not. sotyp_from_climo) then + call error_handler("COULD NOT FIND SOIL TYPE IN FILE. PLEASE SET SOTYP_FROM_CLIMO=.TRUE. . EXITING", rc) + else + vname = "sotyp" + slev = "surface" + call get_var_cond(vname,this_miss_var_method=method, this_miss_var_value=value, & + loc=varnum) + call handle_grib_error(vname, slev ,method,value,varnum,read_from_input,rc, var= dummy2d) + if (rc == 1) then ! missing_var_method == skip or no entry in varmap table + print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. WILL NOT "//& + "SCALE SOIL MOISTURE FOR DIFFERENCES IN SOIL TYPE. " + dummy2d(:,:) = -99999.0_esmf_kind_r4 + endif + endif + endif + + ! In the event that the soil type on the input grid still contains mismatches between + ! soil type and landmask, this correction is a last-ditch effort to replace these points + ! with soil type from a nearby land point. + + if (.not. sotyp_from_climo) then + do j = 1, j_input + do i = 1, i_input + if(dummy2d(i,j) == 14.0_esmf_kind_r4 .and. slmsk_save(i,j) == 1) dummy2d(i,j) = -99999.9_esmf_kind_r4 + enddo + enddo + + allocate(dummy2d_i(i_input,j_input)) + dummy2d_8 = real(dummy2d,esmf_kind_r8) + dummy2d_i(:,:) = 0 + where(slmsk_save == 1) dummy2d_i = 1 + + call search(dummy2d_8,dummy2d_i,i_input,j_input,1,230) + deallocate(dummy2d_i) + else + dummy2d_8=real(dummy2d,esmf_kind_r8) + endif + + print*,'sotype ',maxval(dummy2d_8),minval(dummy2d_8) + + endif ! read of soil type + + print*,"- CALL FieldScatter FOR INPUT GRID SOIL TYPE." + call ESMF_FieldScatter(soil_type_input_grid,dummy2d_8, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + deallocate(dummy2d) + + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + ! Begin variables whose presence in grib2 files varies, but no climatological + ! data is available, so we have to account for values in the varmap table + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + if (.not. vgfrc_from_climo) then + + if (localpet == 0) then + + print*,"- READ VEG FRACTION." + + jdisc = 2 ! Search for discipline - land products + j = 0 ! Search at beginning of file. + jpdtn = pdt_num ! Search for the product definition template number. + jpdt = -9999 ! Initialize array of values in product definition template Sec4. + jpdt(1) = 0 ! Sec4/oct 10 - parameter category - veg/biomass + jpdt(2) = 4 ! Sec4/oct 11 - parameter number - vegetation + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + + if (rc /= 0 )then + err_msg="COULD NOT FIND VEGETATION FRACTION IN FILE. PLEASE SET VGFRC_FROM_CLIMO=.TRUE." + call error_handler(err_msg, rc) + else + if (maxval(gfld%fld) > 2.0) gfld%fld = gfld%fld / 100.0 +! print*,'vfrac ', maxval(gfld%fld),minval(gfld%fld) + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + + endif + + endif ! localpet 0 + + print*,"- CALL FieldScatter FOR INPUT GRID VEG GREENNESS." + call ESMF_FieldScatter(veg_greenness_input_grid,dummy2d_8, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldScatter", rc) + + endif + + if (.not. minmax_vgfrc_from_climo) then + + if (localpet == 0) then + + print*,"- READ MIN VEG FRACTION." + + jdisc = 2 ! Search for discipline - land products + j = 1105 ! grib2 file does not distinguish between the various veg + ! fractions. Need to search using record number. + jpdtn = pdt_num ! Search for the product definition template number. + jpdt = -9999 ! Initialize array of values in product definition template Sec4. + jpdt(1) = 0 ! Sec4/oct 10 - parameter category - veg/biomass + jpdt(2) = 4 ! Sec4/oct 11 - parameter number - vegetation + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + + if (rc /= 0) then + j = 1101 ! Have to search by record number. + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + if (rc /= 0) then + j = 1151 ! Have to search by record number. + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + err_msg="COULD NOT FIND MIN VEGETATION FRACTION IN FILE. SET MINMAX_VGFRC_FROM_CLIMO=.TRUE." + if (rc/=0) call error_handler(err_msg, rc) + endif + endif + + if (maxval(gfld%fld) > 2.0) gfld%fld = gfld%fld / 100.0 + print*,'vfrac min ', maxval(gfld%fld),minval(gfld%fld) + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + + endif ! localpet == 0 + + print*,"- CALL FieldScatter FOR INPUT GRID MIN VEG GREENNESS." + call ESMF_FieldScatter(min_veg_greenness_input_grid,dummy2d_8, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + + print*,"- READ MAX VEG FRACTION." + + jdisc = 2 ! Search for discipline - land products + j = 1106 ! Have to search by record number. + jpdtn = pdt_num ! Search for the product definition template number. + jpdt = -9999 ! Initialize array of values in product definition template Sec4. + jpdt(1) = 0 ! Sec4/oct 10 - parameter category - veg/biomass + jpdt(2) = 4 ! Sec4/oct 11 - parameter number - vegetation + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + if (rc /= 0) then + j = 1102 ! Have to search by record number. + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + if (rc /= 0) then + j = 1152 ! Have to search by record number. + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + err_msg="COULD NOT FIND MAX VEGETATION FRACTION IN FILE. SET MINMAX_VGFRC_FROM_CLIMO=.TRUE." + if (rc <= 0) call error_handler(err_msg, rc) + endif + endif + + if (maxval(gfld%fld) > 2.0) gfld%fld = gfld%fld / 100.0 +! print*,'vfrac max ', maxval(gfld%fld),minval(gfld%fld) + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + + endif !localpet==0 + + print*,"- CALL FieldScatter FOR INPUT GRID MAX VEG GREENNESS." + call ESMF_FieldScatter(max_veg_greenness_input_grid,dummy2d_8,rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + endif !minmax_vgfrc_from_climo + + if (.not. lai_from_climo) then + + if (localpet == 0) then + + print*,"- READ LAI." + + jdisc = 0 ! Search for discipline - meteorological products + j = 0 ! Search at beginning of file. + jpdtn = pdt_num ! Search for the product definition template number. + jpdt = -9999 ! Initialize array of values in product definition template Sec4. + jpdt(1) = 7 ! Sec4/oct 10 - parameter category - thermo stability indices + jpdt(2) = 198 ! Sec4/oct 11 - parameter number - leaf area index + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + + err_msg="COULD NOT FIND LAI IN FILE. SET LAI_FROM_CLIMO=.TRUE." + if (rc /= 0) call error_handler(err_msg, rc) + +! print*,'lai ', maxval(gfld%fld),minval(gfld%fld) + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + + endif !localpet==0 + + print*,"- CALL FieldScatter FOR INPUT GRID LAI." + call ESMF_FieldScatter(lai_input_grid,dummy2d_8,rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + endif ! lai + + if (localpet == 0) then + + print*,"- READ SEAICE DEPTH." + vname="hice" + slev=":surface:" + call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & + loc=varnum) + + jdisc = 10 ! Search for discipline - ocean products + j = 0 ! Search at beginning of file. + jpdtn = pdt_num ! Search for the product definition template number. + jpdt = -9999 ! Initialize array of values in product definition template Sec4. + jpdt(1) = 2 ! Sec4/oct 10 - parameter category - ice + jpdt(2) = 1 ! Sec4/oct 11 - parameter number - thickness + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + + if (rc /= 0 ) then + call handle_grib_error(vname, slev ,method,value,varnum,read_from_input,rc,var8=dummy2d_8) + if (rc==1) then ! missing_var_method == skip or no entry in varmap table + print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. THIS FIELD WILL BE"//& + " REPLACED WITH CLIMO. SET A FILL "// & + "VALUE IN THE VARMAP TABLE IF THIS IS NOT DESIRABLE." + dummy2d_8(:,:) = 0.0 + endif + else +! print*,'hice ', maxval(gfld%fld),minval(gfld%fld) + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + endif + + endif + + print*,"- CALL FieldScatter FOR INPUT GRID SEAICE DEPTH." + call ESMF_FieldScatter(seaice_depth_input_grid,dummy2d_8, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + + print*,"- READ TPRCP." + vname="tprcp" + slev=":surface:" + call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & + loc=varnum) + +! No test data contained this field. So could not test with g2 library. + rc = 1 + if (rc /= 0) then + call handle_grib_error(vname, slev ,method,value,varnum,read_from_input,rc, var8=dummy2d_8) + if (rc==1) then ! missing_var_method == skip or no entry in varmap table + print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. THIS FIELD WILL NOT"//& + " BE WRITTEN TO THE INPUT FILE. SET A FILL "// & + "VALUE IN THE VARMAP TABLE IF THIS IS NOT DESIRABLE." + dummy2d_8 = 0.0 + endif + endif + print*,'tprcp ',maxval(dummy2d_8),minval(dummy2d_8) + + endif ! tprcp + + print*,"- CALL FieldScatter FOR INPUT GRID TPRCP." + call ESMF_FieldScatter(tprcp_input_grid,dummy2d_8, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + + print*,"- READ FFMM." + vname="ffmm" + slev=":surface:" + call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & + loc=varnum) + +! No sample data contained this field, so could not test g2lib. + rc = 1 + if (rc /= 0) then + call handle_grib_error(vname, slev ,method,value,varnum,read_from_input,rc, var8=dummy2d_8) + if (rc==1) then ! missing_var_method == skip or no entry in varmap table + print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. THIS FIELD WILL NOT"//& + " BE WRITTEN TO THE INPUT FILE. SET A FILL "// & + "VALUE IN THE VARMAP TABLE IF THIS IS NOT DESIRABLE." + dummy2d_8(:,:) = 0.0 + endif + endif + print*,'ffmm ',maxval(dummy2d_8),minval(dummy2d_8) + + endif ! ffmm + + print*,"- CALL FieldScatter FOR INPUT GRID FFMM" + call ESMF_FieldScatter(ffmm_input_grid,dummy2d_8, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + + print*,"- READ USTAR." + vname="fricv" + slev=":surface:" + call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & + loc=varnum) + + jdisc = 0 ! Search for discipline - meteorological products + j = 0 ! Search at beginning of file. + jpdtn = pdt_num ! Search for the product definition template number. + jpdt = -9999 ! Initialize array of values in product definition template Sec4. + jpdt(1) = 2 ! Sec4/oct 10 - parameter category - momentum + jpdt(2) = 30 ! Sec4/oct 11 - parameter number - friction velocity + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + if (rc /= 0) then + jpdt(2) = 197 ! oct 11 - param number - friction vel. + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + endif + + if (rc == 0) then +! print*,'fricv ', maxval(gfld%fld),minval(gfld%fld) + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + else + call handle_grib_error(vname, slev ,method,value,varnum,read_from_input,rc, var8=dummy2d_8) + if (rc==1) then ! missing_var_method == skip or no entry in varmap table + print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. THIS FIELD WILL "//& + "REPLACED WITH CLIMO. SET A FILL "// & + "VALUE IN THE VARMAP TABLE IF THIS IS NOT DESIRABLE." + dummy2d_8(:,:) = 0.0 + endif + endif + + endif ! ustar + + print*,"- CALL FieldScatter FOR INPUT GRID USTAR" + call ESMF_FieldScatter(ustar_input_grid,dummy2d_8, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + + print*,"- READ F10M." + vname="f10m" + slev=":10 m above ground:" + call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & + loc=varnum) + + rc = -1 ! None of the test cases have this record. Can't test with g2lib. + if (rc /= 0) then + call handle_grib_error(vname, slev ,method,value,varnum,read_from_input,rc, var8=dummy2d_8) + if (rc==1) then ! missing_var_method == skip or no entry in varmap table + print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. THIS FIELD WILL NOT"//& + " BE WRITTEN TO THE INPUT FILE. SET A FILL "// & + "VALUE IN THE VARMAP TABLE IF THIS IS NOT DESIRABLE." + dummy2d_8(:,:) = 0.0 + endif + endif + print*,'f10m ',maxval(dummy2d_8),minval(dummy2d_8) + + endif + + print*,"- CALL FieldScatter FOR INPUT GRID F10M." + call ESMF_FieldScatter(f10m_input_grid,dummy2d_8, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + + print*,"- READ CANOPY MOISTURE CONTENT." + vname="cnwat" + slev=":surface:" + call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & + loc=varnum) + + jdisc = 2 ! Search for discipline - land products + j = 0 ! Search from beginning of file + jpdtn = pdt_num ! Search for the product definition template number. + jpdt = -9999 ! Initialize array of values in product definition template Sec4. + jpdt(1) = 0 ! Sec4/oct 10 - parameter category - veg/biomass + jpdt(2) = 13 ! Sec4/oct 11 - parameter number - canopy water + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + + if (rc /= 0 ) then + jpdt(2) = 196 ! Sec4/oct 11 - param number - canopy water + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + endif + + if (rc == 0 ) then + print*,'cnwat ', maxval(gfld%fld),minval(gfld%fld) + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + call check_cnwat(dummy2d_8,i_input,j_input) + else + call handle_grib_error(vname, slev ,method,value,varnum,read_from_input,rc, var8=dummy2d_8) + if (rc==1) then ! missing_var_method == skip or no entry in varmap table + print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. THIS FIELD WILL"//& + " REPLACED WITH CLIMO. SET A FILL "// & + "VALUE IN THE VARMAP TABLE IF THIS IS NOT DESIRABLE." + dummy2d_8 = 0.0 + endif + endif + + endif + + print*,"- CALL FieldScatter FOR INPUT GRID CANOPY MOISTURE CONTENT." + call ESMF_FieldScatter(canopy_mc_input_grid,dummy2d_8, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + + print*,"- READ Z0." + vname="sfcr" + slev=":surface:" + call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & + loc=varnum) + + jdisc = 2 ! Search for discipline - land products + j = 0 ! Search from beginning of file. + jpdtn = pdt_num ! Search for the product definition template number. + jpdt = -9999 ! Initialize array of values in product definition template Sec4. + jpdt(1) = 0 ! Sec4/oct 10 - parameter category - veg/biomass + jpdt(2) = 1 ! Sec4/oct 11 - parameter number - surface roughness + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + + if (rc /= 0 ) then + call handle_grib_error(vname, slev ,method,value,varnum,read_from_input,rc, var8= dummy2d_8) + if (rc==1) then ! missing_var_method == skip or no entry in varmap table + print*, "WARNING: "//trim(vname)//" NOT AVAILABLE IN FILE. THIS FIELD WILL BE"//& + " REPLACED WITH CLIMO. SET A FILL "// & + "VALUE IN THE VARMAP TABLE IF THIS IS NOT DESIRABLE." + dummy2d_8(:,:) = 0.0 + endif + else + gfld%fld = gfld%fld * 10.0 ! Grib files have z0 (m), but fv3 expects z0(cm) +! print*,'sfcr ', maxval(gfld%fld),minval(gfld%fld) + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + endif + + endif + + print*,"- CALL FieldScatter FOR INPUT GRID Z0." + call ESMF_FieldScatter(z0_input_grid,dummy2d_8, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ LIQUID SOIL MOISTURE." + vname = "soill" + vname_file = ":SOILL:" + call read_grib_soil(vname,vname_file,lugb, pdt_num,dummy3d) !!! NEED TO HANDLE + !!! SOIL LEVELS + endif + + print*,"- CALL FieldScatter FOR INPUT LIQUID SOIL MOISTURE." + call ESMF_FieldScatter(soilm_liq_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + if (localpet == 0) then + print*,"- READ TOTAL SOIL MOISTURE." + vname = "soilw" + vname_file = "var2_2_1_" ! the var number instead + call read_grib_soil(vname,vname_file,lugb, pdt_num,dummy3d) + endif + + print*,"- CALL FieldScatter FOR INPUT TOTAL SOIL MOISTURE." + call ESMF_FieldScatter(soilm_tot_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + +!---------------------------------------------------------------------------------------- +! Vegetation type is not available in some files. However, it is needed to identify +! permanent land ice points. At land ice, the total soil moisture is a flag value of +! '1'. Use this flag as a temporary solution. +!---------------------------------------------------------------------------------------- + + print*, "- CALL FieldGather for INPUT SOIL TYPE." + call ESMF_FieldGather(soil_type_input_grid, dummy2d_82, rootPet=0, tile=1, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGather", rc) + + if (localpet == 0) then + + print*,"- READ VEG TYPE." + + jdisc = 2 ! Search for discipline - land products + j = 0 ! Search from beginning of file. + jpdtn = pdt_num ! Search for the product definition template number. + jpdt = -9999 ! Initialize array of values in product definition template Sec4. + jpdt(1) = 0 ! Sec4/oct 10 - parameter category - veg/biomass + jpdt(2) = 198 ! Sec4/oct 11 - parameter number - vegetation type + jpdt(10) = 1 ! Sec4/oct 23 - type of level - ground surface + unpack=.true. + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc) + + if (rc /= 0 ) then + if (.not. vgtyp_from_climo) then + call error_handler("COULD NOT FIND VEGETATION TYPE IN FILE. PLEASE SET VGTYP_FROM_CLIMO=.TRUE. . EXITING", rc) + else ! Set input veg type at land ice from soil moisture flag (1.0). + do j = 1, j_input + do i = 1, i_input + dummy2d_8(i,j) = 0.0 + if(slmsk_save(i,j) == 1 .and. dummy3d(i,j,1) > 0.99) & ! land ice indicated by + ! soil moisture flag of '1'. + dummy2d_8(i,j) = real(veg_type_landice_input,esmf_kind_r8) + enddo + enddo + endif + else ! found vtype in file. + dummy2d_8 = reshape(gfld%fld , (/i_input,j_input/)) + endif + + if (trim(external_model) .ne. "GFS") then + do j = 1, j_input + do i = 1,i_input + if (dummy2d_8(i,j) == 15.0_esmf_kind_r8 .and. slmsk_save(i,j) == 1) then + if (dummy3d(i,j,1) < 0.6) then + dummy2d_8(i,j) = real(veg_type_landice_input,esmf_kind_r8) + elseif (dummy3d(i,j,1) > 0.99) then + slmsk_save(i,j) = 0 + dummy2d_8(i,j) = 0.0_esmf_kind_r8 + dummy2d_82(i,j) = 0.0_esmf_kind_r8 + endif + elseif (dummy2d_8(i,j) == 17.0_esmf_kind_r8 .and. slmsk_save(i,j)==0) then + dummy2d_8(i,j) = 0.0_esmf_kind_r8 + endif + enddo + enddo + endif + +! print*,'vgtyp ',maxval(dummy2d_8),minval(dummy2d_8) + + endif ! read veg type + + print*,"- CALL FieldScatter FOR INPUT VEG TYPE." + call ESMF_FieldScatter(veg_type_input_grid, dummy2d_8, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + print*,"- CALL FieldScatter FOR INPUT SOIL TYPE." + call ESMF_FieldScatter(soil_type_input_grid, dummy2d_82, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + deallocate(dummy2d_82) + + print*,"- CALL FieldScatter FOR INPUT LANDSEA MASK." + call ESMF_FieldScatter(landsea_mask_input_grid,real(slmsk_save,esmf_kind_r8),rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + +!--------------------------------------------------------------------------------- +! At open water (slmsk==0), the soil temperature array is not used and set +! to the filler value of SST. At lake/sea ice points (slmsk=2), the soil +! temperature array holds ice column temperature. This field is not available +! in the grib data, so set to a default value. +!--------------------------------------------------------------------------------- + + if (localpet == 0) then + print*,"- READ SOIL TEMPERATURE." + vname = "soilt" + vname_file = ":TSOIL:" + call read_grib_soil(vname,vname_file,lugb,pdt_num,dummy3d) + call check_soilt(dummy3d,slmsk_save,tsk_save,ICET_DEFAULT,i_input,j_input,lsoil_input) + deallocate(tsk_save) + endif + + deallocate(slmsk_save) + + print*,"- CALL FieldScatter FOR INPUT SOIL TEMPERATURE." + call ESMF_FieldScatter(soil_temp_input_grid, dummy3d, rootpet=0, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + + deallocate(dummy3d) + deallocate(dummy2d_8) + + if (localpet == 0) call baclose(lugb, rc) + + end subroutine read_input_sfc_grib2_file + + !> Create surface input grid esmf fields +!! +!! @author George Gayno NCEP/EMC + subroutine init_sfc_esmf_fields + + implicit none + + integer :: rc + + print*,"- CALL FieldCreate FOR INPUT GRID LANDSEA MASK." + landsea_mask_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID Z0." + z0_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID VEGETATION TYPE." + veg_type_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID CANOPY MOISTURE CONTENT." + canopy_mc_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID SEAICE FRACTION." + seaice_fract_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID SEAICE DEPTH." + seaice_depth_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID SEAICE SKIN TEMPERATURE." + seaice_skin_temp_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID SNOW DEPTH." + snow_depth_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID SNOW LIQUID EQUIVALENT." + snow_liq_equiv_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID T2M." + t2m_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID Q2M." + q2m_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID TPRCP." + tprcp_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID F10M." + f10m_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID USTAR." + ustar_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID FFHH." + ffhh_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID FFMM." + ffmm_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT GRID SRFLAG." + srflag_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT SKIN TEMPERATURE." + skin_temp_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT SOIL TYPE." + soil_type_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT TERRAIN." + terrain_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT SOIL TEMPERATURE." + soil_temp_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + ungriddedLBound=(/1/), & + ungriddedUBound=(/lsoil_input/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT TOTAL SOIL MOISTURE." + soilm_tot_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + ungriddedLBound=(/1/), & + ungriddedUBound=(/lsoil_input/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT LIQUID SOIL MOISTURE." + soilm_liq_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, & + ungriddedLBound=(/1/), & + ungriddedUBound=(/lsoil_input/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + + + + if (.not. vgfrc_from_climo) then + print*,"- CALL FieldCreate FOR INPUT VEGETATION GREENNESS." + veg_greenness_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldCreate", rc) + endif + + if (.not. minmax_vgfrc_from_climo) then + print*,"- CALL FieldCreate FOR INPUT MIN VEGETATION GREENNESS." + min_veg_greenness_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldCreate", rc) + + print*,"- CALL FieldCreate FOR INPUT MAX VEGETATION GREENNESS." + max_veg_greenness_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldCreate", rc) + endif + + if (.not. lai_from_climo) then + print*,"- CALL FieldCreate FOR INPUT LEAF AREA INDEX." + lai_input_grid = ESMF_FieldCreate(input_grid, & + typekind=ESMF_TYPEKIND_R8, & + staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldCreate", rc) + endif + end subroutine init_sfc_esmf_fields + +!> Read a record from a netcdf file +!! +!! @param [in] field name of field to be read +!! @param [in] tile_num grid tile number +!! @param [in] imo i-dimension of field +!! @param [in] jmo j-dimension of field +!! @param [in] lmo number of vertical levels of field +!! @param [out] sfcdata 1-d array containing field data +!! @param [out] sfcdata_3d 3-d array containing field data +!! @author George Gayno NCEP/EMC + SUBROUTINE READ_FV3_GRID_DATA_NETCDF(FIELD,TILE_NUM,IMO,JMO,LMO, & + SFCDATA, SFCDATA_3D) + + IMPLICIT NONE + + CHARACTER(LEN=*),INTENT(IN) :: FIELD + + INTEGER, INTENT(IN) :: IMO, JMO, LMO, TILE_NUM + + REAL(ESMF_KIND_R8), INTENT(OUT), OPTIONAL :: SFCDATA(IMO,JMO) + REAL(ESMF_KIND_R8), INTENT(OUT), OPTIONAL :: SFCDATA_3D(IMO,JMO,LMO) + + CHARACTER(LEN=256) :: TILEFILE + + INTEGER :: ERROR, NCID, ID_VAR + + TILEFILE = TRIM(DATA_DIR_INPUT_GRID) // "/" // TRIM(SFC_FILES_INPUT_GRID(TILE_NUM)) + + PRINT*,'WILL READ ',TRIM(FIELD), ' FROM: ', TRIM(TILEFILE) + + ERROR=NF90_OPEN(TRIM(TILEFILE),NF90_NOWRITE,NCID) + CALL NETCDF_ERR(ERROR, 'OPENING: '//TRIM(TILEFILE) ) + + ERROR=NF90_INQ_VARID(NCID, FIELD, ID_VAR) + CALL NETCDF_ERR(ERROR, 'READING FIELD ID' ) + + IF (PRESENT(SFCDATA_3D)) THEN + ERROR=NF90_GET_VAR(NCID, ID_VAR, SFCDATA_3D) + CALL NETCDF_ERR(ERROR, 'READING FIELD' ) + ELSE + ERROR=NF90_GET_VAR(NCID, ID_VAR, SFCDATA) + CALL NETCDF_ERR(ERROR, 'READING FIELD' ) + ENDIF + + ERROR = NF90_CLOSE(NCID) + + END SUBROUTINE READ_FV3_GRID_DATA_NETCDF + + !> Read soil temperature and soil moisture fields from a GRIB2 file. +!! +!! @param [in] vname variable name in varmap table +!! @param [in] vname_file variable name in grib2 file +!! @param [in] lugb logical unit number for surface grib2 file +!! @param [in] pdt_num product definition template number. +!! @param [inout] dummy3d array of soil data +!! @author George Gayno NCEP/EMC + subroutine read_grib_soil(vname, vname_file, lugb, pdt_num, dummy3d) + + use grib_mod + + implicit none + + character(len=20), intent(in) :: vname,vname_file + + integer, intent(in) :: lugb, pdt_num + + real(esmf_kind_r8), intent(inout) :: dummy3d(:,:,:) + + character(len=50) :: slevs(lsoil_input) + character(len=50) :: method + + integer :: varnum, i, j, k, rc, rc2 + integer :: jdisc, jgdtn, jpdtn, lugi + integer :: jids(200), jgdt(200), jpdt(200) + integer :: iscale1, iscale2 + + logical :: unpack + + real(esmf_kind_r4), allocatable :: dummy2d(:,:) + real(esmf_kind_r4) :: value + + type(gribfield) :: gfld + + allocate(dummy2d(i_input,j_input)) + + if(lsoil_input == 4) then + slevs = (/character(24)::':0-0.1 m below ground:', ':0.1-0.4 m below ground:', & + ':0.4-1 m below ground:', ':1-2 m below ground:'/) + elseif(lsoil_input == 9) then + slevs = (/character(26)::':0-0 m below ground',':0.01-0.01 m below ground:',':0.04-0.04 m below ground:', & + ':0.1-0.1 m below ground:',':0.3-0.3 m below ground:',':0.6-0.6 m below ground:', & + ':1-1 m below ground:',':1.6-1.6 m below ground:',':3-3 m below ground:'/) + else + rc = -1 + call error_handler("reading soil levels. File must have 4 or 9 soil levels.", rc) + endif + + call get_var_cond(vname,this_miss_var_method=method,this_miss_var_value=value, & + loc=varnum) + + lugi = 0 ! unit number for index file + jdisc = 2 ! search for discipline - land products + j = 0 ! search at beginning of file. + jpdt = -9999 ! array of values in product definition template 4.n + jids = -9999 ! array of values in identification section, set to wildcard + jgdt = -9999 ! array of values in grid definition template 3.m + jgdtn = -1 ! search for any grid definition number. + jpdtn = pdt_num ! Search for the product definition template number. + jpdt(1) = 0 ! Section 4/Octet 10 - parameter category - veg/biomass + if (trim(vname) == 'soilt') jpdt(2) = 2 ! Section 4/Octet 11 - parameter number - soil temp + if (trim(vname) == 'soilw') jpdt(2) = 192 ! Section 4/Octet 11 - parameter number - total soilm + if (trim(vname) == 'soill') then + jpdt(1) = 3 ! Section 4/Octet 10 - soil products + jpdt(2) = 192 ! Section 4/Octet 11 - parameter number - liquid soilm + endif + jpdt(10) = 106 ! Section 4/Octet 23 - depth below ground + jpdt(13) = 106 ! Section 4/Octet 29 - depth below ground + unpack=.true. + + do i = 1,lsoil_input + + call getgb2(lugb, lugi, j, jdisc, jids, jpdtn, jpdt, jgdtn, jgdt, & + unpack, k, gfld, rc2) + + if (rc2 /= 0) then ! record not found. + call handle_grib_error(vname_file, slevs(i),method,value,varnum,read_from_input,rc,var=dummy2d) + if (rc==1 .and. trim(vname) /= "soill") then + ! missing_var_method == skip or no entry in varmap table + call error_handler("READING IN "//trim(vname)//". SET A FILL "// & + "VALUE IN THE VARMAP TABLE IF THIS ERROR IS NOT DESIRABLE.",rc) + elseif (rc==1) then + dummy3d(:,:,:) = 0.0_esmf_kind_r8 + return + endif + endif + + if (rc2 == 0) then ! record found. + iscale1 = 10 ** gfld%ipdtmpl(11) + iscale2 = 10 ** gfld%ipdtmpl(14) +! print*,'getgb2 top of soil layer in m ', float(gfld%ipdtmpl(12))/float(iscale1) +! print*,'getgb2 bot of soil layer in m ', float(gfld%ipdtmpl(15))/float(iscale2) + dummy2d = reshape(real(gfld%fld,kind=esmf_kind_r4), (/i_input,j_input/) ) + endif + + j = k + + dummy3d(:,:,i) = real(dummy2d,esmf_kind_r8) + + enddo + + deallocate(dummy2d) + + end subroutine read_grib_soil + + !> Free up memory associated with sfc data. +!! +!! @author George Gayno NCEP/EMC + subroutine cleanup_input_sfc_data + + implicit none + + integer :: rc + + print*,"- CALL FieldDestroy FOR INPUT GRID FIELDS." + + call ESMF_FieldDestroy(canopy_mc_input_grid, rc=rc) + call ESMF_FieldDestroy(f10m_input_grid, rc=rc) + call ESMF_FieldDestroy(ffmm_input_grid, rc=rc) + if (.not. convert_nst) then + call ESMF_FieldDestroy(landsea_mask_input_grid, rc=rc) + endif + call ESMF_FieldDestroy(q2m_input_grid, rc=rc) + call ESMF_FieldDestroy(seaice_depth_input_grid, rc=rc) + call ESMF_FieldDestroy(seaice_fract_input_grid, rc=rc) + call ESMF_FieldDestroy(seaice_skin_temp_input_grid, rc=rc) + call ESMF_FieldDestroy(skin_temp_input_grid, rc=rc) + call ESMF_FieldDestroy(snow_depth_input_grid, rc=rc) + call ESMF_FieldDestroy(snow_liq_equiv_input_grid, rc=rc) + call ESMF_FieldDestroy(soil_temp_input_grid, rc=rc) + call ESMF_FieldDestroy(soil_type_input_grid, rc=rc) + call ESMF_FieldDestroy(soilm_liq_input_grid, rc=rc) + call ESMF_FieldDestroy(soilm_tot_input_grid, rc=rc) + call ESMF_FieldDestroy(srflag_input_grid, rc=rc) + call ESMF_FieldDestroy(t2m_input_grid, rc=rc) + call ESMF_FieldDestroy(tprcp_input_grid, rc=rc) + call ESMF_FieldDestroy(ustar_input_grid, rc=rc) + call ESMF_FieldDestroy(veg_type_input_grid, rc=rc) + call ESMF_FieldDestroy(z0_input_grid, rc=rc) + call ESMF_FieldDestroy(terrain_input_grid, rc=rc) + if (.not. vgfrc_from_climo) then + call ESMF_FieldDestroy(veg_greenness_input_grid, rc=rc) + endif + if (.not. minmax_vgfrc_from_climo) then + call ESMF_FieldDestroy(min_veg_greenness_input_grid, rc=rc) + call ESMF_FieldDestroy(max_veg_greenness_input_grid, rc=rc) + endif + if (.not. lai_from_climo) then + call ESMF_FieldDestroy(lai_input_grid, rc=rc) + endif + + end subroutine cleanup_input_sfc_data + + end module sfc_input_data diff --git a/sorc/chgres_cube.fd/static_data.F90 b/sorc/chgres_cube.fd/static_data.F90 index ad9634da0..e95756c6c 100644 --- a/sorc/chgres_cube.fd/static_data.F90 +++ b/sorc/chgres_cube.fd/static_data.F90 @@ -14,6 +14,8 @@ module static_data use esmf + use utilities, only : error_handler, netcdf_err + implicit none private @@ -46,8 +48,7 @@ module static_data !! @author George Gayno NCEP/EMC subroutine get_static_fields(localpet) - use model_grid, only : target_grid, & - num_tiles_target_grid, & + use model_grid, only : num_tiles_target_grid, & i_target, j_target implicit none diff --git a/sorc/chgres_cube.fd/surface.F90 b/sorc/chgres_cube.fd/surface.F90 index b113c9af4..4eb769868 100644 --- a/sorc/chgres_cube.fd/surface.F90 +++ b/sorc/chgres_cube.fd/surface.F90 @@ -22,6 +22,30 @@ module surface use esmf + use surface_target_data, only : canopy_mc_target_grid, t2m_target_grid, & + q2m_target_grid, tprcp_target_grid, & + f10m_target_grid, seaice_fract_target_grid, & + ffhh_target_grid, ffmm_target_grid, ustar_target_grid, & + srflag_target_grid, soil_temp_target_grid, & + seaice_depth_target_grid, snow_liq_equiv_target_grid, & + seaice_skin_temp_target_grid, skin_temp_target_grid, & + snow_depth_target_grid, z0_target_grid, & + c_d_target_grid, c_0_target_grid, & + d_conv_target_grid, dt_cool_target_grid, & + ifd_target_grid, qrain_target_grid, & + tref_target_grid, w_d_target_grid, & + w_0_target_grid, xs_target_grid, & + xt_target_grid, xu_target_grid, & + xv_target_grid, xz_target_grid, & + xtts_target_grid, xzts_target_grid, & + z_c_target_grid, zm_target_grid, & + soilm_tot_target_grid, lai_target_grid, & + soilm_liq_target_grid + + use write_data, only : write_fv3_sfc_data_netcdf + + use utilities, only : error_handler + implicit none private @@ -32,94 +56,6 @@ module surface !< The Noah LSM land ice physics !< are applied at these points. -! surface fields (not including nst) - type(esmf_field), public :: canopy_mc_target_grid - !< canopy moisture content - type(esmf_field), public :: f10m_target_grid - !< log((z0+10)*1/z0) - !< See sfc_diff.f for details - type(esmf_field), public :: ffhh_target_grid - !< log((ztmax+z1)*1/ztmax) - !< See sfc_diff.f for details - type(esmf_field), public :: ffmm_target_grid - !< log((z0+z1)*1/z0) - !< See sfc_diff.f for details - type(esmf_field), public :: q2m_target_grid - !< 2-m specific humidity - type(esmf_field), public :: seaice_depth_target_grid - !< sea ice depth - type(esmf_field), public :: seaice_fract_target_grid - !< sea ice fraction - type(esmf_field), public :: seaice_skin_temp_target_grid - !< sea ice skin temperature - type(esmf_field), public :: skin_temp_target_grid - !< skin temperature/sst - type(esmf_field), public :: srflag_target_grid - !< snow/rain flag - type(esmf_field), public :: snow_liq_equiv_target_grid - !< liquid equiv snow depth - type(esmf_field), public :: snow_depth_target_grid - !< physical snow depth - type(esmf_field), public :: soil_temp_target_grid - !< 3-d soil temperature - type(esmf_field), public :: soilm_liq_target_grid - !< 3-d liquid soil moisture - type(esmf_field), public :: soilm_tot_target_grid - !< 3-d total soil moisture - type(esmf_field), public :: t2m_target_grid - !< 2-m temperatrure - type(esmf_field), public :: tprcp_target_grid - !< precip - type(esmf_field), public :: ustar_target_grid - !< friction velocity - type(esmf_field), public :: z0_target_grid - !< roughness length - type(esmf_field), public :: lai_target_grid - !< leaf area index - -! nst fields - type(esmf_field), public :: c_d_target_grid - !< Coefficient 2 to calculate d(tz)/d(ts) - type(esmf_field), public :: c_0_target_grid - !< Coefficient 1 to calculate d(tz)/d(ts) - type(esmf_field), public :: d_conv_target_grid - !< Thickness of free convection layer - type(esmf_field), public :: dt_cool_target_grid - !< Sub-layer cooling amount - type(esmf_field), public :: ifd_target_grid - !< Model mode index. 0-diurnal model not - !< started; 1-diurnal model started. - type(esmf_field), public :: qrain_target_grid - !< Sensible heat flux due to rainfall - type(esmf_field), public :: tref_target_grid - !< reference temperature - type(esmf_field), public :: w_d_target_grid - !< Coefficient 4 to calculate d(tz)/d(ts) - type(esmf_field), public :: w_0_target_grid - !< Coefficient 3 to calculate d(tz)/d(ts) - type(esmf_field), public :: xs_target_grid - !< Salinity content in diurnal - !< thermocline layer - type(esmf_field), public :: xt_target_grid - !< Heat content in diurnal thermocline - !< layer - type(esmf_field), public :: xu_target_grid - !< u-current content in diurnal - !< thermocline layer - type(esmf_field), public :: xv_target_grid - !< v-current content in diurnal - !< thermocline layer - type(esmf_field), public :: xz_target_grid - !< Diurnal thermocline layer thickness - type(esmf_field), public :: xtts_target_grid - !< d(xt)/d(ts) - type(esmf_field), public :: xzts_target_grid - !< d(xz)/d(ts) - type(esmf_field), public :: z_c_target_grid - !< Sub-layer cooling thickness - type(esmf_field), public :: zm_target_grid - !< Oceanic mixed layer depth - type(esmf_field) :: soil_type_from_input_grid !< soil type interpolated from !< input grid @@ -140,14 +76,26 @@ module surface !< gravity real, parameter, private :: hlice = 3.335E5 !< latent heat of fusion + + + type realptr_2d + real(esmf_kind_r8), pointer :: p(:,:) + !< array of 2d pointers + end type realptr_2d + !< pointer to hold array of 2d pointers + type realptr_3d + real(esmf_kind_r8), pointer :: p(:,:,:) + !< array of 3d pointers + end type realptr_3d + !< pointer to hold array of 3d pointers public :: surface_driver public :: create_nst_esmf_fields public :: interp public :: create_surface_esmf_fields - public :: cleanup_target_sfc_data public :: nst_land_fill - public :: cleanup_target_nst_data + public :: regrid_many + public :: search_many contains @@ -158,9 +106,10 @@ module surface !! @author George Gayno NCEP/EMC subroutine surface_driver(localpet) - use input_data, only : cleanup_input_sfc_data, & - cleanup_input_nst_data, & - read_input_sfc_data, & + use sfc_input_data, only : cleanup_input_sfc_data, & + read_input_sfc_data + + use nst_input_data, only : cleanup_input_nst_data, & read_input_nst_data use program_setup, only : calc_soil_params_driver, & @@ -169,6 +118,10 @@ subroutine surface_driver(localpet) use static_data, only : get_static_fields, & cleanup_static_fields + use surface_target_data, only : cleanup_target_nst_data + + use utilities, only : error_handler + implicit none integer, intent(in) :: localpet @@ -222,8 +175,7 @@ subroutine surface_driver(localpet) call interp(localpet) !--------------------------------------------------------------------------------------------- -! Adjust soil/landice column temperatures for any change in elevation between -! the +! Adjust soil/landice column temperatures for any change in elevation between the ! input and target grids. !--------------------------------------------------------------------------------------------- @@ -279,7 +231,7 @@ subroutine surface_driver(localpet) if (convert_nst) call cleanup_target_nst_data - call cleanup_target_sfc_data + call cleanup_all_target_sfc_data call cleanup_static_fields @@ -298,7 +250,7 @@ subroutine interp(localpet) use mpi use esmf - use input_data, only : canopy_mc_input_grid, & + use sfc_input_data, only : canopy_mc_input_grid, & f10m_input_grid, & ffhh_input_grid, & ffmm_input_grid, & @@ -319,7 +271,13 @@ subroutine interp(localpet) ustar_input_grid, & veg_type_input_grid, & z0_input_grid, & - c_d_input_grid, & + veg_type_landice_input, & + veg_greenness_input_grid, & + max_veg_greenness_input_grid, & + min_veg_greenness_input_grid, & + lai_input_grid + + use nst_input_data, only : c_d_input_grid, & c_0_input_grid, & d_conv_input_grid, & dt_cool_input_grid, & @@ -336,12 +294,9 @@ subroutine interp(localpet) xtts_input_grid, & xzts_input_grid, & z_c_input_grid, & - zm_input_grid, terrain_input_grid, & - veg_type_landice_input, & - veg_greenness_input_grid, & - max_veg_greenness_input_grid, & - min_veg_greenness_input_grid, & - lai_input_grid + zm_input_grid + + use atm_input_data, only : terrain_input_grid use model_grid, only : input_grid, target_grid, & i_target, j_target, & @@ -357,9 +312,7 @@ subroutine interp(localpet) vgfrc_from_climo, & minmax_vgfrc_from_climo, & lai_from_climo, & - tg3_from_soil, & - external_model, & - input_type + tg3_from_soil use static_data, only : veg_type_target_grid, & soil_type_target_grid, & @@ -378,6 +331,9 @@ subroutine interp(localpet) integer :: i, j, ij, rc, tile integer :: clb_target(2), cub_target(2) integer :: isrctermprocessing + integer :: num_fields + integer :: vgfrc_ind, mmvg_ind, lai_ind + integer, allocatable :: search_nums(:) integer(esmf_kind_i4), pointer :: unmapped_ptr(:) integer(esmf_kind_i4), pointer :: mask_input_ptr(:,:) integer(esmf_kind_i4), pointer :: mask_target_ptr(:,:) @@ -391,47 +347,14 @@ subroutine interp(localpet) real(esmf_kind_r8), allocatable :: data_one_tile2(:,:) real(esmf_kind_r8), allocatable :: data_one_tile_3d(:,:,:) real(esmf_kind_r8), allocatable :: latitude_one_tile(:,:) - real(esmf_kind_r8), allocatable :: soil_type_target_grid_save(:,:) - real(esmf_kind_r8), pointer :: canopy_mc_target_ptr(:,:) - real(esmf_kind_r8), pointer :: c_d_target_ptr(:,:) - real(esmf_kind_r8), pointer :: c_0_target_ptr(:,:) - real(esmf_kind_r8), pointer :: d_conv_target_ptr(:,:) - real(esmf_kind_r8), pointer :: dt_cool_target_ptr(:,:) - real(esmf_kind_r8), pointer :: ifd_target_ptr(:,:) - real(esmf_kind_r8), pointer :: qrain_target_ptr(:,:) - real(esmf_kind_r8), pointer :: tref_target_ptr(:,:) - real(esmf_kind_r8), pointer :: w_d_target_ptr(:,:) - real(esmf_kind_r8), pointer :: w_0_target_ptr(:,:) - real(esmf_kind_r8), pointer :: xs_target_ptr(:,:) - real(esmf_kind_r8), pointer :: xt_target_ptr(:,:) - real(esmf_kind_r8), pointer :: xu_target_ptr(:,:) - real(esmf_kind_r8), pointer :: xv_target_ptr(:,:) - real(esmf_kind_r8), pointer :: xz_target_ptr(:,:) - real(esmf_kind_r8), pointer :: xtts_target_ptr(:,:) - real(esmf_kind_r8), pointer :: xzts_target_ptr(:,:) - real(esmf_kind_r8), pointer :: z_c_target_ptr(:,:) - real(esmf_kind_r8), pointer :: zm_target_ptr(:,:) - real(esmf_kind_r8), pointer :: seaice_depth_target_ptr(:,:) real(esmf_kind_r8), pointer :: seaice_fract_target_ptr(:,:) - real(esmf_kind_r8), pointer :: seaice_skin_temp_target_ptr(:,:) - real(esmf_kind_r8), pointer :: skin_temp_target_ptr(:,:) - real(esmf_kind_r8), pointer :: snow_depth_target_ptr(:,:) - real(esmf_kind_r8), pointer :: snow_liq_equiv_target_ptr(:,:) - real(esmf_kind_r8), pointer :: soil_temp_target_ptr(:,:,:) - real(esmf_kind_r8), pointer :: soil_type_from_input_ptr(:,:) - real(esmf_kind_r8), pointer :: soil_type_target_ptr(:,:) - real(esmf_kind_r8), pointer :: soilm_tot_target_ptr(:,:,:) real(esmf_kind_r8), pointer :: srflag_target_ptr(:,:) real(esmf_kind_r8), pointer :: terrain_from_input_ptr(:,:) real(esmf_kind_r8), pointer :: veg_type_target_ptr(:,:) - real(esmf_kind_r8), pointer :: z0_target_ptr(:,:) + real(esmf_kind_r8), pointer :: soil_type_target_ptr(:,:) real(esmf_kind_r8), pointer :: landmask_input_ptr(:,:) real(esmf_kind_r8), pointer :: veg_type_input_ptr(:,:) real(esmf_kind_r8), allocatable :: veg_type_target_one_tile(:,:) - real(esmf_kind_r8), pointer :: veg_greenness_target_ptr(:,:) - real(esmf_kind_r8), pointer :: min_veg_greenness_target_ptr(:,:) - real(esmf_kind_r8), pointer :: max_veg_greenness_target_ptr(:,:) - real(esmf_kind_r8), pointer :: lai_target_ptr(:,:) type(esmf_regridmethod_flag) :: method type(esmf_routehandle) :: regrid_bl_no_mask @@ -441,6 +364,15 @@ subroutine interp(localpet) type(esmf_routehandle) :: regrid_nonland type(esmf_routehandle) :: regrid_seaice type(esmf_routehandle) :: regrid_water + + type(esmf_fieldbundle) :: bundle_all_target, bundle_all_input + type(esmf_fieldbundle) :: bundle_seaice_target, bundle_seaice_input + type(esmf_fieldbundle) :: bundle_water_target, bundle_water_input + type(esmf_fieldbundle) :: bundle_allland_target, bundle_allland_input + type(esmf_fieldbundle) :: bundle_landice_target, bundle_landice_input + type(esmf_fieldbundle) :: bundle_nolandice_target, bundle_nolandice_input + + logical, allocatable :: dozero(:) !----------------------------------------------------------------------- ! Interpolate fieids that do not require 'masked' interpolation. @@ -460,71 +392,42 @@ subroutine interp(localpet) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldRegridStore", rc) - print*,"- CALL Field_Regrid T2M." - call ESMF_FieldRegrid(t2m_input_grid, & - t2m_target_grid, & - routehandle=regrid_bl_no_mask, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - - print*,"- CALL Field_Regrid Q2M." - call ESMF_FieldRegrid(q2m_input_grid, & - q2m_target_grid, & - routehandle=regrid_bl_no_mask, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - - print*,"- CALL Field_Regrid TPRCP." - call ESMF_FieldRegrid(tprcp_input_grid, & - tprcp_target_grid, & - routehandle=regrid_bl_no_mask, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - - print*,"- CALL Field_Regrid F10M." - call ESMF_FieldRegrid(f10m_input_grid, & - f10m_target_grid, & - routehandle=regrid_bl_no_mask, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - -!cggg only for warm restart files. - print*,"- CALL Field_Regrid FFHH." - call ESMF_FieldRegrid(ffhh_input_grid, & - ffhh_target_grid, & - routehandle=regrid_bl_no_mask, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - - print*,"- CALL Field_Regrid FFMM." - call ESMF_FieldRegrid(ffmm_input_grid, & - ffmm_target_grid, & - routehandle=regrid_bl_no_mask, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - - print*,"- CALL Field_Regrid USTAR." - call ESMF_FieldRegrid(ustar_input_grid, & - ustar_target_grid, & - routehandle=regrid_bl_no_mask, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) +!cggg only for warm restart files - add FFHH. + bundle_all_target = ESMF_FieldBundleCreate(name="all points target", rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleCreate", rc) + bundle_all_input = ESMF_FieldBundleCreate(name="all points input", rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleCreate", rc) + + call ESMF_FieldBundleAdd(bundle_all_target, (/t2m_target_grid,q2m_target_grid,tprcp_target_grid, & + f10m_target_grid,ffhh_target_grid,ffmm_target_grid,ustar_target_grid,srflag_target_grid/), & + rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleAdd", rc) + call ESMF_FieldBundleAdd(bundle_all_input, (/t2m_input_grid,q2m_input_grid,tprcp_input_grid, & + f10m_input_grid,ffhh_input_grid,ffmm_input_grid,ustar_input_grid,srflag_input_grid/), & + rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleAdd", rc) + + call ESMF_FieldBundleGet(bundle_all_target,fieldCount=num_fields,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleGet", rc) + + allocate(dozero(num_fields)) + dozero(:) = .True. - print*,"- CALL Field_Regrid SRFLAG." - call ESMF_FieldRegrid(srflag_input_grid, & - srflag_target_grid, & - routehandle=regrid_bl_no_mask, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) + call regrid_many(bundle_all_input,bundle_all_target,num_fields,regrid_bl_no_mask,dozero) + deallocate(dozero) + call ESMF_FieldBundleDestroy(bundle_all_target,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleDestroy", rc) + call ESMF_FieldBundleDestroy(bundle_all_input,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleDestroy", rc) + print*,"- CALL FieldGet FOR SRFLAG." call ESMF_FieldGet(srflag_target_grid, & farrayPtr=srflag_target_ptr, rc=rc) @@ -599,12 +502,10 @@ subroutine interp(localpet) allocate(data_one_tile(i_target,j_target)) allocate(data_one_tile_3d(i_target,j_target,lsoil_target)) allocate(mask_target_one_tile(i_target,j_target)) - allocate(soil_type_target_grid_save(i_target,j_target)) else allocate(data_one_tile(0,0)) allocate(data_one_tile_3d(0,0,0)) allocate(mask_target_one_tile(0,0)) - allocate(soil_type_target_grid_save(0,0)) endif !----------------------------------------------------------------------- @@ -756,7 +657,7 @@ subroutine interp(localpet) mask_input_ptr = 1 where (nint(landmask_input_ptr) == 1) mask_input_ptr = 0 - mask_target_ptr = seamask_target_ptr + mask_target_ptr = int(seamask_target_ptr,kind=esmf_kind_i4) method=ESMF_REGRIDMETHOD_CONSERVE @@ -905,175 +806,66 @@ subroutine interp(localpet) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldRegridStore", rc) - print*,"- CALL Field_Regrid for soil temperature over seaice." - call ESMF_FieldRegrid(soil_temp_input_grid, & - soil_temp_target_grid, & - routehandle=regrid_seaice, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - - print*,"- CALL FieldGet FOR TARGET grid soil temperature over seaice." - call ESMF_FieldGet(soil_temp_target_grid, & - farrayPtr=soil_temp_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL Field_Regrid for sea ice depth." - call ESMF_FieldRegrid(seaice_depth_input_grid, & - seaice_depth_target_grid, & - routehandle=regrid_seaice, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - - print*,"- CALL FieldGet FOR TARGET grid sea ice depth." - call ESMF_FieldGet(seaice_depth_target_grid, & - farrayPtr=seaice_depth_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL Field_Regrid for snow depth." - call ESMF_FieldRegrid(snow_depth_input_grid, & - snow_depth_target_grid, & - routehandle=regrid_seaice, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - - print*,"- CALL FieldGet FOR TARGET grid snow depth." - call ESMF_FieldGet(snow_depth_target_grid, & - farrayPtr=snow_depth_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL Field_Regrid for snow liq equiv." - call ESMF_FieldRegrid(snow_liq_equiv_input_grid, & - snow_liq_equiv_target_grid, & - routehandle=regrid_seaice, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - - print*,"- CALL FieldGet FOR TARGET grid snow liq equiv." - call ESMF_FieldGet(snow_liq_equiv_target_grid, & - farrayPtr=snow_liq_equiv_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL Field_Regrid for sea ice skin temp." - call ESMF_FieldRegrid(seaice_skin_temp_input_grid, & - seaice_skin_temp_target_grid, & - routehandle=regrid_seaice, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) + bundle_seaice_target = ESMF_FieldBundleCreate(name="sea ice target", rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleCreate", rc) + bundle_seaice_input = ESMF_FieldBundleCreate(name="sea ice input", rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleCreate", rc) + call ESMF_FieldBundleAdd(bundle_seaice_target, (/seaice_depth_target_grid, snow_depth_target_grid, & + snow_liq_equiv_target_grid, seaice_skin_temp_target_grid, & + soil_temp_target_grid/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleAdd", rc) + call ESMF_FieldBundleAdd(bundle_seaice_input, (/seaice_depth_input_grid, snow_depth_input_grid, & + snow_liq_equiv_input_grid, seaice_skin_temp_input_grid, & + soil_temp_input_grid/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleAdd", rc) + call ESMF_FieldBundleGet(bundle_seaice_target,fieldCount=num_fields,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleGet", rc) + - print*,"- CALL FieldGet FOR TARGET grid sea ice skin temp." - call ESMF_FieldGet(seaice_skin_temp_target_grid, & - farrayPtr=seaice_skin_temp_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) + allocate(search_nums(num_fields)) + allocate(dozero(num_fields)) + search_nums = (/92,66,65,21,21/) + dozero(:) = .True. + l = lbound(unmapped_ptr) u = ubound(unmapped_ptr) - - do ij = l(1), u(1) - call ij_to_i_j(unmapped_ptr(ij), i_target, j_target, i, j) - seaice_depth_target_ptr(i,j) = -9999.9 - snow_depth_target_ptr(i,j) = -9999.9 - snow_liq_equiv_target_ptr(i,j) = -9999.9 - seaice_skin_temp_target_ptr(i,j) = -9999.9 - soil_temp_target_ptr(i,j,:) = -9999.9 - enddo + + call regrid_many(bundle_seaice_input,bundle_seaice_target,num_fields,regrid_seaice,dozero, & + unmapped_ptr=unmapped_ptr ) + deallocate(dozero) + call ESMF_FieldBundleDestroy(bundle_seaice_input,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleDestroy", rc) do tile = 1, num_tiles_target_grid - print*,"- CALL FieldGather FOR TARGET GRID SEAICE DEPTH TILE: ", tile - call ESMF_FieldGather(seaice_depth_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - print*,"- CALL FieldGather FOR TARGET LANDMASK TILE: ", tile call ESMF_FieldGather(landmask_target_grid, mask_target_one_tile, rootPet=0, tile=tile, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldGather", rc) - if (localpet == 0) then - ! I don't think is needed anymore with the more recent fixes to fill values in input_data - !if (count(landmask_target_ptr == 2) == 0) data_one_tile(:,:) =0.0_esmf_kind_r8 - + if (localpet == 0) then where(mask_target_one_tile == 1) mask_target_one_tile = 0 where(mask_target_one_tile == 2) mask_target_one_tile = 1 - call search(data_one_tile, mask_target_one_tile, i_target, j_target, tile, 92) - endif - - print*,"- CALL FieldScatter FOR TARGET GRID SEAICE DEPTH TILE: ", tile - call ESMF_FieldScatter(seaice_depth_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - print*,"- CALL FieldGather FOR TARGET GRID SNOW DEPTH TILE: ", tile - call ESMF_FieldGather(snow_depth_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - call search(data_one_tile, mask_target_one_tile, i_target, j_target, tile, 66) - endif - - print*,"- CALL FieldScatter FOR TARGET GRID SNOW DEPTH TILE: ", tile - call ESMF_FieldScatter(snow_depth_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - print*,"- CALL FieldGather FOR TARGET GRID SNOW LIQ EQUIV TILE: ", tile - call ESMF_FieldGather(snow_liq_equiv_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - call search(data_one_tile, mask_target_one_tile, i_target, j_target, tile, 65) - endif - - print*,"- CALL FieldScatter FOR TARGET GRID SNOW LIQ EQUIV TILE: ", tile - call ESMF_FieldScatter(snow_liq_equiv_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - print*,"- CALL FieldGather FOR TARGET GRID SEAICE SKIN TEMP: ", tile - call ESMF_FieldGather(seaice_skin_temp_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - call search(data_one_tile, mask_target_one_tile, i_target, j_target, tile, 21) - endif - - print*,"- CALL FieldScatter FOR TARGET GRID SEAICE SKIN TEMP: ", tile - call ESMF_FieldScatter(seaice_skin_temp_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - print*,"- CALL FieldGather FOR TARGET GRID SEAICE COLUMN TEMP: ", tile - call ESMF_FieldGather(soil_temp_target_grid, data_one_tile_3d, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - do j = 1, lsoil_target - data_one_tile = data_one_tile_3d(:,:,j) - call search(data_one_tile, mask_target_one_tile, i_target, j_target, tile, 21) - data_one_tile_3d(:,:,j) = data_one_tile - enddo + call search_many(num_fields,bundle_seaice_target,tile, search_nums,localpet, & + mask=mask_target_one_tile) + else + call search_many(num_fields,bundle_seaice_target, tile,search_nums,localpet) endif - print*,"- CALL FieldScatter FOR TARGET GRID SEAICE COLUMN TEMP: ", tile - call ESMF_FieldScatter(soil_temp_target_grid, data_one_tile_3d, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) enddo + deallocate(search_nums) + call ESMF_FieldBundleDestroy(bundle_seaice_target,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldBundleDestroy", rc) + print*,"- CALL FieldRegridRelease." call ESMF_FieldRegridRelease(routehandle=regrid_seaice, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & @@ -1106,683 +898,109 @@ subroutine interp(localpet) unmappedDstList=unmapped_ptr, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldRegridStore", rc) - - print*,"- CALL Field_Regrid for skin temperature over water." - call ESMF_FieldRegrid(skin_temp_input_grid, & - skin_temp_target_grid, & - routehandle=regrid_water, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - print*,"- CALL FieldGet FOR TARGET skin temperature." - call ESMF_FieldGet(skin_temp_target_grid, & - farrayPtr=skin_temp_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) + bundle_water_target = ESMF_FieldBundleCreate(name="water target", rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleCreate", rc) + bundle_water_input = ESMF_FieldBundleCreate(name="water input", rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleCreate", rc) + call ESMF_FieldBundleAdd(bundle_water_target, (/skin_temp_target_grid, z0_target_grid/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleAdd", rc) + call ESMF_FieldBundleAdd(bundle_water_input, (/skin_temp_input_grid, z0_input_grid/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleAdd", rc) - print*,"- CALL Field_Regrid for z0 over water." - call ESMF_FieldRegrid(z0_input_grid, & - z0_target_grid, & - routehandle=regrid_water, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) + if (convert_nst) then - print*,"- CALL FieldGet FOR TARGET z0." - call ESMF_FieldGet(z0_target_grid, & - farrayPtr=z0_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) + call ESMF_FieldBundleAdd(bundle_water_target, (/c_d_target_grid,c_0_target_grid,d_conv_target_grid, & + dt_cool_target_grid,ifd_target_grid,qrain_target_grid,tref_target_grid, & + w_d_target_grid,w_0_target_grid,xs_target_grid,xt_target_grid,xu_target_grid, & + xv_target_grid,xz_target_grid,xtts_target_grid,xzts_target_grid, & + z_c_target_grid,zm_target_grid/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleAdd", rc) + + call ESMF_FieldBundleAdd(bundle_water_input, (/c_d_input_grid,c_0_input_grid,d_conv_input_grid, & + dt_cool_input_grid,ifd_input_grid,qrain_input_grid,tref_input_grid, & + w_d_input_grid,w_0_input_grid,xs_input_grid,xt_input_grid,xu_input_grid, & + xv_input_grid,xz_input_grid,xtts_input_grid,xzts_input_grid, & + z_c_input_grid,zm_input_grid/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleAdd", rc) + call ESMF_FieldBundleGet(bundle_water_target,fieldCount=num_fields,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleGet", rc) + + allocate(search_nums(num_fields)) + allocate(dozero(num_fields)) + + search_nums(:)=(/11,83,0,0,0,0,1,0,11,0,0,0,0,0,0,30,0,0,0,0/) + dozero(:) = .True. + + else + call ESMF_FieldBundleGet(bundle_water_target,fieldCount=num_fields,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleGet", rc) + + allocate(search_nums(num_fields)) + allocate(dozero(num_fields)) + search_nums(:)=(/11,83/) + dozero(:) = .True. + endif - l = lbound(unmapped_ptr) - u = ubound(unmapped_ptr) + call regrid_many(bundle_water_input,bundle_water_target,num_fields,regrid_water,dozero, & + unmapped_ptr=unmapped_ptr, resetifd=.True.) + deallocate(dozero) + call ESMF_FieldBundleDestroy(bundle_water_input,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleDestroy", rc) - do ij = l(1), u(1) - call ij_to_i_j(unmapped_ptr(ij), i_target, j_target, i, j) - skin_temp_target_ptr(i,j) = -9999.9 - z0_target_ptr(i,j) = -9999.9 - enddo - if (convert_nst) then + if (localpet == 0) then + allocate(latitude_one_tile(i_target,j_target)) + else + allocate(latitude_one_tile(0,0)) + endif - print*,"- CALL Field_Regrid for c_d over water." - call ESMF_FieldRegrid(c_d_input_grid, & - c_d_target_grid, & - routehandle=regrid_water, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) + do tile = 1, num_tiles_target_grid - print*,"- CALL Field_Regrid for c_0 over water." - call ESMF_FieldRegrid(c_0_input_grid, & - c_0_target_grid, & - routehandle=regrid_water, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) + print*,"- CALL FieldGather FOR TARGET LANDMASK TILE: ", tile + call ESMF_FieldGather(landmask_target_grid, mask_target_one_tile, rootPet=0, tile=tile, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) + call error_handler("IN FieldGather", rc) - print*,"- CALL Field_Regrid for d_conv over water." - call ESMF_FieldRegrid(d_conv_input_grid, & - d_conv_target_grid, & - routehandle=regrid_water, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) + print*,"- CALL FieldGather FOR TARGET LATITUDE TILE: ", tile + call ESMF_FieldGather(latitude_target_grid, latitude_one_tile, rootPet=0, tile=tile, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) + call error_handler("IN FieldGather", rc) - print*,"- CALL Field_Regrid for dt_cool over water." - call ESMF_FieldRegrid(dt_cool_input_grid, & - dt_cool_target_grid, & - routehandle=regrid_water, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) + if (localpet == 0) then + allocate(water_target_one_tile(i_target,j_target)) + water_target_one_tile = 0 + where(mask_target_one_tile == 0) water_target_one_tile = 1 - print*,"- CALL Field_Regrid for ifd over water." - call ESMF_FieldRegrid(ifd_input_grid, & - ifd_target_grid, & - routehandle=regrid_water, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) + call search_many(num_fields,bundle_water_target, tile,search_nums,localpet, & + latitude=latitude_one_tile,mask=water_target_one_tile) + else + call search_many(num_fields,bundle_water_target, tile,search_nums,localpet) + endif - print*,"- CALL Field_Regrid for qrain over water." - call ESMF_FieldRegrid(qrain_input_grid, & - qrain_target_grid, & - routehandle=regrid_water, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) + if (localpet == 0) deallocate(water_target_one_tile) - print*,"- CALL Field_Regrid for tref over water." - call ESMF_FieldRegrid(tref_input_grid, & - tref_target_grid, & - routehandle=regrid_water, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) + enddo - print*,"- CALL Field_Regrid for w_d over water." - call ESMF_FieldRegrid(w_d_input_grid, & - w_d_target_grid, & - routehandle=regrid_water, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) + deallocate(latitude_one_tile,search_nums) + + call ESMF_FieldBundleDestroy(bundle_water_target,rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) + call error_handler("IN FieldBundleDestroy", rc) - print*,"- CALL Field_Regrid for w_0 over water." - call ESMF_FieldRegrid(w_0_input_grid, & - w_0_target_grid, & - routehandle=regrid_water, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - - print*,"- CALL Field_Regrid for xs over water." - call ESMF_FieldRegrid(xs_input_grid, & - xs_target_grid, & - routehandle=regrid_water, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - - print*,"- CALL Field_Regrid for xt over water." - call ESMF_FieldRegrid(xt_input_grid, & - xt_target_grid, & - routehandle=regrid_water, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - - print*,"- CALL Field_Regrid for xu over water." - call ESMF_FieldRegrid(xu_input_grid, & - xu_target_grid, & - routehandle=regrid_water, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - - print*,"- CALL Field_Regrid for xv over water." - call ESMF_FieldRegrid(xv_input_grid, & - xv_target_grid, & - routehandle=regrid_water, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - - print*,"- CALL Field_Regrid for xz over water." - call ESMF_FieldRegrid(xz_input_grid, & - xz_target_grid, & - routehandle=regrid_water, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - - print*,"- CALL Field_Regrid for xtts over water." - call ESMF_FieldRegrid(xtts_input_grid, & - xtts_target_grid, & - routehandle=regrid_water, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - - print*,"- CALL Field_Regrid for xzts over water." - call ESMF_FieldRegrid(xzts_input_grid, & - xzts_target_grid, & - routehandle=regrid_water, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - - print*,"- CALL Field_Regrid for z_c over water." - call ESMF_FieldRegrid(z_c_input_grid, & - z_c_target_grid, & - routehandle=regrid_water, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - - print*,"- CALL Field_Regrid for zm over water." - call ESMF_FieldRegrid(zm_input_grid, & - zm_target_grid, & - routehandle=regrid_water, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - -! Tag unmapped points - - print*,"- CALL FieldGet FOR TARGET c_d." - call ESMF_FieldGet(c_d_target_grid, & - farrayPtr=c_d_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR TARGET c_0." - call ESMF_FieldGet(c_0_target_grid, & - farrayPtr=c_0_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR TARGET d_conv." - call ESMF_FieldGet(d_conv_target_grid, & - farrayPtr=d_conv_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR TARGET dt_cool." - call ESMF_FieldGet(dt_cool_target_grid, & - farrayPtr=dt_cool_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR TARGET ifd." - call ESMF_FieldGet(ifd_target_grid, & - farrayPtr=ifd_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - ifd_target_ptr = float(nint(ifd_target_ptr)) - - print*,"- CALL FieldGet FOR TARGET qrain." - call ESMF_FieldGet(qrain_target_grid, & - farrayPtr=qrain_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR TARGET tref." - call ESMF_FieldGet(tref_target_grid, & - farrayPtr=tref_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR TARGET w_d." - call ESMF_FieldGet(w_d_target_grid, & - farrayPtr=w_d_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR TARGET w_0." - call ESMF_FieldGet(w_0_target_grid, & - farrayPtr=w_0_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR TARGET xs." - call ESMF_FieldGet(xs_target_grid, & - farrayPtr=xs_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR TARGET xt." - call ESMF_FieldGet(xt_target_grid, & - farrayPtr=xt_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR TARGET xu." - call ESMF_FieldGet(xu_target_grid, & - farrayPtr=xu_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR TARGET xv." - call ESMF_FieldGet(xv_target_grid, & - farrayPtr=xv_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR TARGET xz." - call ESMF_FieldGet(xz_target_grid, & - farrayPtr=xz_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR TARGET xtts." - call ESMF_FieldGet(xtts_target_grid, & - farrayPtr=xtts_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR TARGET xzts." - call ESMF_FieldGet(xzts_target_grid, & - farrayPtr=xzts_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR TARGET z_c." - call ESMF_FieldGet(z_c_target_grid, & - farrayPtr=z_c_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR TARGET zm." - call ESMF_FieldGet(zm_target_grid, & - farrayPtr=zm_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - do ij = l(1), u(1) - call ij_to_i_j(unmapped_ptr(ij), i_target, j_target, i, j) - c_d_target_ptr(i,j) = -9999.9 - c_0_target_ptr(i,j) = -9999.9 - d_conv_target_ptr(i,j) = -9999.9 - dt_cool_target_ptr(i,j) = -9999.9 - ifd_target_ptr(i,j) = -9999.9 - qrain_target_ptr(i,j) = -9999.9 - tref_target_ptr(i,j) = -9999.9 - w_d_target_ptr(i,j) = -9999.9 - w_0_target_ptr(i,j) = -9999.9 - xs_target_ptr(i,j) = -9999.9 - xt_target_ptr(i,j) = -9999.9 - xu_target_ptr(i,j) = -9999.9 - xv_target_ptr(i,j) = -9999.9 - xz_target_ptr(i,j) = -9999.9 - xtts_target_ptr(i,j) = -9999.9 - xzts_target_ptr(i,j) = -9999.9 - z_c_target_ptr(i,j) = -9999.9 - zm_target_ptr(i,j) = -9999.9 - enddo - - endif - - if (localpet == 0) then - allocate(latitude_one_tile(i_target,j_target)) - else - allocate(latitude_one_tile(0,0)) - endif - - do tile = 1, num_tiles_target_grid - -! skin temp - - print*,"- CALL FieldGather FOR TARGET GRID SKIN TEMPERATURE TILE: ", tile - call ESMF_FieldGather(skin_temp_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - print*,"- CALL FieldGather FOR TARGET LANDMASK TILE: ", tile - call ESMF_FieldGather(landmask_target_grid, mask_target_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - print*,"- CALL FieldGather FOR TARGET LATITUDE TILE: ", tile - call ESMF_FieldGather(latitude_target_grid, latitude_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - allocate(water_target_one_tile(i_target,j_target)) - water_target_one_tile = 0 - where(mask_target_one_tile == 0) water_target_one_tile = 1 - call search(data_one_tile, water_target_one_tile, i_target, j_target, tile, 11, & - latitude=latitude_one_tile) - endif - - print*,"- CALL FieldScatter FOR TARGET GRID SKIN TEMP: ", tile - call ESMF_FieldScatter(skin_temp_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! z0 - - print*,"- CALL FieldGather FOR TARGET GRID Z0 TILE: ", tile - call ESMF_FieldGather(z0_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - call search(data_one_tile, water_target_one_tile, i_target, j_target, tile, 83) - endif - - print*,"- CALL FieldScatter FOR TARGET GRID Z0: ", tile - call ESMF_FieldScatter(z0_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (convert_nst) then - -! c_d - - print*,"- CALL FieldGather FOR TARGET GRID C_D TILE: ", tile - call ESMF_FieldGather(c_d_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - call search(data_one_tile, water_target_one_tile, i_target, j_target, tile, 0) - endif - - print*,"- CALL FieldScatter FOR TARGET GRID C_D: ", tile - call ESMF_FieldScatter(c_d_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! c_0 - - print*,"- CALL FieldGather FOR TARGET GRID C_0 TILE: ", tile - call ESMF_FieldGather(c_0_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - call search(data_one_tile, water_target_one_tile, i_target, j_target, tile, 0) - endif - - print*,"- CALL FieldScatter FOR TARGET GRID C_0: ", tile - call ESMF_FieldScatter(c_0_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! d_conv - - print*,"- CALL FieldGather FOR TARGET GRID D_CONV TILE: ", tile - call ESMF_FieldGather(d_conv_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - call search(data_one_tile, water_target_one_tile, i_target, j_target, tile, 0) - endif - - print*,"- CALL FieldScatter FOR TARGET GRID D_CONV: ", tile - call ESMF_FieldScatter(d_conv_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! dt_cool - - print*,"- CALL FieldGather FOR TARGET GRID DT_COOL TILE: ", tile - call ESMF_FieldGather(dt_cool_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - call search(data_one_tile, water_target_one_tile, i_target, j_target, tile, 0) - endif - - print*,"- CALL FieldScatter FOR TARGET GRID DT_COOL: ", tile - call ESMF_FieldScatter(dt_cool_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! ifd - - print*,"- CALL FieldGather FOR TARGET GRID IFD TILE: ", tile - call ESMF_FieldGather(ifd_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - call search(data_one_tile, water_target_one_tile, i_target, j_target, tile, 1) - endif - - print*,"- CALL FieldScatter FOR TARGET GRID IFD: ", tile - call ESMF_FieldScatter(ifd_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! qrain - - print*,"- CALL FieldGather FOR TARGET GRID QRAIN TILE: ", tile - call ESMF_FieldGather(qrain_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - call search(data_one_tile, water_target_one_tile, i_target, j_target, tile, 0) - endif - - print*,"- CALL FieldScatter FOR TARGET GRID QRAIN: ", tile - call ESMF_FieldScatter(qrain_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! tref - - print*,"- CALL FieldGather FOR TARGET GRID TREF TILE: ", tile - call ESMF_FieldGather(tref_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - call search(data_one_tile, water_target_one_tile, i_target, j_target, tile, 11, & - latitude=latitude_one_tile) - endif - - print*,"- CALL FieldScatter FOR TARGET GRID TREF: ", tile - call ESMF_FieldScatter(tref_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! w_d - - print*,"- CALL FieldGather FOR TARGET GRID W_D TILE: ", tile - call ESMF_FieldGather(w_d_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - call search(data_one_tile, water_target_one_tile, i_target, j_target, tile, 0) - endif - - print*,"- CALL FieldScatter FOR TARGET GRID W_D: ", tile - call ESMF_FieldScatter(w_d_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! w_0 - - print*,"- CALL FieldGather FOR TARGET GRID W_0 TILE: ", tile - call ESMF_FieldGather(w_0_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - call search(data_one_tile, water_target_one_tile, i_target, j_target, tile, 0) - endif - - print*,"- CALL FieldScatter FOR TARGET GRID W_0: ", tile - call ESMF_FieldScatter(w_0_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! xs - - print*,"- CALL FieldGather FOR TARGET GRID XS TILE: ", tile - call ESMF_FieldGather(xs_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - call search(data_one_tile, water_target_one_tile, i_target, j_target, tile, 0) - endif - - print*,"- CALL FieldScatter FOR TARGET GRID XS: ", tile - call ESMF_FieldScatter(xs_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! xt - - print*,"- CALL FieldGather FOR TARGET GRID XT TILE: ", tile - call ESMF_FieldGather(xt_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - call search(data_one_tile, water_target_one_tile, i_target, j_target, tile, 0) - endif - - print*,"- CALL FieldScatter FOR TARGET GRID XT: ", tile - call ESMF_FieldScatter(xt_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! xu - - print*,"- CALL FieldGather FOR TARGET GRID XU TILE: ", tile - call ESMF_FieldGather(xu_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - call search(data_one_tile, water_target_one_tile, i_target, j_target, tile, 0) - endif - - print*,"- CALL FieldScatter FOR TARGET GRID XU: ", tile - call ESMF_FieldScatter(xu_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! xv - - print*,"- CALL FieldGather FOR TARGET GRID XV TILE: ", tile - call ESMF_FieldGather(xv_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - call search(data_one_tile, water_target_one_tile, i_target, j_target, tile, 0) - endif - - print*,"- CALL FieldScatter FOR TARGET GRID XV: ", tile - call ESMF_FieldScatter(xv_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! xz - - print*,"- CALL FieldGather FOR TARGET GRID XZ TILE: ", tile - call ESMF_FieldGather(xz_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - call search(data_one_tile, water_target_one_tile, i_target, j_target, tile, 30) - endif - - print*,"- CALL FieldScatter FOR TARGET GRID XZ: ", tile - call ESMF_FieldScatter(xz_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! xtts - - print*,"- CALL FieldGather FOR TARGET GRID XTTS TILE: ", tile - call ESMF_FieldGather(xtts_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - call search(data_one_tile, water_target_one_tile, i_target, j_target, tile, 0) - endif - - print*,"- CALL FieldScatter FOR TARGET GRID XTTS: ", tile - call ESMF_FieldScatter(xtts_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! xzts - - print*,"- CALL FieldGather FOR TARGET GRID XZTS TILE: ", tile - call ESMF_FieldGather(xzts_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - call search(data_one_tile, water_target_one_tile, i_target, j_target, tile, 0) - endif - - print*,"- CALL FieldScatter FOR TARGET GRID XZTS: ", tile - call ESMF_FieldScatter(xzts_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! z_c - - print*,"- CALL FieldGather FOR TARGET GRID Z_C TILE: ", tile - call ESMF_FieldGather(z_c_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - call search(data_one_tile, water_target_one_tile, i_target, j_target, tile, 0) - endif - - print*,"- CALL FieldScatter FOR TARGET GRID Z_C: ", tile - call ESMF_FieldScatter(z_c_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - -! zm - - print*,"- CALL FieldGather FOR TARGET GRID ZM TILE: ", tile - call ESMF_FieldGather(zm_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - call search(data_one_tile, water_target_one_tile, i_target, j_target, tile, 0) - endif - - print*,"- CALL FieldScatter FOR TARGET GRID ZM: ", tile - call ESMF_FieldScatter(zm_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - endif - - if (localpet == 0) deallocate(water_target_one_tile) - - enddo - - deallocate(latitude_one_tile) - - print*,"- CALL FieldRegridRelease." - call ESMF_FieldRegridRelease(routehandle=regrid_water, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegridRelease", rc) + print*,"- CALL FieldRegridRelease." + call ESMF_FieldRegridRelease(routehandle=regrid_water, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldRegridRelease", rc) !--------------------------------------------------------------------------------------------- ! Now interpolate "all land" to "all land". Here, "all land" means landice and non-land ice. @@ -1812,69 +1030,40 @@ subroutine interp(localpet) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldRegridStore", rc) - print*,"- CALL Field_Regrid for snow depth over land." - call ESMF_FieldRegrid(snow_depth_input_grid, & - snow_depth_target_grid, & - routehandle=regrid_all_land, & - termorderflag=ESMF_TERMORDER_SRCSEQ, & - zeroregion=ESMF_REGION_SELECT, & ! flag needed so snow over sea - ! ice is not zeroed out. - rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - - print*,"- CALL Field_Regrid for snow liq equiv over land." - call ESMF_FieldRegrid(snow_liq_equiv_input_grid, & - snow_liq_equiv_target_grid, & - routehandle=regrid_all_land, & - termorderflag=ESMF_TERMORDER_SRCSEQ, & - zeroregion=ESMF_REGION_SELECT, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - - print*,"- CALL Field_Regrid for canopy mc." - call ESMF_FieldRegrid(canopy_mc_input_grid, & - canopy_mc_target_grid, & - routehandle=regrid_all_land, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - - print*,"- CALL FieldGet FOR TARGET snow depth." - call ESMF_FieldGet(snow_depth_target_grid, & - farrayPtr=snow_depth_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR TARGET snow liq equiv." - call ESMF_FieldGet(snow_liq_equiv_target_grid, & - farrayPtr=snow_liq_equiv_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR TARGET canopy moisture." - call ESMF_FieldGet(canopy_mc_target_grid, & - farrayPtr=canopy_mc_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - l = lbound(unmapped_ptr) - u = ubound(unmapped_ptr) + bundle_allland_target = ESMF_FieldBundleCreate(name="all land target", rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleCreate", rc) + bundle_allland_input = ESMF_FieldBundleCreate(name="all land input", rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleCreate", rc) + call ESMF_FieldBundleAdd(bundle_allland_target, (/canopy_mc_target_grid, snow_depth_target_grid, & + snow_liq_equiv_target_grid/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleAdd", rc) + call ESMF_FieldBundleAdd(bundle_allland_input, (/canopy_mc_input_grid, snow_depth_input_grid, & + snow_liq_equiv_input_grid/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleAdd", rc) + call ESMF_FieldBundleGet(bundle_allland_target,fieldCount=num_fields,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleGet", rc) + + allocate(search_nums(num_fields)) + allocate(dozero(num_fields)) - do ij = l(1), u(1) - call ij_to_i_j(unmapped_ptr(ij), i_target, j_target, i, j) - snow_depth_target_ptr(i,j) = -9999.9 - snow_liq_equiv_target_ptr(i,j) = -9999.9 - canopy_mc_target_ptr(i,j) = -9999.9 - enddo + search_nums = (/223,66,65/) + dozero=(/.True.,.False.,.False./) + + call regrid_many(bundle_allland_input,bundle_allland_target,num_fields,regrid_all_land,dozero, & + unmapped_ptr=unmapped_ptr) + deallocate(dozero) + call ESMF_FieldBundleDestroy(bundle_allland_input,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleDestroy", rc) + do tile = 1, num_tiles_target_grid - print*,"- CALL FieldGather FOR TARGET GRID SNOW DEPTH TILE: ", tile - call ESMF_FieldGather(snow_depth_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - print*,"- CALL FieldGather FOR TARGET LANDMASK TILE: ", tile call ESMF_FieldGather(landmask_target_grid, mask_target_one_tile, rootPet=0, tile=tile, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & @@ -1884,45 +1073,21 @@ subroutine interp(localpet) allocate(land_target_one_tile(i_target,j_target)) land_target_one_tile = 0 where(mask_target_one_tile == 1) land_target_one_tile = 1 - call search(data_one_tile, land_target_one_tile, i_target, j_target, tile, 66) - endif - - print*,"- CALL FieldScatter FOR TARGET GRID SNOW DEPTH: ", tile - call ESMF_FieldScatter(snow_depth_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - print*,"- CALL FieldGather FOR TARGET GRID SNOW LIQUID EQUIV: ", tile - call ESMF_FieldGather(snow_liq_equiv_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - call search(data_one_tile, land_target_one_tile, i_target, j_target, tile, 65) - endif - - print*,"- CALL FieldScatter FOR TARGET GRID SNOW LIQUID EQUIV: ", tile - call ESMF_FieldScatter(snow_liq_equiv_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - print*,"- CALL FieldGather FOR TARGET GRID CANOPY MC: ", tile - call ESMF_FieldGather(canopy_mc_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - call search(data_one_tile, land_target_one_tile, i_target, j_target, tile, 223) - deallocate(land_target_one_tile) + + call search_many(num_fields,bundle_allland_target, & + tile,search_nums,localpet, mask=land_target_one_tile) + else + call search_many(num_fields,bundle_allland_target, tile,search_nums,localpet) endif - print*,"- CALL FieldScatter FOR TARGET GRID CANOPY MC: ", tile - call ESMF_FieldScatter(canopy_mc_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - + if (localpet == 0) deallocate(land_target_one_tile) enddo + deallocate(search_nums) + call ESMF_FieldBundleDestroy(bundle_allland_target,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleDestroy", rc) + print*,"- CALL FieldRegridRelease." call ESMF_FieldRegridRelease(routehandle=regrid_all_land, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & @@ -1970,83 +1135,53 @@ subroutine interp(localpet) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldRegridStore", rc) - print*,"- CALL Field_Regrid for soil temperature over landice." - call ESMF_FieldRegrid(soil_temp_input_grid, & - soil_temp_target_grid, & - routehandle=regrid_landice, & - termorderflag=ESMF_TERMORDER_SRCSEQ, & - zeroregion=ESMF_REGION_SELECT, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - - print*,"- CALL Field_Regrid for skin temperature over landice." - call ESMF_FieldRegrid(skin_temp_input_grid, & - skin_temp_target_grid, & - routehandle=regrid_landice, & - termorderflag=ESMF_TERMORDER_SRCSEQ, & - zeroregion=ESMF_REGION_SELECT, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - - print*,"- CALL Field_Regrid for terrain over landice." - call ESMF_FieldRegrid(terrain_input_grid, & - terrain_from_input_grid, & - routehandle=regrid_landice, & - termorderflag=ESMF_TERMORDER_SRCSEQ, & - zeroregion=ESMF_REGION_SELECT, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - - print*,"- CALL FieldGet FOR TARGET grid column temperature over landice." - call ESMF_FieldGet(soil_temp_target_grid, & - farrayPtr=soil_temp_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR TARGET skin temperature." - call ESMF_FieldGet(skin_temp_target_grid, & - farrayPtr=skin_temp_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR terrain from input grid." - call ESMF_FieldGet(terrain_from_input_grid, & - farrayPtr=terrain_from_input_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - + bundle_landice_target = ESMF_FieldBundleCreate(name="landice target", rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleCreate", rc) + bundle_landice_input = ESMF_FieldBundleCreate(name="landice input", rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleCreate", rc) + call ESMF_FieldBundleAdd(bundle_landice_target, (/skin_temp_target_grid, terrain_from_input_grid,& + soil_temp_target_grid/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleAdd", rc) + call ESMF_FieldBundleAdd(bundle_landice_input, (/skin_temp_input_grid, terrain_input_grid,& + soil_temp_input_grid/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldBundleAdd", rc) + if (.not. sotyp_from_climo) then - print*,"- CALL FieldGather FOR SOIL TYPE TARGET GRID, TILE: ", tile - call ESMF_FieldGather(soil_type_target_grid,soil_type_target_grid_save,rootPet=0,tile=1, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldGather", rc) - - print*,"- CALL Field_Regrid for soil type over landice." - call ESMF_FieldRegrid(soil_type_input_grid, & - soil_type_target_grid, & - routehandle=regrid_landice, & - termorderflag=ESMF_TERMORDER_SRCSEQ, & - rc=rc) + call ESMF_FieldBundleAdd(bundle_landice_input, (/soil_type_input_grid/),rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldRegrid", rc) - - print*,"- CALL FieldGet FOR SOIL TYPE TARGET GRID." - call ESMF_FieldGet(soil_type_target_grid, & - farrayPtr=soil_type_from_input_ptr, rc=rc) + call error_handler("IN FieldBundleAdd", rc) + call ESMF_FieldBundleAdd(bundle_landice_target,(/soil_type_target_grid/),rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldGet", rc) - endif + call error_handler("IN FieldBundleAdd", rc) + endif - l = lbound(unmapped_ptr) - u = ubound(unmapped_ptr) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleAdd", rc) + call ESMF_FieldBundleGet(bundle_landice_target,fieldCount=num_fields,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleGet", rc) - do ij = l(1), u(1) - call ij_to_i_j(unmapped_ptr(ij), i_target, j_target, i, j) - soil_temp_target_ptr(i,j,:) = -9999.9 - skin_temp_target_ptr(i,j) = -9999.9 - terrain_from_input_ptr(i,j) = -9999.9 - if (.not.sotyp_from_climo) soil_type_from_input_ptr(i,j) = -9999.9 - enddo + allocate(search_nums(num_fields)) + allocate(dozero(num_fields)) + + if (sotyp_from_climo) then + search_nums = (/21,7,21/) + dozero(:)=.False. + else + search_nums = (/21,7,21,231/) + dozero(:)=(/.False.,.False.,.False.,.True./) + endif + + call regrid_many(bundle_landice_input,bundle_landice_target,num_fields,regrid_landice,dozero, & + unmapped_ptr=unmapped_ptr ) + deallocate(dozero) + call ESMF_FieldBundleDestroy(bundle_landice_input,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleDestroy", rc) if (localpet == 0) then allocate (veg_type_target_one_tile(i_target,j_target)) @@ -2059,12 +1194,6 @@ subroutine interp(localpet) endif do tile = 1, num_tiles_target_grid - - print*,"- CALL FieldGather FOR TARGET GRID SKIN TEMP TILE: ", tile - call ESMF_FieldGather(skin_temp_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - print*,"- CALL FieldGather FOR TARGET VEG TYPE TILE: ", tile call ESMF_FieldGather(veg_type_target_grid, veg_type_target_one_tile, rootPet=0, tile=tile, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & @@ -2073,71 +1202,28 @@ subroutine interp(localpet) if (localpet == 0) then land_target_one_tile = 0 where(nint(veg_type_target_one_tile) == veg_type_landice_target) land_target_one_tile = 1 - call search(data_one_tile, land_target_one_tile, i_target, j_target, tile, 21) endif - - print*,"- CALL FieldScatter FOR TARGET GRID SKIN TEMP, TILE: ", tile - call ESMF_FieldScatter(skin_temp_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - print*,"- CALL FieldGather FOR TERRAIN FROM INPUT GRID, TILE: ", tile - call ESMF_FieldGather(terrain_from_input_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - + print*,"- CALL FieldGather FOR TERRAIN FROM INPUT GRID LAND, TILE: ", tile - call ESMF_FieldGather(terrain_from_input_grid_land, data_one_tile2, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - call search(data_one_tile, land_target_one_tile, i_target, j_target, tile, 7, terrain_land=data_one_tile2) - endif - - print*,"- CALL FieldScatter FOR TERRAIN FROM INPUT GRID, TILE: ", tile - call ESMF_FieldScatter(terrain_from_input_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - print*,"- CALL FieldGather FOR TARGET GRID LANDICE COLUMN TEMP: ", tile - call ESMF_FieldGather(soil_temp_target_grid, data_one_tile_3d, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - do j = 1, lsoil_target - data_one_tile = data_one_tile_3d(:,:,j) - call search(data_one_tile, land_target_one_tile, i_target, j_target, tile, 21) - data_one_tile_3d(:,:,j) = data_one_tile - enddo - endif + call ESMF_FieldGather(terrain_from_input_grid_land, data_one_tile2, rootPet=0, tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGather", rc) - print*,"- CALL FieldScatter FOR TARGET GRID SEAICE COLUMN TEMP: ", tile - call ESMF_FieldScatter(soil_temp_target_grid, data_one_tile_3d, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (.not. sotyp_from_climo) then - print*,"- CALL FieldGather FOR SOIL TYPE TARGET GRID LAND, TILE: ",tile - call ESMF_FieldGather(soil_type_target_grid, data_one_tile,rootPet=0,tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - call search(data_one_tile, mask_target_one_tile, i_target, j_target,tile,231) - endif - - print*,"- CALL FieldScatter FOR SOIL TYPE TARGET GRID, TILE: ", tile - call ESMF_FieldScatter(soil_type_target_grid,data_one_tile,rootPet=0,tile=tile,rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) + if (localpet==0) then + call search_many(num_fields,bundle_landice_target,tile,search_nums,localpet,& + terrain_land=data_one_tile2,mask=land_target_one_tile) + else + call search_many(num_fields,bundle_landice_target,tile,search_nums,localpet) endif - enddo deallocate (veg_type_target_one_tile) deallocate (land_target_one_tile) + deallocate(search_nums) + + call ESMF_FieldBundleDestroy(bundle_landice_target,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleDestroy", rc) print*,"- CALL FieldRegridRelease." call ESMF_FieldRegridRelease(routehandle=regrid_landice, rc=rc) @@ -2168,188 +1254,152 @@ subroutine interp(localpet) srctermprocessing=isrctermprocessing, & unmappedaction=ESMF_UNMAPPEDACTION_IGNORE, & normtype=ESMF_NORMTYPE_FRACAREA, & - routehandle=regrid_land, & - regridmethod=method, & - unmappedDstList=unmapped_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegridStore", rc) - - print*,"- CALL Field_Regrid for total soil moisture over land." - call ESMF_FieldRegrid(soilm_tot_input_grid, & - soilm_tot_target_grid, & - routehandle=regrid_land, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - - print*,"- CALL Field_Regrid for soil temperature over land." - call ESMF_FieldRegrid(soil_temp_input_grid, & - soil_temp_target_grid, & - routehandle=regrid_land, & - termorderflag=ESMF_TERMORDER_SRCSEQ, & - zeroregion=ESMF_REGION_SELECT, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - - print*,"- CALL Field_Regrid for skin temperature over land." - call ESMF_FieldRegrid(skin_temp_input_grid, & - skin_temp_target_grid, & - routehandle=regrid_land, & - termorderflag=ESMF_TERMORDER_SRCSEQ, & - zeroregion=ESMF_REGION_SELECT, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - - print*,"- CALL Field_Regrid for terrain over land." - call ESMF_FieldRegrid(terrain_input_grid, & - terrain_from_input_grid, & - routehandle=regrid_land, & - termorderflag=ESMF_TERMORDER_SRCSEQ, & - zeroregion=ESMF_REGION_SELECT, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - - if (.not. sotyp_from_climo) then - print*,"- CALL Field_Regrid for soil type over land." - call ESMF_FieldRegrid(soil_type_input_grid, & - soil_type_target_grid, & - routehandle=regrid_land, & - zeroregion=ESMF_REGION_SELECT, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldRegrid", rc) - endif - - print*,"- CALL Field_Regrid for soil type over land." - call ESMF_FieldRegrid(soil_type_input_grid, & - soil_type_from_input_grid, & - routehandle=regrid_land, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - - if (.not. vgfrc_from_climo) then - print*,"- CALL Field_Regrid for veg greenness over land." - call ESMF_FieldRegrid(veg_greenness_input_grid, & - veg_greenness_target_grid, & - routehandle=regrid_land, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldRegrid", rc) - endif - - if (.not. minmax_vgfrc_from_climo) then - print*,"- CALL Field_Regrid for max veg greenness over land." - call ESMF_FieldRegrid(max_veg_greenness_input_grid, & - max_veg_greenness_target_grid, & - routehandle=regrid_land, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldRegrid", rc) - - print*,"- CALL Field_Regrid for min veg greenness over land." - call ESMF_FieldRegrid(min_veg_greenness_input_grid, & - min_veg_greenness_target_grid, & - routehandle=regrid_land, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldRegrid", rc) - endif - - if (.not. lai_from_climo) then - print*,"- CALL Field_Regrid for leaf area index over land." - call ESMF_FieldRegrid(lai_input_grid, & - lai_target_grid, & - routehandle=regrid_land, & - termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldRegrid", rc) - - endif - - print*,"- CALL FieldGet FOR TARGET grid total soil moisture over land." - call ESMF_FieldGet(soilm_tot_target_grid, & - farrayPtr=soilm_tot_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR TARGET grid soil temp over ice." - call ESMF_FieldGet(soil_temp_target_grid, & - farrayPtr=soil_temp_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR TARGET skin temperature." - call ESMF_FieldGet(skin_temp_target_grid, & - farrayPtr=skin_temp_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR terrain from input grid." - call ESMF_FieldGet(terrain_from_input_grid, & - farrayPtr=terrain_from_input_ptr, rc=rc) + routehandle=regrid_land, & + regridmethod=method, & + unmappedDstList=unmapped_ptr, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) + call error_handler("IN FieldRegridStore", rc) - if (.not. sotyp_from_climo) then - print*,"- CALL FieldGet FOR soil type target grid." + bundle_nolandice_target = ESMF_FieldBundleCreate(name="land no landice target", rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleCreate", rc) + + bundle_nolandice_input = ESMF_FieldBundleCreate(name="land no landice input", rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleCreate", rc) + + call ESMF_FieldBundleAdd(bundle_nolandice_target, (/skin_temp_target_grid, terrain_from_input_grid,& + soil_type_from_input_grid,soilm_tot_target_grid,soil_temp_target_grid/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleAdd", rc) + + call ESMF_FieldBundleAdd(bundle_nolandice_input, (/skin_temp_input_grid, terrain_input_grid,& + soil_type_input_grid,soilm_tot_input_grid,soil_temp_input_grid/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleAdd", rc) + + + if (.not. sotyp_from_climo) then +! call ESMF_FieldBundleAdd(bundle_nolandice_target, (/soil_type_target_grid/), rc=rc) +! if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & +! call error_handler("IN FieldBundleAdd", rc) +! call ESMF_FieldBundleAdd(bundle_nolandice_input, (/soil_type_input_grid/), rc=rc) +! if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & +! call error_handler("IN FieldBundleAdd", rc) + print*,"- CALL Field_Regrid ." + call ESMF_FieldRegrid(soil_type_input_grid, & + soil_type_target_grid, & + routehandle=regrid_land, & + zeroregion=ESMF_REGION_SELECT, & + termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldRegrid", rc) + call ESMF_FieldGet(soil_type_target_grid, & farrayPtr=soil_type_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldGet", rc) - endif + + l = lbound(unmapped_ptr) + u = ubound(unmapped_ptr) - print*,"- CALL FieldGet FOR soil type from input grid." - call ESMF_FieldGet(soil_type_from_input_grid, & - farrayPtr=soil_type_from_input_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) + do ij = l(1), u(1) + call ij_to_i_j(unmapped_ptr(ij), i_target, j_target, i, j) + soil_type_target_ptr(i,j) = -9999.9 + enddo + ! call ESMF_FieldBundleGet(bundle_nolandice_target,fieldCount=num_fields,rc=rc) + ! if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + ! call error_handler("IN FieldBundleGet", rc) + ! sotyp_ind = 3 + endif + + if (.not. vgfrc_from_climo) then + call ESMF_FieldBundleAdd(bundle_nolandice_target, (/veg_greenness_target_grid/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleAdd", rc) + call ESMF_FieldBundleAdd(bundle_nolandice_input, (/veg_greenness_input_grid/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleAdd", rc) + call ESMF_FieldBundleGet(bundle_nolandice_target,fieldCount=num_fields,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleGet", rc) + vgfrc_ind = num_fields + endif + + if (.not. lai_from_climo) then + call ESMF_FieldBundleAdd(bundle_nolandice_target, (/lai_target_grid/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleAdd", rc) + call ESMF_FieldBundleAdd(bundle_nolandice_input, (/lai_input_grid/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleAdd", rc) + call ESMF_FieldBundleGet(bundle_nolandice_target,fieldCount=num_fields,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleGet", rc) + lai_ind = num_fields + endif + + if (.not. minmax_vgfrc_from_climo) then + call ESMF_FieldBundleAdd(bundle_nolandice_target, (/max_veg_greenness_target_grid/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleAdd", rc) + call ESMF_FieldBundleAdd(bundle_nolandice_input, (/max_veg_greenness_input_grid/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleAdd", rc) + + call ESMF_FieldBundleAdd(bundle_nolandice_target, (/min_veg_greenness_target_grid/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleAdd", rc) + call ESMF_FieldBundleAdd(bundle_nolandice_input, (/min_veg_greenness_input_grid/), rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleAdd", rc) + + call ESMF_FieldBundleGet(bundle_nolandice_target,fieldCount=num_fields,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleGet", rc) + + mmvg_ind = num_fields-1 + endif + + call ESMF_FieldBundleGet(bundle_nolandice_target,fieldCount=num_fields,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleGet", rc) + allocate(search_nums(num_fields)) + allocate(dozero(num_fields)) + + search_nums(1:5) = (/85,7,224,85,86/) + dozero(1:5) = (/.False.,.False.,.True.,.True.,.False./) + + !if (.not.sotyp_from_climo) then + ! search_nums(sotyp_ind) = 226 + ! dozero(sotyp_ind) = .False. + !endif + if (.not. vgfrc_from_climo) then - print*,"- CALL FieldGet FOR TARGET veg greenness." - call ESMF_FieldGet(veg_greenness_target_grid, & - farrayPtr=veg_greenness_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGet", rc) + search_nums(vgfrc_ind) = 224 + dozero(vgfrc_ind) = .True. + endif + + if (.not. lai_from_climo) then + search_nums(lai_ind) = 229 + dozero(lai_ind) = .True. endif if (.not. minmax_vgfrc_from_climo) then - print*,"- CALL FieldGet FOR TARGET max veg greenness." - call ESMF_FieldGet(max_veg_greenness_target_grid, & - farrayPtr=max_veg_greenness_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldGet", rc) - - print*,"- CALL FieldGet FOR TARGET min veg greenness." - call ESMF_FieldGet(min_veg_greenness_target_grid, & - farrayPtr=min_veg_greenness_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldGet", rc) - endif - - if (.not. lai_from_climo) then - print*,"- CALL FieldGet FOR TARGET lai." - call ESMF_FieldGet(lai_target_grid, & - farrayPtr=lai_target_ptr, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldGet", rc) - endif + search_nums(mmvg_ind) = 227 + dozero(mmvg_ind) = .True. + + search_nums(mmvg_ind+1) = 228 + dozero(mmvg_ind+1) = .True. + endif - l = lbound(unmapped_ptr) - u = ubound(unmapped_ptr) - do ij = l(1), u(1) - call ij_to_i_j(unmapped_ptr(ij), i_target, j_target, i, j) - soilm_tot_target_ptr(i,j,:) = -9999.9 - soil_temp_target_ptr(i,j,:) = -9999.9 - skin_temp_target_ptr(i,j) = -9999.9 - terrain_from_input_ptr(i,j) = -9999.9 - if (.not. sotyp_from_climo) soil_type_target_ptr(i,j) = -9999.9 - soil_type_from_input_ptr(i,j) = -9999.9 - veg_greenness_target_ptr(i,j) = -9999.9 - max_veg_greenness_target_ptr(i,j) = -9999.9 - min_veg_greenness_target_ptr(i,j) = -9999.9 - lai_target_ptr(i,j) = -9999.9 - enddo + call regrid_many(bundle_nolandice_input,bundle_nolandice_target,num_fields,regrid_land,dozero, & + unmapped_ptr=unmapped_ptr) + deallocate(dozero) + call ESMF_FieldBundleDestroy(bundle_nolandice_input,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleDestroy", rc) if (localpet == 0) then allocate (veg_type_target_one_tile(i_target,j_target)) @@ -2369,140 +1419,20 @@ subroutine interp(localpet) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldGather", rc) - print*,"- CALL FieldGather FOR TERRAIN FROM INPUT GRID, TILE: ", tile - call ESMF_FieldGather(terrain_from_input_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - if (localpet == 0) then where(nint(veg_type_target_one_tile) == veg_type_landice_target) mask_target_one_tile = 0 - call search(data_one_tile, mask_target_one_tile, i_target, j_target, tile, 7) - endif - - print*,"- CALL FieldScatter FOR TERRAIN FROM INPUT GRID, TILE: ", tile - call ESMF_FieldScatter(terrain_from_input_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - print*,"- CALL FieldGather FOR TARGET GRID SKIN TEMPERATURE, TILE: ", tile - call ESMF_FieldGather(skin_temp_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - call search(data_one_tile, mask_target_one_tile, i_target, j_target, tile, 85) endif - - print*,"- CALL FieldScatter FOR TARGET GRID SKIN TEMPERATURE, TILE: ", tile - call ESMF_FieldScatter(skin_temp_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - print*,"- CALL FieldGather FOR SOIL TYPE FROM INPUT GRID, TILE: ", tile - call ESMF_FieldGather(soil_type_from_input_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - + print*,"- CALL FieldGather FOR SOIL TYPE TARGET GRID, TILE: ", tile call ESMF_FieldGather(soil_type_target_grid, data_one_tile2, rootPet=0,tile=tile, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& call error_handler("IN FieldGather", rc) - -!--------------------------------------------------------------------------------------- -! Some grib2 data does not have soil type. Set soil type interpolated from input -! grid to the target (model) grid soil type. This turns off the soil moisture -! rescaling. -!--------------------------------------------------------------------------------------- - - if (.not. sotyp_from_climo) then - if (localpet==0) then - call search(data_one_tile2, mask_target_one_tile, i_target, j_target, tile, 224,soilt_climo=soil_type_target_grid_save) - endif + if (localpet==0) then + call search_many(num_fields,bundle_nolandice_target,tile,search_nums,localpet, & + soilt_climo=data_one_tile2, mask=mask_target_one_tile) else - if (localpet == 0 .and. maxval(data_one_tile) > 0 .and. (trim(external_model) .ne. "GFS" .or. trim(input_type) .ne. "grib2")) then - ! If soil type from the input grid has any non-zero points then soil type must exist for - ! use - call search(data_one_tile, mask_target_one_tile, i_target, j_target, tile, 224) - elseif (localpet == 0) then - data_one_tile = data_one_tile2 - endif - endif - - if (.not. sotyp_from_climo) then - print*,"- CALL FieldScatter FOR SOIL TYPE TARGET GRID, TILE: ", tile - call ESMF_FieldScatter(soil_type_target_grid, data_one_tile2, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) + call search_many(num_fields,bundle_nolandice_target, tile,search_nums,localpet) endif - - print*,"- CALL FieldScatter FOR SOIL TYPE FROM INPUT GRID, TILE: ", tile - call ESMF_FieldScatter(soil_type_from_input_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - - if (.not. vgfrc_from_climo) then - print*,"- CALL FieldGather FOR TARGET GRID VEG GREENNESS, TILE: ", tile - call ESMF_FieldGather(veg_greenness_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldGather", rc) - - if (localpet == 0 .and. maxval(data_one_tile) > 0.0) then - call search(data_one_tile, mask_target_one_tile, i_target, j_target, tile, 226) - endif - - print*,"- CALL FieldScatter FOR VEG GREENNESS TARGET GRID, TILE: ", tile - call ESMF_FieldScatter(veg_greenness_target_grid, data_one_tile, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - endif - - if (.not. minmax_vgfrc_from_climo) then - print*,"- CALL FieldGather FOR TARGET GRID MAX VEG GREENNESS, TILE: ", tile - call ESMF_FieldGather(max_veg_greenness_target_grid, data_one_tile, rootPet=0,tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldGather", rc) - - if (localpet == 0 .and. maxval(data_one_tile) > 0.0) then - call search(data_one_tile, mask_target_one_tile, i_target, j_target,tile, 227) - endif - - print*,"- CALL FieldScatter FOR MAX VEG GREENNESS TARGET GRID, TILE: ", tile - call ESMF_FieldScatter(max_veg_greenness_target_grid, data_one_tile, rootPet=0,tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - - print*,"- CALL FieldGather FOR TARGET GRID MIN VEG GREENNESS, TILE: ", tile - call ESMF_FieldGather(min_veg_greenness_target_grid, data_one_tile,rootPet=0,tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldGather", rc) - - if (localpet == 0 .and. maxval(data_one_tile) > 0.0) then - call search(data_one_tile, mask_target_one_tile, i_target, j_target,tile,228) - endif - - - print*,"- CALL FieldScatter FOR MIN VEG GREENNESS TARGET GRID, TILE: ",tile - call ESMF_FieldScatter(min_veg_greenness_target_grid, data_one_tile,rootPet=0,tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - - endif - - if (.not. lai_from_climo) then - print*,"- CALL FieldGather FOR TARGET GRID LEAF AREA INDEX, TILE: ", tile - call ESMF_FieldGather(lai_target_grid, data_one_tile, rootPet=0,tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldGather", rc) - - if (localpet == 0 .and. maxval(data_one_tile) > 0.0) then - call search(data_one_tile, mask_target_one_tile, i_target, j_target,tile, 229) - endif - - print*,"- CALL FieldScatter FOR LEAF AREA INDEX TARGET GRID, TILE: ", tile - call ESMF_FieldScatter(lai_target_grid, data_one_tile, rootPet=0,tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& - call error_handler("IN FieldScatter", rc) - endif print*,"- CALL FieldGather FOR TARGET GRID TOTAL SOIL MOISTURE, TILE: ", tile call ESMF_FieldGather(soilm_tot_target_grid, data_one_tile_3d, rootPet=0, tile=tile, rc=rc) @@ -2517,28 +1447,10 @@ subroutine interp(localpet) enddo endif - print*,"- CALL FieldScatter FOR TARGET GRID TOTAL SOIL MOISTURE, TILE: ", tile - call ESMF_FieldScatter(soilm_tot_target_grid, data_one_tile_3d, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) - print*,"- CALL FieldGather FOR TARGET GRID SOIL TEMPERATURE, TILE: ", tile call ESMF_FieldGather(soil_temp_target_grid, data_one_tile_3d, rootPet=0, tile=tile, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldGather", rc) - - if (localpet == 0) then - do j = 1, lsoil_target - data_one_tile = data_one_tile_3d(:,:,j) - call search(data_one_tile, mask_target_one_tile, i_target, j_target, tile, 85) - data_one_tile_3d(:,:,j) = data_one_tile - enddo - endif - - print*,"- CALL FieldScatter FOR TARGET GRID SOIL TEMPERATURE, TILE: ", tile - call ESMF_FieldScatter(soil_temp_target_grid, data_one_tile_3d, rootPet=0, tile=tile, rc=rc) - if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & - call error_handler("IN FieldScatter", rc) if (tg3_from_soil) then print*,"- CALL FieldScatter FOR TARGET GRID SUBSTRATE TEMPERATURE, TILE: ", tile @@ -2546,9 +1458,30 @@ subroutine interp(localpet) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldScatter", rc) endif + + if (.not. sotyp_from_climo) then + print*,"- CALL FieldGather FOR SOIL TYPE TARGET GRID LAND, TILE: ",tile + call ESMF_FieldGather(soil_type_target_grid, data_one_tile,rootPet=0,tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldGather", rc) + + if (localpet == 0) then + call search(data_one_tile, mask_target_one_tile, i_target, j_target,tile,226) + endif + + print*,"- CALL FieldScatter FOR SOIL TYPE TARGET GRID, TILE: ", tile + call ESMF_FieldScatter(soil_type_target_grid,data_one_tile,rootPet=0,tile=tile,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + endif enddo + deallocate(search_nums) + call ESMF_FieldBundleDestroy(bundle_nolandice_target,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleDestroy", rc) + print*,"- CALL FieldRegridRelease." call ESMF_FieldRegridRelease(routehandle=regrid_land, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & @@ -3095,11 +2028,12 @@ end subroutine adjust_soilt_for_terrain !! @author Jeff Beck subroutine adjust_soil_levels(localpet) use model_grid, only : lsoil_target, i_input, j_input, input_grid - use input_data, only : lsoil_input, soil_temp_input_grid, & + use sfc_input_data, only : lsoil_input, soil_temp_input_grid, & soilm_liq_input_grid, soilm_tot_input_grid implicit none integer, intent(in) :: localpet - character(len=1000) :: msg + character(len=500) :: msg + character(len=2) :: lsoil_input_ch, lsoil_target_ch integer :: rc real(esmf_kind_r8) :: tmp(i_input,j_input), & data_one_tile(i_input,j_input,lsoil_input), & @@ -3194,12 +2128,11 @@ subroutine adjust_soil_levels(localpet) elseif (lsoil_input /= lsoil_target) then rc = -1 - - write(msg,'("NUMBER OF SOIL LEVELS IN INPUT (",I2,") and OUPUT & - (",I2,") MUST EITHER BE EQUAL OR 9 AND 4, RESPECTIVELY")') & - lsoil_input, lsoil_target - - call error_handler(trim(msg), rc) + write(lsoil_input_ch, '(i2)') lsoil_input + write(lsoil_target_ch, '(i2)') lsoil_target + msg="NUMBER OF SOIL LEVELS IN INPUT " // lsoil_input_ch // " AND OUTPUT " & + // lsoil_target_ch // " MUST EITHER BE EQUAL OR 9 AND 4 RESPECTIVELY." + call error_handler(msg, rc) endif end subroutine adjust_soil_levels @@ -3695,6 +2628,7 @@ subroutine create_surface_esmf_fields print*,"- CALL FieldCreate FOR TARGET GRID T2M." t2m_target_grid = ESMF_FieldCreate(target_grid, & typekind=ESMF_TYPEKIND_R8, & + name="t2m_target_grid", & staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) @@ -3710,6 +2644,7 @@ subroutine create_surface_esmf_fields print*,"- CALL FieldCreate FOR TARGET GRID Q2M." q2m_target_grid = ESMF_FieldCreate(target_grid, & typekind=ESMF_TYPEKIND_R8, & + name="q2m_target_grid", & staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) @@ -3725,6 +2660,7 @@ subroutine create_surface_esmf_fields print*,"- CALL FieldCreate FOR TARGET GRID TPRCP." tprcp_target_grid = ESMF_FieldCreate(target_grid, & typekind=ESMF_TYPEKIND_R8, & + name="tprcp_target_grid", & staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) @@ -3740,6 +2676,7 @@ subroutine create_surface_esmf_fields print*,"- CALL FieldCreate FOR TARGET GRID F10M." f10m_target_grid = ESMF_FieldCreate(target_grid, & typekind=ESMF_TYPEKIND_R8, & + name="f10m_target_grid", & staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) @@ -3755,6 +2692,7 @@ subroutine create_surface_esmf_fields print*,"- CALL FieldCreate FOR TARGET GRID FFMM." ffmm_target_grid = ESMF_FieldCreate(target_grid, & typekind=ESMF_TYPEKIND_R8, & + name="ffmm_target_grid", & staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) @@ -3770,6 +2708,7 @@ subroutine create_surface_esmf_fields print*,"- CALL FieldCreate FOR TARGET GRID FFHH." ffhh_target_grid = ESMF_FieldCreate(target_grid, & typekind=ESMF_TYPEKIND_R8, & + name="ffhh_target_grid", & staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) @@ -3785,6 +2724,7 @@ subroutine create_surface_esmf_fields print*,"- CALL FieldCreate FOR TARGET GRID USTAR." ustar_target_grid = ESMF_FieldCreate(target_grid, & typekind=ESMF_TYPEKIND_R8, & + name="ustar_target_grid", & staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) @@ -3800,6 +2740,7 @@ subroutine create_surface_esmf_fields print*,"- CALL FieldCreate FOR TARGET GRID SNOW LIQ EQUIV." snow_liq_equiv_target_grid = ESMF_FieldCreate(target_grid, & typekind=ESMF_TYPEKIND_R8, & + name="snow_liq_equiv_target_grid", & staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) @@ -3815,6 +2756,7 @@ subroutine create_surface_esmf_fields print*,"- CALL FieldCreate FOR TARGET GRID SNOW DEPTH." snow_depth_target_grid = ESMF_FieldCreate(target_grid, & typekind=ESMF_TYPEKIND_R8, & + name="snow_depth_target_grid", & staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) @@ -3830,6 +2772,7 @@ subroutine create_surface_esmf_fields print*,"- CALL FieldCreate FOR TARGET GRID SEA ICE FRACTION." seaice_fract_target_grid = ESMF_FieldCreate(target_grid, & typekind=ESMF_TYPEKIND_R8, & + name="seaice_fract_target_grid", & staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) @@ -3845,6 +2788,7 @@ subroutine create_surface_esmf_fields print*,"- CALL FieldCreate FOR TARGET GRID SEA ICE DEPTH." seaice_depth_target_grid = ESMF_FieldCreate(target_grid, & typekind=ESMF_TYPEKIND_R8, & + name="seaice_depth_target_grid", & staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) @@ -3860,6 +2804,7 @@ subroutine create_surface_esmf_fields print*,"- CALL FieldCreate FOR TARGET GRID SEA ICE SKIN TEMP." seaice_skin_temp_target_grid = ESMF_FieldCreate(target_grid, & typekind=ESMF_TYPEKIND_R8, & + name="seaice_skin_temp_target_grid", & staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) @@ -3875,6 +2820,7 @@ subroutine create_surface_esmf_fields print*,"- CALL FieldCreate FOR TARGET GRID SRFLAG." srflag_target_grid = ESMF_FieldCreate(target_grid, & typekind=ESMF_TYPEKIND_R8, & + name="srflag_target_grid", & staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) @@ -3890,6 +2836,7 @@ subroutine create_surface_esmf_fields print*,"- CALL FieldCreate FOR TARGET GRID SKIN TEMPERATURE." skin_temp_target_grid = ESMF_FieldCreate(target_grid, & typekind=ESMF_TYPEKIND_R8, & + name="skin_temp_target_grid", & staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) @@ -3905,6 +2852,7 @@ subroutine create_surface_esmf_fields print*,"- CALL FieldCreate FOR TARGET GRID CANOPY MOISTURE CONTENT." canopy_mc_target_grid = ESMF_FieldCreate(target_grid, & typekind=ESMF_TYPEKIND_R8, & + name="canopy_mc_target_grid", & staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) @@ -3920,6 +2868,7 @@ subroutine create_surface_esmf_fields print*,"- CALL FieldCreate FOR TARGET GRID LEAF AREA INDEX." lai_target_grid = ESMF_FieldCreate(target_grid, & typekind=ESMF_TYPEKIND_R8, & + name="lai_target_grid",& staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) @@ -3935,6 +2884,7 @@ subroutine create_surface_esmf_fields print*,"- CALL FieldCreate FOR TARGET GRID Z0." z0_target_grid = ESMF_FieldCreate(target_grid, & typekind=ESMF_TYPEKIND_R8, & + name="z0_target_grid", & staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) @@ -3950,6 +2900,7 @@ subroutine create_surface_esmf_fields print*,"- CALL FieldCreate FOR INTERPOLATED TARGET GRID TERRAIN." terrain_from_input_grid = ESMF_FieldCreate(target_grid, & typekind=ESMF_TYPEKIND_R8, & + name="terrain_from_input_grid", & staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) @@ -3965,7 +2916,8 @@ subroutine create_surface_esmf_fields print*,"- CALL FieldCreate FOR INTERPOLATED TARGET GRID SOIL TYPE." soil_type_from_input_grid = ESMF_FieldCreate(target_grid, & typekind=ESMF_TYPEKIND_R8, & - staggerloc=ESMF_STAGGERLOC_CENTER, rc=rc) + staggerloc=ESMF_STAGGERLOC_CENTER, & + name="soil_type_from_input_grid", rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & call error_handler("IN FieldCreate", rc) @@ -3981,6 +2933,7 @@ subroutine create_surface_esmf_fields soil_temp_target_grid = ESMF_FieldCreate(target_grid, & typekind=ESMF_TYPEKIND_R8, & staggerloc=ESMF_STAGGERLOC_CENTER, & + name="soil_temp_target_grid", & ungriddedLBound=(/1/), & ungriddedUBound=(/lsoil_target/), rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & @@ -3998,6 +2951,7 @@ subroutine create_surface_esmf_fields soilm_tot_target_grid = ESMF_FieldCreate(target_grid, & typekind=ESMF_TYPEKIND_R8, & staggerloc=ESMF_STAGGERLOC_CENTER, & + name="soilm_tot_target_grid", & ungriddedLBound=(/1/), & ungriddedUBound=(/lsoil_target/), rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & @@ -4015,6 +2969,7 @@ subroutine create_surface_esmf_fields soilm_liq_target_grid = ESMF_FieldCreate(target_grid, & typekind=ESMF_TYPEKIND_R8, & staggerloc=ESMF_STAGGERLOC_CENTER, & + name="soilm_liq_target_grid", & ungriddedLBound=(/1/), & ungriddedUBound=(/lsoil_target/), rc=rc) if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & @@ -4220,75 +3175,290 @@ subroutine ij_to_i_j(ij, itile, jtile, i, j) end subroutine ij_to_i_j +!> Regrid multiple ESMF fields from input to target grid +!! +!! @param[in] bundle_pre ESMF fieldBundle on input grid +!! @param[in] bundle_post ESMF fieldBundle on target grid +!! @param[in] num_field Number of fields in target field pointer +!! @param[inout] route Route handle to saved ESMF regridding instructions +!! @param[in] dozero Logical length num_field for whether field should be zeroed out before regridding +!! @param[inout] unmapped_ptr (optional) Pointer to unmapped points from FieldRegrid +!! @param[in] resetifd (optional) Logical for whether to reset ifd (only for water where nst data is used) +!! @author Larissa Reames, OU CIMMS/NOAA/NSSL + subroutine regrid_many(bundle_pre,bundle_post, num_field,route,dozero, & + unmapped_ptr,resetifd) + + use esmf + use program_setup, only : convert_nst + use model_grid, only : i_target, j_target + + implicit none + + integer, intent(in) :: num_field + type(esmf_routehandle), intent(inout) :: route + type(esmf_fieldbundle), intent(in) :: bundle_pre, bundle_post + logical, intent(in) :: dozero(num_field) + logical, intent(in), optional :: resetifd + integer(esmf_kind_i4), intent(inout), optional :: unmapped_ptr(:) + + type(esmf_field) :: field_pre,field_post + real(esmf_kind_r8), pointer :: tmp_ptr(:,:) + type(realptr_2d),allocatable :: ptr_2d(:) + type(realptr_3d),allocatable :: ptr_3d(:) + logical :: is2d(num_field) + character(len=50) :: fname + integer :: i, j, k, ij, ind_2d, ind_3d, rc, ndims,n2d, n3d,localpet, l(1), u(1) + type(esmf_vm) :: vm + + ind_2d = 0 + ind_3d = 0 + + if(present(unmapped_ptr)) then + l = lbound(unmapped_ptr) + u = ubound(unmapped_ptr) + endif + + do i = 1, num_field + call ESMF_FieldBundleGet(bundle_pre,i,field_pre,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleGet", rc) + + call ESMF_FieldBundleGet(bundle_post,i,field_post,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldBundleGet", rc) + + call ESMF_FieldGet(field_post,dimCount=ndims,name=fname,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldGet", rc) + + call ESMF_VMGetGlobal(vm, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN VMGetGlobal", rc) + call ESMF_VMGet(vm, localPet=localpet, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN VMGet", rc) + if(localpet==0) print*, "in regrid_many fname = ", fname, ndims + if (ndims == 2) is2d(i) = .True. + if (ndims == 3) is2d(i) = .False. + + if (dozero(i)) then + call ESMF_FieldRegrid(field_pre, & + field_post, & + routehandle=route, & + termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldRegrid", rc) + else + call ESMF_FieldRegrid(field_pre, & + field_post, & + routehandle=route, & + zeroregion=ESMF_REGION_SELECT, & + termorderflag=ESMF_TERMORDER_SRCSEQ, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldRegrid", rc) + endif + enddo + + if (present(resetifd)) then + if( resetifd .and. convert_nst) then + call ESMF_FieldGet(ifd_target_grid,farrayPtr=tmp_ptr,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + tmp_ptr = float(nint(tmp_ptr)) + endif + endif + + n2d = count(is2d(:)) + n3d = count(.not.is2d(:)) + if(localpet==0) print*, is2d(:) + if (present(unmapped_ptr)) then + allocate(ptr_2d(n2d)) + if (n3d .ne. 0) allocate(ptr_3d(n3d)) + do i=1, num_field + if (is2d(i)) then + ind_2d = ind_2d + 1 + call ESMF_FieldBundleGet(bundle_post,i,field_post,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldBundleGet", rc) + call ESMF_FieldGet(field_post, farrayPtr=ptr_2d(ind_2d)%p, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + call ESMF_FieldGet(field_post,name=fname,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldGet", rc) + if (localpet==0) print*, "in doreplace loop, 2d field = ", trim(fname) + else + ind_3d = ind_3d + 1 + call ESMF_FieldBundleGet(bundle_post,i,field_post,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldBundleGet", rc) + call ESMF_FieldGet(field_post,name=fname,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldGet", rc) + if (localpet==0) print*, "in doreplace loop, 3d field = ", trim(fname) + call ESMF_FieldGet(field_post, farrayPtr=ptr_3d(ind_3d)%p, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__)) & + call error_handler("IN FieldGet", rc) + endif + end do + + do ij = l(1), u(1) + call ij_to_i_j(unmapped_ptr(ij), i_target, j_target, i, j) + do k = 1,n2d + ptr_2d(k)%p(i,j) = -9999.9 + enddo + do k = 1,n3d + ptr_3d(k)%p(i,j,:) = -9999.9 + enddo + enddo + deallocate(ptr_2d) + if(n3d .ne. 0) deallocate(ptr_3d) + endif + end subroutine regrid_many + +!> Execute the search function for multple fields +!! +!! @param[in] num_field Number of fields to process. +!! @param[inout] bundle_target ESMF FieldBundle holding target fields to search +!! @param[in] tile Current cubed sphere tile. +!! @param[inout] search_nums Array length num_field holding search field numbers corresponding to each field provided for searching. +!! @param[in] localpet ESMF local persistent execution thread. +!! @param[in] latitude (optional) A real array size i_target,j_target of latitude on the target grid +!! @param[in] terrain_land (optional) A real array size i_target,j_target of terrain height (m) on the target grid +!! @param[in] soilt_climo (optional) A real array size i_target,j_target of climatological soil type on the target grid +!! @param[inout] mask (optional) An integer array of size i_target,j_target that holds masked (0) and unmasked (1) +!! values indicating where to execute search (only at +!unmasked points). +!! @author Larissa Reames, OU CIMMS/NOAA/NSSL + subroutine search_many(num_field,bundle_target,tile,search_nums,localpet,latitude, & + terrain_land,soilt_climo, mask) + + use model_grid, only : i_target,j_target, lsoil_target + use program_setup, only : external_model, input_type + use search_util + + implicit none + + integer, intent(in) :: num_field + type(esmf_fieldbundle), intent(inout) :: bundle_target + + real(esmf_kind_r8), intent(inout), optional :: latitude(i_target,j_target) + real(esmf_kind_r8), intent(inout), optional :: terrain_land(i_target,j_target) + real(esmf_kind_r8), intent(inout), optional :: soilt_climo(i_target,j_target) + integer(esmf_kind_i8), intent(inout), optional :: mask(i_target,j_target) + + real(esmf_kind_r8), allocatable :: field_data_2d(:,:) + real(esmf_kind_r8), allocatable :: field_data_3d(:,:,:) + integer, intent(in) :: tile,localpet + integer, intent(inout) :: search_nums(num_field) + + type(esmf_field) :: temp_field + character(len=50) :: fname + integer, parameter :: SOTYP_LAND_FIELD_NUM = 224 + integer, parameter :: SST_FIELD_NUM = 11 + integer, parameter :: TERRAIN_FIELD_NUM= 7 + integer :: j,k, rc, ndims + + + do k = 1,num_field + call ESMF_FieldBundleGet(bundle_target,k,temp_field, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldGet", rc) + call ESMF_FieldGet(temp_field, name=fname, dimcount=ndims,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldGet", rc) + if (localpet==0) then + allocate(field_data_2d(i_target,j_target)) + else + allocate(field_data_2d(0,0)) + endif + if (ndims .eq. 2) then + call ESMF_FieldGather(temp_field,field_data_2d,rootPet=0,tile=tile, rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldGather", rc) + if (localpet == 0) then + if (present(latitude) .and. search_nums(k).eq.SST_FIELD_NUM) then + ! Sea surface temperatures; pass latitude field to search + call search(field_data_2d, mask, i_target, j_target, tile,search_nums(k),latitude=latitude) + elseif (present(terrain_land) .and. search_nums(k) .eq. TERRAIN_FIELD_NUM) then + ! Terrain height; pass optional climo terrain array to search + call search(field_data_2d, mask, i_target, j_target, tile,search_nums(k),terrain_land=terrain_land) + elseif (search_nums(k) .eq. SOTYP_LAND_FIELD_NUM) then + ! Soil type over land + if (fname .eq. "soil_type_target_grid") then + ! Soil type over land when interpolating input data to target grid + ! *with* the intention of retaining interpolated data in output + call search(field_data_2d, mask, i_target, j_target, tile,search_nums(k),soilt_climo=soilt_climo) + elseif (present(soilt_climo)) then + if (maxval(field_data_2d) > 0 .and. (trim(external_model) .ne. "GFS" .or. trim(input_type) .ne. "grib2")) then + ! Soil type over land when interpolating input data to target grid + ! *without* the intention of retaining data in output file + call search(field_data_2d, mask, i_target, j_target, tile, search_nums(k)) + else + ! If no soil type field exists in input data (e.g., GFS grib2) then don't search + ! but simply set data to the climo field. This may result in + ! somewhat inaccurate soil moistures as no scaling will occur + field_data_2d = soilt_climo + endif !check field value + endif !sotype from target grid + else + ! Any field that doesn't require any of the special treatments or + ! passing of additional variables as in those above + call search(field_data_2d, mask, i_target, j_target, tile,search_nums(k)) + endif !if present + endif !localpet + call ESMF_FieldScatter(temp_field, field_data_2d, rootPet=0, tile=tile,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + else + if (localpet==0) then + allocate(field_data_3d(i_target,j_target,lsoil_target)) + else + allocate(field_data_3d(0,0,0)) + endif + + ! Process 3d fields soil temperature, moisture, and liquid + call ESMF_FieldGather(temp_field,field_data_3d,rootPet=0,tile=tile,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldGather", rc) + + if (localpet==0) then + do j = 1, lsoil_target + field_data_2d = field_data_3d(:,:,j) + call search(field_data_2d, mask, i_target, j_target, tile, 21) + field_data_3d(:,:,j) = field_data_2d + enddo + endif + call ESMF_FieldScatter(temp_field, field_data_3d, rootPet=0, tile=tile,rc=rc) + if(ESMF_logFoundError(rcToCheck=rc,msg=ESMF_LOGERR_PASSTHRU,line=__LINE__,file=__FILE__))& + call error_handler("IN FieldScatter", rc) + deallocate(field_data_3d) + endif !ndims + deallocate(field_data_2d) + end do !fields + + end subroutine search_many + !> Free up memory once the target grid surface fields are !! no longer needed. !! !! @author George Gayno NOAA/EMC - subroutine cleanup_target_sfc_data + subroutine cleanup_all_target_sfc_data + + use surface_target_data, only : cleanup_target_sfc_data implicit none integer :: rc - print*,"- DESTROY TARGET GRID SURFACE FIELDS." - - call ESMF_FieldDestroy(t2m_target_grid, rc=rc) - call ESMF_FieldDestroy(q2m_target_grid, rc=rc) - call ESMF_FieldDestroy(tprcp_target_grid, rc=rc) - call ESMF_FieldDestroy(f10m_target_grid, rc=rc) - call ESMF_FieldDestroy(ffhh_target_grid, rc=rc) - call ESMF_FieldDestroy(ffmm_target_grid, rc=rc) - call ESMF_FieldDestroy(ustar_target_grid, rc=rc) - call ESMF_FieldDestroy(snow_liq_equiv_target_grid, rc=rc) - call ESMF_FieldDestroy(snow_depth_target_grid, rc=rc) - call ESMF_FieldDestroy(seaice_fract_target_grid, rc=rc) - call ESMF_FieldDestroy(seaice_depth_target_grid, rc=rc) - call ESMF_FieldDestroy(seaice_skin_temp_target_grid, rc=rc) - call ESMF_FieldDestroy(srflag_target_grid, rc=rc) - call ESMF_FieldDestroy(skin_temp_target_grid, rc=rc) - call ESMF_FieldDestroy(canopy_mc_target_grid, rc=rc) - call ESMF_FieldDestroy(lai_target_grid,rc=rc) - call ESMF_FieldDestroy(z0_target_grid, rc=rc) + print*,"- DESTROY LOCAL TARGET GRID SURFACE FIELDS." + call ESMF_FieldDestroy(terrain_from_input_grid, rc=rc) call ESMF_FieldDestroy(terrain_from_input_grid_land, rc=rc) call ESMF_FieldDestroy(soil_type_from_input_grid, rc=rc) - call ESMF_FieldDestroy(soil_temp_target_grid, rc=rc) - call ESMF_FieldDestroy(soilm_tot_target_grid, rc=rc) - call ESMF_FieldDestroy(soilm_liq_target_grid, rc=rc) - - end subroutine cleanup_target_sfc_data - -!> Free up memory once the target grid nst fields are -!! no longer needed. -!! -!! @author George Gayno NOAA/EMC - subroutine cleanup_target_nst_data - implicit none + call cleanup_target_sfc_data - integer :: rc - - print*,"- DESTROY TARGET GRID NST DATA." - - call ESMF_FieldDestroy(c_d_target_grid, rc=rc) - call ESMF_FieldDestroy(c_0_target_grid, rc=rc) - call ESMF_FieldDestroy(d_conv_target_grid, rc=rc) - call ESMF_FieldDestroy(dt_cool_target_grid, rc=rc) - call ESMF_FieldDestroy(ifd_target_grid, rc=rc) - call ESMF_FieldDestroy(qrain_target_grid, rc=rc) - call ESMF_FieldDestroy(tref_target_grid, rc=rc) - call ESMF_FieldDestroy(w_d_target_grid, rc=rc) - call ESMF_FieldDestroy(w_0_target_grid, rc=rc) - call ESMF_FieldDestroy(xs_target_grid, rc=rc) - call ESMF_FieldDestroy(xt_target_grid, rc=rc) - call ESMF_FieldDestroy(xu_target_grid, rc=rc) - call ESMF_FieldDestroy(xv_target_grid, rc=rc) - call ESMF_FieldDestroy(xz_target_grid, rc=rc) - call ESMF_FieldDestroy(xtts_target_grid, rc=rc) - call ESMF_FieldDestroy(xzts_target_grid, rc=rc) - call ESMF_FieldDestroy(z_c_target_grid, rc=rc) - call ESMF_FieldDestroy(zm_target_grid, rc=rc) - - end subroutine cleanup_target_nst_data + end subroutine cleanup_all_target_sfc_data end module surface diff --git a/sorc/chgres_cube.fd/surface_target_data.F90 b/sorc/chgres_cube.fd/surface_target_data.F90 new file mode 100644 index 000000000..749032599 --- /dev/null +++ b/sorc/chgres_cube.fd/surface_target_data.F90 @@ -0,0 +1,176 @@ +!> @file +!! @brief Define target grid surface data variables. +!! @author George Gayno NCEP/EMC + +!> Module to hold ESMF fields associated +!! with the target grid surface data. +!! +!! @author George Gayno NCEP/EMC + module surface_target_data + + use esmf + + implicit none + + private + +! surface fields (not including nst) + type(esmf_field), public :: canopy_mc_target_grid + !< Canopy moisture content. + type(esmf_field), public :: f10m_target_grid + !< log((z0+10)*1/z0) + !< See sfc_diff.f for details. + type(esmf_field), public :: ffhh_target_grid + !< log((ztmax+z1)*1/ztmax) + !< See sfc_diff.f for details + type(esmf_field), public :: ffmm_target_grid + !< log((z0+z1)*1/z0) + !< See sfc_diff.f for details. + type(esmf_field), public :: q2m_target_grid + !< 2-m specific humidity. + type(esmf_field), public :: seaice_depth_target_grid + !< Sea ice depth. + type(esmf_field), public :: seaice_fract_target_grid + !< Sea ice fraction. + type(esmf_field), public :: seaice_skin_temp_target_grid + !< Sea ice skin temperature. + type(esmf_field), public :: skin_temp_target_grid + !< Skin temperature/sst. + type(esmf_field), public :: srflag_target_grid + !< Snow/rain flag. + type(esmf_field), public :: snow_liq_equiv_target_grid + !< Liquid equivalent snow depth. + type(esmf_field), public :: snow_depth_target_grid + !< Physical snow depth. + type(esmf_field), public :: soil_temp_target_grid + !< 3-d soil temperature. + type(esmf_field), public :: soilm_liq_target_grid + !< 3-d liquid soil moisture. + type(esmf_field), public :: soilm_tot_target_grid + !< 3-d total soil moisture. + type(esmf_field), public :: t2m_target_grid + !< 2-m temperatrure. + type(esmf_field), public :: tprcp_target_grid + !< Precipitation. + type(esmf_field), public :: ustar_target_grid + !< Friction velocity. + type(esmf_field), public :: z0_target_grid + !< Roughness length. + type(esmf_field), public :: lai_target_grid + !< Leaf area index. + +! nst fields + type(esmf_field), public :: c_d_target_grid + !< Coefficient 2 to calculate d(tz)/d(ts). + type(esmf_field), public :: c_0_target_grid + !< Coefficient 1 to calculate d(tz)/d(ts). + type(esmf_field), public :: d_conv_target_grid + !< Thickness of free convection layer. + type(esmf_field), public :: dt_cool_target_grid + !< Sub-layer cooling amount. + type(esmf_field), public :: ifd_target_grid + !< Model mode index. 0-diurnal model not + !< started; 1-diurnal model started. + type(esmf_field), public :: qrain_target_grid + !< Sensible heat flux due to rainfall. + type(esmf_field), public :: tref_target_grid + !< Reference temperature. + type(esmf_field), public :: w_d_target_grid + !< Coefficient 4 to calculate d(tz)/d(ts). + type(esmf_field), public :: w_0_target_grid + !< Coefficient 3 to calculate d(tz)/d(ts). + type(esmf_field), public :: xs_target_grid + !< Salinity content in diurnal + !< thermocline layer. + type(esmf_field), public :: xt_target_grid + !< Heat content in diurnal thermocline + !< layer. + type(esmf_field), public :: xu_target_grid + !< u-current content in diurnal + !< thermocline layer. + type(esmf_field), public :: xv_target_grid + !< v-current content in diurnal + !< thermocline layer. + type(esmf_field), public :: xz_target_grid + !< Diurnal thermocline layer thickness. + type(esmf_field), public :: xtts_target_grid + !< d(xt)/d(ts). + type(esmf_field), public :: xzts_target_grid + !< d(xz)/d(ts). + type(esmf_field), public :: z_c_target_grid + !< Sub-layer cooling thickness. + type(esmf_field), public :: zm_target_grid + !< Oceanic mixed layer depth. + + public :: cleanup_target_nst_data + public :: cleanup_target_sfc_data + + contains + +!> Free up memory once the target grid surface fields are +!! no longer needed. +!! +!! @author George Gayno NOAA/EMC + subroutine cleanup_target_sfc_data + + implicit none + + integer :: rc + + print*,"- DESTROY TARGET GRID SURFACE FIELDS." + call ESMF_FieldDestroy(t2m_target_grid, rc=rc) + call ESMF_FieldDestroy(q2m_target_grid, rc=rc) + call ESMF_FieldDestroy(tprcp_target_grid, rc=rc) + call ESMF_FieldDestroy(f10m_target_grid, rc=rc) + call ESMF_FieldDestroy(ffmm_target_grid, rc=rc) + call ESMF_FieldDestroy(ustar_target_grid, rc=rc) + call ESMF_FieldDestroy(snow_liq_equiv_target_grid, rc=rc) + call ESMF_FieldDestroy(snow_depth_target_grid, rc=rc) + call ESMF_FieldDestroy(seaice_fract_target_grid, rc=rc) + call ESMF_FieldDestroy(seaice_depth_target_grid, rc=rc) + call ESMF_FieldDestroy(seaice_skin_temp_target_grid, rc=rc) + call ESMF_FieldDestroy(srflag_target_grid, rc=rc) + call ESMF_FieldDestroy(skin_temp_target_grid, rc=rc) + call ESMF_FieldDestroy(canopy_mc_target_grid, rc=rc) + call ESMF_FieldDestroy(lai_target_grid,rc=rc) + call ESMF_FieldDestroy(z0_target_grid, rc=rc) + call ESMF_FieldDestroy(soil_temp_target_grid, rc=rc) + call ESMF_FieldDestroy(soilm_tot_target_grid, rc=rc) + call ESMF_FieldDestroy(soilm_liq_target_grid, rc=rc) + + end subroutine cleanup_target_sfc_data + +!> Free up memory once the target grid nst fields are +!! no longer needed. +!! +!! @author George Gayno NOAA/EMC + subroutine cleanup_target_nst_data + + implicit none + + integer :: rc + + print*,"- DESTROY TARGET GRID NST DATA." + + call ESMF_FieldDestroy(c_d_target_grid, rc=rc) + call ESMF_FieldDestroy(c_0_target_grid, rc=rc) + call ESMF_FieldDestroy(d_conv_target_grid, rc=rc) + call ESMF_FieldDestroy(dt_cool_target_grid, rc=rc) + call ESMF_FieldDestroy(ifd_target_grid, rc=rc) + call ESMF_FieldDestroy(qrain_target_grid, rc=rc) + call ESMF_FieldDestroy(tref_target_grid, rc=rc) + call ESMF_FieldDestroy(w_d_target_grid, rc=rc) + call ESMF_FieldDestroy(w_0_target_grid, rc=rc) + call ESMF_FieldDestroy(xs_target_grid, rc=rc) + call ESMF_FieldDestroy(xt_target_grid, rc=rc) + call ESMF_FieldDestroy(xu_target_grid, rc=rc) + call ESMF_FieldDestroy(xv_target_grid, rc=rc) + call ESMF_FieldDestroy(xz_target_grid, rc=rc) + call ESMF_FieldDestroy(xtts_target_grid, rc=rc) + call ESMF_FieldDestroy(xzts_target_grid, rc=rc) + call ESMF_FieldDestroy(z_c_target_grid, rc=rc) + call ESMF_FieldDestroy(zm_target_grid, rc=rc) + + end subroutine cleanup_target_nst_data + + end module surface_target_data diff --git a/sorc/chgres_cube.fd/thompson_mp_climo_data.F90 b/sorc/chgres_cube.fd/thompson_mp_climo_data.F90 index 1dfd98d31..beb3c45a5 100644 --- a/sorc/chgres_cube.fd/thompson_mp_climo_data.F90 +++ b/sorc/chgres_cube.fd/thompson_mp_climo_data.F90 @@ -12,6 +12,7 @@ module thompson_mp_climo_data use netcdf use program_setup, only : cycle_mon, cycle_day, cycle_hour, & thomp_mp_climo_file + use utilities, only : error_handler, netcdf_err implicit none diff --git a/sorc/chgres_cube.fd/utils.F90 b/sorc/chgres_cube.fd/utils.F90 index 568d0de0e..c46540c5e 100644 --- a/sorc/chgres_cube.fd/utils.F90 +++ b/sorc/chgres_cube.fd/utils.F90 @@ -1,3 +1,6 @@ +module utilities + +contains !> @file !! @brief Contains utility routines. !! @@ -18,7 +21,7 @@ subroutine error_handler(string, rc) integer :: ierr - print*,"- FATAL ERROR: ", string + print*,"- FATAL ERROR: ", trim(string) print*,"- IOSTAT IS: ", rc call mpi_abort(mpi_comm_world, 999, ierr) @@ -99,3 +102,399 @@ subroutine to_lower(strIn) end do strIn(:) = strOut(:) end subroutine to_lower + +!> Handle GRIB2 read error based on the user selected +!! method in the varmap file. +!! +!! @param [in] vname grib2 variable name +!! @param [in] lev grib2 variable level +!! @param [in] method how missing data is handled +!! @param [in] value fill value for missing data +!! @param [in] varnum grib2 variable number +!! @param [inout] iret return status code +!! @param [inout] var 4-byte array of corrected data +!! @param [inout] var8 8-byte array of corrected data +!! @param [inout] var3d 3-d array of corrected data +!! @param [inout] read_from_input logical array indicating if variable was read in +!! @author Larissa Reames +subroutine handle_grib_error(vname,lev,method,value,varnum,read_from_input, iret,var,var8,var3d) + + use, intrinsic :: ieee_arithmetic + use esmf + + implicit none + + real(esmf_kind_r4), intent(in) :: value + logical, intent(inout) :: read_from_input(:) + real(esmf_kind_r4), intent(inout), optional :: var(:,:) + real(esmf_kind_r8), intent(inout), optional :: var8(:,:) + real(esmf_kind_r8), intent(inout), optional :: var3d(:,:,:) + + character(len=20), intent(in) :: vname, lev, method + character(len=200) :: err_msg + + integer, intent(in) :: varnum + integer, intent(inout) :: iret + + iret = 0 + if (varnum == 9999) then + print*, "WARNING: ", trim(vname), " NOT FOUND AT LEVEL ", lev, " IN EXTERNAL FILE ", & + "AND NO ENTRY EXISTS IN VARMAP TABLE. VARIABLE WILL NOT BE USED." + iret = 1 + + return + endif + + if (trim(method) == "skip" ) then + print*, "WARNING: SKIPPING ", trim(vname), " IN FILE" + read_from_input(varnum) = .false. + iret = 1 + elseif (trim(method) == "set_to_fill") then + print*, "WARNING: ,", trim(vname), " NOT AVAILABLE AT LEVEL ", trim(lev), & + ". SETTING EQUAL TO FILL VALUE OF ", value + if(present(var)) var(:,:) = value + if(present(var8)) var8(:,:) = value + if(present(var3d)) var3d(:,:,:) = value + elseif (trim(method) == "set_to_NaN") then + print*, "WARNING: ,", trim(vname), " NOT AVAILABLE AT LEVEL ", trim(lev), & + ". SETTING EQUAL TO NaNs" + if(present(var)) var(:,:) = ieee_value(var,IEEE_QUIET_NAN) + if(present(var8)) var8(:,:) = ieee_value(var8,IEEE_QUIET_NAN) + if(present(var3d)) var3d(:,:,:) = ieee_value(var3d,IEEE_QUIET_NAN) + elseif (trim(method) == "stop") then + err_msg="READING " // trim(vname) // " at level " //lev// ". TO MAKE THIS NON-" // & + "FATAL, CHANGE STOP TO SKIP FOR THIS VARIABLE IN YOUR VARMAP FILE." + call error_handler(err_msg, iret) + elseif (trim(method) == "intrp") then + print*, "WARNING: ,"//trim(vname)//" NOT AVAILABLE AT LEVEL "//trim(lev)// & + ". WILL INTERPOLATE INTERSPERSED MISSING LEVELS AND/OR FILL MISSING"//& + " LEVELS AT EDGES." + else + err_msg="ERROR USING MISSING_VAR_METHOD. PLEASE SET VALUES IN" // & + " VARMAP TABLE TO ONE OF: set_to_fill, set_to_NaN, intrp, skip, or stop." + call error_handler(err_msg, 1) + endif + +end subroutine handle_grib_error + +!> Sort an array of values. +!! +!! @param a the sorted array +!! @param first the first value of sorted array +!! @param last the last value of sorted array +!! @author Jili Dong NOAA/EMC +recursive subroutine quicksort(a, first, last) + implicit none + real*8 a(*), x, t + integer first, last + integer i, j + + x = a( (first+last) / 2 ) + i = first + j = last + do + do while (a(i) < x) + i=i+1 + end do + do while (x < a(j)) + j=j-1 + end do + if (i >= j) exit + t = a(i); a(i) = a(j); a(j) = t + i=i+1 + j=j-1 + end do + if (first < i-1) call quicksort(a, first, i-1) + if (j+1 < last) call quicksort(a, j+1, last) +end subroutine quicksort + +!> Check for and replace certain values in soil temperature. +!> At open water points (landmask=0) use skin temperature as +!> a filler value. At land points (landmask=1) with excessive +!> soil temperature, replace soil temperature with skin temperature. +!> In GEFSv12.0 data there are some erroneous missing values at +!> land points which this corrects. At sea ice points (landmask=2), +!> store a default ice column temperature because grib2 files do not +!> have ice column temperature which FV3 expects at these points. +!! +!! @param soilt [inout] 3-dimensional soil temperature arrray +!! @param landmask [in] landmask of the input grid +!! @param skint [in] 2-dimensional skin temperature array +!! @param ICET_DEFAULT [in] Default temperature to apply at ice points +!! @param i_input [in] i-dimension of input grid +!! @param j_input [in] j-dimension of input grid +!! @param lsoil_input [in] soil layers dimension of input grid +!! @author Larissa Reames CIMMS/NSSL + +subroutine check_soilt(soilt, landmask, skint,ICET_DEFAULT,i_input,j_input,lsoil_input) + use esmf + implicit none + integer, intent(in) :: i_input, j_input, lsoil_input + real(esmf_kind_r8), intent(inout) :: soilt(i_input,j_input,lsoil_input) + real(esmf_kind_r8), intent(in) :: skint(i_input,j_input) + real, intent(in) :: ICET_DEFAULT + integer(esmf_kind_i4), intent(in) :: landmask(i_input,j_input) + + integer :: i, j, k + + do k=1,lsoil_input + do j = 1, j_input + do i = 1, i_input + if (landmask(i,j) == 0_esmf_kind_i4 ) then + soilt(i,j,k) = skint(i,j) + else if (landmask(i,j) == 1_esmf_kind_i4 .and. soilt(i,j,k) > 350.0_esmf_kind_r8) then + soilt(i,j,k) = skint(i,j) + else if (landmask(i,j) == 2_esmf_kind_i4 ) then + soilt(i,j,k) = ICET_DEFAULT + endif + enddo + enddo + enddo +end subroutine check_soilt + +!> When using GEFS data, some points on the target grid have +!> unreasonable canpy moisture content, so zero out any +!> locations with unrealistic canopy moisture values (>0.5). +!! +!! @param cnwat [input] 2-dimensional canopy moisture content +!! @param i_input [in] i-dimension of input grid +!! @param j_input [in] j-dimension of input grid +!! @author Larissa Reames CIMMS/NSSL + +subroutine check_cnwat(cnwat,i_input,j_input) + use esmf + implicit none + integer, intent(in) :: i_input, j_input + real(esmf_kind_r8), intent(inout) :: cnwat(i_input,j_input) + + real(esmf_kind_r8) :: max_cnwat = 0.5 + + integer :: i, j + + do i = 1,i_input + do j = 1,j_input + if (cnwat(i,j) .gt. max_cnwat) cnwat(i,j) = 0.0_esmf_kind_r8 + enddo + enddo +end subroutine check_cnwat + +!> Pressure to presure vertical interpolation for tracers with linear or lnP +!> interpolation. Input tracers on pres levels are interpolated +!> to the target output pressure levels. The matching levels of input and +!> output will keep the same. Extrapolation is also allowed but needs +!> caution. The routine is mostly for GFSV16 combined grib2 input when spfh has +!> missing levels in low and mid troposphere from U/T/HGT/DZDT. +!! +!! @param [in] ppin 1d input pres levs +!! @param [in] xxin 1d input tracer +!! @param [in] npin number of input levs +!! @param [in] ppout 1d target pres levs +!! @param [out] xxout 1d interpolated tracer +!! @param [in] npout number of target levs +!! @param [in] linlog interp method.1:linear;not 1:log;neg:extrp allowed +!! @param [in] xmsg fill values of missing levels (-999.0) +!! @param [out] ier error status. non 0: failed interpolation +!! @author Jili Dong NCEP/EMC +!! @date 2021/07/30 +SUBROUTINE DINT2P(PPIN,XXIN,NPIN,PPOUT,XXOUT,NPOUT & + ,LINLOG,XMSG,IER) + IMPLICIT NONE + +! NCL code for pressure level interpolation +! +! This code was designed for one simple task. It has since +! been mangled and abused for assorted reasons. For example, +! early gfortran compilers had some issues with automatic arrays. +! Hence, the C-Wrapper was used to create 'work' arrays which +! were then passed to this code. The original focused (non-NCL) +! task was to handle PPIN & PPOUT that had the same 'monotonicity.' +! Extra code was added to handle the more general case. +! Blah-Blah: Punch line: it is embarrassingly convoluted!!! +! +! ! input types + INTEGER NPIN,NPOUT,LINLOG,IER + real*8 PPIN(NPIN),XXIN(NPIN),PPOUT(NPOUT),XMSG + ! output + real*8 XXOUT(NPOUT) + ! work + real*8 PIN(NPIN),XIN(NPIN),P(NPIN),X(NPIN) + real*8 POUT(NPOUT),XOUT(NPOUT) + +! local + INTEGER NP,NL,NLMAX,NLSAVE,NP1,NO1,N1,N2,LOGLIN, & + NLSTRT + real*8 SLOPE,PA,PB,PC + + LOGLIN = ABS(LINLOG) + +! error check: enough points: pressures consistency? + + IER = 0 + IF (NPOUT.GT.0) THEN + DO NP = 1,NPOUT + XXOUT(NP) = XMSG + END DO + END IF +! Jili Dong input levels have to be the same as output levels: +! we only interpolate for levels with missing variables +! IF (.not. all(PPIN .eq. PPOUT)) IER = IER+1 + + IF (NPIN.LT.2 .OR. NPOUT.LT.1) IER = IER + 1 + + IF (IER.NE.0) THEN +! PRINT *,'INT2P: error exit: ier=',IER + RETURN + END IF + +! should *input arrays* be reordered? want p(1) > p(2) > p(3) etc +! so that it will match order for which code was originally designed +! copy to 'work' arrays + + NP1 = 0 + NO1 = 0 + IF (PPIN(1).LT.PPIN(2)) THEN + NP1 = NPIN + 1 + END IF + IF (PPOUT(1).LT.PPOUT(2)) THEN + NO1 = NPOUT + 1 + END IF + + DO NP = 1,NPIN + PIN(NP) = PPIN(ABS(NP1-NP)) + XIN(NP) = XXIN(ABS(NP1-NP)) + END DO + + DO NP = 1,NPOUT + POUT(NP) = PPOUT(ABS(NO1-NP)) + END DO + +! eliminate XIN levels with missing data. +! . This can happen with observational data. + + NL = 0 + DO NP = 1,NPIN + IF (XIN(NP).NE.XMSG .AND. PIN(NP).NE.XMSG) THEN + NL = NL + 1 + P(NL) = PIN(NP) + X(NL) = XIN(NP) + END IF + END DO + NLMAX = NL + + ! all missing data + IF (NLMAX.LT.2) THEN + IER = IER + 1000 + PRINT *,'INT2P: ier=',IER + RETURN + END IF + +! ===============> pressure in decreasing order <================ +! perform the interpolation [pin(1)>pin(2)>...>pin(npin)] +! ( p ,x) +! ------------------------- p(nl+1), x(nl+1) example (200,5) +! . +! ------------------------- pout(np), xout(np) (250,?) +! . +! ------------------------- p(nl) , x(nl) (300,10) + + +! exact p-level matches + NLSTRT = 1 + NLSAVE = 1 + DO NP = 1,NPOUT + XOUT(NP) = XMSG + DO NL = NLSTRT,NLMAX + IF (POUT(NP).EQ.P(NL)) THEN + XOUT(NP) = X(NL) + NLSAVE = NL + 1 + GO TO 10 + END IF + END DO + 10 NLSTRT = NLSAVE + END DO + + IF (LOGLIN.EQ.1) THEN + DO NP = 1,NPOUT + DO NL = 1,NLMAX - 1 + IF (POUT(NP).LT.P(NL) .AND. POUT(NP).GT.P(NL+1)) THEN + SLOPE = (X(NL)-X(NL+1))/ (P(NL)-P(NL+1)) + XOUT(NP) = X(NL+1) + SLOPE* (POUT(NP)-P(NL+1)) + END IF + END DO + END DO + ELSE + DO NP = 1,NPOUT + DO NL = 1,NLMAX - 1 + IF (POUT(NP).LT.P(NL) .AND. POUT(NP).GT.P(NL+1)) THEN + PA = LOG(P(NL)) + PB = LOG(POUT(NP)) +! special case: In case someome inadvertently enter p=0. + if (p(nl+1).gt.0.d0) then + PC = LOG(P(NL+1)) + else + PC = LOG(1.E-4) + end if + + SLOPE = (X(NL)-X(NL+1))/ (PA-PC) + XOUT(NP) = X(NL+1) + SLOPE* (PB-PC) + END IF + END DO + END DO + END IF + +! extrapolate? +! . use the 'last' valid slope for extrapolating + + IF (LINLOG.LT.0) THEN + DO NP = 1,NPOUT + DO NL = 1,NLMAX + IF (POUT(NP).GT.P(1)) THEN + IF (LOGLIN.EQ.1) THEN + SLOPE = (X(2)-X(1))/ (P(2)-P(1)) + XOUT(NP) = X(1) + SLOPE* (POUT(NP)-P(1)) + ELSE + PA = LOG(P(2)) + PB = LOG(POUT(NP)) + PC = LOG(P(1)) + SLOPE = (X(2)-X(1))/ (PA-PC) + XOUT(NP) = X(1) + SLOPE* (PB-PC) + END IF + ELSE IF (POUT(NP).LT.P(NLMAX)) THEN + N1 = NLMAX + N2 = NLMAX - 1 + IF (LOGLIN.EQ.1) THEN + SLOPE = (X(N1)-X(N2))/ (P(N1)-P(N2)) + XOUT(NP) = X(N1) + SLOPE* (POUT(NP)-P(N1)) + ELSE + PA = LOG(P(N1)) + PB = LOG(POUT(NP)) + PC = LOG(P(N2)) + SLOPE = (X(N1)-X(N2))/ (PA-PC) + !XOUT(NP) = X(N1) + SLOPE* (PB-PC) !bug fixed below + XOUT(NP) = X(N1) + SLOPE* (PB-PA) + END IF + END IF + END DO + END DO + END IF + +! place results in the return array; +! . possibly .... reverse to original order + + if (NO1.GT.0) THEN + DO NP = 1,NPOUT + n1 = ABS(NO1-NP) + PPOUT(NP) = POUT(n1) + XXOUT(NP) = XOUT(n1) + END DO + ELSE + DO NP = 1,NPOUT + PPOUT(NP) = POUT(NP) + XXOUT(NP) = XOUT(NP) + END DO + END IF + + + RETURN + END SUBROUTINE DINT2P +end module utilities diff --git a/sorc/chgres_cube.fd/wam_climo_data.f90 b/sorc/chgres_cube.fd/wam_climo_data.f90 index 0ba5647bc..6430c86d0 100644 --- a/sorc/chgres_cube.fd/wam_climo_data.f90 +++ b/sorc/chgres_cube.fd/wam_climo_data.f90 @@ -1,2798 +1,138 @@ !> @file !! @brief Process vertical profile climatologic data for WAM. !! -!! This file contains all data need to form exosphere and used -!! whole atmsopheric modeling (WAM). it has two modules and some -!! routines to compute the temperature and compositions of neutral -!! density in specific values. -!! the original package contains fortran 77 blockdata and common statement -!! they are all recoded to use modules and use-statements. -!! -!! @author Hann-Ming Henry Juang NCEP/EMC - -!----------------------------------------------------------------------- -!> Use moduke for blockdata gtd7bk -!! -!! All variables originalyl in blockdata used for this packahe are -!! getting from NRLMSISE-00. -!! NRLMSISE-00 is an empirical, global reference atmospheric model of -!! the Earth from ground to space. It models the temperatures and densities -!! of the atmosphere's components. -!! NRL stands for the US Naval Research Laboratory. MSIS stands for mass -!! spectrometer and incoherent scatter radar, the two primary data sources -!! for development of earlier versions of the model. E indicates that the -!! model extends from the ground through exosphere and 00 is the year of -!! release in 2000. Over the years since introduction, NRLMSISE-00 has -!! become the standard for international space research. (wikipedia) -!! -!! @author Hann-Ming Henry Juang - module wam_gtd7bk_mod -! msise-00 01-feb-02 -! - real :: pt1(50) !< block space data for temperature - real :: pt2(50) !< block space data for temperature - real :: pt3(50) !< block space data for temperature - real :: pa1(50) !< block space data for he denisity - real :: pa2(50) !< block space data for he denisity - real :: pa3(50) !< block space data for he denisity - real :: pb1(50) !< block space data for o density - real :: pb2(50) !< block space data for o density - real :: pb3(50) !< block space data for o density - real :: pc1(50) !< block space data for n2 density - real :: pc2(50) !< block space data for n2 density - real :: pc3(50) !< block space data for n2 density - real :: pd1(50) !< block space data for tlb - real :: pd2(50) !< block space data for tlb - real :: pd3(50) !< block space data for tlb - real :: pe1(50) !< block space data for o2 density - real :: pe2(50) !< block space data for o2 density - real :: pe3(50) !< block space data for o2 density - real :: pf1(50) !< block space data for ar density - real :: pf2(50) !< block space data for ar density - real :: pf3(50) !< block space data for ar density - real :: pg1(50) !< block space data for h density - real :: pg2(50) !< block space data for h density - real :: pg3(50) !< block space data for h density - real :: ph1(50) !< block space data for n density - real :: ph2(50) !< block space data for n density - real :: ph3(50) !< block space data for n density - real :: pi1(50) !< block space data for hot o density - real :: pi2(50) !< block space data for hot o density - real :: pi3(50) !< block space data for hot o density - real :: pj1(50) !< block space data for s param - real :: pj2(50) !< block space data for s param - real :: pj3(50) !< block space data for s param - real :: pk1(50) !< block space data for turbo - real :: pl1(50) !< block space data for tn1(2) - real :: pl2(50) !< block space data for tn1(2) - real :: pm1(50) !< block space data for tn1(3) - real :: pm2(50) !< block space data for tn1(3) - real :: pn1(50) !< block space data for tn1(4) - real :: pn2(50) !< block space data for tn1(4) - real :: po1(50) !< block space data for tn1(5) tn2(1) - real :: po2(50) !< block space data for tn1(5) tn2(1) - real :: pp1(50) !< block space data for tn2(2) - real :: pp2(50) !< block space data for tn2(2) - real :: pq1(50) !< block space data for tn2(3) - real :: pq2(50) !< block space data for tn2(3) - real :: pr1(50) !< block space data for tn2(4) tn3(1) - real :: pr2(50) !< block space data for tn2(4) tn3(1) - real :: ps1(50) !< block space data for tn3(2) - real :: ps2(50) !< block space data for tn3(2) - real :: pu1(50) !< block space data for tn3(3) - real :: pu2(50) !< block space data for tn3(3) - real :: pv1(50) !< block space data for tn3(4) - real :: pv2(50) !< block space data for tn3(4) - real :: pw1(50) !< block space data for tn3(5) surface temperature tsl - real :: pw2(50) !< block space data for tn3(5) surface temperature tsl - real :: px1(50) !< block space data for tgn3(2) surface grad tslg - real :: px2(50) !< block space data for tgn3(2) surface grad tslg - real :: py1(50) !< block space data for tgn2(1) tgn1(2) - real :: py2(50) !< block space data for tgn2(1) tgn1(2) - real :: pz1(50) !< block space data for tgn3(1) tgn2(2) - real :: pz2(50) !< block space data for tgn3(1) tgn2(2) - real :: paa1(50) !< block space data for semiannual mult sam - real :: paa2(50) !< block space data for semiannual mult sam -! - real :: ptm(10) !< block space data for lower boundary - real :: pdm(10,8) !< block space data for lower boundary -! - real :: pavgm(10) !< block space data for middle atmosphere averages -! - character*4:: isdate(3) !< define date - character*4:: istime(2) !< define time - character*4:: name(2) !< define data name -! - integer :: imr !< define version -! - real :: pr65(2,65) !< define pressures - real :: pr151(2,151) !< define pressures - - data imr/0/ - data isdate/'01-f','eb-0','2 '/,istime/'15:4','9:27'/ - data name/'msis','e-00'/ -! temperature - data pt1/ & - 9.86573e-01, 1.62228e-02, 1.55270e-02,-1.04323e-01,-3.75801e-03,& - -1.18538e-03,-1.24043e-01, 4.56820e-03, 8.76018e-03,-1.36235e-01,& - -3.52427e-02, 8.84181e-03,-5.92127e-03,-8.61650e+00, 0.00000e+00,& - 1.28492e-02, 0.00000e+00, 1.30096e+02, 1.04567e-02, 1.65686e-03,& - -5.53887e-06, 2.97810e-03, 0.00000e+00, 5.13122e-03, 8.66784e-02,& - 1.58727e-01, 0.00000e+00, 0.00000e+00, 0.00000e+00,-7.27026e-06,& - 0.00000e+00, 6.74494e+00, 4.93933e-03, 2.21656e-03, 2.50802e-03,& - 0.00000e+00, 0.00000e+00,-2.08841e-02,-1.79873e+00, 1.45103e-03,& - 2.81769e-04,-1.44703e-03,-5.16394e-05, 8.47001e-02, 1.70147e-01,& - 5.72562e-03, 5.07493e-05, 4.36148e-03, 1.17863e-04, 4.74364e-03/ - data pt2/ & - 6.61278e-03, 4.34292e-05, 1.44373e-03, 2.41470e-05, 2.84426e-03,& - 8.56560e-04, 2.04028e-03, 0.00000e+00,-3.15994e+03,-2.46423e-03,& - 1.13843e-03, 4.20512e-04, 0.00000e+00,-9.77214e+01, 6.77794e-03,& - 5.27499e-03, 1.14936e-03, 0.00000e+00,-6.61311e-03,-1.84255e-02,& - -1.96259e-02, 2.98618e+04, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 6.44574e+02, 8.84668e-04, 5.05066e-04, 0.00000e+00, 4.02881e+03,& - -1.89503e-03, 0.00000e+00, 0.00000e+00, 8.21407e-04, 2.06780e-03,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - -1.20410e-02,-3.63963e-03, 9.92070e-05,-1.15284e-04,-6.33059e-05,& - -6.05545e-01, 8.34218e-03,-9.13036e+01, 3.71042e-04, 0.00000e+00/ - data pt3/ & - 4.19000e-04, 2.70928e-03, 3.31507e-03,-4.44508e-03,-4.96334e-03,& - -1.60449e-03, 3.95119e-03, 2.48924e-03, 5.09815e-04, 4.05302e-03,& - 2.24076e-03, 0.00000e+00, 6.84256e-03, 4.66354e-04, 0.00000e+00,& - -3.68328e-04, 0.00000e+00, 0.00000e+00,-1.46870e+02, 0.00000e+00,& - 0.00000e+00, 1.09501e-03, 4.65156e-04, 5.62583e-04, 3.21596e+00,& - 6.43168e-04, 3.14860e-03, 3.40738e-03, 1.78481e-03, 9.62532e-04,& - 5.58171e-04, 3.43731e+00,-2.33195e-01, 5.10289e-04, 0.00000e+00,& - 0.00000e+00,-9.25347e+04, 0.00000e+00,-1.99639e-03, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00/ -! he density - data pa1/ & - 1.09979e+00,-4.88060e-02,-1.97501e-01,-9.10280e-02,-6.96558e-03,& - 2.42136e-02, 3.91333e-01,-7.20068e-03,-3.22718e-02, 1.41508e+00,& - 1.68194e-01, 1.85282e-02, 1.09384e-01,-7.24282e+00, 0.00000e+00,& - 2.96377e-01,-4.97210e-02, 1.04114e+02,-8.61108e-02,-7.29177e-04,& - 1.48998e-06, 1.08629e-03, 0.00000e+00, 0.00000e+00, 8.31090e-02,& - 1.12818e-01,-5.75005e-02,-1.29919e-02,-1.78849e-02,-2.86343e-06,& - 0.00000e+00,-1.51187e+02,-6.65902e-03, 0.00000e+00,-2.02069e-03,& - 0.00000e+00, 0.00000e+00, 4.32264e-02,-2.80444e+01,-3.26789e-03,& - 2.47461e-03, 0.00000e+00, 0.00000e+00, 9.82100e-02, 1.22714e-01,& - -3.96450e-02, 0.00000e+00,-2.76489e-03, 0.00000e+00, 1.87723e-03/ - data pa2/ & - -8.09813e-03, 4.34428e-05,-7.70932e-03, 0.00000e+00,-2.28894e-03,& - -5.69070e-03,-5.22193e-03, 6.00692e-03,-7.80434e+03,-3.48336e-03,& - -6.38362e-03,-1.82190e-03, 0.00000e+00,-7.58976e+01,-2.17875e-02,& - -1.72524e-02,-9.06287e-03, 0.00000e+00, 2.44725e-02, 8.66040e-02,& - 1.05712e-01, 3.02543e+04, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - -6.01364e+03,-5.64668e-03,-2.54157e-03, 0.00000e+00, 3.15611e+02,& - -5.69158e-03, 0.00000e+00, 0.00000e+00,-4.47216e-03,-4.49523e-03,& - 4.64428e-03, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 4.51236e-02, 2.46520e-02, 6.17794e-03, 0.00000e+00, 0.00000e+00,& - -3.62944e-01,-4.80022e-02,-7.57230e+01,-1.99656e-03, 0.00000e+00/ - data pa3/ & - -5.18780e-03,-1.73990e-02,-9.03485e-03, 7.48465e-03, 1.53267e-02,& - 1.06296e-02, 1.18655e-02, 2.55569e-03, 1.69020e-03, 3.51936e-02,& - -1.81242e-02, 0.00000e+00,-1.00529e-01,-5.10574e-03, 0.00000e+00,& - 2.10228e-03, 0.00000e+00, 0.00000e+00,-1.73255e+02, 5.07833e-01,& - -2.41408e-01, 8.75414e-03, 2.77527e-03,-8.90353e-05,-5.25148e+00,& - -5.83899e-03,-2.09122e-02,-9.63530e-03, 9.77164e-03, 4.07051e-03,& - 2.53555e-04,-5.52875e+00,-3.55993e-01,-2.49231e-03, 0.00000e+00,& - 0.00000e+00, 2.86026e+01, 0.00000e+00, 3.42722e-04, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00/ -! o density - data pb1/ & - 1.02315e+00,-1.59710e-01,-1.06630e-01,-1.77074e-02,-4.42726e-03,& - 3.44803e-02, 4.45613e-02,-3.33751e-02,-5.73598e-02, 3.50360e-01,& - 6.33053e-02, 2.16221e-02, 5.42577e-02,-5.74193e+00, 0.00000e+00,& - 1.90891e-01,-1.39194e-02, 1.01102e+02, 8.16363e-02, 1.33717e-04,& - 6.54403e-06, 3.10295e-03, 0.00000e+00, 0.00000e+00, 5.38205e-02,& - 1.23910e-01,-1.39831e-02, 0.00000e+00, 0.00000e+00,-3.95915e-06,& - 0.00000e+00,-7.14651e-01,-5.01027e-03, 0.00000e+00,-3.24756e-03,& - 0.00000e+00, 0.00000e+00, 4.42173e-02,-1.31598e+01,-3.15626e-03,& - 1.24574e-03,-1.47626e-03,-1.55461e-03, 6.40682e-02, 1.34898e-01,& - -2.42415e-02, 0.00000e+00, 0.00000e+00, 0.00000e+00, 6.13666e-04/ - data pb2/ & - -5.40373e-03, 2.61635e-05,-3.33012e-03, 0.00000e+00,-3.08101e-03,& - -2.42679e-03,-3.36086e-03, 0.00000e+00,-1.18979e+03,-5.04738e-02,& - -2.61547e-03,-1.03132e-03, 1.91583e-04,-8.38132e+01,-1.40517e-02,& - -1.14167e-02,-4.08012e-03, 1.73522e-04,-1.39644e-02,-6.64128e-02,& - -6.85152e-02,-1.34414e+04, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 6.07916e+02,-4.12220e-03,-2.20996e-03, 0.00000e+00, 1.70277e+03,& - -4.63015e-03, 0.00000e+00, 0.00000e+00,-2.25360e-03,-2.96204e-03,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 3.92786e-02, 1.31186e-02,-1.78086e-03, 0.00000e+00, 0.00000e+00,& - -3.90083e-01,-2.84741e-02,-7.78400e+01,-1.02601e-03, 0.00000e+00/ - data pb3/ & - -7.26485e-04,-5.42181e-03,-5.59305e-03, 1.22825e-02, 1.23868e-02,& - 6.68835e-03,-1.03303e-02,-9.51903e-03, 2.70021e-04,-2.57084e-02,& - -1.32430e-02, 0.00000e+00,-3.81000e-02,-3.16810e-03, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00,-9.05762e-04,-2.14590e-03,-1.17824e-03, 3.66732e+00,& - -3.79729e-04,-6.13966e-03,-5.09082e-03,-1.96332e-03,-3.08280e-03,& - -9.75222e-04, 4.03315e+00,-2.52710e-01, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00/ -! n2 density - data pc1/ & - 1.16112e+00, 0.00000e+00, 0.00000e+00, 3.33725e-02, 0.00000e+00,& - 3.48637e-02,-5.44368e-03, 0.00000e+00,-6.73940e-02, 1.74754e-01,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 1.74712e+02, 0.00000e+00,& - 1.26733e-01, 0.00000e+00, 1.03154e+02, 5.52075e-02, 0.00000e+00,& - 0.00000e+00, 8.13525e-04, 0.00000e+00, 0.00000e+00, 8.66784e-02,& - 1.58727e-01, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00,-2.50482e+01, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,-2.48894e-03,& - 6.16053e-04,-5.79716e-04, 2.95482e-03, 8.47001e-02, 1.70147e-01,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00/ - data pc2/ & - 0.00000e+00, 2.47425e-05, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00/ - data pc3/ & - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00/ -! tlb - data pd1/ & - 9.44846e-01, 0.00000e+00, 0.00000e+00,-3.08617e-02, 0.00000e+00,& - -2.44019e-02, 6.48607e-03, 0.00000e+00, 3.08181e-02, 4.59392e-02,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 1.74712e+02, 0.00000e+00,& - 2.13260e-02, 0.00000e+00,-3.56958e+02, 0.00000e+00, 1.82278e-04,& - 0.00000e+00, 3.07472e-04, 0.00000e+00, 0.00000e+00, 8.66784e-02,& - 1.58727e-01, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 3.83054e-03, 0.00000e+00, 0.00000e+00,& - -1.93065e-03,-1.45090e-03, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00,-1.23493e-03, 1.36736e-03, 8.47001e-02, 1.70147e-01,& - 3.71469e-03, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00/ - data pd2/ & - 5.10250e-03, 2.47425e-05, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 3.68756e-03, 0.00000e+00, 0.00000e+00, 0.00000e+00/ - data pd3/ & - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00/ -! o2 density - data pe1/ & - 1.35580e+00, 1.44816e-01, 0.00000e+00, 6.07767e-02, 0.00000e+00,& - 2.94777e-02, 7.46900e-02, 0.00000e+00,-9.23822e-02, 8.57342e-02,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 2.38636e+01, 0.00000e+00,& - 7.71653e-02, 0.00000e+00, 8.18751e+01, 1.87736e-02, 0.00000e+00,& - 0.00000e+00, 1.49667e-02, 0.00000e+00, 0.00000e+00, 8.66784e-02,& - 1.58727e-01, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00,-3.67874e+02, 5.48158e-03, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 8.47001e-02, 1.70147e-01,& - 1.22631e-02, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00/ - data pe2/ & - 8.17187e-03, 3.71617e-05, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,-2.10826e-03,& - -3.13640e-03, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - -7.35742e-02,-5.00266e-02, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 1.94965e-02, 0.00000e+00, 0.00000e+00, 0.00000e+00/ - data pe3/ & - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00/ -! ar density - data pf1/ & - 1.04761e+00, 2.00165e-01, 2.37697e-01, 3.68552e-02, 0.00000e+00,& - 3.57202e-02,-2.14075e-01, 0.00000e+00,-1.08018e-01,-3.73981e-01,& - 0.00000e+00, 3.10022e-02,-1.16305e-03,-2.07596e+01, 0.00000e+00,& - 8.64502e-02, 0.00000e+00, 9.74908e+01, 5.16707e-02, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 8.66784e-02,& - 1.58727e-01, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 3.46193e+02, 1.34297e-02, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,-3.48509e-03,& - -1.54689e-04, 0.00000e+00, 0.00000e+00, 8.47001e-02, 1.70147e-01,& - 1.47753e-02, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00/ - data pf2/ & - 1.89320e-02, 3.68181e-05, 1.32570e-02, 0.00000e+00, 0.00000e+00,& - 3.59719e-03, 7.44328e-03,-1.00023e-03,-6.50528e+03, 0.00000e+00,& - 1.03485e-02,-1.00983e-03,-4.06916e-03,-6.60864e+01,-1.71533e-02,& - 1.10605e-02, 1.20300e-02,-5.20034e-03, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - -2.62769e+03, 7.13755e-03, 4.17999e-03, 0.00000e+00, 1.25910e+04,& - 0.00000e+00, 0.00000e+00, 0.00000e+00,-2.23595e-03, 4.60217e-03,& - 5.71794e-03, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - -3.18353e-02,-2.35526e-02,-1.36189e-02, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 2.03522e-02,-6.67837e+01,-1.09724e-03, 0.00000e+00/ - data pf3/ & - -1.38821e-02, 1.60468e-02, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 1.51574e-02,& - -5.44470e-04, 0.00000e+00, 7.28224e-02, 6.59413e-02, 0.00000e+00,& - -5.15692e-03, 0.00000e+00, 0.00000e+00,-3.70367e+03, 0.00000e+00,& - 0.00000e+00, 1.36131e-02, 5.38153e-03, 0.00000e+00, 4.76285e+00,& - -1.75677e-02, 2.26301e-02, 0.00000e+00, 1.76631e-02, 4.77162e-03,& - 0.00000e+00, 5.39354e+00, 0.00000e+00,-7.51710e-03, 0.00000e+00,& - 0.00000e+00,-8.82736e+01, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00/ -! h density - data pg1/ & - 1.26376e+00,-2.14304e-01,-1.49984e-01, 2.30404e-01, 2.98237e-02,& - 2.68673e-02, 2.96228e-01, 2.21900e-02,-2.07655e-02, 4.52506e-01,& - 1.20105e-01, 3.24420e-02, 4.24816e-02,-9.14313e+00, 0.00000e+00,& - 2.47178e-02,-2.88229e-02, 8.12805e+01, 5.10380e-02,-5.80611e-03,& - 2.51236e-05,-1.24083e-02, 0.00000e+00, 0.00000e+00, 8.66784e-02,& - 1.58727e-01,-3.48190e-02, 0.00000e+00, 0.00000e+00, 2.89885e-05,& - 0.00000e+00, 1.53595e+02,-1.68604e-02, 0.00000e+00, 1.01015e-02,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 2.84552e-04,& - -1.22181e-03, 0.00000e+00, 0.00000e+00, 8.47001e-02, 1.70147e-01,& - -1.04927e-02, 0.00000e+00, 0.00000e+00, 0.00000e+00,-5.91313e-03/ - data pg2/ & - -2.30501e-02, 3.14758e-05, 0.00000e+00, 0.00000e+00, 1.26956e-02,& - 8.35489e-03, 3.10513e-04, 0.00000e+00, 3.42119e+03,-2.45017e-03,& - -4.27154e-04, 5.45152e-04, 1.89896e-03, 2.89121e+01,-6.49973e-03,& - -1.93855e-02,-1.48492e-02, 0.00000e+00,-5.10576e-02, 7.87306e-02,& - 9.51981e-02,-1.49422e+04, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 2.65503e+02, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 6.37110e-03, 3.24789e-04,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 6.14274e-02, 1.00376e-02,-8.41083e-04, 0.00000e+00, 0.00000e+00,& - 0.00000e+00,-1.27099e-02, 0.00000e+00, 0.00000e+00, 0.00000e+00/ - data pg3/ & - -3.94077e-03,-1.28601e-02,-7.97616e-03, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00,-6.71465e-03,-1.69799e-03, 1.93772e-03, 3.81140e+00,& - -7.79290e-03,-1.82589e-02,-1.25860e-02,-1.04311e-02,-3.02465e-03,& - 2.43063e-03, 3.63237e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00/ -! n density - data ph1/ & - 7.09557e+01,-3.26740e-01, 0.00000e+00,-5.16829e-01,-1.71664e-03,& - 9.09310e-02,-6.71500e-01,-1.47771e-01,-9.27471e-02,-2.30862e-01,& - -1.56410e-01, 1.34455e-02,-1.19717e-01, 2.52151e+00, 0.00000e+00,& - -2.41582e-01, 5.92939e-02, 4.39756e+00, 9.15280e-02, 4.41292e-03,& - 0.00000e+00, 8.66807e-03, 0.00000e+00, 0.00000e+00, 8.66784e-02,& - 1.58727e-01, 9.74701e-02, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 6.70217e+01,-1.31660e-03, 0.00000e+00,-1.65317e-02,& - 0.00000e+00, 0.00000e+00, 8.50247e-02, 2.77428e+01, 4.98658e-03,& - 6.15115e-03, 9.50156e-03,-2.12723e-02, 8.47001e-02, 1.70147e-01,& - -2.38645e-02, 0.00000e+00, 0.00000e+00, 0.00000e+00, 1.37380e-03/ - data ph2/ & - -8.41918e-03, 2.80145e-05, 7.12383e-03, 0.00000e+00,-1.66209e-02,& - 1.03533e-04,-1.68898e-02, 0.00000e+00, 3.64526e+03, 0.00000e+00,& - 6.54077e-03, 3.69130e-04, 9.94419e-04, 8.42803e+01,-1.16124e-02,& - -7.74414e-03,-1.68844e-03, 1.42809e-03,-1.92955e-03, 1.17225e-01,& - -2.41512e-02, 1.50521e+04, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 1.60261e+03, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00,-3.54403e-04,-1.87270e-02,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 2.76439e-02, 6.43207e-03,-3.54300e-02, 0.00000e+00, 0.00000e+00,& - 0.00000e+00,-2.80221e-02, 8.11228e+01,-6.75255e-04, 0.00000e+00/ - data ph3/ & - -1.05162e-02,-3.48292e-03,-6.97321e-03, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00,-1.45546e-03,-1.31970e-02,-3.57751e-03,-1.09021e+00,& - -1.50181e-02,-7.12841e-03,-6.64590e-03,-3.52610e-03,-1.87773e-02,& - -2.22432e-03,-3.93895e-01, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00/ -! hot o density - data pi1/ & - 6.04050e-02, 1.57034e+00, 2.99387e-02, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,-1.51018e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00,-8.61650e+00, 1.26454e-02,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 5.50878e-03, 0.00000e+00, 0.00000e+00, 8.66784e-02,& - 1.58727e-01, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 6.23881e-02, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 8.47001e-02, 1.70147e-01,& - -9.45934e-02, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00/ - data pi2/ & - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00/ - data pi3/ & - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00/ -! s param - data pj1/ & - 9.56827e-01, 6.20637e-02, 3.18433e-02, 0.00000e+00, 0.00000e+00,& - 3.94900e-02, 0.00000e+00, 0.00000e+00,-9.24882e-03,-7.94023e-03,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 1.74712e+02, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 2.74677e-03, 0.00000e+00, 1.54951e-02, 8.66784e-02,& - 1.58727e-01, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00,-6.99007e-04, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 1.24362e-02,-5.28756e-03, 8.47001e-02, 1.70147e-01,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00/ - data pj2/ & - 0.00000e+00, 2.47425e-05, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00/ - data pj3/ & - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00/ -! turbo - data pk1/ & - 1.09930e+00, 3.90631e+00, 3.07165e+00, 9.86161e-01, 1.63536e+01,& - 4.63830e+00, 1.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 1.28840e+00, 3.10302e-02, 1.18339e-01,& - 1.00000e+00, 7.00000e-01, 1.15020e+00, 3.44689e+00, 1.28840e+00,& - 1.00000e+00, 1.08738e+00, 1.22947e+00, 1.10016e+00, 7.34129e-01,& - 1.15241e+00, 2.22784e+00, 7.95046e-01, 4.01612e+00, 4.47749e+00,& - 1.23435e+02,-7.60535e-02, 1.68986e-06, 7.44294e-01, 1.03604e+00,& - 1.72783e+02, 1.15020e+00, 3.44689e+00,-7.46230e-01, 9.49154e-01/ -! lower boundary - data ptm/ & - 1.04130e+03, 3.86000e+02, 1.95000e+02, 1.66728e+01, 2.13000e+02,& - 1.20000e+02, 2.40000e+02, 1.87000e+02,-2.00000e+00, 0.00000e+00/ - data pdm/ & - 2.45600e+07, 6.71072e-06, 1.00000e+02, 0.00000e+00, 1.10000e+02,& - 1.00000e+01, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 8.59400e+10, 1.00000e+00, 1.05000e+02,-8.00000e+00, 1.10000e+02,& - 1.00000e+01, 9.00000e+01, 2.00000e+00, 0.00000e+00, 0.00000e+00,& - 2.81000e+11, 0.00000e+00, 1.05000e+02, 2.80000e+01, 2.89500e+01,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 3.30000e+10, 2.68270e-01, 1.05000e+02, 1.00000e+00, 1.10000e+02,& - 1.00000e+01, 1.10000e+02,-1.00000e+01, 0.00000e+00, 0.00000e+00,& - 1.33000e+09, 1.19615e-02, 1.05000e+02, 0.00000e+00, 1.10000e+02,& - 1.00000e+01, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 1.76100e+05, 1.00000e+00, 9.50000e+01,-8.00000e+00, 1.10000e+02,& - 1.00000e+01, 9.00000e+01, 2.00000e+00, 0.00000e+00, 0.00000e+00,& - 1.00000e+07, 1.00000e+00, 1.05000e+02,-8.00000e+00, 1.10000e+02,& - 1.00000e+01, 9.00000e+01, 2.00000e+00, 0.00000e+00, 0.00000e+00,& - 1.00000e+06, 1.00000e+00, 1.05000e+02,-8.00000e+00, 5.50000e+02,& - 7.60000e+01, 9.00000e+01, 2.00000e+00, 0.00000e+00, 4.00000e+03/ -! tn1(2) - data pl1/ & - 1.00858e+00, 4.56011e-02,-2.22972e-02,-5.44388e-02, 5.23136e-04,& - -1.88849e-02, 5.23707e-02,-9.43646e-03, 6.31707e-03,-7.80460e-02,& - -4.88430e-02, 0.00000e+00, 0.00000e+00,-7.60250e+00, 0.00000e+00,& - -1.44635e-02,-1.76843e-02,-1.21517e+02, 2.85647e-02, 0.00000e+00,& - 0.00000e+00, 6.31792e-04, 0.00000e+00, 5.77197e-03, 8.66784e-02,& - 1.58727e-01, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00,-8.90272e+03, 3.30611e-03, 3.02172e-03, 0.00000e+00,& - -2.13673e-03,-3.20910e-04, 0.00000e+00, 0.00000e+00, 2.76034e-03,& - 2.82487e-03,-2.97592e-04,-4.21534e-03, 8.47001e-02, 1.70147e-01,& - 8.96456e-03, 0.00000e+00,-1.08596e-02, 0.00000e+00, 0.00000e+00/ - data pl2/ & - 5.57917e-03, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 9.65405e-03, 0.00000e+00, 0.00000e+00, 2.00000e+00/ -! tn1(3) - data pm1/ & - 9.39664e-01, 8.56514e-02,-6.79989e-03, 2.65929e-02,-4.74283e-03,& - 1.21855e-02,-2.14905e-02, 6.49651e-03,-2.05477e-02,-4.24952e-02,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 1.19148e+01, 0.00000e+00,& - 1.18777e-02,-7.28230e-02,-8.15965e+01, 1.73887e-02, 0.00000e+00,& - 0.00000e+00, 0.00000e+00,-1.44691e-02, 2.80259e-04, 8.66784e-02,& - 1.58727e-01, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 2.16584e+02, 3.18713e-03, 7.37479e-03, 0.00000e+00,& - -2.55018e-03,-3.92806e-03, 0.00000e+00, 0.00000e+00,-2.89757e-03,& - -1.33549e-03, 1.02661e-03, 3.53775e-04, 8.47001e-02, 1.70147e-01,& - -9.17497e-03, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00/ - data pm2/ & - 3.56082e-03, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00,-1.00902e-02, 0.00000e+00, 0.00000e+00, 2.00000e+00/ -! tn1(4) - data pn1/ & - 9.85982e-01,-4.55435e-02, 1.21106e-02, 2.04127e-02,-2.40836e-03,& - 1.11383e-02,-4.51926e-02, 1.35074e-02,-6.54139e-03, 1.15275e-01,& - 1.28247e-01, 0.00000e+00, 0.00000e+00,-5.30705e+00, 0.00000e+00,& - -3.79332e-02,-6.24741e-02, 7.71062e-01, 2.96315e-02, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 6.81051e-03,-4.34767e-03, 8.66784e-02,& - 1.58727e-01, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 1.07003e+01,-2.76907e-03, 4.32474e-04, 0.00000e+00,& - 1.31497e-03,-6.47517e-04, 0.00000e+00,-2.20621e+01,-1.10804e-03,& - -8.09338e-04, 4.18184e-04, 4.29650e-03, 8.47001e-02, 1.70147e-01,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00/ - data pn2/ & - -4.04337e-03, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,-9.52550e-04,& - 8.56253e-04, 4.33114e-04, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 1.21223e-03,& - 2.38694e-04, 9.15245e-04, 1.28385e-03, 8.67668e-04,-5.61425e-06,& - 1.04445e+00, 3.41112e+01, 0.00000e+00,-8.40704e-01,-2.39639e+02,& - 7.06668e-01,-2.05873e+01,-3.63696e-01, 2.39245e+01, 0.00000e+00,& - -1.06657e-03,-7.67292e-04, 1.54534e-04, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 2.00000e+00/ -! tn1(5) tn2(1) - data po1/ & - 1.00320e+00, 3.83501e-02,-2.38983e-03, 2.83950e-03, 4.20956e-03,& - 5.86619e-04, 2.19054e-02,-1.00946e-02,-3.50259e-03, 4.17392e-02,& - -8.44404e-03, 0.00000e+00, 0.00000e+00, 4.96949e+00, 0.00000e+00,& - -7.06478e-03,-1.46494e-02, 3.13258e+01,-1.86493e-03, 0.00000e+00,& - -1.67499e-02, 0.00000e+00, 0.00000e+00, 5.12686e-04, 8.66784e-02,& - 1.58727e-01,-4.64167e-03, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 4.37353e-03,-1.99069e+02, 0.00000e+00,-5.34884e-03, 0.00000e+00,& - 1.62458e-03, 2.93016e-03, 2.67926e-03, 5.90449e+02, 0.00000e+00,& - 0.00000e+00,-1.17266e-03,-3.58890e-04, 8.47001e-02, 1.70147e-01,& - 0.00000e+00, 0.00000e+00, 1.38673e-02, 0.00000e+00, 0.00000e+00/ - data po2/ & - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 1.60571e-03,& - 6.28078e-04, 5.05469e-05, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,-1.57829e-03,& - -4.00855e-04, 5.04077e-05,-1.39001e-03,-2.33406e-03,-4.81197e-04,& - 1.46758e+00, 6.20332e+00, 0.00000e+00, 3.66476e-01,-6.19760e+01,& - 3.09198e-01,-1.98999e+01, 0.00000e+00,-3.29933e+02, 0.00000e+00,& - -1.10080e-03,-9.39310e-05, 1.39638e-04, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 2.00000e+00/ -! tn2(2) - data pp1/ & - 9.81637e-01,-1.41317e-03, 3.87323e-02, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,-3.58707e-02,& - -8.63658e-03, 0.00000e+00, 0.00000e+00,-2.02226e+00, 0.00000e+00,& - -8.69424e-03,-1.91397e-02, 8.76779e+01, 4.52188e-03, 0.00000e+00,& - 2.23760e-02, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00,-7.07572e-03, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - -4.11210e-03, 3.50060e+01, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00,-8.36657e-03, 1.61347e+01, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00,-1.45130e-02, 0.00000e+00, 0.00000e+00/ - data pp2/ & - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 1.24152e-03,& - 6.43365e-04, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 1.33255e-03,& - 2.42657e-03, 1.60666e-03,-1.85728e-03,-1.46874e-03,-4.79163e-06,& - 1.22464e+00, 3.53510e+01, 0.00000e+00, 4.49223e-01,-4.77466e+01,& - 4.70681e-01, 8.41861e+00,-2.88198e-01, 1.67854e+02, 0.00000e+00,& - 7.11493e-04, 6.05601e-04, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 2.00000e+00/ -! tn2(3) - data pq1/ & - 1.00422e+00,-7.11212e-03, 5.24480e-03, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,-5.28914e-02,& - -2.41301e-02, 0.00000e+00, 0.00000e+00,-2.12219e+01,-1.03830e-02,& - -3.28077e-03, 1.65727e-02, 1.68564e+00,-6.68154e-03, 0.00000e+00,& - 1.45155e-02, 0.00000e+00, 8.42365e-03, 0.00000e+00, 0.00000e+00,& - 0.00000e+00,-4.34645e-03, 0.00000e+00, 0.00000e+00, 2.16780e-02,& - 0.00000e+00,-1.38459e+02, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 7.04573e-03,-4.73204e+01, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 1.08767e-02, 0.00000e+00, 0.00000e+00/ - data pq2/ & - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,-8.08279e-03,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 5.21769e-04,& - -2.27387e-04, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 3.26769e-03,& - 3.16901e-03, 4.60316e-04,-1.01431e-04, 1.02131e-03, 9.96601e-04,& - 1.25707e+00, 2.50114e+01, 0.00000e+00, 4.24472e-01,-2.77655e+01,& - 3.44625e-01, 2.75412e+01, 0.00000e+00, 7.94251e+02, 0.00000e+00,& - 2.45835e-03, 1.38871e-03, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 2.00000e+00/ -! tn2(4) tn3(1) - data pr1/ & - 1.01890e+00,-2.46603e-02, 1.00078e-02, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,-6.70977e-02,& - -4.02286e-02, 0.00000e+00, 0.00000e+00,-2.29466e+01,-7.47019e-03,& - 2.26580e-03, 2.63931e-02, 3.72625e+01,-6.39041e-03, 0.00000e+00,& - 9.58383e-03, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00,-1.85291e-03, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 1.39717e+02, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 9.19771e-03,-3.69121e+02, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00,-1.57067e-02, 0.00000e+00, 0.00000e+00/ - data pr2/ & - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,-7.07265e-03,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,-2.92953e-03,& - -2.77739e-03,-4.40092e-04, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 2.47280e-03,& - 2.95035e-04,-1.81246e-03, 2.81945e-03, 4.27296e-03, 9.78863e-04,& - 1.40545e+00,-6.19173e+00, 0.00000e+00, 0.00000e+00,-7.93632e+01,& - 4.44643e-01,-4.03085e+02, 0.00000e+00, 1.15603e+01, 0.00000e+00,& - 2.25068e-03, 8.48557e-04,-2.98493e-04, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 2.00000e+00/ -! tn3(2) - data ps1/ & - 9.75801e-01, 3.80680e-02,-3.05198e-02, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 3.85575e-02,& - 5.04057e-02, 0.00000e+00, 0.00000e+00,-1.76046e+02, 1.44594e-02,& - -1.48297e-03,-3.68560e-03, 3.02185e+01,-3.23338e-03, 0.00000e+00,& - 1.53569e-02, 0.00000e+00,-1.15558e-02, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 4.89620e-03, 0.00000e+00, 0.00000e+00,-1.00616e-02,& - -8.21324e-03,-1.57757e+02, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 6.63564e-03, 4.58410e+01, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00,-2.51280e-02, 0.00000e+00, 0.00000e+00/ - data ps2/ & - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 9.91215e-03,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,-8.73148e-04,& - -1.29648e-03,-7.32026e-05, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,-4.68110e-03,& - -4.66003e-03,-1.31567e-03,-7.39390e-04, 6.32499e-04,-4.65588e-04,& - -1.29785e+00,-1.57139e+02, 0.00000e+00, 2.58350e-01,-3.69453e+01,& - 4.10672e-01, 9.78196e+00,-1.52064e-01,-3.85084e+03, 0.00000e+00,& - -8.52706e-04,-1.40945e-03,-7.26786e-04, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 2.00000e+00/ -! tn3(3) - data pu1/ & - 9.60722e-01, 7.03757e-02,-3.00266e-02, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 2.22671e-02,& - 4.10423e-02, 0.00000e+00, 0.00000e+00,-1.63070e+02, 1.06073e-02,& - 5.40747e-04, 7.79481e-03, 1.44908e+02, 1.51484e-04, 0.00000e+00,& - 1.97547e-02, 0.00000e+00,-1.41844e-02, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 5.77884e-03, 0.00000e+00, 0.00000e+00, 9.74319e-03,& - 0.00000e+00,-2.88015e+03, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00,-4.44902e-03,-2.92760e+01, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 2.34419e-02, 0.00000e+00, 0.00000e+00/ - data pu2/ & - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 5.36685e-03,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,-4.65325e-04,& - -5.50628e-04, 3.31465e-04, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,-2.06179e-03,& - -3.08575e-03,-7.93589e-04,-1.08629e-04, 5.95511e-04,-9.05050e-04,& - 1.18997e+00, 4.15924e+01, 0.00000e+00,-4.72064e-01,-9.47150e+02,& - 3.98723e-01, 1.98304e+01, 0.00000e+00, 3.73219e+03, 0.00000e+00,& - -1.50040e-03,-1.14933e-03,-1.56769e-04, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 2.00000e+00/ -! tn3(4) - data pv1/ & - 1.03123e+00,-7.05124e-02, 8.71615e-03, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,-3.82621e-02,& - -9.80975e-03, 0.00000e+00, 0.00000e+00, 2.89286e+01, 9.57341e-03,& - 0.00000e+00, 0.00000e+00, 8.66153e+01, 7.91938e-04, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 4.68917e-03, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 7.86638e-03, 0.00000e+00, 0.00000e+00, 9.90827e-03,& - 0.00000e+00, 6.55573e+01, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00,-4.00200e+01, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 7.07457e-03, 0.00000e+00, 0.00000e+00/ - data pv2/ & - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 5.72268e-03,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,-2.04970e-04,& - 1.21560e-03,-8.05579e-06, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,-2.49941e-03,& - -4.57256e-04,-1.59311e-04, 2.96481e-04,-1.77318e-03,-6.37918e-04,& - 1.02395e+00, 1.28172e+01, 0.00000e+00, 1.49903e-01,-2.63818e+01,& - 0.00000e+00, 4.70628e+01,-2.22139e-01, 4.82292e-02, 0.00000e+00,& - -8.67075e-04,-5.86479e-04, 5.32462e-04, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 2.00000e+00/ -! tn3(5) surface temp tsl - data pw1/ & - 1.00828e+00,-9.10404e-02,-2.26549e-02, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,-2.32420e-02,& - -9.08925e-03, 0.00000e+00, 0.00000e+00, 3.36105e+01, 0.00000e+00,& - 0.00000e+00, 0.00000e+00,-1.24957e+01,-5.87939e-03, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 2.79765e+01, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 2.01237e+03, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00,-1.75553e-02, 0.00000e+00, 0.00000e+00/ - data pw2/ & - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 3.29699e-03,& - 1.26659e-03, 2.68402e-04, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 1.17894e-03,& - 1.48746e-03, 1.06478e-04, 1.34743e-04,-2.20939e-03,-6.23523e-04,& - 6.36539e-01, 1.13621e+01, 0.00000e+00,-3.93777e-01, 2.38687e+03,& - 0.00000e+00, 6.61865e+02,-1.21434e-01, 9.27608e+00, 0.00000e+00,& - 1.68478e-04, 1.24892e-03, 1.71345e-03, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 2.00000e+00/ -! tgn3(2) surface grad tslg - data px1/ & - 1.57293e+00,-6.78400e-01, 6.47500e-01, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,-7.62974e-02,& - -3.60423e-01, 0.00000e+00, 0.00000e+00, 1.28358e+02, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 4.68038e+01, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00,-1.67898e-01, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 2.90994e+04, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 3.15706e+01, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00/ - data px2/ & - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 2.00000e+00/ -! tgn2(1) tgn1(2) - data py1/ & - 8.60028e-01, 3.77052e-01, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,-1.17570e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 7.77757e-03, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 1.01024e+02, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 6.54251e+02, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00/ - data py2/ & - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,-1.56959e-02,& - 1.91001e-02, 3.15971e-02, 1.00982e-02,-6.71565e-03, 2.57693e-03,& - 1.38692e+00, 2.82132e-01, 0.00000e+00, 0.00000e+00, 3.81511e+02,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 2.00000e+00/ -! tgn3(1) tgn2(2) - data pz1/ & - 1.06029e+00,-5.25231e-02, 3.73034e-01, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 3.31072e-02,& - -3.88409e-01, 0.00000e+00, 0.00000e+00,-1.65295e+02,-2.13801e-01,& - -4.38916e-02,-3.22716e-01,-8.82393e+01, 1.18458e-01, 0.00000e+00,& - -4.35863e-01, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00,-1.19782e-01, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 2.62229e+01, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00,-5.37443e+01, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00,-4.55788e-01, 0.00000e+00, 0.00000e+00/ - data pz2/ & - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 3.84009e-02,& - 3.96733e-02, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 5.05494e-02,& - 7.39617e-02, 1.92200e-02,-8.46151e-03,-1.34244e-02, 1.96338e-02,& - 1.50421e+00, 1.88368e+01, 0.00000e+00, 0.00000e+00,-5.13114e+01,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 5.11923e-02, 3.61225e-02, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 2.00000e+00/ -! semiannual mult sam - data paa1/ & - 1.00000e+00, 1.00000e+00, 1.00000e+00, 1.00000e+00, 1.00000e+00,& - 1.00000e+00, 1.00000e+00, 1.00000e+00, 1.00000e+00, 1.00000e+00,& - 1.00000e+00, 1.00000e+00, 1.00000e+00, 1.00000e+00, 1.00000e+00,& - 1.00000e+00, 1.00000e+00, 1.00000e+00, 1.00000e+00, 1.00000e+00,& - 1.00000e+00, 1.00000e+00, 1.00000e+00, 1.00000e+00, 1.00000e+00,& - 1.00000e+00, 1.00000e+00, 1.00000e+00, 1.00000e+00, 1.00000e+00,& - 1.00000e+00, 1.00000e+00, 1.00000e+00, 1.00000e+00, 1.00000e+00,& - 1.00000e+00, 1.00000e+00, 1.00000e+00, 1.00000e+00, 1.00000e+00,& - 1.00000e+00, 1.00000e+00, 1.00000e+00, 1.00000e+00, 1.00000e+00,& - 1.00000e+00, 1.00000e+00, 1.00000e+00, 1.00000e+00, 1.00000e+00/ - data paa2/ & - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00,& - 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00, 0.00000e+00/ -! middle atmosphere averages - data pavgm/ & - 2.61000e+02, 2.64000e+02, 2.29000e+02, 2.17000e+02, 2.17000e+02,& - 2.23000e+02, 2.86760e+02,-2.93940e+00, 2.50000e+00, 0.00000e+00/ - end module wam_gtd7bk_mod - -!----------------------------------------------------------------------- -!> Use moduke for common blocks -!! -!! All variables under this module are originalyl in common block used -!! for subroutine gettemp and others in this package. -!! -!! @author Hann-Ming Henry Juang - module gettemp_mod -! - real :: tlb !< labeled temperature - real :: s !< scale inverse to temperature difference - real :: db04 !< diffusive density at zlb for g4 - real :: db16 !< diffusive density at zlb for g18 - real :: db28 !< diffusive density at zlb for g28 - real :: db32 !< diffusive density at zlb for g32 - real :: db40 !< diffusive density at zlb for g40 - real :: db48 !< diffusive density at zlb for g48 - real :: db01 !< diffusive density at zlb for g01 - real :: za !< joining altitude of bates and spline - real :: t0 !< initial temperature - real :: z0 !< initial height - real :: g0 !< initial gradient variations - real :: rl !< correction to specified mixing ratio at ground - real :: dd !< diffusive density at alt - real :: db14 !< diffusive density at zlb for g14 - real :: tr12 !< try factor 1 or 2 -! - real :: tn1(5) !< temperature at node 1 (~mesosphere) - real :: tn2(4) !< temperature at node 2 (~stratosphere) - real :: tn3(5) !< temperature at node 3 (~troposphere) - real :: tgn1(2) !< temperature gradient at node 1 (~mesosphere) - real :: tgn2(2) !< temperature gradient at node 2 (~stratosphere) - real :: tgn3(2) !< temperature gradient at node 3 (~troposphere) -! - real :: pt(150) !< temperature - real :: pd(150,9) !< he density - real :: ps(150) !< s parameter - real :: pdl(25,2) !< turbo - real :: ptl(100,4) !< upper temperature - real :: pma(100,10) !< middle and low temperature - real :: sam(100) !< semiannual mult sam -! - real :: sw(25) !< weighting - real :: swc(25) !< weighting -! - real :: dm04 !< mixed density at alt04 - real :: dm16 !< mixed density at alt16 - real :: dm28 !< mixed density at alt28 - real :: dm32 !< mixed density at alt32 - real :: dm40 !< mixed density at alt40 - real :: dm01 !< mixed density at alt01 - real :: dm14 !< mixed density at alt14 -! - real :: gsurf !< surface gravitation force at given latitude - real :: re !< referenced height related to gsurf -! - real :: tinfg !< startinf referenced point for tt - real :: tt(15) !< referenced temperature -! - real :: plg(9,4) !< Legendre polynomial points - real :: ctloc !< cosine of the location - real :: stloc !< sine of the location - real :: c2tloc !< cosine of 2 time location - real :: s2tloc !< sine of 2 time location - real :: c3tloc !< cosine of 3 time location - real :: s3tloc !< sine of 3 time location - real :: day !< day in a year - real :: df !< the difference of f10.7 effect - real :: dfa !< the difference to reference value - real :: apd !< parameter calcumate for magnetic activity - real :: apdf !< the same as apd - real :: apt(4) !< daily magnetic activity - real :: xlong !< a given longitude -! - integer :: isw !< indix for sw - integer :: iyr !< integer for a given year -! - end module gettemp_mod - -! ---------------------------------------------------------------------- -!> Entry routine to get WAM needed temperature and composition profiles. -!! -!! Calculate temperature at each grid point useing nrlmsise00_sub -!! @param[in] iday calendat date with array dimension of nday -!! @param[in] nday dimension length of iday -!! @param[in] xlat latitudes with dimension nlat -!! @param[in] nlat dimension length of xlat -!! @param[in] pr pressure in vertical with dimension of np -!! @param[in] np dimension length of pr -!! @param[out] temp temperature -!! @param[out] n_o single oxygen number -!! @param[out] n_o2 oxygen number -!! @param[out] n_n2 nitrogen number -!! -!! @author Hann-Ming Henry Juang NCEP/EMC - subroutine gettemp(iday,nday,xlat,nlat,pr,np,temp,n_o,n_o2,n_n2) - implicit none - integer, intent(in) :: nday ! number of days - integer, intent(in) :: nlat ! number of latitudes - integer, intent(in) :: np ! number of pressure layer - real, intent(in) :: pr(np) ! pressure in mb - real, intent(in) :: xlat(nlat) ! latitude in degree - integer, intent(in) :: iday(nday) ! calender day - real, intent(out) :: temp(np,nlat,nday) ! temperature - real, intent(out) :: n_o(np,nlat,nday) ! number density of o - real, intent(out) :: n_o2(np,nlat,nday) ! number density of o2 - real, intent(out) :: n_n2(np,nlat,nday) ! number density of n2 - real :: alt(np,nlat,nday) ! altitude in km - real :: d(9),t(2),sw(25),ap(7),ut,xlong,xlst,f107, & - f107a - integer :: k,il,ip -! set magnetic index average value - data ap/7*9./ -! set swich 7,8,10,14 zero to avoid diurnal changes in output temperatu -! swich #7 is for diurnal,#8 is for semidiurnal,# 10 is for all ut/longi -! effect,#14 is for terdiurnal - data sw/1.,1.,1.,1.,1.,1.,0.,0.,1.,0.,1.,1.,1.,0.,1.,1.,1.,1.,1., & - 1.,1.,1.,1.,1.,1./ -! set 10.7cm flux be average value - f107=150. - f107a=150. -! turn on swich - call tselec(sw) -! set longitude, ut, local time , it should not make difference to outpu - ut=0. - xlong=0. - xlst=ut/3600.+xlong/15. -! calculate temperature for each lat,pres level,day - do k=1,nday - do il=1,nlat - do ip=1,np - call ghp7(iday(k),ut,alt(ip,il,k),xlat(il),xlong,xlst,f107a,f107, & - ap,d,t,pr(ip)) - temp(ip,il,k)=t(2) - n_o(ip,il,k)=d(2) - n_o2(ip,il,k)=d(4) - n_n2(ip,il,k)=d(3) - enddo - enddo - enddo - end subroutine gettemp - -!----------------------------------------------------------------------- -!> The nrlmsise-00 subroutine gtd7. -!! -!! Neutral atmosphere empirical model from the surface to lower exosphere. -!! -!! New features: -!! Extensive satellite drag database used in model generation -!! Revised o2 (and o) in lower thermosphere -!! Additional nonlinear solar activity term -!! "anomalous oxygen" number density, output d(9) -!! at high altitudes (> 500 km), hot atomic oxygen or ionized -!! oxygen can become appreciable for some ranges of subroutine -!! inputs, thereby affecting drag on satellites and debris. we -!! group these species under the term "anomalous oxygen," since -!! their individual variations are not presently separable with -!! the drag data used to define this model component. -!! And d(6) is the sum of the mass densities of t -!! species labeled by indices 1-5 and 7-8 in output variable d. -!! this includes he, o, n2, o2, ar, h, and n but does not includ -!! anomalous oxygen (species index 9). -!! -!! Notes on input variables: -!! ut, local time, and longitude are used independently in the -!! model and are not of equal importance for every situation. -!! for the most physically realistic calculation these three -!! variables should be consistent (stl=sec/3600+glong/15). -!! the equation of time departures from the above formula -!! for apparent local time can be included if available but -!! are of minor importance. -!! -!! f107 and f107a values used to generate the model correspond -!! to the 10.7 cm radio flux at the actual distance of the earth -!! from the sun rather than the radio flux at 1 au. the following -!! site provides both classes of values: -!! ftp://ftp.ngdc.noaa.gov/stp/solar_data/solar_radio/flux/ -!! -!! f107, f107a, and ap effects are neither large nor well -!! established below 80 km and these parameters should be set to -!! 150., 150., and 4. respectively. -!! -!! Subroutines for special outputs: -!! High altitude drag: effective total mass density -!! (subroutine gtd7d, output d(6)) -!! for atmospheric drag calculations at altitudes above 500 km, -!! call subroutine gtd7d to compute the "effective total mass -!! density" by including contributions from "anomalous oxygen." -!! see "notes on output variables" below on d(6). -!! Pressure grid (subroutine ghp7) -!! see subroutine ghp7 to specify outputs at a pressure level -!! rather than at an altitude. -!! Output in m-3 and kg/m3: call meters(.true.) -!! -!! Notes on output variables: -!! To get output in m-3 and kg/m3: call meters(.true.) -!! o, h, and n are set to zero below 72.5 km -!! t(1), exospheric temperature, is set to global average for -!! altitudes below 120 km. the 120 km gradient is left at global -!! average value for altitudes below 72 km. -!! d(6), total mass density, is not the same for subroutines gtd7 -!! and gtd7d -!! -!! -!! Switches: the following is for test and special purposes: -!! To turn on and off particular variations call tselec(sw), -!! where sw is a 25 element array containing 0. for off, 1. -!! for on, or 2. for main effects off but cross terms on -!! for the following variations -!! 1 f10.7 effect on mean -!! 2 time independent -!! 3 symmetrical annual -!! 4 symmetrical semiannual -!! 5 asymmetrical annual -!! 6 asymmetrical semiannual -!! 7 diurnal -!! 8 semidiurnal -!! 9 daily ap -!! 10 all ut/long effects -!! 11 longitudinal -!! 12 ut and mixed ut/long -!! 13 mixed ap/ut/long -!! 14 terdiurnal -!! 15 departures from diffusive equilibrium -!! 16 all tinf var -!! 17 all tlb var -!! 18 all tn1 var -!! 19 all s var -!! 20 all tn2 var -!! 21 all nlb var -!! 22 all tn3 var -!! 23 turbo scale height var -!! -!! @param[in] iyd year and day as yyddd (day of year from 1 to 365 or 366) -!! @param[in] sec ut(sec) -!! @param[in] alt altitude(km) -!! @param[in] glat geodetic latitude(deg) -!! @param[in] glong geodetic longitude(deg) -!! @param[in] stl local apparent solar time(hrs; see note below) -!! @param[in] f107a 81 day average of f10.7 flux (centered on day ddd) -!! @param[in] f107 daily f10.7 flux for previous day -!! @param[in] ap magnetic index(daily) or when sw(9)=-1. : -!! array containing: -!! ap(1) daily ap -!! ap(2) 3 hr ap index for current time -!! ap(3) 3 hr ap index for 3 hrs before current time -!! ap(4) 3 hr ap index for 6 hrs before current time -!! ap(5) 3 hr ap index for 9 hrs before current time -!! ap(6) average of eight 3 hr ap indicies from 12 to 33 hrs pr -!! to current time -!! ap(7) average of eight 3 hr ap indicies from 36 to 57 hrs pr -!! to current time -!! @param[in] mass mass number (only density for selected gas is -!! calculated. mass 0 is temperature. mass 48 for all. -!! mass 17 is anomalous o only.) -!! -!! @param[out] d size of 9 with following definition. -!! d(1) he number density(cm-3) -!! d(2) o number density(cm-3) -!! d(3) n2 number density(cm-3) -!! d(4) o2 number density(cm-3) -!! d(5) ar number density(cm-3) -!! d(6) total mass density(gm/cm3) -!! d(7) h number density(cm-3) -!! d(8) n number density(cm-3) -!! d(9) anomalous oxygen number density(cm-3) -!! @param[out] t - size of 2 array with following definition. -!! t(1) exospheric temperature -!! t(2) temperature at alt -!! -!! @author Hann-Ming Henry Juang - subroutine gtd7(iyd,sec,alt,glat,glong,stl,f107a,f107,ap,mass,d,t) - use wam_gtd7bk_mod - use gettemp_mod, only: dd, tn1,tn2,tn3,tgn1,tgn2,tgn3, & - pt,pd,ps,pdl,ptl,pma,sam,sw,isw,& - dm28,gsurf,re - - dimension d(9),t(2),ap(7),ds(9),ts(2) - dimension zn3(5),zn2(4),sv(25) -! - save - data mn3/5/,zn3/32.5,20.,15.,10.,0./ - data mn2/4/,zn2/72.5,55.,45.,32.5/ - data zmix/62.5/,alast/99999./,mssl/-999/ - data sv/25*1./ -! ==== assign common/parm7/ - pt(1:50) =pt1(1:50); pt(51:100) =pt2(1:50); pt(101:150) =pt3(1:50) - pd(1:50,1)=pa1(1:50); pd(51:100,1)=pa2(1:50); pd(101:150,1)=pa3(1:50) - pd(1:50,2)=pb1(1:50); pd(51:100,2)=pb2(1:50); pd(101:150,2)=pb3(1:50) - pd(1:50,3)=pc1(1:50); pd(51:100,3)=pc2(1:50); pd(101:150,3)=pc3(1:50) - pd(1:50,4)=pd1(1:50); pd(51:100,4)=pd2(1:50); pd(101:150,4)=pd3(1:50) - pd(1:50,5)=pe1(1:50); pd(51:100,5)=pe2(1:50); pd(101:150,5)=pe3(1:50) - pd(1:50,6)=pf1(1:50); pd(51:100,6)=pf2(1:50); pd(101:150,6)=pf3(1:50) - pd(1:50,7)=pg1(1:50); pd(51:100,7)=pg2(1:50); pd(101:150,7)=pg3(1:50) - pd(1:50,8)=ph1(1:50); pd(51:100,8)=ph2(1:50); pd(101:150,8)=ph3(1:50) - pd(1:50,9)=pi1(1:50); pd(51:100,9)=pi2(1:50); pd(101:150,9)=pi3(1:50) - ps(1:50) =pj1(1:50); ps(51:100) =pj2(1:50); ps(101:150) =pj3(1:50) - pdl(1:25,1)=pk1(1:25); pdl(1:25,2)=pk1(26:50) - ptl(1:50,1)=pl1(1:50); ptl(51:100,1)=pl2(1:50) - ptl(1:50,2)=pm1(1:50); ptl(51:100,2)=pm2(1:50) - ptl(1:50,3)=pn1(1:50); ptl(51:100,3)=pn2(1:50) - ptl(1:50,4)=po1(1:50); ptl(51:100,4)=po2(1:50) - pma(1:50,1)=pp1(1:50); pma(51:100,1)=pp2(1:50) - pma(1:50,2)=pq1(1:50); pma(51:100,2)=pq2(1:50) - pma(1:50,3)=pr1(1:50); pma(51:100,3)=pr2(1:50) - pma(1:50,4)=ps1(1:50); pma(51:100,4)=ps2(1:50) - pma(1:50,5)=pu1(1:50); pma(51:100,5)=pu2(1:50) - pma(1:50,6)=pv1(1:50); pma(51:100,6)=pv2(1:50) - pma(1:50,7)=pw1(1:50); pma(51:100,7)=pw2(1:50) - pma(1:50,8)=px1(1:50); pma(51:100,8)=px2(1:50) - pma(1:50,9)=py1(1:50); pma(51:100,9)=py2(1:50) - pma(1:50,10)=pz1(1:50); pma(51:100,10)=pz2(1:50) - sam(1:50)=paa1(1:50); sam(51:100)=paa2(1:50) -! - if(isw.ne.64999) call tselec(sv) -! -! test for changed input - v1=vtst7(iyd,sec,glat,glong,stl,f107a,f107,ap,1) -! latitude variation of gravity (none for sw(2)=0) - xlat=glat - if(sw(2).eq.0) xlat=45. - call glatf(xlat,gsurf,re) -! - xmm=pdm(5,3) -! -! thermosphere/mesosphere (above zn2(1)) - altt=amax1(alt,zn2(1)) - mss=mass -! only calculate n2 in thermosphere if alt in mixed region - if(alt.lt.zmix.and.mass.gt.0) mss=28 -! only calculate thermosphere if input parameters changed -! or altitude above zn2(1) in mesosphere - if(v1.eq.1..or.alt.gt.zn2(1).or.alast.gt.zn2(1).or.mss.ne.mssl) then - call gts7(iyd,sec,altt,glat,glong,stl,f107a,f107,ap,mss,ds,ts) - dm28m=dm28 -! metric adjustment - if(imr.eq.1) dm28m=dm28*1.e6 - mssl=mss - endif - t(1)=ts(1) - t(2)=ts(2) - if(alt.ge.zn2(1)) then - do 5 j=1,9 - d(j)=ds(j) - 5 continue - goto 10 - endif -! -! lower mesosphere/upper stratosphere [between zn3(1) and zn2(1)] -! temperature at nodes and gradients at end nodes -! inverse temperature a linear function of spherical harmonics -! only calculate nodes if input changed - if(v1.eq.1..or.alast.ge.zn2(1)) then - tgn2(1)=tgn1(2) - tn2(1)=tn1(5) - tn2(2)=pma(1,1)*pavgm(1)/(1.-sw(20)*glob7s(pma(1,1))) - tn2(3)=pma(1,2)*pavgm(2)/(1.-sw(20)*glob7s(pma(1,2))) - tn2(4)=pma(1,3)*pavgm(3)/(1.-sw(20)*sw(22)*glob7s(pma(1,3))) - tgn2(2)=pavgm(9)*pma(1,10)*(1.+sw(20)*sw(22)*glob7s(pma(1,10))) & - *tn2(4)*tn2(4)/(pma(1,3)*pavgm(3))**2 - tn3(1)=tn2(4) - endif - if(alt.ge.zn3(1)) goto 6 -! -! lower stratosphere and troposphere [below zn3(1)] -! temperature at nodes and gradients at end nodes -! inverse temperature a linear function of spherical harmonics -! only calculate nodes if input changed - if(v1.eq.1..or.alast.ge.zn3(1)) then - tgn3(1)=tgn2(2) - tn3(2)=pma(1,4)*pavgm(4)/(1.-sw(22)*glob7s(pma(1,4))) - tn3(3)=pma(1,5)*pavgm(5)/(1.-sw(22)*glob7s(pma(1,5))) - tn3(4)=pma(1,6)*pavgm(6)/(1.-sw(22)*glob7s(pma(1,6))) - tn3(5)=pma(1,7)*pavgm(7)/(1.-sw(22)*glob7s(pma(1,7))) - tgn3(2)=pma(1,8)*pavgm(8)*(1.+sw(22)*glob7s(pma(1,8))) & - *tn3(5)*tn3(5)/(pma(1,7)*pavgm(7))**2 - endif - 6 continue - if(mass.eq.0) goto 50 -! linear transition to full mixing below zn2(1) - dmc=0 - if(alt.gt.zmix) dmc=1.-(zn2(1)-alt)/(zn2(1)-zmix) - dz28=ds(3) -! ***** n2 density **** - dmr=ds(3)/dm28m-1. - d(3)=densm(alt,dm28m,xmm,tz,mn3,zn3,tn3,tgn3,mn2,zn2,tn2,tgn2) - d(3)=d(3)*(1.+dmr*dmc) -! ***** he density **** - d(1)=0 - if(mass.ne.4.and.mass.ne.48) goto 204 - dmr=ds(1)/(dz28*pdm(2,1))-1. - d(1)=d(3)*pdm(2,1)*(1.+dmr*dmc) - 204 continue -! **** o density **** - d(2)=0 - d(9)=0 - 216 continue -! ***** o2 density **** - d(4)=0 - if(mass.ne.32.and.mass.ne.48) goto 232 - dmr=ds(4)/(dz28*pdm(2,4))-1. - d(4)=d(3)*pdm(2,4)*(1.+dmr*dmc) - 232 continue -! ***** ar density **** - d(5)=0 - if(mass.ne.40.and.mass.ne.48) goto 240 - dmr=ds(5)/(dz28*pdm(2,5))-1. - d(5)=d(3)*pdm(2,5)*(1.+dmr*dmc) - 240 continue -! ***** hydrogen density **** - d(7)=0 -! ***** atomic nitrogen density **** - d(8)=0 -! -! total mass density -! - if(mass.eq.48) then - d(6) = 1.66e-24*(4.*d(1)+16.*d(2)+28.*d(3)+32.*d(4)+40.*d(5)+ & - d(7)+14.*d(8)) - if(imr.eq.1) d(6)=d(6)/1000. - endif - t(2)=tz - 10 continue - goto 90 - 50 continue - dd=densm(alt,1.,0.,tz,mn3,zn3,tn3,tgn3,mn2,zn2,tn2,tgn2) - t(2)=tz - 90 continue - alast=alt - return - end subroutine gtd7 - -!----------------------------------------------------------------------- -!> The nrlmsise-00 subroutine gtd7d -!! -!! This subroutine provides effective total mass density for -!! output d(6) which includes contributions from "anomalous -!! oxygen" which can affect satellite drag above 500 km. this -!! subroutine is part of the distribution package for the -!! neutral atmosphere empirical model from the surface to lower -!! exosphere. see subroutine gtd7 for more extensive comments. -!! And d(6) is the "effective total mass density -!! for drag" and is the sum of the mass densities of all species -!! in this model, including anomalous oxygen. -!! -!! @param[in] iyd year and day as yyddd (day of year from 1 to 365 (or 366) -!! @param[in] sec ut(sec) -!! @param[in] alt altitude(km) -!! @param[in] glat geodetic latitude(deg) -!! @param[in] glong geodetic longitude(deg) -!! @param[in] stl local apparent solar time(hrs; see note below) -!! @param[in] f107a 81 day average of f10.7 flux (centered on day ddd) -!! @param[in] f107 daily f10.7 flux for previous day -!! @param[in] ap magnetic index(daily) or when sw(9)=-1. : -!! ap array containing: -!! ap(1) daily ap -!! ap(2) 3 hr ap index for current time -!! ap(3) 3 hr ap index for 3 hrs before current time -!! ap(4) 3 hr ap index for 6 hrs before current time -!! ap(5) 3 hr ap index for 9 hrs before current time -!! ap(6) average of eight 3 hr ap indicies from 12 to 33 hrs pr -!! to current time -!! ap(7) average of eight 3 hr ap indicies from 36 to 57 hrs pr -!! to current time -!! @param[in] mass mass number (only density for selected gas is -!! calculated. mass 0 is temperature. mass 48 for all. -!! mass 17 is anomalous o only.) -!! -!! @param[out] d density array with length of 9 -!! @param[out] t temperature array with length of 2 -!! d array contains: -!! d(1) he number density(cm-3) -!! d(2) o number density(cm-3) -!! d(3) n2 number density(cm-3) -!! d(4) o2 number density(cm-3) -!! d(5) ar number density(cm-3) -!! d(6) total mass density(gm/cm3) [includes anomalous oxygen] -!! d(7) h number density(cm-3) -!! d(8) n number density(cm-3) -!! d(9) anomalous oxygen number density(cm-3) -!! t array conyains: -!! t(1) exospheric temperature -!! t(2) temperature at alt -!! -!! @author Hann-Ming Henry Juang - subroutine gtd7d(iyd,sec,alt,glat,glong,stl,f107a,f107,ap,mass,d,t) - use wam_gtd7bk_mod, only: imr -! - dimension d(9),t(2),ap(7) - call gtd7(iyd,sec,alt,glat,glong,stl,f107a,f107,ap,mass,d,t) -! total mass density -! - if(mass.eq.48) then - d(6) = 1.66e-24*(4.*d(1)+16.*d(2)+28.*d(3)+32.*d(4)+40.*d(5)+ & - d(7)+14.*d(8)+16.*d(9)) - if(imr.eq.1) d(6)=d(6)/1000. - endif - return - end subroutine gtd7d - -!----------------------------------------------------------------------- -!> Find altitude of pressure surface (press) from gtd7 -!! -!! input: -!! @param[in] iyd year and day as yyddd -!! @param[in] sec ut(sec) -!! @param[in] glat geodetic latitude(deg) -!! @param[in] glong geodetic longitude(deg) -!! @param[in] stl local apparent solar time(hrs) -!! @param[in] f107a 3 month average of f10.7 flux -!! @param[in] f107 daily f10.7 flux for previous day -!! @param[in] ap magnetic index(daily) or when sw(9)=-1. : -!! array containing: -!! ap(1) daily ap -!! ap(2) 3 hr ap index for current time -!! ap(3) 3 hr ap index for 3 hrs before current time -!! ap(4) 3 hr ap index for 6 hrs before current time -!! ap(5) 3 hr ap index for 9 hrs before current time -!! ap(6) average of eight 3 hr ap indicies from 12 to 33 hrs pr -!! to current time -!! ap(7) average of eight 3 hr ap indicies from 36 to 59 hrs pr -!! to current time -!! @param[in] press pressure level(mb) -!! output: -!! @param[out] alt altitude(km) -!! @param[out] d density array with length of 8 -!! d(1) he number density(cm-3) -!! d(2) o number density(cm-3) -!! d(3) n2 number density(cm-3) -!! d(4) o2 number density(cm-3) -!! d(5) ar number density(cm-3) -!! d(6) total mass density(gm/cm3) -!! d(7) h number density(cm-3) -!! d(8) n number density(cm-3) -!! d(9) hot o number density(cm-3) -!! @param[out] t temperature array with length of 2 -!! t(1) exospheric temperature -!! t(2) temperature at alt -!! -!! @author Hann-Ming Henry Juang - subroutine ghp7(iyd,sec,alt,glat,glong,stl,f107a,f107,ap,d,t,press) - use gettemp_mod, only: gsurf,re - use wam_gtd7bk_mod, only: imr -! - dimension d(9),t(2),ap(7) - save - data bm/1.3806e-19/,rgas/831.4/ - data test/.00043/,ltest/12/ -!! bm=1.3806e-19; rgas=831.4 -!! test=.00043; ltest=12 - pl=alog10(press) -! initial altitude estimate - if(pl.ge.-5.) then - if(pl.gt.2.5) zi=18.06*(3.00-pl) - if(pl.gt..75.and.pl.le.2.5) zi=14.98*(3.08-pl) - if(pl.gt.-1..and.pl.le..75) zi=17.8*(2.72-pl) - if(pl.gt.-2..and.pl.le.-1.) zi=14.28*(3.64-pl) - if(pl.gt.-4..and.pl.le.-2.) zi=12.72*(4.32-pl) - if(pl.le.-4.) zi=25.3*(.11-pl) - iday=mod(iyd,1000) - cl=glat/90. - cl2=cl*cl - if(iday.lt.182) cd=1.-iday/91.25 - if(iday.ge.182) cd=iday/91.25-3. - ca=0 - if(pl.gt.-1.11.and.pl.le.-.23) ca=1.0 - if(pl.gt.-.23) ca=(2.79-pl)/(2.79+.23) - if(pl.le.-1.11.and.pl.gt.-3.) ca=(-2.93-pl)/(-2.93+1.11) - z=zi-4.87*cl*cd*ca-1.64*cl2*ca+.31*ca*cl - endif - if(pl.lt.-5.) z=22.*(pl+4.)**2+110 -! iteration loop - l=0 - 10 continue - l=l+1 - call gtd7(iyd,sec,z,glat,glong,stl,f107a,f107,ap,48,d,t) - xn=d(1)+d(2)+d(3)+d(4)+d(5)+d(7)+d(8) - p=bm*xn*t(2) - if(imr.eq.1) p=p*1.e-6 - diff=pl-alog10(p) - if(abs(diff).lt.test .or. l.eq.ltest) goto 20 - xm=d(6)/xn/1.66e-24 - if(imr.eq.1) xm = xm*1.e3 - g=gsurf/(1.+z/re)**2 - sh=rgas*t(2)/(xm*g) -! new altitude estimate using scale height - if(l.lt.6) then - z=z-sh*diff*2.302 - else - z=z-sh*diff - endif - goto 10 - 20 continue - if(l.eq.ltest) write(6,100) press,diff - 100 format(1x,29hghp7 not converging for press, 1pe12.2,e12.2) - alt=z - return - end subroutine ghp7 - -!----------------------------------------------------------------------- -!> Calculate latitude variable. -!! -!! @param[in] lat latitude in degree -!! @param[out] gv gravity -!! @param[out] reff effective radius -!! -!! @author Hann-Ming Henry Juang - subroutine glatf(lat,gv,reff) - real lat - save - data dgtr/1.74533e-2/ -!! dgtr=1.74533e-2 - c2 = cos(2.*dgtr*lat) - gv = 980.616*(1.-.0026373*c2) - reff = 2.*gv/(3.085462e-6 + 2.27e-9*c2)*1.e-5 - return - end subroutine glatf - -!----------------------------------------------------------------------- -!> Test variable condition. -!! -!! Test if geophysical variables or switches changed and save -!! return 0 if unchanged and 1 if changed -!! -!! @param[in] iyd year and day as yyddd -!! @param[in] sec ut(sec) -!! @param[in] glat geodetic latitude(deg) -!! @param[in] glong geodetic longitude(deg) -!! @param[in] stl local apparent solar time(hrs) -!! @param[in] f107a 3 month average of f10.7 flux -!! @param[in] f107 daily f10.7 flux for previous day -!! @param[in] ap magnetic index(daily) or when sw(9)=-1. : -!! array containing: -!! ap(1) daily ap -!! ap(2) 3 hr ap index for current time -!! ap(3) 3 hr ap index for 3 hrs before current time -!! ap(4) 3 hr ap index for 6 hrs before current time -!! ap(5) 3 hr ap index for 9 hrs before current time -!! ap(6) average of eight 3 hr ap indicies from 12 to 33 hrs pr -!! to current time -!! ap(7) average of eight 3 hr ap indicies from 36 to 59 hrs pr -!! to current time -!! @param[in] ic initial point -!! @return vtst7 tested value -!! -!! @author Hann-Ming Henry Juang - function vtst7(iyd,sec,glat,glong,stl,f107a,f107,ap,ic) - use gettemp_mod, only: sw,swc -! - dimension ap(7),iydl(2),secl(2),glatl(2),gll(2),stll(2) - dimension fal(2),fl(2),apl(7,2),swl(25,2),swcl(25,2) - save - data iydl/2*-999/,secl/2*-999./,glatl/2*-999./,gll/2*-999./ - data stll/2*-999./,fal/2*-999./,fl/2*-999./,apl/14*-999./ - data swl/50*-999./,swcl/50*-999./ - vtst7=0 - if(iyd.ne.iydl(ic)) goto 10 - if(sec.ne.secl(ic)) goto 10 - if(glat.ne.glatl(ic)) goto 10 - if(glong.ne.gll(ic)) goto 10 - if(stl.ne.stll(ic)) goto 10 - if(f107a.ne.fal(ic)) goto 10 - if(f107.ne.fl(ic)) goto 10 - do 5 i=1,7 - if(ap(i).ne.apl(i,ic)) goto 10 - 5 end do - do 7 i=1,25 - if(sw(i).ne.swl(i,ic)) goto 10 - if(swc(i).ne.swcl(i,ic)) goto 10 - 7 end do - goto 20 - 10 continue - vtst7=1 - iydl(ic)=iyd - secl(ic)=sec - glatl(ic)=glat - gll(ic)=glong - stll(ic)=stl - fal(ic)=f107a - fl(ic)=f107 - do 15 i=1,7 - apl(i,ic)=ap(i) - 15 end do - do 16 i=1,25 - swl(i,ic)=sw(i) - swcl(i,ic)=swc(i) - 16 end do - 20 continue - return - end function vtst7 - -!----------------------------------------------------------------------- -!> Thermospheric portion of nrlmsise-00 -!! -!! See gtd7 for more extensive comments -!! Output in m-3 and kg/m3: call meters(.true.) -!! -!! @param[in] iyd year and day as yyddd (day of year from 1 to 365 or 366 -!! @param[in] sec ut(sec) -!! @param[in] alt altitude(km) (>72.5 km) -!! @param[in] glat geodetic latitude(deg) -!! @param[in] glong geodetic longitude(deg) -!! @param[in] stl local apparent solar time(hrs) -!! @param[in] f107a 3 month average of f10.7 flux -!! @param[in] f107 daily f10.7 flux for previous day -!! @param[in] ap magnetic index(daily) or when sw(9)=-1. : -!! array containing: -!! ap(1) daily ap -!! ap(2) 3 hr ap index for current time -!! ap(3) 3 hr ap index for 3 hrs before current time -!! ap(4) 3 hr ap index for 6 hrs before current time -!! ap(5) 3 hr ap index for 9 hrs before current time -!! ap(6) average of eight 3 hr ap indicies from 12 to 33 hrs pr -!! to current time -!! ap(7) average of eight 3 hr ap indicies from 36 to 59 hrs pr -!! to current time -!! @param[in] mass - mass number (only density for selected gas is -!! calculated. mass 0 is temperature. mass 48 for all. -!! mass 17 is anomalous o only.) -!! @param[out] d density array with length of 8 -!! d(1) he number density(cm-3) -!! d(2) o number density(cm-3) -!! d(3) n2 number density(cm-3) -!! d(4) o2 number density(cm-3) -!! d(5) ar number density(cm-3) -!! d(6) total mass density(gm/cm3) -!! d(7) h number density(cm-3) -!! d(8) n number density(cm-3) -!! d(9) anomalous oxygen number density(cm-3) -!! @param[out] t temperature array with length of 2 -!! t(1) exospheric temperature -!! t(2) temperature at alt -!! -!! @author Hann-Ming Henry Juang - subroutine gts7(iyd,sec,alt,glat,glong,stl,f107a,f107,ap,mass,d,t) - use wam_gtd7bk_mod, only: & - ptm,pdm, & - imr - - use gettemp_mod, only: tlb,s,db04,db16,db28,db32,db40,db48,db01,za,t0, & - z0,g0,rl,dd,db14,tr12,tn1,tgn1, & - pt,pd,ps,pdl,ptl,pma,sw, & - dm04,dm16,dm28,dm32,dm40,dm01,dm14 - - dimension zn1(5),alpha(9) - dimension d(9),t(2),mt(11),ap(*),altl(8) - save - data mt/48,0,4,16,28,32,40,1,49,14,17/ - data altl/200.,300.,160.,250.,240.,450.,320.,450./ - data mn1/5/,zn1/120.,110.,100.,90.,72.5/ - data dgtr/1.74533e-2/,dr/1.72142e-2/,alast/-999./ - data alpha/-0.38,0.,0.,0.,0.17,0.,-0.38,0.,0./ -! test for changed input - v2=vtst7(iyd,sec,glat,glong,stl,f107a,f107,ap,2) -! - yrd=iyd - za=pdl(16,2) - zn1(1)=za - do 2 j=1,9 - d(j)=0. - 2 end do -! tinf variations not important below za or zn1(1) - if(alt.gt.zn1(1)) then - if(v2.eq.1..or.alast.le.zn1(1)) tinf=ptm(1)*pt(1) & - *(1.+sw(16)*globe7(yrd,sec,glat,glong,stl,f107a,f107,ap,pt)) - else - tinf=ptm(1)*pt(1) - endif - t(1)=tinf -! gradient variations not important below zn1(5) - if(alt.gt.zn1(5)) then - if(v2.eq.1.or.alast.le.zn1(5)) g0=ptm(4)*ps(1) & - *(1.+sw(19)*globe7(yrd,sec,glat,glong,stl,f107a,f107,ap,ps)) - else - g0=ptm(4)*ps(1) - endif -! calculate these temperatures only if input changed - if(v2.eq.1. .or. alt.lt.300.) & - tlb=ptm(2)*(1.+sw(17)*globe7(yrd,sec,glat,glong,stl, & - f107a,f107,ap,pd(1,4)))*pd(1,4) - s=g0/(tinf-tlb) -! lower thermosphere temp variations not significant for -! density above 300 km - if(alt.lt.300.) then - if(v2.eq.1..or.alast.ge.300.) then - tn1(2)=ptm(7)*ptl(1,1)/(1.-sw(18)*glob7s(ptl(1,1))) - tn1(3)=ptm(3)*ptl(1,2)/(1.-sw(18)*glob7s(ptl(1,2))) - tn1(4)=ptm(8)*ptl(1,3)/(1.-sw(18)*glob7s(ptl(1,3))) - tn1(5)=ptm(5)*ptl(1,4)/(1.-sw(18)*sw(20)*glob7s(ptl(1,4))) - tgn1(2)=ptm(9)*pma(1,9)*(1.+sw(18)*sw(20)*glob7s(pma(1,9))) & - *tn1(5)*tn1(5)/(ptm(5)*ptl(1,4))**2 - endif - else - tn1(2)=ptm(7)*ptl(1,1) - tn1(3)=ptm(3)*ptl(1,2) - tn1(4)=ptm(8)*ptl(1,3) - tn1(5)=ptm(5)*ptl(1,4) - tgn1(2)=ptm(9)*pma(1,9) & - *tn1(5)*tn1(5)/(ptm(5)*ptl(1,4))**2 - endif -! - z0=zn1(4) - t0=tn1(4) - tr12=1. -! - if(mass.eq.0) go to 50 -! n2 variation factor at zlb - g28=sw(21)*globe7(yrd,sec,glat,glong,stl,f107a,f107, & - ap,pd(1,3)) - day=amod(yrd,1000.) -! variation of turbopause height - zhf=pdl(25,2) & - *(1.+sw(5)*pdl(25,1)*sin(dgtr*glat)*cos(dr*(day-pt(14)))) - yrd=iyd - t(1)=tinf - xmm=pdm(5,3) - z=alt -! - do 10 j = 1,11 - if(mass.eq.mt(j)) go to 15 - 10 end do - write(6,100) mass - go to 90 - 15 if(z.gt.altl(6).and.mass.ne.28.and.mass.ne.48) go to 17 -! -! **** n2 density **** -! -! diffusive density at zlb - db28 = pdm(1,3)*exp(g28)*pd(1,3) -! diffusive density at alt - d(3)=densu(z,db28,tinf,tlb, 28.,alpha(3),t(2),ptm(6),s,mn1,zn1, & - tn1,tgn1) - dd=d(3) -! turbopause - zh28=pdm(3,3)*zhf - zhm28=pdm(4,3)*pdl(6,2) - xmd=28.-xmm -! mixed density at zlb - b28=densu(zh28,db28,tinf,tlb,xmd,alpha(3)-1.,tz,ptm(6),s,mn1, & - zn1,tn1,tgn1) - if(z.gt.altl(3).or.sw(15).eq.0.) go to 17 -! mixed density at alt - dm28=densu(z,b28,tinf,tlb,xmm,alpha(3),tz,ptm(6),s,mn1, & - zn1,tn1,tgn1) -! net density at alt - d(3)=dnet(d(3),dm28,zhm28,xmm,28.) - 17 continue - go to (20,50,20,25,90,35,40,45,25,48,46), j - 20 continue -! -! **** he density **** -! -! density variation factor at zlb - g4 = sw(21)*globe7(yrd,sec,glat,glong,stl,f107a,f107,ap,pd(1,1)) -! diffusive density at zlb - db04 = pdm(1,1)*exp(g4)*pd(1,1) -! diffusive density at alt - d(1)=densu(z,db04,tinf,tlb, 4.,alpha(1),t(2),ptm(6),s,mn1,zn1, & - tn1,tgn1) - dd=d(1) - if(z.gt.altl(1).or.sw(15).eq.0.) go to 24 -! turbopause - zh04=pdm(3,1) -! mixed density at zlb - b04=densu(zh04,db04,tinf,tlb,4.-xmm,alpha(1)-1., & - t(2),ptm(6),s,mn1,zn1,tn1,tgn1) -! mixed density at alt - dm04=densu(z,b04,tinf,tlb,xmm,0.,t(2),ptm(6),s,mn1,zn1,tn1,tgn1) - zhm04=zhm28 -! net density at alt - d(1)=dnet(d(1),dm04,zhm04,xmm,4.) -! correction to specified mixing ratio at ground - rl=alog(b28*pdm(2,1)/b04) - zc04=pdm(5,1)*pdl(1,2) - hc04=pdm(6,1)*pdl(2,2) -! net density corrected at alt - d(1)=d(1)*ccor(z,rl,hc04,zc04) - 24 continue - if(mass.ne.48) go to 90 - 25 continue -! -! **** o density **** -! -! density variation factor at zlb - g16= sw(21)*globe7(yrd,sec,glat,glong,stl,f107a,f107,ap,pd(1,2)) -! diffusive density at zlb - db16 = pdm(1,2)*exp(g16)*pd(1,2) -! diffusive density at alt - d(2)=densu(z,db16,tinf,tlb, 16.,alpha(2),t(2),ptm(6),s,mn1, & - zn1,tn1,tgn1) - dd=d(2) - if(z.gt.altl(2).or.sw(15).eq.0.) go to 34 -! corrected from pdm(3,1) to pdm(3,2) 12/2/85 -! turbopause - zh16=pdm(3,2) -! mixed density at zlb - b16=densu(zh16,db16,tinf,tlb,16-xmm,alpha(2)-1., & - t(2),ptm(6),s,mn1,zn1,tn1,tgn1) -! mixed density at alt - dm16=densu(z,b16,tinf,tlb,xmm,0.,t(2),ptm(6),s,mn1,zn1,tn1,tgn1) - zhm16=zhm28 -! net density at alt - d(2)=dnet(d(2),dm16,zhm16,xmm,16.) -! 3/16/99 change form to match o2 departure from diff equil near 150 -! km and add dependence on f10.7 -! rl=alog(b28*pdm(2,2)*abs(pdl(17,2))/b16) - rl=pdm(2,2)*pdl(17,2)*(1.+sw(1)*pdl(24,1)*(f107a-150.)) - hc16=pdm(6,2)*pdl(4,2) - zc16=pdm(5,2)*pdl(3,2) - hc216=pdm(6,2)*pdl(5,2) - d(2)=d(2)*ccor2(z,rl,hc16,zc16,hc216) -! chemistry correction - hcc16=pdm(8,2)*pdl(14,2) - zcc16=pdm(7,2)*pdl(13,2) - rc16=pdm(4,2)*pdl(15,2) -! net density corrected at alt - d(2)=d(2)*ccor(z,rc16,hcc16,zcc16) - 34 continue - if(mass.ne.48.and.mass.ne.49) go to 90 - 35 continue -! -! **** o2 density **** -! -! density variation factor at zlb - g32= sw(21)*globe7(yrd,sec,glat,glong,stl,f107a,f107,ap,pd(1,5)) -! diffusive density at zlb - db32 = pdm(1,4)*exp(g32)*pd(1,5) -! diffusive density at alt - d(4)=densu(z,db32,tinf,tlb, 32.,alpha(4),t(2),ptm(6),s,mn1, & - zn1,tn1,tgn1) - if(mass.eq.49) then - dd=dd+2.*d(4) - else - dd=d(4) - endif - if(sw(15).eq.0.) go to 39 - if(z.gt.altl(4)) go to 38 -! turbopause - zh32=pdm(3,4) -! mixed density at zlb - b32=densu(zh32,db32,tinf,tlb,32.-xmm,alpha(4)-1., & - t(2),ptm(6),s,mn1,zn1,tn1,tgn1) -! mixed density at alt - dm32=densu(z,b32,tinf,tlb,xmm,0.,t(2),ptm(6),s,mn1,zn1,tn1,tgn1) - zhm32=zhm28 -! net density at alt - d(4)=dnet(d(4),dm32,zhm32,xmm,32.) -! correction to specified mixing ratio at ground - rl=alog(b28*pdm(2,4)/b32) - hc32=pdm(6,4)*pdl(8,2) - zc32=pdm(5,4)*pdl(7,2) - d(4)=d(4)*ccor(z,rl,hc32,zc32) - 38 continue -! correction for general departure from diffusive equilibrium above - hcc32=pdm(8,4)*pdl(23,2) - hcc232=pdm(8,4)*pdl(23,1) - zcc32=pdm(7,4)*pdl(22,2) - rc32=pdm(4,4)*pdl(24,2)*(1.+sw(1)*pdl(24,1)*(f107a-150.)) -! net density corrected at alt - d(4)=d(4)*ccor2(z,rc32,hcc32,zcc32,hcc232) - 39 continue - if(mass.ne.48) go to 90 - 40 continue -! -! **** ar density **** -! -! density variation factor at zlb - g40= sw(21)*globe7(yrd,sec,glat,glong,stl,f107a,f107,ap,pd(1,6)) -! diffusive density at zlb - db40 = pdm(1,5)*exp(g40)*pd(1,6) -! diffusive density at alt - d(5)=densu(z,db40,tinf,tlb, 40.,alpha(5),t(2),ptm(6),s,mn1,zn1,tn1,tgn1) - dd=d(5) - if(z.gt.altl(5).or.sw(15).eq.0.) go to 44 -! turbopause - zh40=pdm(3,5) -! mixed density at zlb - b40=densu(zh40,db40,tinf,tlb,40.-xmm,alpha(5)-1., & - t(2),ptm(6),s,mn1,zn1,tn1,tgn1) -! mixed density at alt - dm40=densu(z,b40,tinf,tlb,xmm,0.,t(2),ptm(6),s,mn1,zn1,tn1,tgn1) - zhm40=zhm28 -! net density at alt - d(5)=dnet(d(5),dm40,zhm40,xmm,40.) -! correction to specified mixing ratio at ground - rl=alog(b28*pdm(2,5)/b40) - hc40=pdm(6,5)*pdl(10,2) - zc40=pdm(5,5)*pdl(9,2) -! net density corrected at alt - d(5)=d(5)*ccor(z,rl,hc40,zc40) - 44 continue - if(mass.ne.48) go to 90 - 45 continue -! -! **** hydrogen density **** -! -! density variation factor at zlb - g1 = sw(21)*globe7(yrd,sec,glat,glong,stl,f107a,f107,ap,pd(1,7)) -! diffusive density at zlb - db01 = pdm(1,6)*exp(g1)*pd(1,7) -! diffusive density at alt - d(7)=densu(z,db01,tinf,tlb,1.,alpha(7),t(2),ptm(6),s,mn1,zn1,tn1,tgn1) - dd=d(7) - if(z.gt.altl(7).or.sw(15).eq.0.) go to 47 -! turbopause - zh01=pdm(3,6) -! mixed density at zlb - b01=densu(zh01,db01,tinf,tlb,1.-xmm,alpha(7)-1., & - t(2),ptm(6),s,mn1,zn1,tn1,tgn1) -! mixed density at alt - dm01=densu(z,b01,tinf,tlb,xmm,0.,t(2),ptm(6),s,mn1,zn1,tn1,tgn1) - zhm01=zhm28 -! net density at alt - d(7)=dnet(d(7),dm01,zhm01,xmm,1.) -! correction to specified mixing ratio at ground - rl=alog(b28*pdm(2,6)*abs(pdl(18,2))/b01) - hc01=pdm(6,6)*pdl(12,2) - zc01=pdm(5,6)*pdl(11,2) - d(7)=d(7)*ccor(z,rl,hc01,zc01) -! chemistry correction - hcc01=pdm(8,6)*pdl(20,2) - zcc01=pdm(7,6)*pdl(19,2) - rc01=pdm(4,6)*pdl(21,2) -! net density corrected at alt - d(7)=d(7)*ccor(z,rc01,hcc01,zcc01) - 47 continue - if(mass.ne.48) go to 90 - 48 continue -! -! **** atomic nitrogen density **** -! -! density variation factor at zlb - g14 = sw(21)*globe7(yrd,sec,glat,glong,stl,f107a,f107,ap,pd(1,8)) -! diffusive density at zlb - db14 = pdm(1,7)*exp(g14)*pd(1,8) -! diffusive density at alt - d(8)=densu(z,db14,tinf,tlb,14.,alpha(8),t(2),ptm(6),s,mn1, & - zn1,tn1,tgn1) - dd=d(8) - if(z.gt.altl(8).or.sw(15).eq.0.) go to 49 -! turbopause - zh14=pdm(3,7) -! mixed density at zlb - b14=densu(zh14,db14,tinf,tlb,14.-xmm,alpha(8)-1., & - t(2),ptm(6),s,mn1,zn1,tn1,tgn1) -! mixed density at alt - dm14=densu(z,b14,tinf,tlb,xmm,0.,t(2),ptm(6),s,mn1,zn1,tn1,tgn1) - zhm14=zhm28 -! net density at alt - d(8)=dnet(d(8),dm14,zhm14,xmm,14.) -! correction to specified mixing ratio at ground - rl=alog(b28*pdm(2,7)*abs(pdl(3,1))/b14) - hc14=pdm(6,7)*pdl(2,1) - zc14=pdm(5,7)*pdl(1,1) - d(8)=d(8)*ccor(z,rl,hc14,zc14) -! chemistry correction - hcc14=pdm(8,7)*pdl(5,1) - zcc14=pdm(7,7)*pdl(4,1) - rc14=pdm(4,7)*pdl(6,1) -! net density corrected at alt - d(8)=d(8)*ccor(z,rc14,hcc14,zcc14) - 49 continue - if(mass.ne.48) go to 90 - 46 continue -! -! **** anomalous oxygen density **** -! - g16h = sw(21)*globe7(yrd,sec,glat,glong,stl,f107a,f107,ap,pd(1,9)) - db16h = pdm(1,8)*exp(g16h)*pd(1,9) - tho=pdm(10,8)*pdl(7,1) - dd=densu(z,db16h,tho,tho,16.,alpha(9),t2,ptm(6),s,mn1, & - zn1,tn1,tgn1) - zsht=pdm(6,8) - zmho=pdm(5,8) - zsho=scalh(zmho,16.,tho) - d(9)=dd*exp(-zsht/zsho*(exp(-(z-zmho)/zsht)-1.)) - if(mass.ne.48) go to 90 -! -! total mass density -! - d(6) = 1.66e-24*(4.*d(1)+16.*d(2)+28.*d(3)+32.*d(4)+40.*d(5)+ & - d(7)+14.*d(8)) - db48=1.66e-24*(4.*db04+16.*db16+28.*db28+32.*db32+40.*db40+db01+ & - 14.*db14) - go to 90 -! temperature at altitude - 50 continue - z=abs(alt) - ddum = densu(z,1., tinf,tlb,0.,0.,t(2),ptm(6),s,mn1,zn1,tn1,tgn1) - 90 continue -! adjust densities from cgs to kgm - if(imr.eq.1) then - do 95 i=1,9 - d(i)=d(i)*1.e6 - 95 continue - d(6)=d(6)/1000. - endif - alast=alt - return - 100 format(1x,'mass', i5, ' not valid') - end subroutine gts7 - -!----------------------------------------------------------------------- -!> Convert outputs to kg & meters if meter true. -!! @param[in] meter logical true or false -!! @author Hann-Ming Henry Juang - subroutine meters(meter) - use wam_gtd7bk_mod, only: imr -! - logical meter - save - imr=0 - if(meter) imr=1 - end subroutine meters - -!----------------------------------------------------------------------- -!> Calculate scale height (km) -!! @param[in] alt altitude [km] -!! @param[in] xm molecular weihjt -!! @param[in] temp temperature -!! @return scalh scale height -!! -!! @author Hann-Ming Henry Juang - function scalh(alt,xm,temp) - use gettemp_mod, only: gsurf,re -! - save - data rgas/831.4/ - g=gsurf/(1.+alt/re)**2 - scalh=rgas*temp/(g*xm) - return - end function scalh - -!----------------------------------------------------------------------- -!> Calculate g(l) function for upper thermosphere parameters -!! @param[in] yrd year and day as yyddd -!! @param[in] sec ut(sec) -!! @param[in] lat geodetic latitude(deg) -!! @param[in] long geodetic longitude(deg) -!! @param[in] tloc local apparent solar time(hrs) -!! @param[in] f107a 3 month average of f10.7 flux -!! @param[in] f107 daily f10.7 flux for previous day -!! @param[in] ap magnetic index(daily) or when sw(9)=-1. : -!! array containing: -!! ap(1) daily ap -!! ap(2) 3 hr ap index for current time -!! ap(3) 3 hr ap index for 3 hrs before current time -!! ap(4) 3 hr ap index for 6 hrs before current time -!! ap(5) 3 hr ap index for 9 hrs before current time -!! ap(6) average of eight 3 hr ap indicies from 12 to 33 hrs pr -!! to current time -!! ap(7) average of eight 3 hr ap indicies from 36 to 59 hrs pr -!! to current time -!! @param[in] p pressure level(mb) -!! @return globe7 version of global -!! -!! @author Hann-Ming Henry Juang - function globe7(yrd,sec,lat,long,tloc,f107a,f107,ap,p) - use gettemp_mod, only: tinf=>tinfg,t=>tt, & - sw,swc,isw, & - plg,ctloc,stloc,c2tloc,s2tloc,c3tloc,s3tloc, & - day,df,dfa,apd,apdf,apt,xlong,iyr - real lat, long - dimension p(*),sv(25),ap(*) -!---- functions ------ -! 3hr magnetic activity functions -! eq. a24d - g0(a)=(a-4.+(p(26)-1.)*(a-4.+(exp(-abs(p(25))*(a-4.))-1.)/ & - abs(p(25)))) -! eq. a24c - sumex(ex)=1.+(1.-ex**19)/(1.-ex)*ex**(.5) -! eq. a24a - sg0(ex)=(g0(ap(2))+(g0(ap(3))*ex+g0(ap(4))*ex*ex+g0(ap(5))*ex**3 & - +(g0(ap(6))*ex**4+g0(ap(7))*ex**12)*(1.-ex**8)/(1.-ex)) & - )/sumex(ex) -!--------------------- - save - data dgtr/1.74533e-2/,dr/1.72142e-2/, xl/1000./,tll/1000./ - data sw9/1./,dayl/-1./,p14/-1000./,p18/-1000./,p32/-1000./ - data hr/.2618/,sr/7.2722e-5/,sv/25*1./,nsw/14/,p39/-1000./ - if(isw.ne.64999) call tselec(sv) - do 10 j=1,14 - t(j)=0 - 10 end do - if(sw(9).gt.0) sw9=1. - if(sw(9).lt.0) sw9=-1. - iyr = yrd/1000. - day = yrd - iyr*1000. - xlong=long -! eq. a22 (remainder of code) - if(xl.eq.lat) go to 15 -! calculate legendre polynomials - c = sin(lat*dgtr) - s = cos(lat*dgtr) - c2 = c*c - c4 = c2*c2 - s2 = s*s - plg(2,1) = c - plg(3,1) = 0.5*(3.*c2 -1.) - plg(4,1) = 0.5*(5.*c*c2-3.*c) - plg(5,1) = (35.*c4 - 30.*c2 + 3.)/8. - plg(6,1) = (63.*c2*c2*c - 70.*c2*c + 15.*c)/8. - plg(7,1) = (11.*c*plg(6,1) - 5.*plg(5,1))/6. -! plg(8,1) = (13.*c*plg(7,1) - 6.*plg(6,1))/7. - plg(2,2) = s - plg(3,2) = 3.*c*s - plg(4,2) = 1.5*(5.*c2-1.)*s - plg(5,2) = 2.5*(7.*c2*c-3.*c)*s - plg(6,2) = 1.875*(21.*c4 - 14.*c2 +1.)*s - plg(7,2) = (11.*c*plg(6,2)-6.*plg(5,2))/5. -! plg(8,2) = (13.*c*plg(7,2)-7.*plg(6,2))/6. -! plg(9,2) = (15.*c*plg(8,2)-8.*plg(7,2))/7. - plg(3,3) = 3.*s2 - plg(4,3) = 15.*s2*c - plg(5,3) = 7.5*(7.*c2 -1.)*s2 - plg(6,3) = 3.*c*plg(5,3)-2.*plg(4,3) - plg(7,3)=(11.*c*plg(6,3)-7.*plg(5,3))/4. - plg(8,3)=(13.*c*plg(7,3)-8.*plg(6,3))/5. - plg(4,4) = 15.*s2*s - plg(5,4) = 105.*s2*s*c - plg(6,4)=(9.*c*plg(5,4)-7.*plg(4,4))/2. - plg(7,4)=(11.*c*plg(6,4)-8.*plg(5,4))/3. - xl=lat - 15 continue - if(tll.eq.tloc) go to 16 - if(sw(7).eq.0.and.sw(8).eq.0.and.sw(14).eq.0) goto 16 - stloc = sin(hr*tloc) - ctloc = cos(hr*tloc) - s2tloc = sin(2.*hr*tloc) - c2tloc = cos(2.*hr*tloc) - s3tloc = sin(3.*hr*tloc) - c3tloc = cos(3.*hr*tloc) - tll = tloc - 16 continue - if(day.ne.dayl.or.p(14).ne.p14) cd14=cos(dr*(day-p(14))) - if(day.ne.dayl.or.p(18).ne.p18) cd18=cos(2.*dr*(day-p(18))) - if(day.ne.dayl.or.p(32).ne.p32) cd32=cos(dr*(day-p(32))) - if(day.ne.dayl.or.p(39).ne.p39) cd39=cos(2.*dr*(day-p(39))) - dayl = day - p14 = p(14) - p18 = p(18) - p32 = p(32) - p39 = p(39) -! f10.7 effect - df = f107 - f107a - dfa=f107a-150. - t(1) = p(20)*df*(1.+p(60)*dfa) + p(21)*df*df + p(22)*dfa & - + p(30)*dfa**2 - f1 = 1. + (p(48)*dfa +p(20)*df+p(21)*df*df)*swc(1) - f2 = 1. + (p(50)*dfa+p(20)*df+p(21)*df*df)*swc(1) -! time independent - t(2) = & - (p(2)*plg(3,1) + p(3)*plg(5,1)+p(23)*plg(7,1)) & - +(p(15)*plg(3,1))*dfa*swc(1) & - +p(27)*plg(2,1) -! symmetrical annual - t(3) = & - (p(19) )*cd32 -! symmetrical semiannual - t(4) = & - (p(16)+p(17)*plg(3,1))*cd18 -! asymmetrical annual - t(5) = f1* & - (p(10)*plg(2,1)+p(11)*plg(4,1))*cd14 -! asymmetrical semiannual - t(6) = p(38)*plg(2,1)*cd39 -! diurnal - if(sw(7).eq.0) goto 200 - t71 = (p(12)*plg(3,2))*cd14*swc(5) - t72 = (p(13)*plg(3,2))*cd14*swc(5) - t(7) = f2* & - ((p(4)*plg(2,2) + p(5)*plg(4,2) + p(28)*plg(6,2) & - + t71)*ctloc & - + (p(7)*plg(2,2) + p(8)*plg(4,2) +p(29)*plg(6,2) & - + t72)*stloc) - 200 continue -! semidiurnal - if(sw(8).eq.0) goto 210 - t81 = (p(24)*plg(4,3)+p(36)*plg(6,3))*cd14*swc(5) - t82 = (p(34)*plg(4,3)+p(37)*plg(6,3))*cd14*swc(5) - t(8) = f2* & - ((p(6)*plg(3,3) + p(42)*plg(5,3) + t81)*c2tloc & - +(p(9)*plg(3,3) + p(43)*plg(5,3) + t82)*s2tloc) - 210 continue -! terdiurnal - if(sw(14).eq.0) goto 220 - t(14) = f2* & - ((p(40)*plg(4,4)+(p(94)*plg(5,4)+p(47)*plg(7,4))*cd14*swc(5))* & - s3tloc & - +(p(41)*plg(4,4)+(p(95)*plg(5,4)+p(49)*plg(7,4))*cd14*swc(5))* & - c3tloc) - 220 continue -! magnetic activity based on daily ap - - if(sw9.eq.-1.) go to 30 - apd=(ap(1)-4.) - p44=p(44) - p45=p(45) - if(p44.lt.0) p44=1.e-5 - apdf = apd+(p45-1.)*(apd+(exp(-p44 *apd)-1.)/p44) - if(sw(9).eq.0) goto 40 - t(9)=apdf*(p(33)+p(46)*plg(3,1)+p(35)*plg(5,1)+ & - (p(101)*plg(2,1)+p(102)*plg(4,1)+p(103)*plg(6,1))*cd14*swc(5)+ & - (p(122)*plg(2,2)+p(123)*plg(4,2)+p(124)*plg(6,2))*swc(7)* & - cos(hr*(tloc-p(125)))) - go to 40 - 30 continue - if(p(52).eq.0) go to 40 - exp1 = exp(-10800.*abs(p(52))/(1.+p(139)*(45.-abs(lat)))) - if(exp1.gt..99999) exp1=.99999 - if(p(25).lt.1.e-4) p(25)=1.e-4 - apt(1)=sg0(exp1) -! apt(2)=sg2(exp1) -! apt(3)=sg0(exp2) -! apt(4)=sg2(exp2) - if(sw(9).eq.0) goto 40 - t(9) = apt(1)*(p(51)+p(97)*plg(3,1)+p(55)*plg(5,1)+ & - (p(126)*plg(2,1)+p(127)*plg(4,1)+p(128)*plg(6,1))*cd14*swc(5)+ & - (p(129)*plg(2,2)+p(130)*plg(4,2)+p(131)*plg(6,2))*swc(7)* & - cos(hr*(tloc-p(132)))) - 40 continue - if(sw(10).eq.0.or.long.le.-1000.) go to 49 -! longitudinal - if(sw(11).eq.0) goto 230 - t(11)= (1.+p(81)*dfa*swc(1))* & - ((p(65)*plg(3,2)+p(66)*plg(5,2)+p(67)*plg(7,2) & - +p(104)*plg(2,2)+p(105)*plg(4,2)+p(106)*plg(6,2) & - +swc(5)*(p(110)*plg(2,2)+p(111)*plg(4,2)+p(112)*plg(6,2))*cd14)* & - cos(dgtr*long) & - +(p(91)*plg(3,2)+p(92)*plg(5,2)+p(93)*plg(7,2) & - +p(107)*plg(2,2)+p(108)*plg(4,2)+p(109)*plg(6,2) & - +swc(5)*(p(113)*plg(2,2)+p(114)*plg(4,2)+p(115)*plg(6,2))*cd14)* & - sin(dgtr*long)) - 230 continue -! ut and mixed ut,longitude - if(sw(12).eq.0) goto 240 - t(12)=(1.+p(96)*plg(2,1))*(1.+p(82)*dfa*swc(1))* & - (1.+p(120)*plg(2,1)*swc(5)*cd14)* & - ((p(69)*plg(2,1)+p(70)*plg(4,1)+p(71)*plg(6,1))* & - cos(sr*(sec-p(72)))) - t(12)=t(12)+swc(11)* & - (p(77)*plg(4,3)+p(78)*plg(6,3)+p(79)*plg(8,3))* & - cos(sr*(sec-p(80))+2.*dgtr*long)*(1.+p(138)*dfa*swc(1)) - 240 continue -! ut,longitude magnetic activity - if(sw(13).eq.0) goto 48 - if(sw9.eq.-1.) go to 45 - t(13)= apdf*swc(11)*(1.+p(121)*plg(2,1))* & - ((p( 61)*plg(3,2)+p( 62)*plg(5,2)+p( 63)*plg(7,2))* & - cos(dgtr*(long-p( 64)))) & - +apdf*swc(11)*swc(5)* & - (p(116)*plg(2,2)+p(117)*plg(4,2)+p(118)*plg(6,2))* & - cd14*cos(dgtr*(long-p(119))) & - + apdf*swc(12)* & - (p( 84)*plg(2,1)+p( 85)*plg(4,1)+p( 86)*plg(6,1))* & - cos(sr*(sec-p( 76))) - goto 48 - 45 continue - if(p(52).eq.0) goto 48 - t(13)=apt(1)*swc(11)*(1.+p(133)*plg(2,1))* & - ((p(53)*plg(3,2)+p(99)*plg(5,2)+p(68)*plg(7,2))* & - cos(dgtr*(long-p(98)))) & - +apt(1)*swc(11)*swc(5)* & - (p(134)*plg(2,2)+p(135)*plg(4,2)+p(136)*plg(6,2))* & - cd14*cos(dgtr*(long-p(137))) & - +apt(1)*swc(12)* & - (p(56)*plg(2,1)+p(57)*plg(4,1)+p(58)*plg(6,1))* & - cos(sr*(sec-p(59))) - 48 continue -! parms not used: 83, 90,100,140-150 - 49 continue - tinf=p(31) - do i = 1,nsw - tinf = tinf + abs(sw(i))*t(i) - enddo - globe7 = tinf - return - end function globe7 - -!----------------------------------------------------------------------- -!> Set switches. -!! -!! Output in sw(25),isw,swc(25) -!! The sw for main terms, swc for cross terms -!! To turn on and off particular variations call tselec(sv), -!! where sv is a 25 element array containing 0. for off, 1. -!! for on, or 2. for main effects off but cross terms on -!! To get current values of sw: call tretrv(sw) -!! @param[in] sv array contains switches. -!! -!! @author Hann-Ming Henry Juang - subroutine tselec(sv) - use gettemp_mod, only: sw,swc,isw -! - dimension sv(*),sav(25),svv(*) - save - do 100 i = 1,25 - sav(i)=sv(i) - sw(i)=amod(sv(i),2.) - if(abs(sv(i)).eq.1.or.abs(sv(i)).eq.2.) then - swc(i)=1. - else - swc(i)=0. - endif - 100 end do - isw=64999 - return - entry tretrv(svv) - do 200 i=1,25 - svv(i)=sav(i) - 200 end do - end subroutine tselec - -!----------------------------------------------------------------------- -!> Version of globe for lower atmosphere -!! -!! @param[in] p pressure (mb) -!! @return glob7s version of global -!! -!! @author Hann-Ming Henry Juang - function glob7s(p) - use mpi - use gettemp_mod, only:plg,ctloc,stloc,c2tloc,s2tloc,c3tloc,s3tloc, & - day,dfa,apdf,apt,long=>xlong,sw,swc - dimension p(*),t(14) -! - integer :: rc - save - data dr/1.72142e-2/,dgtr/1.74533e-2/,pset/2./ - data dayl/-1./,p32,p18,p14,p39/4*-1000./ - if(p(100).eq.0) p(100)=pset - if(p(100).ne.pset) then - write(6,900) pset,p(100) - 900 format(1x,'FATAL ERROR: Wrong parameter set for glob7s',3f10.1) - call mpi_abort(mpi_comm_world, 999, rc) - endif - do 10 j=1,14 - t(j)=0. - 10 end do - if(day.ne.dayl.or.p32.ne.p(32)) cd32=cos(dr*(day-p(32))) - if(day.ne.dayl.or.p18.ne.p(18)) cd18=cos(2.*dr*(day-p(18))) - if(day.ne.dayl.or.p14.ne.p(14)) cd14=cos(dr*(day-p(14))) - if(day.ne.dayl.or.p39.ne.p(39)) cd39=cos(2.*dr*(day-p(39))) - dayl=day - p32=p(32) - p18=p(18) - p14=p(14) - p39=p(39) -! -! f10.7 - t(1)=p(22)*dfa -! time independent - t(2)=p(2)*plg(3,1)+p(3)*plg(5,1)+p(23)*plg(7,1) & - +p(27)*plg(2,1)+p(15)*plg(4,1)+p(60)*plg(6,1) -! symmetrical annual - t(3)=(p(19)+p(48)*plg(3,1)+p(30)*plg(5,1))*cd32 -! symmetrical semiannual - t(4)=(p(16)+p(17)*plg(3,1)+p(31)*plg(5,1))*cd18 -! asymmetrical annual - t(5)=(p(10)*plg(2,1)+p(11)*plg(4,1)+p(21)*plg(6,1))*cd14 -! asymmetrical semiannual - t(6)=(p(38)*plg(2,1))*cd39 -! diurnal - if(sw(7).eq.0) goto 200 - t71 = p(12)*plg(3,2)*cd14*swc(5) - t72 = p(13)*plg(3,2)*cd14*swc(5) - t(7) = & - ((p(4)*plg(2,2) + p(5)*plg(4,2) & - + t71)*ctloc & - + (p(7)*plg(2,2) + p(8)*plg(4,2) & - + t72)*stloc) - 200 continue -! semidiurnal - if(sw(8).eq.0) goto 210 - t81 = (p(24)*plg(4,3)+p(36)*plg(6,3))*cd14*swc(5) - t82 = (p(34)*plg(4,3)+p(37)*plg(6,3))*cd14*swc(5) - t(8) = & - ((p(6)*plg(3,3) + p(42)*plg(5,3) + t81)*c2tloc & - +(p(9)*plg(3,3) + p(43)*plg(5,3) + t82)*s2tloc) - 210 continue -! terdiurnal - if(sw(14).eq.0) goto 220 - t(14) = p(40)*plg(4,4)*s3tloc +p(41)*plg(4,4)*c3tloc - 220 continue -! magnetic activity - if(sw(9).eq.0) goto 40 - if(sw(9).eq.1) & - t(9)=apdf*(p(33)+p(46)*plg(3,1)*swc(2)) - if(sw(9).eq.-1) & - t(9)=(p(51)*apt(1)+p(97)*plg(3,1)*apt(1)*swc(2)) - 40 continue - if(sw(10).eq.0.or.sw(11).eq.0.or.long.le.-1000.) go to 49 -! longitudinal - t(11)= (1.+plg(2,1)*(p(81)*swc(5)*cos(dr*(day-p(82))) & - +p(86)*swc(6)*cos(2.*dr*(day-p(87)))) & - +p(84)*swc(3)*cos(dr*(day-p(85))) & - +p(88)*swc(4)*cos(2.*dr*(day-p(89)))) & - *((p(65)*plg(3,2)+p(66)*plg(5,2)+p(67)*plg(7,2) & - +p(75)*plg(2,2)+p(76)*plg(4,2)+p(77)*plg(6,2) & - )*cos(dgtr*long) & - +(p(91)*plg(3,2)+p(92)*plg(5,2)+p(93)*plg(7,2) & - +p(78)*plg(2,2)+p(79)*plg(4,2)+p(80)*plg(6,2) & - )*sin(dgtr*long)) - 49 continue - tt=0. - do i=1,14 - tt=tt+abs(sw(i))*t(i) - enddo - glob7s=tt - return - end function glob7s - -!-------------------------------------------------------------------- -!> Calculate temperature and density profiles. -!! New lower thermo polynomial 10/30/89 -!! -!! @param[in] alt altitude (km) -!! @param[in] dlb altitude (km) -!! @param[in] tinf initial guess -!! @param[in] tlb molecular weight -!! @param[in] xm molecular weight -!! @param[in] alpha initial guess -!! @param[in] tz temperature -!! @param[in] zlb altitude (km) -!! @param[in] s2 altitude (km) -!! @param[in] mn1 size of array zn2 and tn2 -!! @param[in] zn1 altitude (km) -!! @param[in] tn1 temperature -!! @param[in] tgn1 end point temperature -!! @return densu density -!! -!! @author Hann-Ming Henry Juang - function densu(alt,dlb,tinf,tlb,xm,alpha,tz,zlb,s2, & - mn1,zn1,tn1,tgn1) - use gettemp_mod, only: gsurf,re -! - dimension zn1(mn1),tn1(mn1),tgn1(2),xs(5),ys(5),y2out(5) -!function - zeta(zz,zl)=(zz-zl)*(re+zl)/(re+zz) - save - data rgas/831.4/ -!! rgas=831.4 -!cccccwrite(6,*) 'db',alt,dlb,tinf,tlb,xm,alpha,zlb,s2,mn1,zn1,tn1 - densu=1. -! joining altitude of bates and spline - za=zn1(1) - z=amax1(alt,za) -! geopotential altitude difference from zlb - zg2=zeta(z,zlb) -! bates temperature - tt=tinf-(tinf-tlb)*exp(-s2*zg2) - ta=tt - tz=tt - densu=tz - if(alt.ge.za) go to 10 -! -! calculate temperature below za -! temperature gradient at za from bates profile - dta=(tinf-ta)*s2*((re+zlb)/(re+za))**2 - tgn1(1)=dta - tn1(1)=ta - z=amax1(alt,zn1(mn1)) - mn=mn1 - z1=zn1(1) - z2=zn1(mn) - t1=tn1(1) - t2=tn1(mn) -! geopotental difference from z1 - zg=zeta(z,z1) - zgdif=zeta(z2,z1) -! set up spline nodes - do 20 k=1,mn - xs(k)=zeta(zn1(k),z1)/zgdif - ys(k)=1./tn1(k) - 20 end do -! end node derivatives - yd1=-tgn1(1)/(t1*t1)*zgdif - yd2=-tgn1(2)/(t2*t2)*zgdif*((re+z2)/(re+z1))**2 -! calculate spline coefficients - call spline(xs,ys,mn,yd1,yd2,y2out) - x=zg/zgdif - call splint(xs,ys,y2out,mn,x,y) -! temperature at altitude - tz=1./y - densu=tz - 10 if(xm.eq.0.) go to 50 -! -! calculate density above za - glb=gsurf/(1.+zlb/re)**2 - gamma=xm*glb/(s2*rgas*tinf) - expl=exp(-s2*gamma*zg2) - if(expl.gt.50.or.tt.le.0.) then - expl=50. - endif -! density at altitude - densa=dlb*(tlb/tt)**(1.+alpha+gamma)*expl - densu=densa - if(alt.ge.za) go to 50 -! -! calculate density below za - glb=gsurf/(1.+z1/re)**2 - gamm=xm*glb*zgdif/rgas -! integrate spline temperatures - call splini(xs,ys,y2out,mn,x,yi) - expl=gamm*yi - if(expl.gt.50..or.tz.le.0.) then - expl=50. - endif -! density at altitude - densu=densu*(t1/tz)**(1.+alpha)*exp(-expl) - 50 continue - return - end function densu - -!-------------------------------------------------------------------- -!> Calculate temperature and density profiles for lower atmos. -!! -!! @param[in] alt altitude (km) -!! @param[in] d0 initial guess -!! @param[in] xm molecular weight -!! @param[out] tz temperature -!! @param[in] mn3 size of array zn3 amd tn3 -!! @param[in] zn3 altitude (km) -!! @param[in] tn3 temperature -!! @param[in] tgn3 altitude (km) -!! @param[in] mn2 size of array zn2 and tn2 -!! @param[in] zn2 altitude (km) -!! @param[in] tn2 temperature -!! @param[in] tgn2 end point temperature -!! @return densm density -!! -!! @author Hann-Ming Henry Juang - function densm(alt,d0,xm,tz,mn3,zn3,tn3,tgn3,mn2,zn2,tn2,tgn2) - use gettemp_mod, only: gsurf,re -! - dimension zn3(mn3),tn3(mn3),tgn3(2),xs(10),ys(10),y2out(10) - dimension zn2(mn2),tn2(mn2),tgn2(2) -! function - zeta(zz,zl)=(zz-zl)*(re+zl)/(re+zz) - save - data rgas/831.4/ -!! rgas=831.4 - densm=d0 - if(alt.gt.zn2(1)) goto 50 -! stratosphere/mesosphere temperature - z=amax1(alt,zn2(mn2)) - mn=mn2 - z1=zn2(1) - z2=zn2(mn) - t1=tn2(1) - t2=tn2(mn) - zg=zeta(z,z1) - zgdif=zeta(z2,z1) -! set up spline nodes - do 210 k=1,mn - xs(k)=zeta(zn2(k),z1)/zgdif - ys(k)=1./tn2(k) - 210 end do - yd1=-tgn2(1)/(t1*t1)*zgdif - yd2=-tgn2(2)/(t2*t2)*zgdif*((re+z2)/(re+z1))**2 -! calculate spline coefficients - call spline(xs,ys,mn,yd1,yd2,y2out) - x=zg/zgdif - call splint(xs,ys,y2out,mn,x,y) -! temperature at altitude - tz=1./y - if(xm.eq.0.) go to 20 -! -! calculate stratosphere/mesosphere density - glb=gsurf/(1.+z1/re)**2 - gamm=xm*glb*zgdif/rgas -! integrate temperature profile - call splini(xs,ys,y2out,mn,x,yi) - expl=gamm*yi - if(expl.gt.50.) expl=50. -! density at altitude - densm=densm*(t1/tz)*exp(-expl) - 20 continue - if(alt.gt.zn3(1)) goto 50 -! -! troposphere/stratosphere temperature - z=alt - mn=mn3 - z1=zn3(1) - z2=zn3(mn) - t1=tn3(1) - t2=tn3(mn) - zg=zeta(z,z1) - zgdif=zeta(z2,z1) -! set up spline nodes - do 220 k=1,mn - xs(k)=zeta(zn3(k),z1)/zgdif - ys(k)=1./tn3(k) - 220 end do - yd1=-tgn3(1)/(t1*t1)*zgdif - yd2=-tgn3(2)/(t2*t2)*zgdif*((re+z2)/(re+z1))**2 -! calculate spline coefficients - call spline(xs,ys,mn,yd1,yd2,y2out) - x=zg/zgdif - call splint(xs,ys,y2out,mn,x,y) -! temperature at altitude - tz=1./y - if(xm.eq.0.) go to 30 -! -! calculate tropospheric/stratosphere density -! - glb=gsurf/(1.+z1/re)**2 - gamm=xm*glb*zgdif/rgas -! integrate temperature profile - call splini(xs,ys,y2out,mn,x,yi) - expl=gamm*yi - if(expl.gt.50.) expl=50. -! density at altitude - densm=densm*(t1/tz)*exp(-expl) - 30 continue - 50 continue - if(xm.eq.0) densm=tz - return - end function densm - -!----------------------------------------------------------------------- -!> Calculate 2nd derivatives of cubic spline interp function. -!! -!! Adapted from numerical recipes by press et al. -!! @param[in] x arrays of tabulated function in ascending order by x -!! @param[in] y arrays of tabulated function in ascending order by x -!! @param[in] n size of arrays x,y -!! @param[in] yp1 specified derivatives at x(1) -!! @param[in] ypn specified derivatives at x(n) -!! values >= 1e30 signal signal second derivative zero. -!! @param[out] y2 output array of second derivatives -!! -!! @author Hann-Ming Henry Juang - subroutine spline(x,y,n,yp1,ypn,y2) - parameter (nmax=100) - dimension x(n),y(n),y2(n),u(nmax) - save - if(yp1.gt..99e30) then - y2(1)=0 - u(1)=0 - else - y2(1)=-.5 - u(1)=(3./(x(2)-x(1)))*((y(2)-y(1))/(x(2)-x(1))-yp1) - endif - do 11 i=2,n-1 - sig=(x(i)-x(i-1))/(x(i+1)-x(i-1)) - p=sig*y2(i-1)+2. - y2(i)=(sig-1.)/p - u(i)=(6.*((y(i+1)-y(i))/(x(i+1)-x(i))-(y(i)-y(i-1)) & - /(x(i)-x(i-1)))/(x(i+1)-x(i-1))-sig*u(i-1))/p - 11 end do - if(ypn.gt..99e30) then - qn=0 - un=0 - else - qn=.5 - un=(3./(x(n)-x(n-1)))*(ypn-(y(n)-y(n-1))/(x(n)-x(n-1))) - endif - y2(n)=(un-qn*u(n-1))/(qn*y2(n-1)+1.) - do 12 k=n-1,1,-1 - y2(k)=y2(k)*y2(k+1)+u(k) - 12 end do - return - end subroutine spline - -!----------------------------------------------------------------------- -!> Calculate cubic spline interp value. -!! -!! Adapted from numerical recipes by press et al. -!! @param[in] xa arrays of tabulated function in ascending order by x -!! @param[in] ya arrays of tabulated function in ascending order by x -!! @param[in] y2a array of second derivatives -!! @param[in] n size of arrays xa,ya,y2a -!! @param[in] x abscissa for interpolation -!! @param[out] y output value -!! -!! @author Hann-Ming Henry Juang - subroutine splint(xa,ya,y2a,n,x,y) - dimension xa(n),ya(n),y2a(n) - save - klo=1 - khi=n - 1 continue - if(khi-klo.gt.1) then - k=(khi+klo)/2 - if(xa(k).gt.x) then - khi=k - else - klo=k - endif - goto 1 - endif - h=xa(khi)-xa(klo) - if(h.eq.0) write(6,*) 'bad xa input to splint' - a=(xa(khi)-x)/h - b=(x-xa(klo))/h - y=a*ya(klo)+b*ya(khi)+ & - ((a*a*a-a)*y2a(klo)+(b*b*b-b)*y2a(khi))*h*h/6. - return - end subroutine splint - -!----------------------------------------------------------------------- -!> Integrate cubic spline function. -!! -!! @param[in] xa arrays of tabulated function in ascending order by x -!! @param[in] ya arrays of tabulated function in ascending order by x -!! @param[in] y2a array of second derivatives -!! @param[in] n size of arrays xa,ya,y2a -!! @param[in] x abscissa endpoint for integration -!! @param[out] yi output value -!! -!! @author Hann-Ming Henry Juang - subroutine splini(xa,ya,y2a,n,x,yi) - dimension xa(n),ya(n),y2a(n) - save - yi=0 - klo=1 - khi=2 - 1 continue - if(x.gt.xa(klo).and.khi.le.n) then - xx=x - if(khi.lt.n) xx=amin1(x,xa(khi)) - h=xa(khi)-xa(klo) - a=(xa(khi)-xx)/h - b=(xx-xa(klo))/h - a2=a*a - b2=b*b - yi=yi+((1.-a2)*ya(klo)/2.+b2*ya(khi)/2.+ & - ((-(1.+a2*a2)/4.+a2/2.)*y2a(klo)+ & - (b2*b2/4.-b2/2.)*y2a(khi))*h*h/6.)*h - klo=klo+1 - khi=khi+1 - goto 1 - endif - return - end subroutine splini - -!----------------------------------------------------------------------- -!> Turbopause correction. -!! -!! @param[in] dd diffusive density -!! @param[in] dm full mixed density -!! @param[in] zhm transition scale length -!! @param[in] xmm full mixed molecular weight -!! @param[in] xm species molecular weight -!! @return dnet combined density -!! -!! @author Hann-Ming Henry Juang - function dnet(dd,dm,zhm,xmm,xm) - save - a=zhm/(xmm-xm) - if(dm.gt.0.and.dd.gt.0) goto 5 - write(6,*) 'dnet log error',dm,dd,xm - if(dd.eq.0.and.dm.eq.0) dd=1. - if(dm.eq.0) goto 10 - if(dd.eq.0) goto 20 - 5 continue - ylog=a*alog(dm/dd) - if(ylog.lt.-10.) go to 10 - if(ylog.gt.10.) go to 20 - dnet=dd*(1.+exp(ylog))**(1/a) - go to 50 - 10 continue - dnet=dd - go to 50 - 20 continue - dnet=dm - go to 50 - 50 continue - return - end function dnet - -!----------------------------------------------------------------------- -!> Chemistry/dissociation correction. -!! -!! @param[in] alt altitude -!! @param[in] r target ratio -!! @param[in] h1 transition scale length -!! @param[in] zh altitude of 1/2 r -!! @return ccor correction -!! -!! @author Hann-Ming Henry Juang - function ccor(alt, r,h1,zh) - save - e=(alt-zh)/h1 - if(e.gt.70.) go to 20 - if(e.lt.-70.) go to 10 - ex=exp(e) - ccor=r/(1.+ex) - go to 50 - 10 ccor=r - go to 50 - 20 ccor=0. - go to 50 - 50 continue - ccor=exp(ccor) - return - end function ccor - -!----------------------------------------------------------------------- -!> O and O2 chemistry/dissociation correction. -!! -!! @param[in] alt altitude -!! @param[in] r target ratio -!! @param[in] h1 transition scale length 1 -!! @param[in] zh altitude of 1/2 r -!! @param[in] h2 transition scale length 2 -!! @return ccor2 correction -!! -!! @author Hann-Ming Henry Juang - function ccor2(alt, r,h1,zh,h2) - e1=(alt-zh)/h1 - e2=(alt-zh)/h2 - if(e1.gt.70. .or. e2.gt.70.) go to 20 - if(e1.lt.-70. .and. e2.lt.-70) go to 10 - ex1=exp(e1) - ex2=exp(e2) - ccor2=r/(1.+.5*(ex1+ex2)) - go to 50 - 10 ccor2=r - go to 50 - 20 ccor2=0. - go to 50 - 50 continue - ccor2=exp(ccor2) - return - end function ccor2 +!! This software incorporates the MSIS empirical atmospheric model software +!! designed and provided by NRL. Use is governed by the Open Source Academic +!! research License Agreement contained in the file msis2.1/nrlmsis2.1_license.txt +!! +!! @author Adam Kubaryk NCEP/SWPC + +!> Routine that computes temperature and neutral density values utilizing MSIS 2.1. +!! +!! @param[in] iday Calendar day. +!! @param[in] xlat Latitude (degrees). +!! @param[in] pr Pressure in hPa. +!! @param[in] pf Path to parmfile for msisinit. +!! @param[in] np Number of pressure layers. +!! @param[out] temp Temperature (K). +!! @param[out] n_o Number density of o. +!! @param[out] n_o2 Number density of o2. +!! @param[out] n_n2 Number density of n2 +!! +!! @author Adam Kubaryk NCEP/SWPC + subroutine gettemp(iday,xlat,pr,np,pf,temp,n_o,n_o2,n_n2) + use msis_init, only: msisinit + use msis_constants, only: rp + use esmf, only: esmf_kind_r8 + + implicit none + + integer, intent(in) :: iday ! calender day + real(kind=esmf_kind_r8), intent(in) :: xlat ! latitude (degrees) + real(kind=esmf_kind_r8), intent(in) :: pr(np) ! pressure (hPa) + integer, intent(in) :: np ! number of pressure layers + character(*), intent(in) :: pf ! path to parmfile for msisinit + real(kind=esmf_kind_r8), intent(out) :: temp(np) ! temperature (K) + real(kind=esmf_kind_r8), intent(out) :: n_o(np) ! number density of o + real(kind=esmf_kind_r8), intent(out) :: n_o2(np) ! number density of o2 + real(kind=esmf_kind_r8), intent(out) :: n_n2(np) ! number density of n2 +! Local variables + real(kind=rp), parameter :: alt=100, ut=0, f107=150, f107a=150, ap(7)=9, xlong=0 + real(kind=rp) :: t, d(10), zkm + integer :: ip + real(4) :: switch_legacy(1:25) + +! set swich 7,8,10,14 to zero to avoid diurnal changes in output tempe +! #7 is for diurnal, #8 for semidiurnal, #10 is for all ut/longitudinal +! effect, #14 is for terdiurnal + switch_legacy(:) = 1. + switch_legacy(7) = 0. + switch_legacy(8) = 0. + switch_legacy(10) = 0. + switch_legacy(14) = 0. + + call msisinit(parmfile=pf, switch_legacy=switch_legacy) +! calculate temperature, species, for each pres level + do ip=1,np + call ghp8(real(iday, rp), ut, alt, real(xlat, rp), & + xlong , f107a, f107, ap, real(pr(ip), rp), & + zkm, d, t) + temp(ip)=real(t, esmf_kind_r8) + n_n2(ip)=real(d(2), esmf_kind_r8) + n_o2(ip)=real(d(3), esmf_kind_r8) + n_o( ip)=real(d(4), esmf_kind_r8) + enddo + + end subroutine gettemp + +!> Wrapper routine for calls to MSIS 2.1 for computing temperature and neutral density at +!> a given pressure level. +!! +!! @param[in] day Calendar day. +!! @param[in] utsec Seconds into UTC day. +!! @param[in] z0 Initial guess for altitude in km. +!! @param[in] glat Latitude in degrees east. +!! @param[in] glon Longitude in degrees north. +!! @param[in] f107a 41-day average of F10.7 Solar Flux. +!! @param[in] f107 Current day F10.7 Solar Flux. +!! @param[in] ap Array of Ap inputs to MSIS 2.1, documented within MSIS 2.1. +!! @param[in] pres Pressure level at which to solve for temp/den values. +!! @param[out] alt Altitude at which the outputs are valid. +!! @param[out] dn Array of neutral density values, documented within MSIS 2.1. +!! @param[out] tn Temperature in K. +!! +!! @author Adam Kubaryk NCEP/SWPC + subroutine ghp8(day,utsec,z0,glat,glon,f107a,f107,ap,pres,alt,dn,tn) + + use msis_constants, only: kB, NA, g0, rp + use msis_calc, only: msiscalc + use msis_utils, only: alt2gph + + implicit none + + real(kind=rp),intent(in) :: day + real(kind=rp),intent(in) :: utsec + real(kind=rp),intent(in) :: z0 !! first guess + real(kind=rp),intent(in) :: glat,glon + real(kind=rp),intent(in) :: f107a,f107 + real(kind=rp),intent(in) :: ap(7) + real(kind=rp),intent(in) :: pres !!! pressure in hPa + real(kind=rp),intent(out) :: alt + real(kind=rp),intent(out) :: dn(10) + real(kind=rp),intent(out) :: tn +! Local variables + real, parameter :: tol = 0.000043 + integer, parameter :: maxit = 30 + real :: plog,delta + real(kind=rp) :: tex,zkm,pzkm + real :: xn,gz,xmbar,scl + integer :: n + real(8) :: xlat,alt0,alt1 + + plog = log10(pres*100.0_rp) + zkm = z0 + delta = 1.0_rp + + n = 0 + + do while ( abs(delta) .ge. tol .and. n .le. maxit ) + n = n + 1 + + call msiscalc(day,utsec,zkm,glat,glon,f107a,f107,ap,tn,dn,tex) + + xn = sum(dn(2:8)) + pzkm = kB * xn * tn + delta = plog - log10(pzkm) + xmbar = dn(1) / xn / 1.66E-24_rp + xlat = dble(glat) + alt0 = dble(zkm) + alt1 = alt0 + 1.0d0 + gz = real((alt2gph(xlat,alt1) - alt2gph(xlat,alt0)) * g0) + scl = Na * kB * tn / (xmbar * gz) + + ! difference + zkm = zkm - scl * delta / 1000.0_rp + end do + alt = zkm + + end subroutine ghp8 diff --git a/sorc/chgres_cube.fd/write_data.F90 b/sorc/chgres_cube.fd/write_data.F90 index fa28beff6..3556a0137 100644 --- a/sorc/chgres_cube.fd/write_data.F90 +++ b/sorc/chgres_cube.fd/write_data.F90 @@ -1,3 +1,17 @@ + module write_data + + use utilities, only : error_handler, netcdf_err + + private + + public :: write_fv3_atm_header_netcdf + public :: write_fv3_atm_bndy_data_netcdf + public :: write_fv3_atm_data_netcdf + public :: write_fv3_sfc_data_netcdf + public :: write_fv3_atm_warm_restart + + contains + !> @file !! @brief Writes the tiled and header files expected by the forecast !! model. @@ -18,9 +32,9 @@ subroutine write_fv3_atm_header_netcdf(localpet) use netcdf - use atmosphere, only : nvcoord_target, & - vcoord_target, & - levp1_target + use atmosphere_target_data, only : nvcoord_target, & + vcoord_target, & + levp1_target use program_setup, only : num_tracers, use_thomp_mp_climo @@ -30,7 +44,6 @@ subroutine write_fv3_atm_header_netcdf(localpet) character(len=13) :: outfile - integer :: fsize=65536, initial = 0 integer :: header_buffer_val = 16384 integer :: error, ncid, dim_nvcoord integer :: dim_levp1, id_ntrac, id_vcoord @@ -44,8 +57,7 @@ subroutine write_fv3_atm_header_netcdf(localpet) print*,"- WRITE ATMOSPHERIC HEADER FILE: ", trim(outfile) - error = nf90_create(outfile, IOR(NF90_NETCDF4,NF90_CLASSIC_MODEL), & - ncid, initialsize=initial, chunksize=fsize) + error = nf90_create(outfile, NF90_NETCDF4, ncid) call netcdf_err(error, 'CREATING FILE='//trim(outfile) ) error = nf90_def_dim(ncid, 'nvcoord', nvcoord_target, dim_nvcoord) @@ -105,18 +117,12 @@ subroutine write_fv3_atm_bndy_data_netcdf(localpet) use esmf use netcdf - use atmosphere, only : lev_target, levp1_target, & - dzdt_target_grid, & - ps_target_grid, & - tracers_target_grid, & - u_s_target_grid, & - v_s_target_grid, & - u_w_target_grid, & - v_w_target_grid, & - temp_target_grid, & - zh_target_grid, & - qnifa_climo_target_grid, & - qnwfa_climo_target_grid + use atmosphere_target_data, only : lev_target, levp1_target, & + ps_target_grid, zh_target_grid, & + tracers_target_grid, dzdt_target_grid, & + temp_target_grid, qnifa_climo_target_grid, & + qnwfa_climo_target_grid, u_s_target_grid, & + v_s_target_grid, u_w_target_grid, v_w_target_grid use model_grid, only : i_target, ip1_target, j_target, jp1_target @@ -130,7 +136,6 @@ subroutine write_fv3_atm_bndy_data_netcdf(localpet) character(len=50) :: name - integer :: fsize=65536, initial = 0 integer :: header_buffer_val = 16384 integer :: ncid, error, tile, i, n integer :: dim_lon, dim_lat @@ -202,8 +207,7 @@ subroutine write_fv3_atm_bndy_data_netcdf(localpet) if (localpet == 0) then !--- open the file - error = nf90_create("./gfs.bndy.nc", IOR(NF90_NETCDF4,NF90_CLASSIC_MODEL), & - ncid, initialsize=initial, chunksize=fsize) + error = nf90_create("./gfs.bndy.nc", NF90_NETCDF4, ncid) call netcdf_err(error, 'CREATING BNDY FILE' ) error = nf90_def_dim(ncid, 'lon', i_target, dim_lon) @@ -658,16 +662,16 @@ subroutine write_fv3_atm_bndy_data_netcdf(localpet) call error_handler("IN FieldGather", error) if (localpet == 0) then - dum2d_top(:,:) = data_one_tile(i_start_top:i_end_top, j_start_top:j_end_top) + dum2d_top(:,:) = real(data_one_tile(i_start_top:i_end_top, j_start_top:j_end_top),kind=4) error = nf90_put_var( ncid, id_ps_top, dum2d_top) call netcdf_err(error, 'WRITING PS TOP' ) - dum2d_bottom(:,:) = data_one_tile(i_start_bottom:i_end_bottom, j_start_bottom:j_end_bottom) + dum2d_bottom(:,:) = real(data_one_tile(i_start_bottom:i_end_bottom, j_start_bottom:j_end_bottom),kind=4) error = nf90_put_var( ncid, id_ps_bottom, dum2d_bottom) call netcdf_err(error, 'WRITING PS BOTTOM' ) - dum2d_left(:,:) = data_one_tile(i_start_left:i_end_left, j_start_left:j_end_left) + dum2d_left(:,:) = real(data_one_tile(i_start_left:i_end_left, j_start_left:j_end_left),kind=4) error = nf90_put_var( ncid, id_ps_left, dum2d_left) call netcdf_err(error, 'WRITING PS LEFT' ) - dum2d_right(:,:) = data_one_tile(i_start_right:i_end_right, j_start_right:j_end_right) + dum2d_right(:,:) = real(data_one_tile(i_start_right:i_end_right, j_start_right:j_end_right),kind=4) error = nf90_put_var( ncid, id_ps_right, dum2d_right) call netcdf_err(error, 'WRITING PS RIGHT' ) endif @@ -696,19 +700,19 @@ subroutine write_fv3_atm_bndy_data_netcdf(localpet) call error_handler("IN FieldGather", error) if (localpet == 0) then - dum3d_top(:,:,:) = data_one_tile_3d(i_start_top:i_end_top,j_start_top:j_end_top,:) + dum3d_top(:,:,:) = real(data_one_tile_3d(i_start_top:i_end_top,j_start_top:j_end_top,:),kind=4) dum3d_top(:,:,1:levp1_target) = dum3d_top(:,:,levp1_target:1:-1) error = nf90_put_var( ncid, id_zh_top, dum3d_top) call netcdf_err(error, 'WRITING ZH TOP' ) - dum3d_bottom(:,:,:) = data_one_tile_3d(i_start_bottom:i_end_bottom,j_start_bottom:j_end_bottom,:) + dum3d_bottom(:,:,:) = real(data_one_tile_3d(i_start_bottom:i_end_bottom,j_start_bottom:j_end_bottom,:),kind=4) dum3d_bottom(:,:,1:levp1_target) = dum3d_bottom(:,:,levp1_target:1:-1) error = nf90_put_var( ncid, id_zh_bottom, dum3d_bottom) call netcdf_err(error, 'WRITING ZH BOTTOM' ) - dum3d_left(:,:,:) = data_one_tile_3d(i_start_left:i_end_left,j_start_left:j_end_left,:) + dum3d_left(:,:,:) = real(data_one_tile_3d(i_start_left:i_end_left,j_start_left:j_end_left,:),kind=4) dum3d_left(:,:,1:levp1_target) = dum3d_left(:,:,levp1_target:1:-1) error = nf90_put_var( ncid, id_zh_left, dum3d_left) call netcdf_err(error, 'WRITING ZH LEFT' ) - dum3d_right(:,:,:) = data_one_tile_3d(i_start_right:i_end_right,j_start_right:j_end_right,:) + dum3d_right(:,:,:) = real(data_one_tile_3d(i_start_right:i_end_right,j_start_right:j_end_right,:),kind=4) dum3d_right(:,:,1:levp1_target) = dum3d_right(:,:,levp1_target:1:-1) error = nf90_put_var( ncid, id_zh_right, dum3d_right) call netcdf_err(error, 'WRITING ZH RIGHT' ) @@ -740,19 +744,19 @@ subroutine write_fv3_atm_bndy_data_netcdf(localpet) call error_handler("IN FieldGather", error) if (localpet == 0) then - dum3d_top(:,:,:) = data_one_tile_3d(i_start_top:i_end_top,j_start_top:j_end_top,:) + dum3d_top(:,:,:) = real(data_one_tile_3d(i_start_top:i_end_top,j_start_top:j_end_top,:),kind=4) dum3d_top(:,:,1:lev_target) = dum3d_top(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_tracer_top(n), dum3d_top) call netcdf_err(error, 'WRITING TRACER TOP' ) - dum3d_bottom(:,:,:) = data_one_tile_3d(i_start_bottom:i_end_bottom,j_start_bottom:j_end_bottom,:) + dum3d_bottom(:,:,:) = real(data_one_tile_3d(i_start_bottom:i_end_bottom,j_start_bottom:j_end_bottom,:),kind=4) dum3d_bottom(:,:,1:lev_target) = dum3d_bottom(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_tracer_bottom(n), dum3d_bottom) call netcdf_err(error, 'WRITING TRACER BOTTOM' ) - dum3d_left(:,:,:) = data_one_tile_3d(i_start_left:i_end_left,j_start_left:j_end_left,:) + dum3d_left(:,:,:) = real(data_one_tile_3d(i_start_left:i_end_left,j_start_left:j_end_left,:),kind=4) dum3d_left(:,:,1:lev_target) = dum3d_left(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_tracer_left(n), dum3d_left) call netcdf_err(error, 'WRITING TRACER LEFT' ) - dum3d_right(:,:,:) = data_one_tile_3d(i_start_right:i_end_right,j_start_right:j_end_right,:) + dum3d_right(:,:,:) = real(data_one_tile_3d(i_start_right:i_end_right,j_start_right:j_end_right,:),kind=4) dum3d_right(:,:,1:lev_target) = dum3d_right(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_tracer_right(n), dum3d_right) call netcdf_err(error, 'WRITING TRACER RIGHT' ) @@ -768,19 +772,19 @@ subroutine write_fv3_atm_bndy_data_netcdf(localpet) call error_handler("IN FieldGather", error) if (localpet == 0) then - dum3d_top(:,:,:) = data_one_tile_3d(i_start_top:i_end_top,j_start_top:j_end_top,:) + dum3d_top(:,:,:) = real(data_one_tile_3d(i_start_top:i_end_top,j_start_top:j_end_top,:),kind=4) dum3d_top(:,:,1:lev_target) = dum3d_top(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_w_top, dum3d_top) call netcdf_err(error, 'WRITING W TOP' ) - dum3d_bottom(:,:,:) = data_one_tile_3d(i_start_bottom:i_end_bottom,j_start_bottom:j_end_bottom,:) + dum3d_bottom(:,:,:) = real(data_one_tile_3d(i_start_bottom:i_end_bottom,j_start_bottom:j_end_bottom,:),kind=4) dum3d_bottom(:,:,1:lev_target) = dum3d_bottom(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_w_bottom, dum3d_bottom) call netcdf_err(error, 'WRITING W BOTTOM' ) - dum3d_left(:,:,:) = data_one_tile_3d(i_start_left:i_end_left,j_start_left:j_end_left,:) + dum3d_left(:,:,:) = real(data_one_tile_3d(i_start_left:i_end_left,j_start_left:j_end_left,:),kind=4) dum3d_left(:,:,1:lev_target) = dum3d_left(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_w_left, dum3d_left) call netcdf_err(error, 'WRITING W LEFT' ) - dum3d_right(:,:,:) = data_one_tile_3d(i_start_right:i_end_right,j_start_right:j_end_right,:) + dum3d_right(:,:,:) = real(data_one_tile_3d(i_start_right:i_end_right,j_start_right:j_end_right,:),kind=4) dum3d_right(:,:,1:lev_target) = dum3d_right(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_w_right, dum3d_right) call netcdf_err(error, 'WRITING W RIGHT' ) @@ -794,19 +798,19 @@ subroutine write_fv3_atm_bndy_data_netcdf(localpet) call error_handler("IN FieldGather", error) if (localpet == 0) then - dum3d_top(:,:,:) = data_one_tile_3d(i_start_top:i_end_top,j_start_top:j_end_top,:) + dum3d_top(:,:,:) = real(data_one_tile_3d(i_start_top:i_end_top,j_start_top:j_end_top,:),kind=4) dum3d_top(:,:,1:lev_target) = dum3d_top(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_t_top, dum3d_top) call netcdf_err(error, 'WRITING T TOP' ) - dum3d_bottom(:,:,:) = data_one_tile_3d(i_start_bottom:i_end_bottom,j_start_bottom:j_end_bottom,:) + dum3d_bottom(:,:,:) = real(data_one_tile_3d(i_start_bottom:i_end_bottom,j_start_bottom:j_end_bottom,:),kind=4) dum3d_bottom(:,:,1:lev_target) = dum3d_bottom(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_t_bottom, dum3d_bottom) call netcdf_err(error, 'WRITING T BOTTOM' ) - dum3d_left(:,:,:) = data_one_tile_3d(i_start_left:i_end_left,j_start_left:j_end_left,:) + dum3d_left(:,:,:) = real(data_one_tile_3d(i_start_left:i_end_left,j_start_left:j_end_left,:),kind=4) dum3d_left(:,:,1:lev_target) = dum3d_left(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_t_left, dum3d_left) call netcdf_err(error, 'WRITING T LEFT' ) - dum3d_right(:,:,:) = data_one_tile_3d(i_start_right:i_end_right,j_start_right:j_end_right,:) + dum3d_right(:,:,:) = real(data_one_tile_3d(i_start_right:i_end_right,j_start_right:j_end_right,:),kind=4) dum3d_right(:,:,1:lev_target) = dum3d_right(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_t_right, dum3d_right) call netcdf_err(error, 'WRITING T RIGHT' ) @@ -820,19 +824,19 @@ subroutine write_fv3_atm_bndy_data_netcdf(localpet) call error_handler("IN FieldGather", error) if (localpet == 0) then - dum3d_top(:,:,:) = data_one_tile_3d(i_start_top:i_end_top,j_start_top:j_end_top,:) + dum3d_top(:,:,:) = real(data_one_tile_3d(i_start_top:i_end_top,j_start_top:j_end_top,:),kind=4) dum3d_top(:,:,1:lev_target) = dum3d_top(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_qnifa_top, dum3d_top) call netcdf_err(error, 'WRITING QNIFA CLIMO TOP' ) - dum3d_bottom(:,:,:) = data_one_tile_3d(i_start_bottom:i_end_bottom,j_start_bottom:j_end_bottom,:) + dum3d_bottom(:,:,:) = real(data_one_tile_3d(i_start_bottom:i_end_bottom,j_start_bottom:j_end_bottom,:),kind=4) dum3d_bottom(:,:,1:lev_target) = dum3d_bottom(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_qnifa_bottom, dum3d_bottom) call netcdf_err(error, 'WRITING QNIFA CLIMO BOTTOM' ) - dum3d_left(:,:,:) = data_one_tile_3d(i_start_left:i_end_left,j_start_left:j_end_left,:) + dum3d_left(:,:,:) = real(data_one_tile_3d(i_start_left:i_end_left,j_start_left:j_end_left,:),kind=4) dum3d_left(:,:,1:lev_target) = dum3d_left(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_qnifa_left, dum3d_left) call netcdf_err(error, 'WRITING QNIFA CLIMO LEFT' ) - dum3d_right(:,:,:) = data_one_tile_3d(i_start_right:i_end_right,j_start_right:j_end_right,:) + dum3d_right(:,:,:) = real(data_one_tile_3d(i_start_right:i_end_right,j_start_right:j_end_right,:),kind=4) dum3d_right(:,:,1:lev_target) = dum3d_right(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_qnifa_right, dum3d_right) call netcdf_err(error, 'WRITING QNIFA CLIMO RIGHT' ) @@ -844,19 +848,19 @@ subroutine write_fv3_atm_bndy_data_netcdf(localpet) call error_handler("IN FieldGather", error) if (localpet == 0) then - dum3d_top(:,:,:) = data_one_tile_3d(i_start_top:i_end_top,j_start_top:j_end_top,:) + dum3d_top(:,:,:) = real(data_one_tile_3d(i_start_top:i_end_top,j_start_top:j_end_top,:),kind=4) dum3d_top(:,:,1:lev_target) = dum3d_top(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_qnwfa_top, dum3d_top) call netcdf_err(error, 'WRITING QNWFA CLIMO TOP' ) - dum3d_bottom(:,:,:) = data_one_tile_3d(i_start_bottom:i_end_bottom,j_start_bottom:j_end_bottom,:) + dum3d_bottom(:,:,:) = real(data_one_tile_3d(i_start_bottom:i_end_bottom,j_start_bottom:j_end_bottom,:),kind=4) dum3d_bottom(:,:,1:lev_target) = dum3d_bottom(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_qnwfa_bottom, dum3d_bottom) call netcdf_err(error, 'WRITING QNWFA CLIMO BOTTOM' ) - dum3d_left(:,:,:) = data_one_tile_3d(i_start_left:i_end_left,j_start_left:j_end_left,:) + dum3d_left(:,:,:) = real(data_one_tile_3d(i_start_left:i_end_left,j_start_left:j_end_left,:),kind=4) dum3d_left(:,:,1:lev_target) = dum3d_left(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_qnwfa_left, dum3d_left) call netcdf_err(error, 'WRITING QNWFA CLIMO LEFT' ) - dum3d_right(:,:,:) = data_one_tile_3d(i_start_right:i_end_right,j_start_right:j_end_right,:) + dum3d_right(:,:,:) = real(data_one_tile_3d(i_start_right:i_end_right,j_start_right:j_end_right,:),kind=4) dum3d_right(:,:,1:lev_target) = dum3d_right(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_qnwfa_right, dum3d_right) call netcdf_err(error, 'WRITING QNWFA CLIMO RIGHT' ) @@ -976,19 +980,19 @@ subroutine write_fv3_atm_bndy_data_netcdf(localpet) call error_handler("IN FieldGather", error) if (localpet == 0) then - dum3d_top(:,:,:) = data_one_tile_3d(i_start_top:i_end_top,j_start_top:j_end_top,:) + dum3d_top(:,:,:) = real(data_one_tile_3d(i_start_top:i_end_top,j_start_top:j_end_top,:),kind=4) dum3d_top(:,:,1:lev_target) = dum3d_top(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_u_s_top, dum3d_top) call netcdf_err(error, 'WRITING U_S TOP' ) - dum3d_bottom(:,:,:) = data_one_tile_3d(i_start_bottom:i_end_bottom,j_start_bottom:j_end_bottom,:) + dum3d_bottom(:,:,:) = real(data_one_tile_3d(i_start_bottom:i_end_bottom,j_start_bottom:j_end_bottom,:),kind=4) dum3d_bottom(:,:,1:lev_target) = dum3d_bottom(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_u_s_bottom, dum3d_bottom) call netcdf_err(error, 'WRITING U_S BOTTOM' ) - dum3d_left(:,:,:) = data_one_tile_3d(i_start_left:i_end_left,j_start_left:j_end_left,:) + dum3d_left(:,:,:) = real(data_one_tile_3d(i_start_left:i_end_left,j_start_left:j_end_left,:),kind=4) dum3d_left(:,:,1:lev_target) = dum3d_left(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_u_s_left, dum3d_left) call netcdf_err(error, 'WRITING U_S LEFT' ) - dum3d_right(:,:,:) = data_one_tile_3d(i_start_right:i_end_right,j_start_right:j_end_right,:) + dum3d_right(:,:,:) = real(data_one_tile_3d(i_start_right:i_end_right,j_start_right:j_end_right,:),kind=4) dum3d_right(:,:,1:lev_target) = dum3d_right(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_u_s_right, dum3d_right) call netcdf_err(error, 'WRITING U_S RIGHT' ) @@ -1002,19 +1006,19 @@ subroutine write_fv3_atm_bndy_data_netcdf(localpet) call error_handler("IN FieldGather", error) if (localpet == 0) then - dum3d_top(:,:,:) = data_one_tile_3d(i_start_top:i_end_top,j_start_top:j_end_top,:) + dum3d_top(:,:,:) = real(data_one_tile_3d(i_start_top:i_end_top,j_start_top:j_end_top,:),kind=4) dum3d_top(:,:,1:lev_target) = dum3d_top(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_v_s_top, dum3d_top) call netcdf_err(error, 'WRITING V_S TOP' ) - dum3d_bottom(:,:,:) = data_one_tile_3d(i_start_bottom:i_end_bottom,j_start_bottom:j_end_bottom,:) + dum3d_bottom(:,:,:) = real(data_one_tile_3d(i_start_bottom:i_end_bottom,j_start_bottom:j_end_bottom,:),kind=4) dum3d_bottom(:,:,1:lev_target) = dum3d_bottom(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_v_s_bottom, dum3d_bottom) call netcdf_err(error, 'WRITING V_S BOTTOM' ) - dum3d_left(:,:,:) = data_one_tile_3d(i_start_left:i_end_left,j_start_left:j_end_left,:) + dum3d_left(:,:,:) = real(data_one_tile_3d(i_start_left:i_end_left,j_start_left:j_end_left,:),kind=4) dum3d_left(:,:,1:lev_target) = dum3d_left(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_v_s_left, dum3d_left) call netcdf_err(error, 'WRITING V_S LEFT' ) - dum3d_right(:,:,:) = data_one_tile_3d(i_start_right:i_end_right,j_start_right:j_end_right,:) + dum3d_right(:,:,:) = real(data_one_tile_3d(i_start_right:i_end_right,j_start_right:j_end_right,:),kind=4) dum3d_right(:,:,1:lev_target) = dum3d_right(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_v_s_right, dum3d_right) call netcdf_err(error, 'WRITING V_S RIGHT' ) @@ -1132,19 +1136,19 @@ subroutine write_fv3_atm_bndy_data_netcdf(localpet) call error_handler("IN FieldGather", error) if (localpet == 0) then - dum3d_top(:,:,:) = data_one_tile_3d(i_start_top:i_end_top,j_start_top:j_end_top,:) + dum3d_top(:,:,:) = real(data_one_tile_3d(i_start_top:i_end_top,j_start_top:j_end_top,:),kind=4) dum3d_top(:,:,1:lev_target) = dum3d_top(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_u_w_top, dum3d_top) call netcdf_err(error, 'WRITING U_W TOP' ) - dum3d_bottom(:,:,:) = data_one_tile_3d(i_start_bottom:i_end_bottom,j_start_bottom:j_end_bottom,:) + dum3d_bottom(:,:,:) = real(data_one_tile_3d(i_start_bottom:i_end_bottom,j_start_bottom:j_end_bottom,:),kind=4) dum3d_bottom(:,:,1:lev_target) = dum3d_bottom(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_u_w_bottom, dum3d_bottom) call netcdf_err(error, 'WRITING U_W BOTTOM' ) - dum3d_left(:,:,:) = data_one_tile_3d(i_start_left:i_end_left,j_start_left:j_end_left,:) + dum3d_left(:,:,:) = real(data_one_tile_3d(i_start_left:i_end_left,j_start_left:j_end_left,:),kind=4) dum3d_left(:,:,1:lev_target) = dum3d_left(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_u_w_left, dum3d_left) call netcdf_err(error, 'WRITING U_W LEFT' ) - dum3d_right(:,:,:) = data_one_tile_3d(i_start_right:i_end_right,j_start_right:j_end_right,:) + dum3d_right(:,:,:) = real(data_one_tile_3d(i_start_right:i_end_right,j_start_right:j_end_right,:),kind=4) dum3d_right(:,:,1:lev_target) = dum3d_right(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_u_w_right, dum3d_right) call netcdf_err(error, 'WRITING U_W RIGHT' ) @@ -1158,19 +1162,19 @@ subroutine write_fv3_atm_bndy_data_netcdf(localpet) call error_handler("IN FieldGather", error) if (localpet == 0) then - dum3d_top(:,:,:) = data_one_tile_3d(i_start_top:i_end_top,j_start_top:j_end_top,:) + dum3d_top(:,:,:) = real(data_one_tile_3d(i_start_top:i_end_top,j_start_top:j_end_top,:),kind=4) dum3d_top(:,:,1:lev_target) = dum3d_top(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_v_w_top, dum3d_top) call netcdf_err(error, 'WRITING V_W TOP' ) - dum3d_bottom(:,:,:) = data_one_tile_3d(i_start_bottom:i_end_bottom,j_start_bottom:j_end_bottom,:) + dum3d_bottom(:,:,:) = real(data_one_tile_3d(i_start_bottom:i_end_bottom,j_start_bottom:j_end_bottom,:),kind=4) dum3d_bottom(:,:,1:lev_target) = dum3d_bottom(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_v_w_bottom, dum3d_bottom) call netcdf_err(error, 'WRITING V_W BOTTOM' ) - dum3d_left(:,:,:) = data_one_tile_3d(i_start_left:i_end_left,j_start_left:j_end_left,:) + dum3d_left(:,:,:) = real(data_one_tile_3d(i_start_left:i_end_left,j_start_left:j_end_left,:),kind=4) dum3d_left(:,:,1:lev_target) = dum3d_left(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_v_w_left, dum3d_left) call netcdf_err(error, 'WRITING V_W LEFT' ) - dum3d_right(:,:,:) = data_one_tile_3d(i_start_right:i_end_right,j_start_right:j_end_right,:) + dum3d_right(:,:,:) = real(data_one_tile_3d(i_start_right:i_end_right,j_start_right:j_end_right,:),kind=4) dum3d_right(:,:,1:lev_target) = dum3d_right(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_v_w_right, dum3d_right) call netcdf_err(error, 'WRITING V_W RIGHT' ) @@ -1192,7 +1196,7 @@ subroutine write_fv3_atm_warm_restart(localpet) use esmf use netcdf - use atmosphere, only : lev_target, & + use atmosphere_target_data, only : lev_target, & levp1_target, & tracers_target_grid, & temp_target_grid, & @@ -1346,8 +1350,9 @@ subroutine write_fv3_atm_warm_restart(localpet) call netcdf_err(error, 'DEFINING TRACERS' ) enddo - error = nf90_def_var(ncid, 'cld_amt', NF90_FLOAT, (/dim_x,dim_y,dim_z,dim_time/), id_cld) - call netcdf_err(error, 'DEFINING TRACERS' ) +! I think we need to remove this, not sure why it was added in the first place - AMG +! error = nf90_def_var(ncid, 'cld_amt', NF90_FLOAT, (/dim_x,dim_y,dim_z,dim_time/), id_cld) +! call netcdf_err(error, 'DEFINING TRACERS' ) error = nf90_enddef(ncid, header_buffer_val,4,0,4) call netcdf_err(error, 'DEFINING HEADER' ) @@ -1392,11 +1397,12 @@ subroutine write_fv3_atm_warm_restart(localpet) enddo - if (localpet < num_tiles_target_grid) then - dum3d = 0.0 - error = nf90_put_var( ncid, id_cld, dum3d) - call netcdf_err(error, 'WRITING CLD AMT RECORD' ) - endif +! I think we need to remove this, not sure why it was added in the first place - AMG +! if (localpet < num_tiles_target_grid) then +! dum3d = 0.0 +! error = nf90_put_var( ncid, id_cld, dum3d) +! call netcdf_err(error, 'WRITING CLD AMT RECORD' ) +! endif deallocate(id_tracers) deallocate(x_data, y_data, z_data) @@ -1684,20 +1690,13 @@ subroutine write_fv3_atm_data_netcdf(localpet) use_thomp_mp_climo, & regional - use atmosphere, only : lev_target, & - levp1_target, & - ps_target_grid, & - zh_target_grid, & - dzdt_target_grid, & - qnifa_climo_target_grid, & - qnwfa_climo_target_grid, & - tracers_target_grid, & - temp_target_grid, & - delp_target_grid, & - u_s_target_grid, & - v_s_target_grid, & - u_w_target_grid, & - v_w_target_grid + use atmosphere_target_data, only : lev_target, levp1_target, & + ps_target_grid, zh_target_grid, & + dzdt_target_grid, delp_target_grid, & + temp_target_grid, tracers_target_grid, & + qnifa_climo_target_grid, qnwfa_climo_target_grid, & + u_s_target_grid, v_s_target_grid, & + u_w_target_grid, v_w_target_grid use model_grid, only : num_tiles_target_grid, & i_target, j_target, & @@ -1716,7 +1715,6 @@ subroutine write_fv3_atm_data_netcdf(localpet) character(len=128) :: outfile integer :: error, ncid, tile, n - integer :: fsize=65536, initial = 0 integer :: header_buffer_val = 16384 integer :: dim_lon, dim_lat integer :: dim_lonp, dim_latp @@ -1774,8 +1772,7 @@ subroutine write_fv3_atm_data_netcdf(localpet) endif !--- open the file - error = nf90_create(outfile, IOR(NF90_NETCDF4,NF90_CLASSIC_MODEL), & - ncid, initialsize=initial, chunksize=fsize) + error = nf90_create(outfile, NF90_NETCDF4, ncid) call netcdf_err(error, 'CREATING FILE='//trim(outfile) ) !--- define dimension @@ -1936,7 +1933,7 @@ subroutine write_fv3_atm_data_netcdf(localpet) enddo if (localpet < num_tiles_target_grid) then - dum2d(:,:) = data_one_tile(i_start:i_end, j_start:j_end) + dum2d(:,:) = real(data_one_tile(i_start:i_end, j_start:j_end),kind=4) error = nf90_put_var( ncid, id_lon, dum2d) call netcdf_err(error, 'WRITING LONGITUDE RECORD' ) endif @@ -1951,7 +1948,7 @@ subroutine write_fv3_atm_data_netcdf(localpet) enddo if (localpet < num_tiles_target_grid) then - dum2d(:,:) = data_one_tile(i_start:i_end, j_start:j_end) + dum2d(:,:) = real(data_one_tile(i_start:i_end, j_start:j_end),kind=4) error = nf90_put_var( ncid, id_lat, dum2d) call netcdf_err(error, 'WRITING LATITUDE RECORD' ) endif @@ -1966,7 +1963,7 @@ subroutine write_fv3_atm_data_netcdf(localpet) enddo if (localpet < num_tiles_target_grid) then - dum2d(:,:) = data_one_tile(i_start:i_end, j_start:j_end) + dum2d(:,:) = real(data_one_tile(i_start:i_end, j_start:j_end),kind=4) error = nf90_put_var( ncid, id_ps, dum2d) call netcdf_err(error, 'WRITING SURFACE PRESSURE RECORD' ) endif @@ -1991,7 +1988,7 @@ subroutine write_fv3_atm_data_netcdf(localpet) enddo if (localpet < num_tiles_target_grid) then - dum3d(:,:,:) = data_one_tile_3d(i_start:i_end,j_start:j_end,:) + dum3d(:,:,:) = real(data_one_tile_3d(i_start:i_end,j_start:j_end,:),kind=4) dum3d(:,:,1:levp1_target) = dum3d(:,:,levp1_target:1:-1) error = nf90_put_var( ncid, id_zh, dum3d) call netcdf_err(error, 'WRITING HEIGHT RECORD' ) @@ -2017,7 +2014,7 @@ subroutine write_fv3_atm_data_netcdf(localpet) enddo if (localpet < num_tiles_target_grid) then - dum3d(:,:,:) = data_one_tile_3d(i_start:i_end,j_start:j_end,:) + dum3d(:,:,:) = real(data_one_tile_3d(i_start:i_end,j_start:j_end,:),kind=4) dum3d(:,:,1:lev_target) = dum3d(:,:,lev_target:1:-1) print*,"MIN MAX W AT WRITE = ", minval(dum3d(:,:,:)), maxval(dum3d(:,:,:)) error = nf90_put_var( ncid, id_w, dum3d) @@ -2034,7 +2031,7 @@ subroutine write_fv3_atm_data_netcdf(localpet) enddo if (localpet < num_tiles_target_grid) then - dum3d(:,:,:) = data_one_tile_3d(i_start:i_end,j_start:j_end,:) + dum3d(:,:,:) = real(data_one_tile_3d(i_start:i_end,j_start:j_end,:),kind=4) dum3d(:,:,1:lev_target) = dum3d(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_delp, dum3d) call netcdf_err(error, 'WRITING DELP RECORD' ) @@ -2050,7 +2047,7 @@ subroutine write_fv3_atm_data_netcdf(localpet) enddo if (localpet < num_tiles_target_grid) then - dum3d(:,:,:) = data_one_tile_3d(i_start:i_end,j_start:j_end,:) + dum3d(:,:,:) = real(data_one_tile_3d(i_start:i_end,j_start:j_end,:),kind=4) dum3d(:,:,1:lev_target) = dum3d(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_t, dum3d) call netcdf_err(error, 'WRITING TEMPERTAURE RECORD' ) @@ -2068,7 +2065,7 @@ subroutine write_fv3_atm_data_netcdf(localpet) enddo if (localpet < num_tiles_target_grid) then - dum3d(:,:,:) = data_one_tile_3d(i_start:i_end,j_start:j_end,:) + dum3d(:,:,:) = real(data_one_tile_3d(i_start:i_end,j_start:j_end,:),kind=4) dum3d(:,:,1:lev_target) = dum3d(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_tracers(n), dum3d) call netcdf_err(error, 'WRITING TRACER RECORD' ) @@ -2087,7 +2084,7 @@ subroutine write_fv3_atm_data_netcdf(localpet) enddo if (localpet < num_tiles_target_grid) then - dum3d(:,:,:) = data_one_tile_3d(i_start:i_end,j_start:j_end,:) + dum3d(:,:,:) = real(data_one_tile_3d(i_start:i_end,j_start:j_end,:),kind=4) dum3d(:,:,1:lev_target) = dum3d(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_qnifa, dum3d) call netcdf_err(error, 'WRITING QNIFA RECORD' ) @@ -2103,7 +2100,7 @@ subroutine write_fv3_atm_data_netcdf(localpet) enddo if (localpet < num_tiles_target_grid) then - dum3d(:,:,:) = data_one_tile_3d(i_start:i_end,j_start:j_end,:) + dum3d(:,:,:) = real(data_one_tile_3d(i_start:i_end,j_start:j_end,:),kind=4) dum3d(:,:,1:lev_target) = dum3d(:,:,lev_target:1:-1) error = nf90_put_var( ncid, id_qnwfa, dum3d) call netcdf_err(error, 'WRITING QNWFA RECORD' ) @@ -2130,7 +2127,7 @@ subroutine write_fv3_atm_data_netcdf(localpet) enddo if (localpet < num_tiles_target_grid) then - dum2d(:,:) = data_one_tile(i_start:i_end,j_start:jp1_end) + dum2d(:,:) = real(data_one_tile(i_start:i_end,j_start:jp1_end),kind=4) error = nf90_put_var( ncid, id_lon_s, dum2d) call netcdf_err(error, 'WRITING LON_S RECORD' ) endif @@ -2143,7 +2140,7 @@ subroutine write_fv3_atm_data_netcdf(localpet) enddo if (localpet < num_tiles_target_grid) then - dum2d(:,:) = data_one_tile(i_start:i_end,j_start:jp1_end) + dum2d(:,:) = real(data_one_tile(i_start:i_end,j_start:jp1_end),kind=4) error = nf90_put_var( ncid, id_lat_s, dum2d) call netcdf_err(error, 'WRITING LAT_S RECORD' ) endif @@ -2168,7 +2165,7 @@ subroutine write_fv3_atm_data_netcdf(localpet) enddo if (localpet < num_tiles_target_grid) then - dum3d(:,:,:) = data_one_tile_3d(i_start:i_end,j_start:jp1_end,:) + dum3d(:,:,:) = real(data_one_tile_3d(i_start:i_end,j_start:jp1_end,:),kind=4) dum3d(:,:,1:lev_target) = dum3d(:,:,lev_target:1:-1) print*,"MIN MAX US AT WRITE = ", minval(dum3d(:,:,:)), maxval(dum3d(:,:,:)) error = nf90_put_var( ncid, id_u_s, dum3d) @@ -2185,7 +2182,7 @@ subroutine write_fv3_atm_data_netcdf(localpet) enddo if (localpet < num_tiles_target_grid) then - dum3d(:,:,:) = data_one_tile_3d(i_start:i_end,j_start:jp1_end,:) + dum3d(:,:,:) = real(data_one_tile_3d(i_start:i_end,j_start:jp1_end,:),kind=4) dum3d(:,:,1:lev_target) = dum3d(:,:,lev_target:1:-1) print*,"MIN MAX VS AT WRITE = ", minval(dum3d(:,:,:)), maxval(dum3d(:,:,:)) error = nf90_put_var( ncid, id_v_s, dum3d) @@ -2212,7 +2209,7 @@ subroutine write_fv3_atm_data_netcdf(localpet) enddo if (localpet < num_tiles_target_grid) then - dum2d(:,:) = data_one_tile(i_start:ip1_end,j_start:j_end) + dum2d(:,:) = real(data_one_tile(i_start:ip1_end,j_start:j_end),kind=4) error = nf90_put_var( ncid, id_lon_w, dum2d) call netcdf_err(error, 'WRITING LON_W RECORD' ) endif @@ -2225,7 +2222,7 @@ subroutine write_fv3_atm_data_netcdf(localpet) enddo if (localpet < num_tiles_target_grid) then - dum2d(:,:) = data_one_tile(i_start:ip1_end,j_start:j_end) + dum2d(:,:) = real(data_one_tile(i_start:ip1_end,j_start:j_end),kind=4) error = nf90_put_var( ncid, id_lat_w, dum2d) call netcdf_err(error, 'WRITING LAT_W RECORD' ) endif @@ -2250,7 +2247,7 @@ subroutine write_fv3_atm_data_netcdf(localpet) enddo if (localpet < num_tiles_target_grid) then - dum3d(:,:,:) = data_one_tile_3d(i_start:ip1_end,j_start:j_end,:) + dum3d(:,:,:) = real(data_one_tile_3d(i_start:ip1_end,j_start:j_end,:),kind=4) dum3d(:,:,1:lev_target) = dum3d(:,:,lev_target:1:-1) print*,"MIN MAX UW AT WRITE = ", minval(dum3d(:,:,:)), maxval(dum3d(:,:,:)) error = nf90_put_var( ncid, id_u_w, dum3d) @@ -2267,7 +2264,7 @@ subroutine write_fv3_atm_data_netcdf(localpet) enddo if (localpet < num_tiles_target_grid) then - dum3d(:,:,:) = data_one_tile_3d(i_start:ip1_end,j_start:j_end,:) + dum3d(:,:,:) = real(data_one_tile_3d(i_start:ip1_end,j_start:j_end,:),kind=4) dum3d(:,:,1:lev_target) = dum3d(:,:,lev_target:1:-1) print*,"MIN MAX VW AT WRITE = ", minval(dum3d(:,:,:)), maxval(dum3d(:,:,:)) error = nf90_put_var( ncid, id_v_w, dum3d) @@ -2302,7 +2299,7 @@ subroutine write_fv3_sfc_data_netcdf(localpet) use program_setup, only : convert_nst, halo=>halo_bndy, & regional, lai_from_climo - use surface, only : canopy_mc_target_grid, & + use surface_target_data, only : canopy_mc_target_grid, & f10m_target_grid, & ffhh_target_grid, & ffmm_target_grid, & @@ -2361,7 +2358,6 @@ subroutine write_fv3_sfc_data_netcdf(localpet) integer, intent(in) :: localpet character(len=128) :: outfile - integer :: fsize=65536, initial = 0 integer :: header_buffer_val = 16384 integer :: dim_x, dim_y, dim_lsoil, dim_time integer :: error, i, ncid, tile @@ -2413,17 +2409,17 @@ subroutine write_fv3_sfc_data_netcdf(localpet) allocate(lsoil_data(lsoil_target)) do i = 1, lsoil_target - lsoil_data(i) = float(i) + lsoil_data(i) = real(float(i),kind=4) enddo allocate(x_data(i_target_out)) do i = 1, i_target_out - x_data(i) = float(i) + x_data(i) = real(float(i),kind=4) enddo allocate(y_data(j_target_out)) do i = 1, j_target_out - y_data(i) = float(i) + y_data(i) = real(float(i),kind=4) enddo if (convert_nst) then @@ -2457,8 +2453,7 @@ subroutine write_fv3_sfc_data_netcdf(localpet) endif !--- open the file - error = nf90_create(outfile, IOR(NF90_NETCDF4,NF90_CLASSIC_MODEL), & - ncid, initialsize=initial, chunksize=fsize) + error = nf90_create(outfile, NF90_NETCDF4, ncid) call netcdf_err(error, 'CREATING FILE='//trim(outfile) ) !--- define dimensions @@ -3657,6 +3652,7 @@ subroutine write_fv3_sfc_data_netcdf(localpet) call error_handler("IN FieldGather", error) if (localpet == 0) then +! print*,'write zm max/min ',maxval(data_one_tile),minval(data_one_tile) dum2d(:,:) = data_one_tile(istart:iend, jstart:jend) error = nf90_put_var( ncid, id_zm, dum2d, start=(/1,1,1/), count=(/i_target_out,j_target_out,1/)) call netcdf_err(error, 'WRITING ZM RECORD' ) @@ -3678,3 +3674,5 @@ subroutine write_fv3_sfc_data_netcdf(localpet) return end subroutine write_fv3_sfc_data_netcdf + + end module write_data diff --git a/sorc/cpld_gridgen.fd/CMakeLists.txt b/sorc/cpld_gridgen.fd/CMakeLists.txt new file mode 100644 index 000000000..0cdfc3540 --- /dev/null +++ b/sorc/cpld_gridgen.fd/CMakeLists.txt @@ -0,0 +1,62 @@ +# This is the CMake build file for the chgres_cube utility in the +# UFS_UTILS package. +# +# George Gayno, Mark Potts, Kyle Gerheiser + +set(lib_src + angles.F90 + charstrings.F90 + cicegrid.F90 + debugprint.F90 + gengrid_kinds.F90 + grdvars.F90 + inputnml.F90 + mapped_mask.F90 + postwgts.F90 + scripgrid.F90 + topoedits.F90 + tripolegrid.F90 + vartypedefs.F90 + vertices.F90) + +set(exe_src gen_fixgrid.F90) + +if(CMAKE_Fortran_COMPILER_ID MATCHES "^(Intel)$") + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -r8 -assume byterecl") +elseif(CMAKE_Fortran_COMPILER_ID MATCHES "^(GNU)$") + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -ffree-line-length-0 -fdefault-real-8") + + # Turn on this argument mismatch flag for gfortran10. + if(CMAKE_Fortran_COMPILER_VERSION VERSION_GREATER_EQUAL 10) + set(CMAKE_Fortran_FLAGS "${CMAKE_Fortran_FLAGS} -fallow-argument-mismatch") + endif() +endif() + +set(exe_name cpld_gridgen) + +add_library(cpld_gridgen_lib STATIC ${lib_src}) +add_executable(${exe_name} ${exe_src}) + +set(mod_dir "${CMAKE_CURRENT_BINARY_DIR}/mod") +set_target_properties(cpld_gridgen_lib PROPERTIES Fortran_MODULE_DIRECTORY ${mod_dir}) +target_include_directories(cpld_gridgen_lib INTERFACE ${mod_dir}) + +target_link_libraries( + cpld_gridgen_lib + PUBLIC + esmf + MPI::MPI_Fortran + NetCDF::NetCDF_Fortran) + +if(OpenMP_Fortran_FOUND) + target_link_libraries(${exe_name} PUBLIC OpenMP::OpenMP_Fortran) +endif() + +target_link_libraries(${exe_name} PRIVATE cpld_gridgen_lib) + +install(TARGETS ${exe_name}) + +# If doxygen documentation we enabled, build it. +if(ENABLE_DOCS) + add_subdirectory(docs) +endif() diff --git a/sorc/cpld_gridgen.fd/angles.F90 b/sorc/cpld_gridgen.fd/angles.F90 new file mode 100644 index 000000000..31ac0bbcb --- /dev/null +++ b/sorc/cpld_gridgen.fd/angles.F90 @@ -0,0 +1,202 @@ +!> @file +!! @brief Determine the rotation angle on center and +!! corner points +!! @author Denise.Worthen@noaa.gov +!! +!> This module finds the rotation angle for at both center and corner points +!! It utilizes the MOM6 function modulo_around_point +!! @author Denise.Worthen@noaa.gov + +module angles + + use gengrid_kinds, only : dbl_kind, int_kind + use grdvars, only : ni,nj,nx,ny + use grdvars, only : x,y,xsgp1,ysgp1,sg_maxlat + use grdvars, only : latBu,lonBu,lonCt + use grdvars, only : angq,anglet + use grdvars, only : debug + + implicit none + +contains + !> Find the rotation angle on corner grid (Bu) points using the full MOM6 supergrid + !! + !! @author Denise.Worthen@noaa.gov + subroutine find_angq + + ! local variables + integer :: i,j,i1,i2,m,n + + ! pole locations on SG + integer(int_kind) :: ipolesg(2) + + ! from geolonB fix in MOM6 + real(dbl_kind) :: len_lon ! The periodic range of longitudes, usually 360 degrees. + real(dbl_kind) :: pi_720deg ! One quarter the conversion factor from degrees to radians. + real(dbl_kind) :: lonB(2,2) ! The longitude of a point, shifted to have about the same value. + real(dbl_kind) :: lon_scale = 0.0 + + !--------------------------------------------------------------------- + ! to find angleq on seam, replicate supergrid values across seam + !--------------------------------------------------------------------- + + angq = 0.0 + xsgp1 = 0.0; ysgp1 = 0.0 + !pole on supergrid + ipolesg = -1 + j = ny + do i = 1,nx/2 + if(y(i,j) .eq. sg_maxlat)ipolesg(1) = i + enddo + do i = nx/2+1,nx + if(y(i,j) .eq. sg_maxlat)ipolesg(2) = i + enddo + if(debug)print *,'poles found at ',ipolesg + + xsgp1(:,0:ny) = x(:,0:ny) + ysgp1(:,0:ny) = y(:,0:ny) + + !check + do i = ipolesg(1)-5,ipolesg(1)+5 + i2 = ipolesg(2)+(ipolesg(1)-i)+1 + if(debug)print *,i,i2 + enddo + print * + do i = ipolesg(2)-5,ipolesg(2)+5 + i2 = ipolesg(2)+(ipolesg(1)-i)+1 + if(debug)print *,i,i2 + enddo + + !replicate supergrid across pole + do i = 1,nx + i2 = ipolesg(2)+(ipolesg(1)-i) + xsgp1(i,ny+1) = xsgp1(i2,ny) + ysgp1(i,ny+1) = ysgp1(i2,ny) + enddo + + !check + j = ny+1 + i1 = ipolesg(1); i2 = ipolesg(2)-(ipolesg(1)-i1) + print *,'replicate X across seam on SG' + print *,xsgp1(i1-2,j),xsgp1(i2+2,j) + print *,xsgp1(i1-1,j),xsgp1(i2+1,j) + print *,xsgp1(i1, j),xsgp1(i2, j) + print *,xsgp1(i1+1,j),xsgp1(i2-1,j) + print *,xsgp1(i1+2,j),xsgp1(i2-2,j) + + print *,'replicate Y across seam on SG' + print *,ysgp1(i1-2,j),ysgp1(i2+2,j) + print *,ysgp1(i1-1,j),ysgp1(i2+1,j) + print *,ysgp1(i1, j),ysgp1(i2, j) + print *,ysgp1(i1+1,j),ysgp1(i2-1,j) + print *,ysgp1(i1+2,j),ysgp1(i2-2,j) + + !--------------------------------------------------------------------- + ! rotation angle on supergrid vertices + ! lonB: x(i-1,j-1) has same relationship to x(i,j) on SG as + ! geolonT(i,j) has to geolonBu(i,j) on the reduced grid + !--------------------------------------------------------------------- + + ! constants as defined in MOM + pi_720deg = atan(1.0) / 180.0 + len_lon = 360.0 + do j=1,ny ; do i=1,nx-1 + do n=1,2 ; do m=1,2 + lonB(m,n) = modulo_around_point(xsgp1(I+m-2,J+n-2), xsgp1(i-1,j-1), len_lon) + enddo; enddo + lon_scale = cos(pi_720deg*(ysgp1(i-1,j-1) + ysgp1(i+1,j-1) + & + ysgp1(i-1,j+1) + ysgp1(i+1,j+1)) ) + angq(i,j) = atan2(lon_scale*((lonB(1,2) - lonB(2,1)) + (lonB(2,2) - lonB(1,1))), & + ysgp1(i-1,j+1) + ysgp1(i+1,j+1) - & + ysgp1(i-1,j-1) - ysgp1(i+1,j-1) ) + enddo; enddo + + !check + if(debug) then + j = ny + i1 = ipolesg(1); i2 = ipolesg(2)-(ipolesg(1)-i1) + print *,'angq along seam on SG' + print *,angq(i1-2,j),angq(i2+2,j) + print *,angq(i1-1,j),angq(i2+1,j) + print *,angq(i1, j),angq(i2, j) + print *,angq(i1+1,j),angq(i2-1,j) + print *,angq(i1+2,j),angq(i2-2,j) + end if + + end subroutine find_angq + + !> Find the rotation angle on center (Ct) grid points + !! + !! @author Denise.Worthen@noaa.gov + subroutine find_ang + + ! local variables + integer :: i,j,m,n + integer :: ii,jj + + ! from geolonB fix in MOM6 + real(dbl_kind) :: len_lon ! The periodic range of longitudes, usually 360 degrees. + real(dbl_kind) :: pi_720deg ! One quarter the conversion factor from degrees to radians. + real(dbl_kind) :: lonB(2,2) ! The longitude of a point, shifted to have about the same value. + real(dbl_kind) :: lon_scale = 0.0 + + !--------------------------------------------------------------------- + ! rotation angle for "use_bugs" = false case from MOM6 + ! src/initialization/MOM_shared_initialization.F90 but allow for not + ! having halo values + ! note this does not reproduce sin_rot,cos_rot found in MOM6 output + ! differences are ~O 10-6 + !--------------------------------------------------------------------- + + anglet = 0.0 + pi_720deg = atan(1.0) / 180.0 + len_lon = 360.0 + do j=1,nj; do i = 1,ni + do n=1,2 ; do m=1,2 + jj = J+n-2; ii = I+m-2 + if(jj .eq. 0)jj = 1 + if(ii .eq. 0)ii = ni + lonB(m,n) = modulo_around_point(LonBu(ii,jj), LonCt(i,j), len_lon) + ! lonB(m,n) = modulo_around_point(LonBu(I+m-2,J+n-2), LonCt(i,j), len_lon) + enddo; enddo + jj = j-1; ii = i-1 + if(jj .eq. 0)jj = 1 + if(ii .eq. 0)ii = ni + lon_scale = cos(pi_720deg*((LatBu(ii,jj) + LatBu(I,J)) + & + (LatBu(I,jj) + LatBu(ii,J)) ) ) + anglet(i,j) = atan2(lon_scale*((lonB(1,2) - lonB(2,1)) + (lonB(2,2) - lonB(1,1))), & + (LatBu(ii,J) - LatBu(I,jj)) + & + (LatBu(I,J) - LatBu(ii,jj)) ) + + !lon_scale = cos(pi_720deg*((LatBu(I-1,J-1) + LatBu(I,J)) + & + ! (LatBu(I,J-1) + LatBu(I-1,J)) ) ) + !anglet(i,j) = atan2(lon_scale*((lonB(1,2) - lonB(2,1)) + (lonB(2,2) - lonB(1,1))), & + ! (LatBu(I-1,J) - LatBu(I,J-1)) + & + ! (LatBu(I,J) - LatBu(I-1,J-1)) ) + enddo; enddo + + end subroutine find_ang + ! ----------------------------------------------------------------------------- + !> Return the modulo value of x in an interval [xc-(Lx/2) xc+(Lx/2)] + !! If Lx<=0, then it returns x without applying modulo arithmetic. + !! + !! From src/initialization/MOM_shared_initialization.F90: + !! @param[in] x Value to which to apply modulo arithmetic + !! @param[in] xc Center of modulo range + !! @param[in] Lx Modulo range width + !! @return x_mod Value x shifted by an integer multiple of Lx to be close to xc + function modulo_around_point(x, xc, Lx) result(x_mod) + use gengrid_kinds, only : dbl_kind + + real(dbl_kind), intent(in) :: x + real(dbl_kind), intent(in) :: xc + real(dbl_kind), intent(in) :: Lx + real(dbl_kind) :: x_mod + + if (Lx > 0.0) then + x_mod = modulo(x - (xc - 0.5*Lx), Lx) + (xc - 0.5*Lx) + else + x_mod = x + endif + end function modulo_around_point +end module angles diff --git a/sorc/cpld_gridgen.fd/charstrings.F90 b/sorc/cpld_gridgen.fd/charstrings.F90 new file mode 100644 index 000000000..00deab1b4 --- /dev/null +++ b/sorc/cpld_gridgen.fd/charstrings.F90 @@ -0,0 +1,34 @@ +!> @file +!! @brief Define required character string variables +!! @author Denise.Worthen@noaa.gov +!! +!> This module contains the character string variables +!! @author Denise.Worthen@noaa.gov + +module charstrings + + use gengrid_kinds, only : CL,CM,CS + + implicit none + + character(len=CL) :: dirsrc !< The source directory containing the fix files for MOM6 + character(len=CL) :: dirout !< The directory where output files will be written + character(len=CL) :: fv3dir !< The directory containing the FV3 mosaic files + character(len=CS) :: res !< The Ocean/Ice resolution, e.g. 500 (5deg), 100 (1deg) + !! 050 (1/2deg), 025 (1/4deg) + character(len=CS) :: atmres !< The ATM resolution, e.g. C96, C192, C384 + character(len=CL) :: logmsg !< An informational message + + character(len=CL) :: maskfile = 'ocean_mask.nc' !< The name of the MOM6 mask file + character(len=CS) :: maskname = 'mask' !< The variable name of the mask field + character(len=CL) :: editsfile !< The name of the topo edits file (resolution specific) + + character(len=CL) :: topofile !< The name of the MOM6 bathymetry file + character(len=CS) :: toponame = 'depth' !< The name of the bathymetry field + + character(len=CL) :: history !< A documentation string + character(len=CS) :: cdate !< The date stamp of file creation + + character(len= 2), dimension(4) :: staggerlocs = (/'Ct','Cu','Cv','Bu'/) !< The named stagger locations of the grid + +end module charstrings diff --git a/sorc/cpld_gridgen.fd/cicegrid.F90 b/sorc/cpld_gridgen.fd/cicegrid.F90 new file mode 100644 index 000000000..bd7c366f2 --- /dev/null +++ b/sorc/cpld_gridgen.fd/cicegrid.F90 @@ -0,0 +1,95 @@ +!> @file +!! @brief Write the CICE6 grid file +!! @author Denise.Worthen@noaa.gov +!! +!> Write the CICE6 grid file +!! @author Denise.Worthen@noaa.gov + +module cicegrid + + use grdvars, only: ni,nj,ulat,ulon,htn,hte,angle,wet4 + use charstrings, only: history, logmsg + use vartypedefs, only: maxvars, cicevars, cicevars_typedefine + use gengrid_kinds, only: CM + use netcdf + + implicit none + private + + public write_cicegrid + +contains + !> Write the CICE6 grid file + !! + !! @param[in] fname the name of the CICE6 grid file to write + !! + !! @author Denise.Worthen@noaa.gov + + subroutine write_cicegrid(fname) + + character(len=*), intent(in) :: fname + + ! local variables + integer :: ii,id,rc, ncid, dim2(2) + integer :: idimid,jdimid + + character(len=2) :: vtype + character(len=CM) :: vname + character(len=CM) :: vlong + character(len=CM) :: vunit + + !--------------------------------------------------------------------- + ! create the netcdf file + !--------------------------------------------------------------------- + + ! define the output variables and file name + call cicevars_typedefine + + rc = nf90_create(fname, nf90_write, ncid) + logmsg = '==> writing CICE grid to '//trim(fname) + print '(a)', trim(logmsg) + if(rc .ne. 0)print '(a)', 'nf90_create = '//trim(nf90_strerror(rc)) + + rc = nf90_def_dim(ncid, 'ni', ni, idimid) + rc = nf90_def_dim(ncid, 'nj', nj, jdimid) + + do ii = 1,maxvars + if(len_trim(cicevars(ii)%var_name) .gt. 0)then + vname = trim(cicevars(ii)%var_name) + vlong = trim(cicevars(ii)%long_name) + vunit = trim(cicevars(ii)%unit_name) + vtype = trim(cicevars(ii)%var_type) + + dim2(:) = (/idimid, jdimid/) + if(vtype .eq. 'r8')rc = nf90_def_var(ncid, vname, nf90_double, dim2, id) + if(vtype .eq. 'r4')rc = nf90_def_var(ncid, vname, nf90_float, dim2, id) + if(vtype .eq. 'i4')rc = nf90_def_var(ncid, vname, nf90_int, dim2, id) + rc = nf90_put_att(ncid, id, 'units', vunit) + rc = nf90_put_att(ncid, id, 'long_name', vlong) + end if + enddo + rc = nf90_put_att(ncid, nf90_global, 'history', trim(history)) + rc = nf90_enddef(ncid) + + rc = nf90_inq_varid(ncid, 'ulon', id) + rc = nf90_put_var(ncid, id, ulon) + + rc = nf90_inq_varid(ncid, 'ulat', id) + rc = nf90_put_var(ncid, id, ulat) + + rc = nf90_inq_varid(ncid, 'htn', id) + rc = nf90_put_var(ncid, id, htn) + + rc = nf90_inq_varid(ncid, 'hte', id) + rc = nf90_put_var(ncid, id, hte) + + rc = nf90_inq_varid(ncid, 'angle', id) + rc = nf90_put_var(ncid, id, angle) + + rc = nf90_inq_varid(ncid, 'kmt', id) + rc = nf90_put_var(ncid, id, int(wet4)) + + rc = nf90_close(ncid) + + end subroutine write_cicegrid +end module cicegrid diff --git a/sorc/cpld_gridgen.fd/debugprint.F90 b/sorc/cpld_gridgen.fd/debugprint.F90 new file mode 100644 index 000000000..71b9c289a --- /dev/null +++ b/sorc/cpld_gridgen.fd/debugprint.F90 @@ -0,0 +1,247 @@ +!> @file +!! @brief Print debugging information +!! @author Denise.Worthen@noaa.gov +!! +!> Print values for debugging +!! @author Denise.Worthen@noaa.gov + +module debugprint + + use esmf, only : ESMF_LogFoundError, ESMF_LOGERR_PASSTHRU + use grdvars, only : ni,nj,ipole,angle,angleT + use grdvars, only : htn,latCt,lonCt,latCv,lonCv,latCu,lonCu,latBu,lonBu + use grdvars, only : xlatCt,xlonCt,xlatCu,xlonCu + use grdvars, only : latBu_vert,lonBu_vert,latCv_vert,lonCv_vert + use grdvars, only : latCt_vert,lonCt_vert,latCu_vert,lonCu_vert + + implicit none + private + + public :: checkseam, checkxlatlon, checkpoint + +contains + !> Print values across the tripole seam + !! + !! @author Denise.Worthen@noaa.gov + + subroutine checkseam + + ! local variables + integer :: j,i1,i2 + + j = nj + i1 = ipole(1); i2 = ipole(2)+1 + + !htn must be the same along seam + j = nj + i1 = ipole(1); i2 = ipole(2)+1 + print *,'HTN across seam ' + print *,htn(i1-2,j),htn(i2+2,j) + print *,htn(i1-1,j),htn(i2+1,j) + print *,htn(i1, j),htn(i2, j) + print *,htn(i1+1,j),htn(i2-1,j) + print *,htn(i1+2,j),htn(i2-2,j) + + print *,'latCv across seam ' + print *,latCv(i1-2,j),latCv(i2+2,j) + print *,latCv(i1-1,j),latCv(i2+1,j) + print *,latCv(i1, j),latCv(i2, j) + print *,latCv(i1+1,j),latCv(i2-1,j) + print *,latCv(i1+2,j),latCv(i2-2,j) + + print *,'lonCv across seam ' + print *,lonCv(i1-2,j),lonCv(i2+2,j) + print *,lonCv(i1-1,j),lonCv(i2+1,j) + print *,lonCv(i1, j),lonCv(i2, j) + print *,lonCv(i1+1,j),lonCv(i2-1,j) + print *,lonCv(i1+2,j),lonCv(i2-2,j) + + print *,'angleT across seam ' + print *,angleT(i1-2,j),angleT(i2+2,j) + print *,angleT(i1-1,j),angleT(i2+1,j) + print *,angleT(i1, j),angleT(i2, j) + print *,angleT(i1+1,j),angleT(i2-1,j) + print *,angleT(i1+2,j),angleT(i2-2,j) + + print *,'latCu across seam ' + print *,latCu(i1-3,j),latCu(i2+2,j),latCu(i1-3,j)-latCu(i2+2,j) + print *,latCu(i1-2,j),latCu(i2+1,j) + print *,latCu(i1-1,j),latCu(i2+0,j) + print *,latCu(i1, j),latCu(i2-1,j) + print *,latCu(i1+1,j),latCu(i2-2,j) + print *,latCu(i1+2,j),latCu(i2-3,j) + print *,latCu(i1+3,j),latCu(i2-4,j) + + print *,'lonCu across seam ' + print *,lonCu(i1-3,j),lonCu(i2+2,j),lonCu(i1-3,j)+lonCu(i2+2,j) + print *,lonCu(i1-2,j),lonCu(i2+1,j) + print *,lonCu(i1-1,j),lonCu(i2+0,j) + print *,lonCu(i1, j),lonCu(i2-1,j) + print *,lonCu(i1+1,j),lonCu(i2-2,j) + print *,lonCu(i1+2,j),lonCu(i2-3,j) + print *,lonCu(i1+3,j),lonCu(i2-4,j) + + print *,'latCt across seam ' + print *,latCt(i1-3,j),latCt(i2+3,j),latCt(i1-3,j)-latCt(i2+3,j) + print *,latCt(i1-2,j),latCt(i2+2,j) + print *,latCt(i1-1,j),latCt(i2+1,j) + print *,latCt(i1, j),latCt(i2, j) + print *,latCt(i1+1,j),latCt(i2-1,j) + print *,latCt(i1+2,j),latCt(i2-2,j) + print *,latCt(i1+3,j),latCt(i2-3,j) + + print *,'lonCt across seam ' + print *,lonCt(i1-3,j),lonCt(i2+3,j),lonCt(i1-3,j)+lonCt(i2+3,j) + print *,lonCt(i1-2,j),lonCt(i2+2,j) + print *,lonCt(i1-1,j),lonCt(i2+1,j) + print *,lonCt(i1, j),lonCt(i2, j) + print *,lonCt(i1+1,j),lonCt(i2-1,j) + print *,lonCt(i1+2,j),lonCt(i2-2,j) + print *,lonCt(i1+3,j),lonCt(i2-3,j) + print * + end subroutine checkseam + + !> Print values near the poles and along the domain edges + !! + !! @author Denise.Worthen@noaa.gov + + subroutine checkxlatlon + + ! local variables + integer :: i + + print *,'============== Ct grid ===============' + print *,'============== Left pole ============' + do i = ipole(1)-3,ipole(1)+3 + print '(i5,6f12.5)',i,lonCt(i,nj),xlonCt(i),lonCt(i,nj)+xlonCt(i),latCt(i,nj),xlatCt(i),latCt(i,nj)-xlatCt(i) + enddo + print * + + print *,'============ Right pole ============' + do i = ipole(2)-3,ipole(2)+3 + print '(i5,6f12.5)',i,lonCt(i,nj),xlonCt(i),lonCt(i,nj)+xlonCt(i),latCt(i,nj),xlatCt(i),latCt(i,nj)-xlatCt(i) + enddo + print * + + print *,'============== Ct grid ===============' + print *,'============== Left edge ============' + do i = 1,5 + print '(i5,6f12.5)',i,lonCt(i,nj),xlonCt(i),lonCt(i,nj)+xlonCt(i),latCt(i,nj),xlatCt(i),latCt(i,nj)-xlatCt(i) + enddo + print * + print *,'============== Right edge ===========' + do i = ni-4,ni + print '(i5,6f12.5)',i,lonCt(i,nj),xlonCt(i),lonCt(i,nj)+xlonCt(i),latCt(i,nj),xlatCt(i),latCt(i,nj)-xlatCt(i) + enddo + print * + + + print *,'============== Cu grid ===============' + print *,'============== Left pole =============' + do i = ipole(1)-3,ipole(1)+3 + print '(i5,6f12.5)',i,lonCu(i,nj),xlonCu(i),lonCu(i,nj)+xlonCu(i),latCu(i,nj),xlatCu(i),latCu(i,nj)-xlatCu(i) + enddo + print * + + print *,'============ Right pole ============' + do i = ipole(2)-3,ipole(2)+3 + print '(i5,6f12.5)',i,lonCu(i,nj),xlonCu(i),lonCu(i,nj)+xlonCu(i),latCu(i,nj),xlatCu(i),latCu(i,nj)-xlatCu(i) + enddo + print * + + print *,'============== Cu grid ===============' + print *,'============== Left edge ============' + do i = 1,5 + print '(i5,6f12.5)',i,lonCu(i,nj),xlonCu(i),lonCu(i,nj)+xlonCu(i),latCu(i,nj),xlatCu(i),latCu(i,nj)-xlatCu(i) + enddo + print * + print *,'============== Right edge ===========' + do i = ni-4,ni + print '(i5,6f12.5)',i,lonCu(i,nj),xlonCu(i),lonCu(i,nj)+xlonCu(i),latCu(i,nj),xlatCu(i),latCu(i,nj)-xlatCu(i) + enddo + print * + + end subroutine checkxlatlon + + !> Print values at specified point + !! + !! @author Denise.Worthen@noaa.gov + + subroutine checkpoint + + ! local variables + integer :: i,j + + ! check + i = 1; j = nj + print '(f12.5,a,f12.5)',latBu_vert(i,j,2),' ',latBu_vert(i,j,1) + print '(a12,f12.5)',' ',latBu(i,j) + print '(f12.5,a,f12.5)',latBu_vert(i,j,3),' ',latBu_vert(i,j,4) + print * + print '(f12.5,a,f12.5)',lonBu_vert(i,j,2),' ',lonBu_vert(i,j,1) + print '(a12,f12.5)',' ',lonBu(i,j) + print '(f12.5,a,f12.5)',lonBu_vert(i,j,3),' ',lonBu_vert(i,j,4) + print * + print * + ! check + print '(f12.5,a,f12.5)',latCv_vert(i,j,2),' ',latCv_vert(i,j,1) + print '(a12,f12.5)',' ',latCv(i,j) + print '(f12.5,a,f12.5)',latCv_vert(i,j,3),' ',latCv_vert(i,j,4) + print * + print '(f12.5,a,f12.5)',lonCv_vert(i,j,2),' ',lonCv_vert(i,j,1) + print '(a12,f12.5)',' ',lonCv(i,j) + print '(f12.5,a,f12.5)',lonCv_vert(i,j,3),' ',lonCv_vert(i,j,4) + + print * + print * + + i = 1; j = 10 + print '(f12.5,a,f12.5)',latCt_vert(i,j,2),' ',latCt_vert(i,j,1) + print '(a12,f12.5)',' ',latCt(i,j) + print '(f12.5,a,f12.5)',latCt_vert(i,j,3),' ',latCt_vert(i,j,4) + print * + print '(f12.5,a,f12.5)',lonCt_vert(i,j,2),' ',lonCt_vert(i,j,1) + print '(a12,f12.5)',' ',lonCt(i,j) + print '(f12.5,a,f12.5)',lonCt_vert(i,j,3),' ',lonCt_vert(i,j,4) + print * + print * + ! check + print '(f12.5,a,f12.5)',latCu_vert(i,j,2),' ',latCu_vert(i,j,1) + print '(a12,f12.5)',' ',latCu(i,j) + print '(f12.5,a,f12.5)',latCu_vert(i,j,3),' ',latCu_vert(i,j,4) + print * + print '(f12.5,a,f12.5)',lonCu_vert(i,j,2),' ',lonCu_vert(i,j,1) + print '(a12,f12.5)',' ',lonCu(i,j) + print '(f12.5,a,f12.5)',lonCu_vert(i,j,3),' ',lonCu_vert(i,j,4) + + + i = ni; j = 10 + print '(f12.5,a,f12.5)',latCt_vert(i,j,2),' ',latCt_vert(i,j,1) + print '(a12,f12.5)',' ',latCt(i,j) + print '(f12.5,a,f12.5)',latCt_vert(i,j,3),' ',latCt_vert(i,j,4) + print * + print '(f12.5,a,f12.5)',lonCt_vert(i,j,2),' ',lonCt_vert(i,j,1) + print '(a12,f12.5)',' ',lonCt(i,j) + print '(f12.5,a,f12.5)',lonCt_vert(i,j,3),' ',lonCt_vert(i,j,4) + print * + print * + ! check + print '(f12.5,a,f12.5)',latCu_vert(i,j,2),' ',latCu_vert(i,j,1) + print '(a12,f12.5)',' ',latCu(i,j) + print '(f12.5,a,f12.5)',latCu_vert(i,j,3),' ',latCu_vert(i,j,4) + print * + print '(f12.5,a,f12.5)',lonCu_vert(i,j,2),' ',lonCu_vert(i,j,1) + print '(a12,f12.5)',' ',lonCu(i,j) + print '(f12.5,a,f12.5)',lonCu_vert(i,j,3),' ',lonCu_vert(i,j,4) + + print *,"latCt minmax ",minval(latCt),maxval(latCt) + print *,"latCu minmax ",minval(latCu),maxval(latCu) + print *,"latCv minmax ",minval(latCv),maxval(latCv) + print *,"latBu minmax ",minval(latBu),maxval(latBu) + + ! print *,minval(latCt_vert),maxval(latCt_vert) + ! print *,minval(lonCt_vert),maxval(lonCt_vert) + ! print *,minval(latBu_vert),maxval(latBu_vert) + ! print *,minval(lonBu_vert),maxval(lonBu_vert) + end subroutine checkpoint +end module debugprint diff --git a/sorc/cpld_gridgen.fd/docs/CMakeLists.txt b/sorc/cpld_gridgen.fd/docs/CMakeLists.txt new file mode 100644 index 000000000..d9496f340 --- /dev/null +++ b/sorc/cpld_gridgen.fd/docs/CMakeLists.txt @@ -0,0 +1,16 @@ +# This is the CMake file for building the docs directory of UFS_UTILS +# utility cpld_gridgen +# +# Ed Hartnett 3/8/21 + +# Create doxyfile. +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY) + +# Build documentation with target all. +add_custom_target(cpld_gridgen_doc ALL + ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Generating API Documentation with Doxygen" VERBATIM) + +# Ensure top-level docs have been generated. +add_dependencies(cpld_gridgen_doc doc) diff --git a/sorc/cpld_gridgen.fd/docs/Doxyfile.in b/sorc/cpld_gridgen.fd/docs/Doxyfile.in new file mode 100644 index 000000000..62808f419 --- /dev/null +++ b/sorc/cpld_gridgen.fd/docs/Doxyfile.in @@ -0,0 +1,2573 @@ +# Doxyfile 1.9.1 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the configuration +# file that follow. The default is UTF-8 which is also the encoding used for all +# text before the first occurrence of this tag. Doxygen uses libiconv (or the +# iconv built into libc) for the transcoding. See +# https://www.gnu.org/software/libiconv/ for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = cpld_gridgen + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = @PROJECT_VERSION@ + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = ../../../docs/html/cpld_gridgen + +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = NO + +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# The OUTPUT_TEXT_DIRECTION tag is used to specify the direction in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all generated output in the proper direction. +# Possible values are: None, LTR, RTL and Context. +# The default value is: None. + +OUTPUT_TEXT_DIRECTION = None + +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = YES + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = YES + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = YES + +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = YES + +# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line +# such as +# /*************** +# as being the beginning of a Javadoc-style comment "banner". If set to NO, the +# Javadoc-style will behave just like regular comments and it will not be +# interpreted by doxygen. +# The default value is: NO. + +JAVADOC_BANNER = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = YES + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = YES + +# By default Python docstrings are displayed as preformatted text and doxygen's +# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the +# doxygen's special commands can be used and the contents of the docstring +# documentation blocks is shown as doxygen documentation. +# The default value is: YES. + +PYTHON_DOCSTRING = YES + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 4 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines (in the resulting output). You can put ^^ in the value part of an +# alias to insert a newline as if a physical newline was in the original file. +# When you need a literal { or } or , in the value part of an alias you have to +# escape them by means of a backslash (\), this can lead to conflicts with the +# commands \{ and \} for these it is advised to use the version @{ and @} or use +# a double escape (\\{ and \\}) + +ALIASES = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = YES + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = YES + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice +# sources only. Doxygen will then generate output that is more tailored for that +# language. For instance, namespaces will be presented as modules, types will be +# separated into more groups, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_SLICE = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, JavaScript, +# Csharp (C#), C, C++, D, PHP, md (Markdown), Objective-C, Python, Slice, VHDL, +# Fortran (fixed format Fortran: FortranFixed, free formatted Fortran: +# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser +# tries to guess whether the code is fixed or free formatted code, this is the +# default for Fortran type files). For instance to make doxygen treat .inc files +# as Fortran files (default is PHP), and .f files as C (default is Fortran), +# use: inc=Fortran f=C. +# +# Note: For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. When specifying no_extension you should add +# * to the FILE_PATTERNS. +# +# Note see also the list of default file extension mappings. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See https://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 5. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 5 + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = YES + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = YES + +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = YES + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = YES + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +# The NUM_PROC_THREADS specifies the number threads doxygen is allowed to use +# during processing. When set to 0 doxygen will based this on the number of +# cores available in the system. You can set it explicitly to a value larger +# than 0 to get more control over the balance between CPU load and processing +# speed. At this moment only the input processing can be done using multiple +# threads. Since this is still an experimental feature the default is set to 1, +# which efficively disables parallel processing. Please report any issues you +# encounter. Generating dot graphs in parallel is controlled by the +# DOT_NUM_THREADS setting. +# Minimum value: 0, maximum value: 32, default value: 1. + +NUM_PROC_THREADS = 1 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = NO + +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = YES + +# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual +# methods of a class will be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIV_VIRTUAL = NO + +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = YES + +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = YES + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = NO + +# This flag is only useful for Objective-C code. If set to YES, local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO, only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = YES + +# If this flag is set to YES, the name of an unnamed parameter in a declaration +# will be determined by the corresponding definition. By default unnamed +# parameters remain unnamed in the output. +# The default value is: YES. + +RESOLVE_UNNAMED_PARAMS = YES + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# declarations. If set to NO, these declarations will be included in the +# documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO, these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# With the correct setting of option CASE_SENSE_NAMES doxygen will better be +# able to match the capabilities of the underlying filesystem. In case the +# filesystem is case sensitive (i.e. it supports files in the same directory +# whose names only differ in casing), the option must be set to YES to properly +# deal with such files in case they appear in the input. For filesystems that +# are not case sensitive the option should be be set to NO to properly deal with +# output files written for symbols that only differ in casing, such as for two +# classes, one named CLASS and the other named Class, and to also support +# references to files without having to specify the exact matching casing. On +# Windows (including Cygwin) and MacOS, users should typically set this option +# to NO, whereas on Linux or other Unix flavors it should typically be set to +# YES. +# The default value is: system dependent. + +CASE_SENSE_NAMES = YES + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES, the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = YES + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO, the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. + +SORT_BRIEF_DOCS = YES + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = YES + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. +# The default value is: YES. + +GENERATE_TODOLIST = NO + +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. +# The default value is: YES. + +GENERATE_TESTLIST = NO + +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = NO + +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= YES + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = YES + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. If +# EXTRACT_ALL is set to YES then this flag will automatically be disabled. +# The default value is: NO. + +WARN_NO_PARAMDOC = YES + +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS +# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but +# at the end of the doxygen process doxygen will return with a non-zero status. +# Possible values are: NO, YES and FAIL_ON_WARNINGS. +# The default value is: NO. + +WARN_AS_ERROR = YES +#WARN_AS_ERROR = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING +# Note: If this tag is empty the current directory is searched. + +INPUT = @abs_top_srcdir@/sorc/cpld_gridgen.fd/docs/user_guide.md \ + @abs_top_srcdir@/sorc/cpld_gridgen.fd + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: +# https://www.gnu.org/software/libiconv/) for the list of possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# Note the list of default checked file patterns might differ from the list of +# default file extension mappings. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C comment), +# *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd, *.vhdl, +# *.ucf, *.qsf and *.ice. + +FILE_PATTERNS = *.F90 \ + *.f90 \ + *.f \ + *.F \ + *.h \ + *.c \ + *.md \ + *.inc + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = ../../fre-nctools.fd + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = NO + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = user_guide.md + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = NO + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# entity all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = YES + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = YES + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see https://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = NO + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = . + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the style sheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# https://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = NO + +# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML +# documentation will contain a main index with vertical navigation menus that +# are dynamically created via JavaScript. If disabled, the navigation index will +# consists of multiple levels of tabs that are statically embedded in every HTML +# page. Disable this option to support browsers that do not have JavaScript, +# like the Qt help browser. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_MENUS = YES + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: +# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To +# create a documentation set, doxygen will generate a Makefile in the HTML +# output directory. Running make will produce the docset in that directory and +# running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy +# genXcode/_index.html for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: +# https://www.microsoft.com/en-us/download/details.aspx?id=21138) on Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler (hhc.exe). If non-empty, +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the main .chm file (NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location (absolute path +# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to +# run qhelpgenerator on the generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = YES + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg +# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see +# https://inkscape.org) to generate formulas as SVG images instead of PNGs for +# the HTML output. These images will generally look nicer at scaled resolutions. +# Possible values are: png (the default) and svg (looks nicer but requires the +# pdf2svg or inkscape tool). +# The default value is: png. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FORMULA_FORMAT = png + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANSPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands +# to create new LaTeX commands to be used in formulas as building blocks. See +# the section "Including formulas" for details. + +FORMULA_MACROFILE = + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# https://www.mathjax.org) which uses client side JavaScript for the rendering +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from https://www.mathjax.org before deployment. +# The default value is: https://cdn.jsdelivr.net/npm/mathjax@2. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: +# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /