From 2c81c84be0a689f13007bb99f00f1823461d4f4f Mon Sep 17 00:00:00 2001 From: Tracy Date: Thu, 4 Apr 2024 18:27:20 +0000 Subject: [PATCH 01/40] Update hera module for rocky8, remove shell setup scripts --- scm/etc/Cheyenne_setup_gnu.csh | 55 ------------------------------ scm/etc/Cheyenne_setup_gnu.sh | 47 ------------------------- scm/etc/Cheyenne_setup_intel.csh | 55 ------------------------------ scm/etc/Cheyenne_setup_intel.sh | 47 ------------------------- scm/etc/Desktop_setup_gfortran.csh | 51 --------------------------- scm/etc/Desktop_setup_gfortran.sh | 47 ------------------------- scm/etc/Hera_setup_intel.csh | 47 ------------------------- scm/etc/Hera_setup_intel.sh | 39 --------------------- scm/etc/modules/hera_gnu.lua | 4 +-- scm/etc/modules/hera_intel.lua | 4 +-- 10 files changed, 4 insertions(+), 392 deletions(-) delete mode 100755 scm/etc/Cheyenne_setup_gnu.csh delete mode 100755 scm/etc/Cheyenne_setup_gnu.sh delete mode 100755 scm/etc/Cheyenne_setup_intel.csh delete mode 100755 scm/etc/Cheyenne_setup_intel.sh delete mode 100755 scm/etc/Desktop_setup_gfortran.csh delete mode 100755 scm/etc/Desktop_setup_gfortran.sh delete mode 100755 scm/etc/Hera_setup_intel.csh delete mode 100755 scm/etc/Hera_setup_intel.sh diff --git a/scm/etc/Cheyenne_setup_gnu.csh b/scm/etc/Cheyenne_setup_gnu.csh deleted file mode 100755 index c37acbdc2..000000000 --- a/scm/etc/Cheyenne_setup_gnu.csh +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/tcsh - -echo "Setting environment variables for CCPP-SCM on Cheyenne with gcc/gfortran" - -set called=($_) - -if ( "$called" != "") then ### called by source - set MYSCRIPT=`readlink -f -n $called[2]` -else ### called by direct execution of the script - set MYSCRIPT=`readlink -f -n '$0'` -endif -set MYDIR=`dirname $MYSCRIPT` -set MYDIR=`cd $MYDIR && pwd -P` - -setenv SCM_ROOT $MYDIR/../.. - -#start with a "clean" environment; activate and deactivate ncar_pylib in order to successfully deactivate previously activated environment without errors -module load ncarenv/1.3 -conda deactivate -module purge - -#load the modules in order to compile the CCPP SCM -echo "Loading gnu and netcdf modules..." -module load ncarenv/1.3 -module load gnu/11.2.0 -module load mpt/2.25 -module load ncarcompilers/0.5.0 -module load netcdf - -echo "Setting up NCEPLIBS" -module use /glade/work/epicufsrt/contrib/hpc-stack/gnu11.2.0/modulefiles/stack -module load hpc/1.2.0 -module load hpc-gnu/11.2.0 -module load hpc-mpt/2.25 -setenv bacio_ROOT /glade/work/epicufsrt/contrib/hpc-stack/gnu11.2.0/gnu-11.2.0/bacio/2.4.1 -setenv sp_ROOT /glade/work/epicufsrt/contrib/hpc-stack/gnu11.2.0/gnu-11.2.0/sp/2.3.3 -setenv w3emc_ROOT /glade/work/epicufsrt/contrib/hpc-stack/gnu11.2.0/gnu-11.2.0/w3emc/2.9.2 - -echo "Setting CC/CXX/FC environment variables" -setenv CC gcc -setenv CXX g++ -setenv FC gfortran - -echo "Loading cmake" -module load cmake/3.16.4 -setenv CMAKE_C_COMPILER gcc -setenv CMAKE_CXX_COMPILER g++ -setenv CMAKE_Fortran_COMPILER gfortran -setenv CMAKE_Platform cheyenne.gnu - -echo "Setting up python environment for running and plotting." -module load conda/latest - -conda activate /glade/p/ral/jntp/GMTB/CCPP_SCM/conda/ccpp-scm - diff --git a/scm/etc/Cheyenne_setup_gnu.sh b/scm/etc/Cheyenne_setup_gnu.sh deleted file mode 100755 index e1a190fcc..000000000 --- a/scm/etc/Cheyenne_setup_gnu.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash - -echo "Setting environment variables for CCPP-SCM on Cheyenne with gcc/gfortran" - -MYDIR=$(cd "$(dirname "$(readlink -f -n "${BASH_SOURCE[0]}" )" )" && pwd -P) - -export SCM_ROOT=$MYDIR/../.. - -#start with a "clean" environment; activate and deactivate ncar_pylib in order to successfully deactivate previously activated environment without errors -module load ncarenv/1.3 -conda deactivate -module purge - -#load the modules in order to compile the CCPP SCM -echo "Loading gnu and netcdf modules..." -module load ncarenv/1.3 -module load gnu/11.2.0 -module load mpt/2.25 -module load ncarcompilers/0.5.0 -module load netcdf - -echo "Setting up NCEPLIBS" -module use /glade/work/epicufsrt/contrib/hpc-stack/gnu11.2.0/modulefiles/stack -module load hpc/1.2.0 -module load hpc-gnu/11.2.0 -module load hpc-mpt/2.25 -export bacio_ROOT=/glade/work/epicufsrt/contrib/hpc-stack/gnu11.2.0/gnu-11.2.0/bacio/2.4.1 -export sp_ROOT=/glade/work/epicufsrt/contrib/hpc-stack/gnu11.2.0/gnu-11.2.0/sp/2.3.3 -export w3emc_ROOT=/glade/work/epicufsrt/contrib/hpc-stack/gnu11.2.0/gnu-11.2.0/w3emc/2.9.2 - -echo "Setting CC/CXX/FC environment variables" -export CC=gcc -export CXX=g++ -export FC=gfortran - -echo "Loading cmake" -module load cmake/3.22.0 -export CMAKE_C_COMPILER=gcc -export CMAKE_CXX_COMPILER=g++ -export CMAKE_Fortran_COMPILER=gfortran -export CMAKE_Platform=cheyenne.gnu - -echo "Setting up python environment for running and plotting." -module load conda/latest - -conda activate /glade/p/ral/jntp/GMTB/CCPP_SCM/conda/ccpp-scm - diff --git a/scm/etc/Cheyenne_setup_intel.csh b/scm/etc/Cheyenne_setup_intel.csh deleted file mode 100755 index d8bc17890..000000000 --- a/scm/etc/Cheyenne_setup_intel.csh +++ /dev/null @@ -1,55 +0,0 @@ -#!/bin/tcsh - -echo "Setting environment variables for CCPP-SCM on Cheyenne with icc/ifort" - -set called=($_) - -if ( "$called" != "") then ### called by source - set MYSCRIPT=`readlink -f -n $called[2]` -else ### called by direct execution of the script - set MYSCRIPT=`readlink -f -n '$0'` -endif -set MYDIR=`dirname $MYSCRIPT` -set MYDIR=`cd $MYDIR && pwd -P` - -setenv SCM_ROOT $MYDIR/../.. - -#start with a "clean" environment; activate and deactivate ncar_pylib in order to successfully deactivate previously activated environment without errors -module load ncarenv/1.3 -conda deactivate -module purge - -#load the modules in order to compile the CCPP SCM -echo "Loading intel and netcdf modules..." -module load ncarenv/1.3 -module load intel/2022.1 -module load mpt/2.25 -module load ncarcompilers/0.5.0 -module load netcdf - -echo "Setting up NCEPLIBS" -module use /glade/work/epicufsrt/contrib/hpc-stack/intel2022.1/modulefiles/stack -module load hpc/1.2.0 -module load hpc-intel/2022.1 -module load hpc-mpt/2.25 -setenv bacio_ROOT /glade/work/epicufsrt/contrib/hpc-stack/intel2022.1/intel-2022.1/bacio/2.4.1 -setenv sp_ROOT /glade/work/epicufsrt/contrib/hpc-stack/intel2022.1/intel-2022.1/sp/2.3.3 -setenv w3emc_ROOT /glade/work/epicufsrt/contrib/hpc-stack/intel2022.1/intel-2022.1/w3emc/2.9.2 - -echo "Setting CC/CXX/FC environment variables" -setenv CC icc -setenv CXX icpc -setenv FC ifort - -echo "Loading cmake" -module load cmake/3.22.0 -setenv CMAKE_C_COMPILER icc -setenv CMAKE_CXX_COMPILER icpc -setenv CMAKE_Fortran_COMPILER ifort -setenv CMAKE_Platform cheyenne.intel - -echo "Setting up python environment for running and plotting." -module load conda/latest - -conda activate /glade/p/ral/jntp/GMTB/CCPP_SCM/conda/ccpp-scm - diff --git a/scm/etc/Cheyenne_setup_intel.sh b/scm/etc/Cheyenne_setup_intel.sh deleted file mode 100755 index 71727e034..000000000 --- a/scm/etc/Cheyenne_setup_intel.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash - -echo "Setting environment variables for CCPP-SCM on Cheyenne with icc/ifort" - -MYDIR=$(cd "$(dirname "$(readlink -f -n "${BASH_SOURCE[0]}" )" )" && pwd -P) - -export SCM_ROOT=$MYDIR/../.. - -#start with a "clean" environment; activate and deactivate ncar_pylib in order to successfully deactivate previously activated environment without errors -module load ncarenv/1.3 -conda deactivate -module purge - -#load the modules in order to compile the CCPP SCM -echo "Loading intel and netcdf modules..." -module load ncarenv/1.3 -module load intel/2022.1 -module load mpt/2.25 -module load ncarcompilers/0.5.0 -module load netcdf - -echo "Setting up NCEPLIBS" -module use /glade/work/epicufsrt/contrib/hpc-stack/intel2022.1/modulefiles/stack -module load hpc/1.2.0 -module load hpc-intel/2022.1 -module load hpc-mpt/2.25 -export bacio_ROOT=/glade/work/epicufsrt/contrib/hpc-stack/intel2022.1/intel-2022.1/bacio/2.4.1 -export sp_ROOT=/glade/work/epicufsrt/contrib/hpc-stack/intel2022.1/intel-2022.1/sp/2.3.3 -export w3emc_ROOT=/glade/work/epicufsrt/contrib/hpc-stack/intel2022.1/intel-2022.1/w3emc/2.9.2 - -echo "Setting CC/CXX/FC environment variables" -export CC=icc -export CXX=icpc -export FC=ifort - -echo "Loading cmake" -module load cmake/3.22.0 -export CMAKE_C_COMPILER=icc -export CMAKE_CXX_COMPILER=icpc -export CMAKE_Fortran_COMPILER=ifort -export CMAKE_Platform=cheyenne.intel - -echo "Setting up python environment for running and plotting." -module load conda/latest - -conda activate /glade/p/ral/jntp/GMTB/CCPP_SCM/conda/ccpp-scm - diff --git a/scm/etc/Desktop_setup_gfortran.csh b/scm/etc/Desktop_setup_gfortran.csh deleted file mode 100755 index d038405f4..000000000 --- a/scm/etc/Desktop_setup_gfortran.csh +++ /dev/null @@ -1,51 +0,0 @@ -#!/bin/tcsh - -echo "Setting environment variables for CCPP-SCM on Desktop (MacOS) with gcc/gfortran" - -set called=($_) - -if ( "$called" != "") then ### called by source - set MYSCRIPT=`readlink -f -n $called[2]` -else ### called by direct execution of the script - set MYSCRIPT=`readlink -f -n '$0'` -endif -set MYDIR=`dirname $MYSCRIPT` -set MYDIR=`cd $MYDIR && pwd -P` - -setenv SCM_ROOT $MYDIR/../.. - -echo "Setting CC/CXX/FC environment variables" -setenv CC /opt/local/bin/gcc-mp-10 -setenv CXX /opt/local/bin/g++-mp-10 -setenv FC gfortran-mp-10 - -echo "Setting location of NETCDF" -setenv NETCDF /opt/local -setenv LDFLAGS "-I${NETCDF}/include -L${NETCDF}/lib -Wl,-rpath,${NETCDF}/lib" - -echo "Setting location of NCEPLIBS libraries" -setenv BACIO_LIB4 /Users/$USER/NCEPLIBS/lib/libbacio_v2.2.0_4.a -setenv SP_LIBd /Users/$USER/NCEPLIBS/lib/libsp_v2.1.0_d.a -setenv W3NCO_LIBd /Users/$USER/NCEPLIBS/lib/libw3nco_v2.1.0_d.a - -#check to see if CMake is installed locally -echo "Checking if CMake is installed" -cmake --version - -if ( $? != 0 ) then - echo "CMake not found; installing CMake" - pip install cmake -else - echo "CMake is installed" -endif - -#check to see if f90nml is installed locally -echo "Checking if f90nml python module is installed" -python -c "import f90nml" - -if ( $? != 0 ) then - echo "Not found; installing f90nml" - pip install --no-cache-dir f90nml==0.19 -else - echo "f90nml is installed" -endif diff --git a/scm/etc/Desktop_setup_gfortran.sh b/scm/etc/Desktop_setup_gfortran.sh deleted file mode 100755 index 37485a163..000000000 --- a/scm/etc/Desktop_setup_gfortran.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/bash - -echo "Setting environment variables for CCPP-SCM on Desktop (MacOS) with gcc/gfortran" - -if [[ $(uname -s) == Darwin ]]; then - MYDIR=$(cd "$(dirname "$(greadlink -f -n "${BASH_SOURCE[0]}" )" )" && pwd -P) -else - MYDIR=$(cd "$(dirname "$(readlink -f -n "${BASH_SOURCE[0]}" )" )" && pwd -P) -fi - -export SCM_ROOT=$MYDIR/../.. - -echo "Setting CC/CXX/FC environment variables" -export CC=/opt/local/bin/gcc-mp-10 -export CXX=/opt/local/bin/g++-mp-10 -export FC=gfortran-mp-10 - -echo "Setting location of NETCDF" -export NETCDF=/opt/local -export LDFLAGS="-I${NETCDF}/include -L${NETCDF}/lib -Wl,-rpath,${NETCDF}/lib" - -echo "Setting location of NCEPLIBS libraries" -export BACIO_LIB4=/Users/$USER/NCEPLIBS/lib/libbacio_v2.2.0_4.a -export SP_LIBd=/Users/$USER/NCEPLIBS/lib/libsp_v2.1.0_d.a -export W3NCO_LIBd=/Users/$USER/NCEPLIBS/lib/libw3nco_v2.1.0_d.a - -#check to see if CMake is installed locally -echo "Checking if CMake is installed" -cmake --version - -if [ $? -ne 0 ]; then - echo "CMake not found; installing CMake" - pip install cmake -else - echo "CMake is installed" -fi - -#check to see if f90nml is installed locally -echo "Checking if f90nml python module is installed" -python -c "import f90nml" - -if [ $? -ne 0 ]; then - echo "Not found; installing f90nml" - pip install --no-cache-dir f90nml==0.19 -else - echo "f90nml is installed" -fi diff --git a/scm/etc/Hera_setup_intel.csh b/scm/etc/Hera_setup_intel.csh deleted file mode 100755 index 369f6e3af..000000000 --- a/scm/etc/Hera_setup_intel.csh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/tcsh - -echo "Setting environment variables for CCPP-SCM on Hera with icc/ifort" - -set called=($_) - -if ( "$called" != "") then ### called by source - set MYSCRIPT=`readlink -f -n $called[2]` -else ### called by direct execution of the script - set MYSCRIPT=`readlink -f -n '$0'` -endif -set MYDIR=`dirname $MYSCRIPT` -set MYDIR=`cd $MYDIR && pwd -P` - -setenv SCM_ROOT $MYDIR/../.. - -#load the modules in order to compile the CCPP SCM -echo "Loading intel and netcdf modules..." -module purge -module load intel/2022.1.2 -module load impi/2022.1.2 -module use /scratch1/NCEPDEV/nems/role.epic/hpc-stack/libs/intel-2022.1.2/modulefiles/stack -module load hpc/1.2.0 -module load hpc-intel/2022.1.2 -module load hpc-impi/2022.1.2 -module load netcdf - -echo "Setting up NCEPLIBS" -setenv bacio_ROOT /scratch1/NCEPDEV/nems/role.epic/hpc-stack/libs/intel-2022.1.2/intel-2022.1.2/bacio/2.4.1 -setenv sp_ROOT /scratch1/NCEPDEV/nems/role.epic/hpc-stack/libs/intel-2022.1.2/intel-2022.1.2/sp/2.3.3 -setenv w3emc_ROOT /scratch1/NCEPDEV/nems/role.epic/hpc-stack/libs/intel-2022.1.2/intel-2022.1.2/w3emc/2.9.2 - -echo "Setting CC/CXX/FC environment variables" -setenv CC icc -setenv CXX icpc -setenv FC ifort - -echo "Loading cmake" -module load cmake/3.20.1 -setenv CMAKE_C_COMPILER icc -setenv CMAKE_CXX_COMPILER icpc -setenv CMAKE_Fortran_COMPILER ifort -setenv CMAKE_Platform hera.intel - -echo "Loading the SCM python environment" -source /scratch1/BMC/gmtb/SCM_anaconda/etc/profile.d/conda.csh -conda activate pyccpp diff --git a/scm/etc/Hera_setup_intel.sh b/scm/etc/Hera_setup_intel.sh deleted file mode 100755 index 5d760260b..000000000 --- a/scm/etc/Hera_setup_intel.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/bin/bash - -echo "Setting environment variables for CCPP-SCM on Hera with icc/ifort" - -MYDIR=$(cd "$(dirname "$(readlink -f -n "${BASH_SOURCE[0]}" )" )" && pwd -P) - -export SCM_ROOT=$MYDIR/../.. - -#load the modules in order to compile the CCPP SCM -echo "Loading intel and netcdf modules..." -module purge -module load intel/2022.1.2 -module load impi/2022.1.2 -module use /scratch1/NCEPDEV/nems/role.epic/hpc-stack/libs/intel-2022.1.2/modulefiles/stack -module load hpc/1.2.0 -module load hpc-intel/2022.1.2 -module load hpc-impi/2022.1.2 -module load netcdf - -echo "Setting up NCEPLIBS" -export bacio_ROOT=/scratch1/NCEPDEV/nems/role.epic/hpc-stack/libs/intel-2022.1.2/intel-2022.1.2/bacio/2.4.1 -export sp_ROOT=/scratch1/NCEPDEV/nems/role.epic/hpc-stack/libs/intel-2022.1.2/intel-2022.1.2/sp/2.3.3 -export w3emc_ROOT=/scratch1/NCEPDEV/nems/role.epic/hpc-stack/libs/intel-2022.1.2/intel-2022.1.2/w3emc/2.9.2 - -echo "Setting CC/CXX/FC environment variables" -export CC=icc -export CXX=icpc -export FC=ifort - -echo "Loading cmake" -module load cmake/3.20.1 -export CMAKE_C_COMPILER=icc -export CMAKE_CXX_COMPILER=icpc -export CMAKE_Fortran_COMPILER=ifort -export CMAKE_Platform=hera.intel - -echo "Loading the SCM python environment" -. "/scratch1/BMC/gmtb/SCM_anaconda/etc/profile.d/conda.sh" -conda activate pyccpp diff --git a/scm/etc/modules/hera_gnu.lua b/scm/etc/modules/hera_gnu.lua index 23867c4ac..7d45752fa 100644 --- a/scm/etc/modules/hera_gnu.lua +++ b/scm/etc/modules/hera_gnu.lua @@ -7,10 +7,10 @@ whatis([===[Loads libraries needed for building the CCPP SCM on Hera with GNU co prepend_path("MODULEPATH", "/scratch1/NCEPDEV/jcsda/jedipara/spack-stack/modulefiles") -load("cmake/3.20.1") +load("cmake/3.28.1") load("miniconda/3.9.12") -prepend_path("MODULEPATH", "/scratch1/NCEPDEV/nems/role.epic/spack-stack/spack-stack-1.5.1/envs/unified-env/install/modulefiles/Core") +prepend_path("MODULEPATH", "/scratch1/NCEPDEV/nems/role.epic/spack-stack/spack-stack-1.5.0/envs/unified-env-rocky8/install/modulefiles/Core") load("stack-gcc/9.2.0") load("stack-openmpi/4.1.5") diff --git a/scm/etc/modules/hera_intel.lua b/scm/etc/modules/hera_intel.lua index d84db665c..a97464934 100644 --- a/scm/etc/modules/hera_intel.lua +++ b/scm/etc/modules/hera_intel.lua @@ -6,10 +6,10 @@ the NOAA RDHPC machine Hera using Intel-2021.5.0 whatis([===[Loads libraries needed for building the CCPP SCM on Hera with Intel compilers ]===]) prepend_path("MODULEPATH", "/scratch1/NCEPDEV/jcsda/jedipara/spack-stack/modulefiles") -load("cmake/3.20.1") +load("cmake/3.28.1") load("miniconda/3.9.12") -prepend_path("MODULEPATH", "/scratch1/NCEPDEV/nems/role.epic/spack-stack/spack-stack-1.5.1/envs/unified-env/install/modulefiles/Core") +prepend_path("MODULEPATH", "/scratch1/NCEPDEV/nems/role.epic/spack-stack/spack-stack-1.5.0/envs/unified-env-rocky8/install/modulefiles/Core") load("stack-intel/2021.5.0") load("stack-intel-oneapi-mpi/2021.5.1") From 9da57a802aebe2c72c06b4facf6af5da0471d309 Mon Sep 17 00:00:00 2001 From: Tracy Date: Tue, 9 Apr 2024 21:00:38 +0000 Subject: [PATCH 02/40] update spack versio --- scm/etc/modules/hera_gnu.lua | 2 +- scm/etc/modules/hera_intel.lua | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scm/etc/modules/hera_gnu.lua b/scm/etc/modules/hera_gnu.lua index 7d45752fa..0e28df2d0 100644 --- a/scm/etc/modules/hera_gnu.lua +++ b/scm/etc/modules/hera_gnu.lua @@ -10,7 +10,7 @@ prepend_path("MODULEPATH", "/scratch1/NCEPDEV/jcsda/jedipara/spack-stack/modulef load("cmake/3.28.1") load("miniconda/3.9.12") -prepend_path("MODULEPATH", "/scratch1/NCEPDEV/nems/role.epic/spack-stack/spack-stack-1.5.0/envs/unified-env-rocky8/install/modulefiles/Core") +prepend_path("MODULEPATH", "/scratch1/NCEPDEV/nems/role.epic/spack-stack/spack-stack-1.5.1/envs/unified-env-rocky8/install/modulefiles/Core") load("stack-gcc/9.2.0") load("stack-openmpi/4.1.5") diff --git a/scm/etc/modules/hera_intel.lua b/scm/etc/modules/hera_intel.lua index a97464934..6cdbf7d4c 100644 --- a/scm/etc/modules/hera_intel.lua +++ b/scm/etc/modules/hera_intel.lua @@ -9,7 +9,7 @@ prepend_path("MODULEPATH", "/scratch1/NCEPDEV/jcsda/jedipara/spack-stack/modulef load("cmake/3.28.1") load("miniconda/3.9.12") -prepend_path("MODULEPATH", "/scratch1/NCEPDEV/nems/role.epic/spack-stack/spack-stack-1.5.0/envs/unified-env-rocky8/install/modulefiles/Core") +prepend_path("MODULEPATH", "/scratch1/NCEPDEV/nems/role.epic/spack-stack/spack-stack-1.5.1/envs/unified-env-rocky8/install/modulefiles/Core") load("stack-intel/2021.5.0") load("stack-intel-oneapi-mpi/2021.5.1") From 936b89390029672e630c3b6fd8d10f837a1da4cd Mon Sep 17 00:00:00 2001 From: Tracy Date: Thu, 23 May 2024 15:45:33 +0000 Subject: [PATCH 03/40] add files for 2 MOSAiC cases from Amy Solomon --- scm/etc/case_config/MOSAiC-AMPS.nml | 17 + scm/etc/case_config/MOSAiC-SS.nml | 17 + .../MOSAiC_AMPS_forcing_file_generator.py | 554 ++++++++++++++++++ .../MOSAiC_SS_forcing_file_generator.py | 554 ++++++++++++++++++ scm/etc/scripts/plot_configs/MOSAiC-AMPS.ini | 63 ++ scm/etc/scripts/plot_configs/MOSAiC-SS.ini | 65 ++ scm/etc/scripts/scm_analysis.py | 4 +- scm/etc/scripts/scm_read_obs.py | 67 ++- 8 files changed, 1339 insertions(+), 2 deletions(-) create mode 100644 scm/etc/case_config/MOSAiC-AMPS.nml create mode 100644 scm/etc/case_config/MOSAiC-SS.nml create mode 100644 scm/etc/scripts/MOSAiC_AMPS_forcing_file_generator.py create mode 100644 scm/etc/scripts/MOSAiC_SS_forcing_file_generator.py create mode 100644 scm/etc/scripts/plot_configs/MOSAiC-AMPS.ini create mode 100644 scm/etc/scripts/plot_configs/MOSAiC-SS.ini diff --git a/scm/etc/case_config/MOSAiC-AMPS.nml b/scm/etc/case_config/MOSAiC-AMPS.nml new file mode 100644 index 000000000..ca3148a9f --- /dev/null +++ b/scm/etc/case_config/MOSAiC-AMPS.nml @@ -0,0 +1,17 @@ +$case_config +case_name = 'MOSAiC-AMPS', +runtime = 604800.0, +thermo_forcing_type = 2, +mom_forcing_type = 3, +relax_time = 3600.0, +sfc_flux_spec = .false., +sfc_type = 2, +sfc_roughness_length_cm = 0.02, +reference_profile_choice = 1, +year = 2019, +month = 10, +day = 31, +hour = 0, +column_area = 2.0E9, +lsm_ics = .true., +$end diff --git a/scm/etc/case_config/MOSAiC-SS.nml b/scm/etc/case_config/MOSAiC-SS.nml new file mode 100644 index 000000000..a2f5caa81 --- /dev/null +++ b/scm/etc/case_config/MOSAiC-SS.nml @@ -0,0 +1,17 @@ +$case_config +case_name = 'MOSAiC-SS', +runtime = 604800.0, +thermo_forcing_type = 2, +mom_forcing_type = 3, +relax_time = 3600.0, +sfc_flux_spec = .false., +sfc_type = 2, +sfc_roughness_length_cm = 0.02, +reference_profile_choice = 1, +year = 2020, +month = 3, +day = 2, +hour = 0, +column_area = 2.0E9, +lsm_ics = .true., +$end diff --git a/scm/etc/scripts/MOSAiC_AMPS_forcing_file_generator.py b/scm/etc/scripts/MOSAiC_AMPS_forcing_file_generator.py new file mode 100644 index 000000000..cfbb2d2ba --- /dev/null +++ b/scm/etc/scripts/MOSAiC_AMPS_forcing_file_generator.py @@ -0,0 +1,554 @@ +#!/usr/bin/env python + +from netCDF4 import Dataset +import numpy as np +import forcing_file_common as ffc +import scipy.interpolate +import scm_plotting_routines as spr + +#reload(ffc) + +#read in raw input file + +nc_fid = Dataset("../../data/raw_case_input/MOSAiC_31Oct20190Z_raw.nc", 'r') + +#ncdump to look at raw input file +#nc_attrs, nc_dims, nc_vars = ncdump(nc_fid, False) + +#netCDF how-to +#set attributes +#file_id.setncattr(file_id.variables['variable'].ncattr(), nc_fid.variables['time'].getncattr(ncattr)) +#get attributes +#file_id.variables['variable'].getncattr(index) + +#get raw input variables + +day = nc_fid.variables['day'][:] +hour = nc_fid.variables['hour'][:] +for t in range(day.size): + #find time index corresponding to October 29, 2019 at 0Z + if day[t] == 31 and hour[t] == 0: + start_t_index = t + break + +time = nc_fid.variables['time_offset'][:] #number of seconds since 00Z on 1/17/2006 (starts at 03Z) +#subtract the initial time_offset from all values to get elapsed time since the start of the simulation +time = time - time[start_t_index] +levels = nc_fid.variables['levels'][:] #pressure levels in mb +#convert levels to Pa +levels = 100.0*levels +ice_thickness = np.zeros((2),dtype=float) +#height = nc_fid.variables['alt'][:] +lat = nc_fid.variables['lat'][:] #degrees north +#convert latitutde to degrees north +lon = nc_fid.variables['lon'][:] #degrees east +#use upstream T +T_abs = nc_fid.variables['Tu'][:] #absolute temperature (time, lev) +T_abs = np.swapaxes(T_abs, 0, 1) +thetail = nc_fid.variables['thetail'][:] #theta_il (time, lev) +thetail = np.swapaxes(thetail, 0, 1) +#use unpstream theta instead of thetail +thetailu = nc_fid.variables['thetailu'][:] #theta (time, lev) +thetailu = np.swapaxes(thetailu, 0, 1) +#calculate theta_il from absolute temperature (assuming no condensate) +#thetal = np.zeros((levels.size,time.size),dtype=float) +#for t in range(time.size): +# thetal[:,t] = (ffc.p0/levels)**(ffc.R_dry/ffc.c_p)*T_abs[:,t] +qv = nc_fid.variables['qu'][:] #water vapor mixing ratio in kg/kg (time, lev) +qv = np.swapaxes(qv, 0, 1) +qt = np.zeros((levels.size,time.size),dtype=float) +qt_mr = nc_fid.variables['qt'][:] #water vapor mixing ratio in kg/kg (time, lev) +qt_mr = np.swapaxes(qt_mr, 0, 1) #swap the time and levels axis +qt = qt_mr/(1.0 + qt_mr) #convert to specific humidity from mixing ratio +qtu = np.zeros((levels.size,time.size),dtype=float) +#use upstream qv instead of qt +qtu_mr = nc_fid.variables['qtu'][:] #water vapor mixing ratio in kg/kg (time, lev) +qtu_mr = np.swapaxes(qtu_mr, 0, 1) #swap the time and levels axis +qtu = qtu_mr/(1.0 + qtu_mr) #convert to specific humidity from mixing ratio + +#ql and tke are not specified; set to zero +#ql = np.zeros((levels.size,time.size),dtype=float) +#qi = np.zeros((levels.size,time.size),dtype=float) +ql = nc_fid.variables['ql'][:] #ql (time, lev) +ql = np.swapaxes(ql, 0, 1) +qi = nc_fid.variables['qi'][:] #ql (time, lev) +qi = np.swapaxes(qi, 0, 1) +tke = np.zeros((levels.size,time.size),dtype=float) +# ozone_mmr = nc_fid.variables['o3mmr'][:] +u_wind = nc_fid.variables['u'][:] +u_wind = np.swapaxes(u_wind, 0, 1) #swap the time and levels axis +v_wind = nc_fid.variables['v'][:] +v_wind = np.swapaxes(v_wind, 0, 1) #swap the time and levels axis + +#w_sub = np.zeros((levels.size,time.size),dtype=float) +omega = nc_fid.variables['omega'][:] #vertical pressure velocity in Pa/s +omega = np.swapaxes(omega, 0, 1) #swap the time and levels axis +w_sub = nc_fid.variables['w'][:] #vertical velocity in m/s +w_sub = np.swapaxes(w_sub, 0, 1) #swap the time and levels axis +#convert to w +#for t in range(time.size): +# w_sub[:,t] = ffc.omega_to_w(omega[:,t],levels,T_abs[:,t]) + +T_surf = nc_fid.variables['T_skin'][:] +#T_surf = T_surf + 273.15 #convert to K +#T_surf = (29 + 273.15)*np.ones((time.size),dtype=float) #forcing instructions specify time-invariant 29 deg C. +p_surf = nc_fid.variables['p_srf'][:] #Pa +#p_surf = p_surf*100.0 #convert to Pa + +#h_advec_thil = np.zeros((levels.size,time.size),dtype=float) +h_advec_thil = nc_fid.variables['h_advec_thetail'][:] #K/s +h_advec_thil = np.swapaxes(h_advec_thil, 0, 1) #swap the time and levels axis +#for t in range(time.size): +# h_advec_thil[:,t] = (ffc.p0/levels)**(ffc.R_dry/ffc.c_p)*h_advec_T[:,t] #convert to potential temperature + +#v_advec_thil = np.zeros((levels.size,time.size),dtype=float) +v_advec_thil = nc_fid.variables['v_advec_thetail'][:] #K/s +v_advec_thil = np.swapaxes(v_advec_thil, 0, 1) #swap the time and levels axis +#for t in range(time.size): +# v_advec_thil[:,t] = (ffc.p0/levels)**(ffc.R_dry/ffc.c_p)*v_advec_T[:,t] #convert to potential temperature + +dT_dt = np.zeros((levels.size,time.size),dtype=float) + +# h_advec_T = h_advec_T*86400.0 +# v_advec_T = v_advec_T*86400.0 +# dT_dt = dT_dt*86400.0 +# spr.contour_plot_firl(time, levels, h_advec_T, np.min(h_advec_T), np.max(h_advec_T), 'h advec T', 'time', 'pressure', 'h_advec_T.eps', y_inverted = True) +# spr.contour_plot_firl(time, levels, v_advec_T, np.min(v_advec_T), np.max(v_advec_T), 'v advec T', 'time', 'pressure', 'v_advec_T.eps', y_inverted = True) +# spr.contour_plot_firl(time, levels, dT_dt, np.min(dT_dt), np.max(dT_dt), 'total T tend', 'time', 'pressure', 'dT_dt.eps', y_inverted = True) + +#h_advec_qt = np.zeros((levels.size,time.size),dtype=float) +h_advec_qt = nc_fid.variables['h_advec_qt'][:] #kg/kg/s +h_advec_qt = np.swapaxes(h_advec_qt, 0, 1) #swap the time and levels axis +h_advec_qt = h_advec_qt/(1.0 + qt_mr)**2 #convert to specific humidity + +h_advec_qi = np.zeros((levels.size,time.size),dtype=float) +h_advec_ql = np.zeros((levels.size,time.size),dtype=float) + +#v_advec_qt = np.zeros((levels.size,time.size),dtype=float) +v_advec_qt = nc_fid.variables['v_advec_qt'][:] #kg/kg/s +v_advec_qt = np.swapaxes(v_advec_qt, 0, 1) #swap the time and levels axis +v_advec_qt = v_advec_qt/(1.0 + qt_mr)**2 #convert to specific humidity + +dq_dt = np.zeros((levels.size,time.size),dtype=float) +#dq_dt = nc_fid.variables['dqdt'][:] +#dq_dt = np.swapaxes(dq_dt, 0, 1)*1.0E-3/3600.0 #swap the time and levels axis, convert to K/s + +#h_advec_qt = h_advec_qt*86400.0 +#v_advec_qt = v_advec_qt*86400.0 +#dq_dt = dq_dt*86400.0 +#spr.contour_plot_firl(time, levels, h_advec_qt, np.min(h_advec_qt), np.max(h_advec_qt), 'h advec q', 'time', 'pressure', 'h_advec_q.eps', y_inverted = True) +#spr.contour_plot_firl(time, levels, v_advec_qt, np.min(v_advec_qt), np.max(v_advec_qt), 'v advec q', 'time', 'pressure', 'v_advec_q.eps', y_inverted = True) +#spr.contour_plot_firl(time, levels, dq_dt, np.min(dq_dt), np.max(dq_dt), 'total q tend', 'time', 'pressure', 'dq_dt.eps', y_inverted = True) + +#phi_sfc = nc_fid.variables['phis'][:] +#z_sfc = nc_fid.variables['alt'][:] +height = nc_fid.variables['height'][:] +#height = ffc.get_height_from_pres(T_abs[:,0],levels,z_sfc) + +#the following variables are not in this forcing file, but are included in other cases +#rad_heating = nc_fid.variables['dT_dt_rad'][:] #K/s +#rad_heating = np.swapaxes(rad_heating, 0, 1) #swap the time and levels axis +rad_heating = np.zeros((levels.size,time.size),dtype=float) +u_g = np.zeros((levels.size,time.size),dtype=float) +v_g = np.zeros((levels.size,time.size),dtype=float) + +ozone = np.zeros((levels.size,time.size),dtype=float) +ozone = ozone + 2.e-8 + +tiice = np.zeros((ice_thickness.size),dtype=float) +##tiice[0] = T_surf[start_t_index] +tiice[0] = 271.35 + .75*(T_surf[start_t_index] - 271.35) +tiice[1] = 271.35 + .25*(T_surf[start_t_index] - 271.35) +stc = tiice[0] +smc = 0.33 +slc = 0.33 +hice = 0.3 +slmsk = 2.0 +tsfco = T_surf[start_t_index] +weasd = 200.0 +fice = 1.0 +tisfc = tsfco +snwdph = 2.e-4 +tg3 = 271.35 +zorl = 15.0 +alvsf = 0.23 +alnsf = 0.23 +alvwf = 0.23 +alnwf = 0.23 +facsf = 0.5055632 +facwf = 0.4944368 +vegfrac = 0.0 +canopy = 0.0 +vegtyp = 10 +soiltyp = 12 +uustar = 0.3828793 +shdmin = 0.01 +shdmax = 0.8 +slopetyp = 1 +snoalb = 0.7287961 + +# Open ozone file +#f = open('../../data/raw_case_input/twpice_CRM_ozone.txt', 'r') + +# Read and ignore header lines +#header1 = f.readline() + +#oz_pres = [] +#oz_data = [] +# Loop over lines and extract variables of interest +#for line in f: +# line = line.strip() +# columns = line.split() +# oz_pres.append(float(columns[1])) +# oz_data.append(float(columns[2])) + +#f.close() + +#oz_pres = 100.0*np.array(oz_pres) +#oz_data = np.array(oz_data) +#oz_f = scipy.interpolate.interp1d(oz_pres, oz_data) +#ozone_ppb = oz_f(levels[1:].tolist()) +#ozone_ppb = np.insert(ozone_ppb, 0, oz_data[0]) +#ozone_mmr = ozone_ppb*1.0E-9 + +# +#open processed input file for writing + +writefile_fid = Dataset('../../data/processed_case_input/MOSAiC.nc', 'w', format='NETCDF4') +writefile_fid.description = "CCPP SCM forcing file for MOSAiC case" + +#create groups for scalars, intitialization, and forcing + +writefile_scalar_grp = writefile_fid.createGroup("scalars") +writefile_initial_grp = writefile_fid.createGroup("initial") +writefile_forcing_grp = writefile_fid.createGroup("forcing") + +#create dimensions and write them out + +writefile_time_dim = writefile_fid.createDimension('time', None) +writefile_time_var = writefile_fid.createVariable('time', 'f4', ('time',)) +writefile_time_var[:] = time[start_t_index:] +writefile_time_var.units = 's' +writefile_time_var.description = 'elapsed time since the beginning of the simulation' + +writefile_levels_dim = writefile_fid.createDimension('levels', None) +writefile_levels_var = writefile_fid.createVariable('levels', 'f4', ('levels',)) +writefile_levels_var[:] = levels +writefile_levels_var.units = 'Pa' +writefile_levels_var.description = 'pressure levels' + +writefile_ice_thickness_dim = writefile_fid.createDimension('ice_thickness', None) +writefile_ice_thickness_var = writefile_fid.createVariable('ice_thickness', 'f4', ('ice_thickness',)) +writefile_ice_thickness_var[:] = ice_thickness +writefile_ice_thickness_var.units = 'm' +writefile_ice_thickness_var.description = 'depth of ice layers' + +#create variables and write them out + +#scalar group + +writefile_lat_var = writefile_scalar_grp.createVariable('lat', 'f4') +writefile_lat_var[:] = lat +writefile_lat_var.units = 'degrees N' +writefile_lat_var.description = 'latitude of column' + +writefile_lon_var = writefile_scalar_grp.createVariable('lon', 'f4') +writefile_lon_var[:] = lon +writefile_lon_var.units = 'degrees E' +writefile_lon_var.description = 'longitude of column' + +writefile_hice_var = writefile_scalar_grp.createVariable('hice', 'f4') +writefile_hice_var[:] = hice +writefile_hice_var.units = 'm' +writefile_hice_var.description = 'sea ice thickness' + +writefile_slmsk_var = writefile_scalar_grp.createVariable('slmsk', 'f4') +writefile_slmsk_var[:] = slmsk +writefile_slmsk_var.units = '' +writefile_slmsk_var.description = 'land-sea-ice mask' + +writefile_tsfco_var = writefile_scalar_grp.createVariable('tsfco', 'f4') +writefile_tsfco_var[:] = tsfco +writefile_tsfco_var.units = 'm' +writefile_tsfco_var.description = 'sea ice surface skin temperature' + +writefile_weasd_var = writefile_scalar_grp.createVariable('weasd', 'f4') +writefile_weasd_var[:] = weasd +writefile_weasd_var.units = 'mm' +writefile_weasd_var.description = 'water equivalent accumulated snow depth' + +writefile_fice_var = writefile_scalar_grp.createVariable('fice', 'f4') +writefile_fice_var[:] = fice +writefile_fice_var.units = '1' +writefile_fice_var.description = 'ice fraction' + +writefile_tisfc_var = writefile_scalar_grp.createVariable('tisfc', 'f4') +writefile_tisfc_var[:] = tisfc +writefile_tisfc_var.units = 'K' +writefile_tisfc_var.description = 'ice surface temperature' + +writefile_snwdph_var = writefile_scalar_grp.createVariable('snwdph', 'f4') +writefile_snwdph_var[:] = snwdph +writefile_snwdph_var.units = 'mm' +writefile_snwdph_var.description = 'water equivalent snow depth' + +writefile_tg3_var = writefile_scalar_grp.createVariable('tg3', 'f4') +writefile_tg3_var[:] = tg3 +writefile_tg3_var.units = 'K' +writefile_tg3_var.description = 'deep soil temperature' + +writefile_zorl_var = writefile_scalar_grp.createVariable('zorl', 'f4') +writefile_zorl_var[:] = zorl +writefile_zorl_var.units = 'cm' +writefile_zorl_var.description = 'composite surface roughness length' + +writefile_alvsf_var = writefile_scalar_grp.createVariable('alvsf', 'f4') +writefile_alvsf_var[:] = alvsf +writefile_alvsf_var.units = '' +writefile_alvsf_var.description = '60 degree vis albedo with strong cosz dependency' + +writefile_alnsf_var = writefile_scalar_grp.createVariable('alnsf', 'f4') +writefile_alnsf_var[:] = alnsf +writefile_alnsf_var.units = '' +writefile_alnsf_var.description = '60 degree nir albedo with strong cosz dependency' + +writefile_alvwf_var = writefile_scalar_grp.createVariable('alvwf', 'f4') +writefile_alvwf_var[:] = alvwf +writefile_alvwf_var.units = '' +writefile_alvwf_var.description = '60 degree vis albedo with weak cosz dependency' + +writefile_alnwf_var = writefile_scalar_grp.createVariable('alnwf', 'f4') +writefile_alnwf_var[:] = alnwf +writefile_alnwf_var.units = '' +writefile_alnwf_var.description = '60 degree nir albedo with weak cosz dependency' + +writefile_facsf_var = writefile_scalar_grp.createVariable('facsf', 'f4') +writefile_facsf_var[:] = facsf +writefile_facsf_var.units = '' +writefile_facsf_var.description = 'fractional coverage with strong cosz dependency' + +writefile_facwf_var = writefile_scalar_grp.createVariable('facwf', 'f4') +writefile_facwf_var[:] = facwf +writefile_facwf_var.units = '' +writefile_facwf_var.description = 'fractional coverage with weak cosz dependency' + +writefile_vegfrac_var = writefile_scalar_grp.createVariable('vegfrac', 'f4') +writefile_vegfrac_var[:] = vegfrac +writefile_vegfrac_var.units = '1' +writefile_vegfrac_var.description = 'vegetation fraction' + +writefile_canopy_var = writefile_scalar_grp.createVariable('canopy', 'f4') +writefile_canopy_var[:] = canopy +writefile_canopy_var.units = 'kg m-2' +writefile_canopy_var.description = 'amount of water stored in camopy' + +writefile_vegtyp_var = writefile_scalar_grp.createVariable('vegtyp', 'f4') +writefile_vegtyp_var[:] = vegtyp +writefile_vegtyp_var.units = '' +writefile_vegtyp_var.description = 'vegetation type 1-12' + +writefile_soiltyp_var = writefile_scalar_grp.createVariable('soiltyp', 'f4') +writefile_soiltyp_var[:] = soiltyp +writefile_soiltyp_var.units = '' +writefile_soiltyp_var.description = 'soil type 1-12' + +writefile_uustar_var = writefile_scalar_grp.createVariable('uustar', 'f4') +writefile_uustar_var[:] = uustar +writefile_uustar_var.units = 'm s-1' +writefile_uustar_var.description = 'friction velocity' + +writefile_shdmin_var = writefile_scalar_grp.createVariable('shdmin', 'f4') +writefile_shdmin_var[:] = shdmin +writefile_shdmin_var.units = '1' +writefile_shdmin_var.description = 'minimum vegetation fraction' + +writefile_shdmax_var = writefile_scalar_grp.createVariable('shdmax', 'f4') +writefile_shdmax_var[:] = shdmax +writefile_shdmax_var.units = '1' +writefile_shdmax_var.description = 'maximum vegetation fraction' + +writefile_slopetyp_var = writefile_scalar_grp.createVariable('slopetyp', 'f4') +writefile_slopetyp_var[:] = slopetyp +writefile_slopetyp_var.units = '' +writefile_slopetyp_var.description = 'slope type 1-9' + +writefile_snoalb_var = writefile_scalar_grp.createVariable('snoalb', 'f4') +writefile_snoalb_var[:] = snoalb +writefile_snoalb_var.units = '1' +writefile_snoalb_var.description = 'maximum snow albedo' + +#initial group + +writefile_height_var = writefile_initial_grp.createVariable('height', 'f4', ('levels',)) +writefile_height_var[:] = height +writefile_height_var.units = 'm' +writefile_height_var.description = 'physical height at pressure levels' + +writefile_tiice_var = writefile_initial_grp.createVariable('tiice', 'f4', ('ice_thickness',)) +writefile_tiice_var[:] = tiice +writefile_tiice_var.units = 'K' +writefile_tiice_var.description = 'initial profile of sea ice internal temperature' + +writefile_stc_var = writefile_initial_grp.createVariable('stc', 'f4') +writefile_stc_var[:] = stc +writefile_stc_var.units = 'K' +writefile_stc_var.description = 'initial profile of sea ice internal temperature' + +writefile_smc_var = writefile_initial_grp.createVariable('smc', 'f4') +writefile_smc_var[:] = smc +writefile_smc_var.units = 'm3 m-3' +writefile_smc_var.description = 'initial profile of soil moisture' + +writefile_slc_var = writefile_initial_grp.createVariable('slc', 'f4') +writefile_slc_var[:] = slc +writefile_slc_var.units = 'm3 m-3' +writefile_slc_var.description = 'initial profile of soil liquid water' + +writefile_thetail_var = writefile_initial_grp.createVariable('thetail', 'f4', ('levels',)) +writefile_thetail_var[:] = thetail[:,start_t_index] +writefile_thetail_var.units = 'K' +writefile_thetail_var.description = 'initial profile of ice-liquid water potential temperature' + +writefile_qt_var = writefile_initial_grp.createVariable('qt', 'f4', ('levels',)) +writefile_qt_var[:] = qt[:,start_t_index] +writefile_qt_var.units = 'kg kg^-1' +writefile_qt_var.description = 'initial profile of total water specific humidity' + +writefile_ql_var = writefile_initial_grp.createVariable('ql', 'f4', ('levels',)) +writefile_ql_var[:] = ql[:,start_t_index] +writefile_ql_var.units = 'kg kg^-1' +writefile_ql_var.description = 'initial profile of liquid water specific humidity' + +writefile_qi_var = writefile_initial_grp.createVariable('qi', 'f4', ('levels',)) +writefile_qi_var[:] = qi[:,start_t_index] +writefile_qi_var.units = 'kg kg^-1' +writefile_qi_var.description = 'initial profile of ice water specific humidity' + +writefile_u_var = writefile_initial_grp.createVariable('u', 'f4', ('levels',)) +writefile_u_var[:] = u_wind[:,start_t_index] +writefile_u_var.units = 'm s^-1' +writefile_u_var.description = 'initial profile of E-W horizontal wind' + +writefile_v_var = writefile_initial_grp.createVariable('v', 'f4', ('levels',)) +writefile_v_var[:] = v_wind[:,start_t_index] +writefile_v_var.units = 'm s^-1' +writefile_v_var.description = 'initial profile of N-S horizontal wind' + +writefile_tke_var = writefile_initial_grp.createVariable('tke', 'f4', ('levels',)) +writefile_tke_var[:] = tke[:,start_t_index] +writefile_tke_var.units = 'm^2 s^-2' +writefile_tke_var.description = 'initial profile of turbulence kinetic energy' + +writefile_ozone_var = writefile_initial_grp.createVariable('ozone', 'f4', ('levels',)) +writefile_ozone_var[:] = ozone[:,start_t_index] +writefile_ozone_var.units = 'kg kg^-1' +writefile_ozone_var.description = 'initial profile of ozone mass mixing ratio' + +#forcing group + +writefile_p_surf_var = writefile_forcing_grp.createVariable('p_surf', 'f4', ('time',)) +writefile_p_surf_var[:] = p_surf[start_t_index:] +writefile_p_surf_var.units = 'Pa' +writefile_p_surf_var.description = 'surface pressure' + +writefile_T_surf_var = writefile_forcing_grp.createVariable('T_surf', 'f4', ('time',)) +writefile_T_surf_var[:] = T_surf[start_t_index:] +writefile_T_surf_var.units = 'K' +writefile_T_surf_var.description = 'surface absolute temperature' + +writefile_w_ls_var = writefile_forcing_grp.createVariable('w_ls', 'f4', ('levels','time',)) +writefile_w_ls_var[:] = w_sub[:,start_t_index:] +writefile_w_ls_var.units = 'm s^-1' +writefile_w_ls_var.description = 'large scale vertical velocity' + +writefile_omega_var = writefile_forcing_grp.createVariable('omega', 'f4', ('levels','time',)) +writefile_omega_var[:] = omega[:,start_t_index:] +writefile_omega_var.units = 'Pa s^-1' +writefile_omega_var.description = 'large scale pressure vertical velocity' + +writefile_u_g_var = writefile_forcing_grp.createVariable('u_g', 'f4', ('levels','time',)) +writefile_u_g_var[:] = u_g[:,start_t_index:] +writefile_u_g_var.units = 'm s^-1' +writefile_u_g_var.description = 'large scale geostrophic E-W wind' + +writefile_v_g_var = writefile_forcing_grp.createVariable('v_g', 'f4', ('levels','time',)) +writefile_v_g_var[:] = v_g[:,start_t_index:] +writefile_v_g_var.units = 'm s^-1' +writefile_v_g_var.description = 'large scale geostrophic N-S wind' + +writefile_u_nudge_var = writefile_forcing_grp.createVariable('u_nudge', 'f4', ('levels','time',)) +writefile_u_nudge_var[:] = u_wind[:,start_t_index:] +writefile_u_nudge_var.units = 'm s^-1' +writefile_u_nudge_var.description = 'E-W wind to nudge toward' + +writefile_v_nudge_var = writefile_forcing_grp.createVariable('v_nudge', 'f4', ('levels','time',)) +writefile_v_nudge_var[:] = v_wind[:,start_t_index:] +writefile_v_nudge_var.units = 'm s^-1' +writefile_v_nudge_var.description = 'N-S wind to nudge toward' + +writefile_T_nudge_var = writefile_forcing_grp.createVariable('T_nudge', 'f4', ('levels','time',)) +writefile_T_nudge_var[:] = T_abs[:,start_t_index:] +writefile_T_nudge_var.units = 'K' +writefile_T_nudge_var.description = 'absolute temperature to nudge toward' + +writefile_thil_nudge_var = writefile_forcing_grp.createVariable('thil_nudge', 'f4', ('levels','time',)) +writefile_thil_nudge_var[:] = thetailu[:,start_t_index:] +writefile_thil_nudge_var.units = 'K' +writefile_thil_nudge_var.description = 'potential temperature to nudge toward' + +writefile_qt_nudge_var = writefile_forcing_grp.createVariable('qt_nudge', 'f4', ('levels','time',)) +writefile_qt_nudge_var[:] = qtu[:,start_t_index:] +writefile_qt_nudge_var.units = 'kg kg^-1' +writefile_qt_nudge_var.description = 'q_t to nudge toward' + +writefile_qi_nudge_var = writefile_forcing_grp.createVariable('qi_nudge', 'f4', ('levels','time',)) +writefile_qi_nudge_var[:] = qi[:,start_t_index:] +writefile_qi_nudge_var.units = 'kg kg^-1' +writefile_qi_nudge_var.description = 'q_i to nudge toward' + +writefile_ql_nudge_var = writefile_forcing_grp.createVariable('ql_nudge', 'f4', ('levels','time',)) +writefile_ql_nudge_var[:] = ql[:,start_t_index:] +writefile_ql_nudge_var.units = 'kg kg^-1' +writefile_ql_nudge_var.description = 'q_l to nudge toward' + +writefile_rad_heating_var = writefile_forcing_grp.createVariable('dT_dt_rad', 'f4', ('levels','time',)) +writefile_rad_heating_var[:] = rad_heating[:,start_t_index:] +writefile_rad_heating_var.units = 'K s^-1' +writefile_rad_heating_var.description = 'prescribed radiative heating rate' + +writefile_h_advec_thil_var = writefile_forcing_grp.createVariable('h_advec_thetail', 'f4', ('levels','time',)) +writefile_h_advec_thil_var[:] = h_advec_thil[:,start_t_index:] +writefile_h_advec_thil_var.units = 'K s^-1' +writefile_h_advec_thil_var.description = 'prescribed theta_il tendency due to horizontal advection' + +writefile_v_advec_thil_var = writefile_forcing_grp.createVariable('v_advec_thetail', 'f4', ('levels','time',)) +writefile_v_advec_thil_var[:] = v_advec_thil[:,start_t_index:] +writefile_v_advec_thil_var.units = 'K s^-1' +writefile_v_advec_thil_var.description = 'prescribed theta_il tendency due to vertical advection' + +writefile_h_advec_qt_var = writefile_forcing_grp.createVariable('h_advec_qt', 'f4', ('levels','time',)) +writefile_h_advec_qt_var[:] = h_advec_qt[:,start_t_index:] +writefile_h_advec_qt_var.units = 'kg kg^-1 s^-1' +writefile_h_advec_qt_var.description = 'prescribed q_t tendency due to horizontal advection' + +writefile_h_advec_qi_var = writefile_forcing_grp.createVariable('h_advec_qi', 'f4', ('levels','time',)) +writefile_h_advec_qi_var[:] = h_advec_qi[:,start_t_index:] +writefile_h_advec_qi_var.units = 'kg kg^-1 s^-1' +writefile_h_advec_qi_var.description = 'prescribed q_i tendency due to horizontal advection' + +writefile_h_advec_ql_var = writefile_forcing_grp.createVariable('h_advec_ql', 'f4', ('levels','time',)) +writefile_h_advec_ql_var[:] = h_advec_ql[:,start_t_index:] +writefile_h_advec_ql_var.units = 'kg kg^-1 s^-1' +writefile_h_advec_ql_var.description = 'prescribed q_l tendency due to horizontal advection' + +writefile_v_advec_qt_var = writefile_forcing_grp.createVariable('v_advec_qt', 'f4', ('levels','time',)) +writefile_v_advec_qt_var[:] = v_advec_qt[:,start_t_index:] +writefile_v_advec_qt_var.units = 'kg kg^-1 s^-1' +writefile_v_advec_qt_var.description = 'prescribed q_t tendency due to vertical advection' + + +#close processed input file +writefile_fid.close() + +#close raw input file +nc_fid.close() diff --git a/scm/etc/scripts/MOSAiC_SS_forcing_file_generator.py b/scm/etc/scripts/MOSAiC_SS_forcing_file_generator.py new file mode 100644 index 000000000..918eea33e --- /dev/null +++ b/scm/etc/scripts/MOSAiC_SS_forcing_file_generator.py @@ -0,0 +1,554 @@ +#!/usr/bin/env python + +from netCDF4 import Dataset +import numpy as np +import forcing_file_common as ffc +import scipy.interpolate +import scm_plotting_routines as spr + +#reload(ffc) + +#read in raw input file + +nc_fid = Dataset("../../data/raw_case_input/MOSAiC_2Mar20200Z_raw.nc", 'r') + +#ncdump to look at raw input file +#nc_attrs, nc_dims, nc_vars = ncdump(nc_fid, False) + +#netCDF how-to +#set attributes +#file_id.setncattr(file_id.variables['variable'].ncattr(), nc_fid.variables['time'].getncattr(ncattr)) +#get attributes +#file_id.variables['variable'].getncattr(index) + +#get raw input variables + +day = nc_fid.variables['day'][:] +hour = nc_fid.variables['hour'][:] +for t in range(day.size): + #find time index corresponding to October 29, 2019 at 0Z + if day[t] == 2 and hour[t] == 0: + start_t_index = t + break + +time = nc_fid.variables['time_offset'][:] #number of seconds since 00Z on 1/17/2006 (starts at 03Z) +#subtract the initial time_offset from all values to get elapsed time since the start of the simulation +time = time - time[start_t_index] +levels = nc_fid.variables['levels'][:] #pressure levels in mb +#convert levels to Pa +levels = 100.0*levels +ice_thickness = np.zeros((2),dtype=float) +#height = nc_fid.variables['alt'][:] +lat = nc_fid.variables['lat'][:] #degrees north +#convert latitutde to degrees north +lon = nc_fid.variables['lon'][:] #degrees east +#use upstream T +T_abs = nc_fid.variables['Tu'][:] #absolute temperature (time, lev) +T_abs = np.swapaxes(T_abs, 0, 1) +thetailu = nc_fid.variables['thetailu'][:] #theta_il (time, lev) +thetailu = np.swapaxes(thetailu, 0, 1) +#use unpstream theta instead of thetail +thetail = nc_fid.variables['thetail'][:] #theta (time, lev) +thetail = np.swapaxes(thetail, 0, 1) +#calculate theta_il from absolute temperature (assuming no condensate) +#thetal = np.zeros((levels.size,time.size),dtype=float) +#for t in range(time.size): +# thetal[:,t] = (ffc.p0/levels)**(ffc.R_dry/ffc.c_p)*T_abs[:,t] +qv = nc_fid.variables['qu'][:] #water vapor mixing ratio in kg/kg (time, lev) +qv = np.swapaxes(qv, 0, 1) +qt = np.zeros((levels.size,time.size),dtype=float) +qt_mr = nc_fid.variables['qt'][:] #water vapor mixing ratio in kg/kg (time, lev) +qt_mr = np.swapaxes(qt_mr, 0, 1) #swap the time and levels axis +qt = qt_mr/(1.0 + qt_mr) #convert to specific humidity from mixing ratio +qtu = np.zeros((levels.size,time.size),dtype=float) +#use upstream qv instead of qt +qtu_mr = nc_fid.variables['qtu'][:] #water vapor mixing ratio in kg/kg (time, lev) +qtu_mr = np.swapaxes(qtu_mr, 0, 1) #swap the time and levels axis +qtu = qtu_mr/(1.0 + qtu_mr) #convert to specific humidity from mixing ratio + +#ql and tke are not specified; set to zero +#ql = np.zeros((levels.size,time.size),dtype=float) +#qi = np.zeros((levels.size,time.size),dtype=float) +ql = nc_fid.variables['ql'][:] #ql (time, lev) +ql = np.swapaxes(ql, 0, 1) +qi = nc_fid.variables['qi'][:] #ql (time, lev) +qi = np.swapaxes(qi, 0, 1) +tke = np.zeros((levels.size,time.size),dtype=float) +# ozone_mmr = nc_fid.variables['o3mmr'][:] +u_wind = nc_fid.variables['u'][:] +u_wind = np.swapaxes(u_wind, 0, 1) #swap the time and levels axis +v_wind = nc_fid.variables['v'][:] +v_wind = np.swapaxes(v_wind, 0, 1) #swap the time and levels axis + +#w_sub = np.zeros((levels.size,time.size),dtype=float) +omega = nc_fid.variables['omega'][:] #vertical pressure velocity in Pa/s +omega = np.swapaxes(omega, 0, 1) #swap the time and levels axis +w_sub = nc_fid.variables['w'][:] #vertical velocity in m/s +w_sub = np.swapaxes(w_sub, 0, 1) #swap the time and levels axis +#convert to w +#for t in range(time.size): +# w_sub[:,t] = ffc.omega_to_w(omega[:,t],levels,T_abs[:,t]) + +T_surf = nc_fid.variables['T_skin'][:] +#T_surf = T_surf + 273.15 #convert to K +#T_surf = (29 + 273.15)*np.ones((time.size),dtype=float) #forcing instructions specify time-invariant 29 deg C. +p_surf = nc_fid.variables['p_srf'][:] #Pa +#p_surf = p_surf*100.0 #convert to Pa + +#h_advec_thil = np.zeros((levels.size,time.size),dtype=float) +h_advec_thil = nc_fid.variables['h_advec_thetail'][:] #K/s +h_advec_thil = np.swapaxes(h_advec_thil, 0, 1) #swap the time and levels axis +#for t in range(time.size): +# h_advec_thil[:,t] = (ffc.p0/levels)**(ffc.R_dry/ffc.c_p)*h_advec_T[:,t] #convert to potential temperature + +#v_advec_thil = np.zeros((levels.size,time.size),dtype=float) +v_advec_thil = nc_fid.variables['v_advec_thetail'][:] #K/s +v_advec_thil = np.swapaxes(v_advec_thil, 0, 1) #swap the time and levels axis +#for t in range(time.size): +# v_advec_thil[:,t] = (ffc.p0/levels)**(ffc.R_dry/ffc.c_p)*v_advec_T[:,t] #convert to potential temperature + +dT_dt = np.zeros((levels.size,time.size),dtype=float) + +# h_advec_T = h_advec_T*86400.0 +# v_advec_T = v_advec_T*86400.0 +# dT_dt = dT_dt*86400.0 +# spr.contour_plot_firl(time, levels, h_advec_T, np.min(h_advec_T), np.max(h_advec_T), 'h advec T', 'time', 'pressure', 'h_advec_T.eps', y_inverted = True) +# spr.contour_plot_firl(time, levels, v_advec_T, np.min(v_advec_T), np.max(v_advec_T), 'v advec T', 'time', 'pressure', 'v_advec_T.eps', y_inverted = True) +# spr.contour_plot_firl(time, levels, dT_dt, np.min(dT_dt), np.max(dT_dt), 'total T tend', 'time', 'pressure', 'dT_dt.eps', y_inverted = True) + +#h_advec_qt = np.zeros((levels.size,time.size),dtype=float) +h_advec_qt = nc_fid.variables['h_advec_qt'][:] #kg/kg/s +h_advec_qt = np.swapaxes(h_advec_qt, 0, 1) #swap the time and levels axis +h_advec_qt = h_advec_qt/(1.0 + qt_mr)**2 #convert to specific humidity + +h_advec_qi = np.zeros((levels.size,time.size),dtype=float) +h_advec_ql = np.zeros((levels.size,time.size),dtype=float) + +#v_advec_qt = np.zeros((levels.size,time.size),dtype=float) +v_advec_qt = nc_fid.variables['v_advec_qt'][:] #kg/kg/s +v_advec_qt = np.swapaxes(v_advec_qt, 0, 1) #swap the time and levels axis +v_advec_qt = v_advec_qt/(1.0 + qt_mr)**2 #convert to specific humidity + +dq_dt = np.zeros((levels.size,time.size),dtype=float) +#dq_dt = nc_fid.variables['dqdt'][:] +#dq_dt = np.swapaxes(dq_dt, 0, 1)*1.0E-3/3600.0 #swap the time and levels axis, convert to K/s + +#h_advec_qt = h_advec_qt*86400.0 +#v_advec_qt = v_advec_qt*86400.0 +#dq_dt = dq_dt*86400.0 +#spr.contour_plot_firl(time, levels, h_advec_qt, np.min(h_advec_qt), np.max(h_advec_qt), 'h advec q', 'time', 'pressure', 'h_advec_q.eps', y_inverted = True) +#spr.contour_plot_firl(time, levels, v_advec_qt, np.min(v_advec_qt), np.max(v_advec_qt), 'v advec q', 'time', 'pressure', 'v_advec_q.eps', y_inverted = True) +#spr.contour_plot_firl(time, levels, dq_dt, np.min(dq_dt), np.max(dq_dt), 'total q tend', 'time', 'pressure', 'dq_dt.eps', y_inverted = True) + +#phi_sfc = nc_fid.variables['phis'][:] +#z_sfc = nc_fid.variables['alt'][:] +height = nc_fid.variables['height'][:] +#height = ffc.get_height_from_pres(T_abs[:,0],levels,z_sfc) + +#the following variables are not in this forcing file, but are included in other cases +#rad_heating = nc_fid.variables['dT_dt_rad'][:] #K/s +#rad_heating = np.swapaxes(rad_heating, 0, 1) #swap the time and levels axis +rad_heating = np.zeros((levels.size,time.size),dtype=float) +u_g = np.zeros((levels.size,time.size),dtype=float) +v_g = np.zeros((levels.size,time.size),dtype=float) + +ozone = np.zeros((levels.size,time.size),dtype=float) +ozone = ozone + 2.e-8 + +tiice = np.zeros((ice_thickness.size),dtype=float) +##tiice[0] = T_surf[start_t_index] +tiice[0] = 271.35 + .75*(T_surf[start_t_index] - 271.35) +tiice[1] = 271.35 + .25*(T_surf[start_t_index] - 271.35) +stc = tiice[0] +smc = 0.33 +slc = 0.33 +hice = 0.3 +slmsk = 2.0 +tsfco = T_surf[start_t_index] +weasd = 200.0 +fice = 1.0 +tisfc = tsfco +snwdph = 2.e-4 +tg3 = 271.35 +zorl = 15.0 +alvsf = 0.23 +alnsf = 0.23 +alvwf = 0.23 +alnwf = 0.23 +facsf = 0.5055632 +facwf = 0.4944368 +vegfrac = 0.0 +canopy = 0.0 +vegtyp = 10 +soiltyp = 12 +uustar = 0.3828793 +shdmin = 0.01 +shdmax = 0.8 +slopetyp = 1 +snoalb = 0.7287961 + +# Open ozone file +#f = open('../../data/raw_case_input/twpice_CRM_ozone.txt', 'r') + +# Read and ignore header lines +#header1 = f.readline() + +#oz_pres = [] +#oz_data = [] +# Loop over lines and extract variables of interest +#for line in f: +# line = line.strip() +# columns = line.split() +# oz_pres.append(float(columns[1])) +# oz_data.append(float(columns[2])) + +#f.close() + +#oz_pres = 100.0*np.array(oz_pres) +#oz_data = np.array(oz_data) +#oz_f = scipy.interpolate.interp1d(oz_pres, oz_data) +#ozone_ppb = oz_f(levels[1:].tolist()) +#ozone_ppb = np.insert(ozone_ppb, 0, oz_data[0]) +#ozone_mmr = ozone_ppb*1.0E-9 + +# +#open processed input file for writing + +writefile_fid = Dataset('../../data/processed_case_input/MOSAiC.nc', 'w', format='NETCDF4') +writefile_fid.description = "CCPP SCM forcing file for MOSAiC case" + +#create groups for scalars, intitialization, and forcing + +writefile_scalar_grp = writefile_fid.createGroup("scalars") +writefile_initial_grp = writefile_fid.createGroup("initial") +writefile_forcing_grp = writefile_fid.createGroup("forcing") + +#create dimensions and write them out + +writefile_time_dim = writefile_fid.createDimension('time', None) +writefile_time_var = writefile_fid.createVariable('time', 'f4', ('time',)) +writefile_time_var[:] = time[start_t_index:] +writefile_time_var.units = 's' +writefile_time_var.description = 'elapsed time since the beginning of the simulation' + +writefile_levels_dim = writefile_fid.createDimension('levels', None) +writefile_levels_var = writefile_fid.createVariable('levels', 'f4', ('levels',)) +writefile_levels_var[:] = levels +writefile_levels_var.units = 'Pa' +writefile_levels_var.description = 'pressure levels' + +writefile_ice_thickness_dim = writefile_fid.createDimension('ice_thickness', None) +writefile_ice_thickness_var = writefile_fid.createVariable('ice_thickness', 'f4', ('ice_thickness',)) +writefile_ice_thickness_var[:] = ice_thickness +writefile_ice_thickness_var.units = 'm' +writefile_ice_thickness_var.description = 'depth of ice layers' + +#create variables and write them out + +#scalar group + +writefile_lat_var = writefile_scalar_grp.createVariable('lat', 'f4') +writefile_lat_var[:] = lat +writefile_lat_var.units = 'degrees N' +writefile_lat_var.description = 'latitude of column' + +writefile_lon_var = writefile_scalar_grp.createVariable('lon', 'f4') +writefile_lon_var[:] = lon +writefile_lon_var.units = 'degrees E' +writefile_lon_var.description = 'longitude of column' + +writefile_hice_var = writefile_scalar_grp.createVariable('hice', 'f4') +writefile_hice_var[:] = hice +writefile_hice_var.units = 'm' +writefile_hice_var.description = 'sea ice thickness' + +writefile_slmsk_var = writefile_scalar_grp.createVariable('slmsk', 'f4') +writefile_slmsk_var[:] = slmsk +writefile_slmsk_var.units = '' +writefile_slmsk_var.description = 'land-sea-ice mask' + +writefile_tsfco_var = writefile_scalar_grp.createVariable('tsfco', 'f4') +writefile_tsfco_var[:] = tsfco +writefile_tsfco_var.units = 'm' +writefile_tsfco_var.description = 'sea ice surface skin temperature' + +writefile_weasd_var = writefile_scalar_grp.createVariable('weasd', 'f4') +writefile_weasd_var[:] = weasd +writefile_weasd_var.units = 'mm' +writefile_weasd_var.description = 'water equivalent accumulated snow depth' + +writefile_fice_var = writefile_scalar_grp.createVariable('fice', 'f4') +writefile_fice_var[:] = fice +writefile_fice_var.units = '1' +writefile_fice_var.description = 'ice fraction' + +writefile_tisfc_var = writefile_scalar_grp.createVariable('tisfc', 'f4') +writefile_tisfc_var[:] = tisfc +writefile_tisfc_var.units = 'K' +writefile_tisfc_var.description = 'ice surface temperature' + +writefile_snwdph_var = writefile_scalar_grp.createVariable('snwdph', 'f4') +writefile_snwdph_var[:] = snwdph +writefile_snwdph_var.units = 'mm' +writefile_snwdph_var.description = 'water equivalent snow depth' + +writefile_tg3_var = writefile_scalar_grp.createVariable('tg3', 'f4') +writefile_tg3_var[:] = tg3 +writefile_tg3_var.units = 'K' +writefile_tg3_var.description = 'deep soil temperature' + +writefile_zorl_var = writefile_scalar_grp.createVariable('zorl', 'f4') +writefile_zorl_var[:] = zorl +writefile_zorl_var.units = 'cm' +writefile_zorl_var.description = 'composite surface roughness length' + +writefile_alvsf_var = writefile_scalar_grp.createVariable('alvsf', 'f4') +writefile_alvsf_var[:] = alvsf +writefile_alvsf_var.units = '' +writefile_alvsf_var.description = '60 degree vis albedo with strong cosz dependency' + +writefile_alnsf_var = writefile_scalar_grp.createVariable('alnsf', 'f4') +writefile_alnsf_var[:] = alnsf +writefile_alnsf_var.units = '' +writefile_alnsf_var.description = '60 degree nir albedo with strong cosz dependency' + +writefile_alvwf_var = writefile_scalar_grp.createVariable('alvwf', 'f4') +writefile_alvwf_var[:] = alvwf +writefile_alvwf_var.units = '' +writefile_alvwf_var.description = '60 degree vis albedo with weak cosz dependency' + +writefile_alnwf_var = writefile_scalar_grp.createVariable('alnwf', 'f4') +writefile_alnwf_var[:] = alnwf +writefile_alnwf_var.units = '' +writefile_alnwf_var.description = '60 degree nir albedo with weak cosz dependency' + +writefile_facsf_var = writefile_scalar_grp.createVariable('facsf', 'f4') +writefile_facsf_var[:] = facsf +writefile_facsf_var.units = '' +writefile_facsf_var.description = 'fractional coverage with strong cosz dependency' + +writefile_facwf_var = writefile_scalar_grp.createVariable('facwf', 'f4') +writefile_facwf_var[:] = facwf +writefile_facwf_var.units = '' +writefile_facwf_var.description = 'fractional coverage with weak cosz dependency' + +writefile_vegfrac_var = writefile_scalar_grp.createVariable('vegfrac', 'f4') +writefile_vegfrac_var[:] = vegfrac +writefile_vegfrac_var.units = '1' +writefile_vegfrac_var.description = 'vegetation fraction' + +writefile_canopy_var = writefile_scalar_grp.createVariable('canopy', 'f4') +writefile_canopy_var[:] = canopy +writefile_canopy_var.units = 'kg m-2' +writefile_canopy_var.description = 'amount of water stored in camopy' + +writefile_vegtyp_var = writefile_scalar_grp.createVariable('vegtyp', 'f4') +writefile_vegtyp_var[:] = vegtyp +writefile_vegtyp_var.units = '' +writefile_vegtyp_var.description = 'vegetation type 1-12' + +writefile_soiltyp_var = writefile_scalar_grp.createVariable('soiltyp', 'f4') +writefile_soiltyp_var[:] = soiltyp +writefile_soiltyp_var.units = '' +writefile_soiltyp_var.description = 'soil type 1-12' + +writefile_uustar_var = writefile_scalar_grp.createVariable('uustar', 'f4') +writefile_uustar_var[:] = uustar +writefile_uustar_var.units = 'm s-1' +writefile_uustar_var.description = 'friction velocity' + +writefile_shdmin_var = writefile_scalar_grp.createVariable('shdmin', 'f4') +writefile_shdmin_var[:] = shdmin +writefile_shdmin_var.units = '1' +writefile_shdmin_var.description = 'minimum vegetation fraction' + +writefile_shdmax_var = writefile_scalar_grp.createVariable('shdmax', 'f4') +writefile_shdmax_var[:] = shdmax +writefile_shdmax_var.units = '1' +writefile_shdmax_var.description = 'maximum vegetation fraction' + +writefile_slopetyp_var = writefile_scalar_grp.createVariable('slopetyp', 'f4') +writefile_slopetyp_var[:] = slopetyp +writefile_slopetyp_var.units = '' +writefile_slopetyp_var.description = 'slope type 1-9' + +writefile_snoalb_var = writefile_scalar_grp.createVariable('snoalb', 'f4') +writefile_snoalb_var[:] = snoalb +writefile_snoalb_var.units = '1' +writefile_snoalb_var.description = 'maximum snow albedo' + +#initial group + +writefile_height_var = writefile_initial_grp.createVariable('height', 'f4', ('levels',)) +writefile_height_var[:] = height +writefile_height_var.units = 'm' +writefile_height_var.description = 'physical height at pressure levels' + +writefile_tiice_var = writefile_initial_grp.createVariable('tiice', 'f4', ('ice_thickness',)) +writefile_tiice_var[:] = tiice +writefile_tiice_var.units = 'K' +writefile_tiice_var.description = 'initial profile of sea ice internal temperature' + +writefile_stc_var = writefile_initial_grp.createVariable('stc', 'f4') +writefile_stc_var[:] = stc +writefile_stc_var.units = 'K' +writefile_stc_var.description = 'initial profile of sea ice internal temperature' + +writefile_smc_var = writefile_initial_grp.createVariable('smc', 'f4') +writefile_smc_var[:] = smc +writefile_smc_var.units = 'm3 m-3' +writefile_smc_var.description = 'initial profile of soil moisture' + +writefile_slc_var = writefile_initial_grp.createVariable('slc', 'f4') +writefile_slc_var[:] = slc +writefile_slc_var.units = 'm3 m-3' +writefile_slc_var.description = 'initial profile of soil liquid water' + +writefile_thetail_var = writefile_initial_grp.createVariable('thetail', 'f4', ('levels',)) +writefile_thetail_var[:] = thetail[:,start_t_index] +writefile_thetail_var.units = 'K' +writefile_thetail_var.description = 'initial profile of ice-liquid water potential temperature' + +writefile_qt_var = writefile_initial_grp.createVariable('qt', 'f4', ('levels',)) +writefile_qt_var[:] = qt[:,start_t_index] +writefile_qt_var.units = 'kg kg^-1' +writefile_qt_var.description = 'initial profile of total water specific humidity' + +writefile_ql_var = writefile_initial_grp.createVariable('ql', 'f4', ('levels',)) +writefile_ql_var[:] = ql[:,start_t_index] +writefile_ql_var.units = 'kg kg^-1' +writefile_ql_var.description = 'initial profile of liquid water specific humidity' + +writefile_qi_var = writefile_initial_grp.createVariable('qi', 'f4', ('levels',)) +writefile_qi_var[:] = qi[:,start_t_index] +writefile_qi_var.units = 'kg kg^-1' +writefile_qi_var.description = 'initial profile of ice water specific humidity' + +writefile_u_var = writefile_initial_grp.createVariable('u', 'f4', ('levels',)) +writefile_u_var[:] = u_wind[:,start_t_index] +writefile_u_var.units = 'm s^-1' +writefile_u_var.description = 'initial profile of E-W horizontal wind' + +writefile_v_var = writefile_initial_grp.createVariable('v', 'f4', ('levels',)) +writefile_v_var[:] = v_wind[:,start_t_index] +writefile_v_var.units = 'm s^-1' +writefile_v_var.description = 'initial profile of N-S horizontal wind' + +writefile_tke_var = writefile_initial_grp.createVariable('tke', 'f4', ('levels',)) +writefile_tke_var[:] = tke[:,start_t_index] +writefile_tke_var.units = 'm^2 s^-2' +writefile_tke_var.description = 'initial profile of turbulence kinetic energy' + +writefile_ozone_var = writefile_initial_grp.createVariable('ozone', 'f4', ('levels',)) +writefile_ozone_var[:] = ozone[:,start_t_index] +writefile_ozone_var.units = 'kg kg^-1' +writefile_ozone_var.description = 'initial profile of ozone mass mixing ratio' + +#forcing group + +writefile_p_surf_var = writefile_forcing_grp.createVariable('p_surf', 'f4', ('time',)) +writefile_p_surf_var[:] = p_surf[start_t_index:] +writefile_p_surf_var.units = 'Pa' +writefile_p_surf_var.description = 'surface pressure' + +writefile_T_surf_var = writefile_forcing_grp.createVariable('T_surf', 'f4', ('time',)) +writefile_T_surf_var[:] = T_surf[start_t_index:] +writefile_T_surf_var.units = 'K' +writefile_T_surf_var.description = 'surface absolute temperature' + +writefile_w_ls_var = writefile_forcing_grp.createVariable('w_ls', 'f4', ('levels','time',)) +writefile_w_ls_var[:] = w_sub[:,start_t_index:] +writefile_w_ls_var.units = 'm s^-1' +writefile_w_ls_var.description = 'large scale vertical velocity' + +writefile_omega_var = writefile_forcing_grp.createVariable('omega', 'f4', ('levels','time',)) +writefile_omega_var[:] = omega[:,start_t_index:] +writefile_omega_var.units = 'Pa s^-1' +writefile_omega_var.description = 'large scale pressure vertical velocity' + +writefile_u_g_var = writefile_forcing_grp.createVariable('u_g', 'f4', ('levels','time',)) +writefile_u_g_var[:] = u_g[:,start_t_index:] +writefile_u_g_var.units = 'm s^-1' +writefile_u_g_var.description = 'large scale geostrophic E-W wind' + +writefile_v_g_var = writefile_forcing_grp.createVariable('v_g', 'f4', ('levels','time',)) +writefile_v_g_var[:] = v_g[:,start_t_index:] +writefile_v_g_var.units = 'm s^-1' +writefile_v_g_var.description = 'large scale geostrophic N-S wind' + +writefile_u_nudge_var = writefile_forcing_grp.createVariable('u_nudge', 'f4', ('levels','time',)) +writefile_u_nudge_var[:] = u_wind[:,start_t_index:] +writefile_u_nudge_var.units = 'm s^-1' +writefile_u_nudge_var.description = 'E-W wind to nudge toward' + +writefile_v_nudge_var = writefile_forcing_grp.createVariable('v_nudge', 'f4', ('levels','time',)) +writefile_v_nudge_var[:] = v_wind[:,start_t_index:] +writefile_v_nudge_var.units = 'm s^-1' +writefile_v_nudge_var.description = 'N-S wind to nudge toward' + +writefile_T_nudge_var = writefile_forcing_grp.createVariable('T_nudge', 'f4', ('levels','time',)) +writefile_T_nudge_var[:] = T_abs[:,start_t_index:] +writefile_T_nudge_var.units = 'K' +writefile_T_nudge_var.description = 'absolute temperature to nudge toward' + +writefile_thil_nudge_var = writefile_forcing_grp.createVariable('thil_nudge', 'f4', ('levels','time',)) +writefile_thil_nudge_var[:] = thetailu[:,start_t_index:] +writefile_thil_nudge_var.units = 'K' +writefile_thil_nudge_var.description = 'potential temperature to nudge toward' + +writefile_qt_nudge_var = writefile_forcing_grp.createVariable('qt_nudge', 'f4', ('levels','time',)) +writefile_qt_nudge_var[:] = qtu[:,start_t_index:] +writefile_qt_nudge_var.units = 'kg kg^-1' +writefile_qt_nudge_var.description = 'q_t to nudge toward' + +writefile_qi_nudge_var = writefile_forcing_grp.createVariable('qi_nudge', 'f4', ('levels','time',)) +writefile_qi_nudge_var[:] = qi[:,start_t_index:] +writefile_qi_nudge_var.units = 'kg kg^-1' +writefile_qi_nudge_var.description = 'q_i to nudge toward' + +writefile_ql_nudge_var = writefile_forcing_grp.createVariable('ql_nudge', 'f4', ('levels','time',)) +writefile_ql_nudge_var[:] = ql[:,start_t_index:] +writefile_ql_nudge_var.units = 'kg kg^-1' +writefile_ql_nudge_var.description = 'q_l to nudge toward' + +writefile_rad_heating_var = writefile_forcing_grp.createVariable('dT_dt_rad', 'f4', ('levels','time',)) +writefile_rad_heating_var[:] = rad_heating[:,start_t_index:] +writefile_rad_heating_var.units = 'K s^-1' +writefile_rad_heating_var.description = 'prescribed radiative heating rate' + +writefile_h_advec_thil_var = writefile_forcing_grp.createVariable('h_advec_thetail', 'f4', ('levels','time',)) +writefile_h_advec_thil_var[:] = h_advec_thil[:,start_t_index:] +writefile_h_advec_thil_var.units = 'K s^-1' +writefile_h_advec_thil_var.description = 'prescribed theta_il tendency due to horizontal advection' + +writefile_v_advec_thil_var = writefile_forcing_grp.createVariable('v_advec_thetail', 'f4', ('levels','time',)) +writefile_v_advec_thil_var[:] = v_advec_thil[:,start_t_index:] +writefile_v_advec_thil_var.units = 'K s^-1' +writefile_v_advec_thil_var.description = 'prescribed theta_il tendency due to vertical advection' + +writefile_h_advec_qt_var = writefile_forcing_grp.createVariable('h_advec_qt', 'f4', ('levels','time',)) +writefile_h_advec_qt_var[:] = h_advec_qt[:,start_t_index:] +writefile_h_advec_qt_var.units = 'kg kg^-1 s^-1' +writefile_h_advec_qt_var.description = 'prescribed q_t tendency due to horizontal advection' + +writefile_h_advec_qi_var = writefile_forcing_grp.createVariable('h_advec_qi', 'f4', ('levels','time',)) +writefile_h_advec_qi_var[:] = h_advec_qi[:,start_t_index:] +writefile_h_advec_qi_var.units = 'kg kg^-1 s^-1' +writefile_h_advec_qi_var.description = 'prescribed q_i tendency due to horizontal advection' + +writefile_h_advec_ql_var = writefile_forcing_grp.createVariable('h_advec_ql', 'f4', ('levels','time',)) +writefile_h_advec_ql_var[:] = h_advec_ql[:,start_t_index:] +writefile_h_advec_ql_var.units = 'kg kg^-1 s^-1' +writefile_h_advec_ql_var.description = 'prescribed q_l tendency due to horizontal advection' + +writefile_v_advec_qt_var = writefile_forcing_grp.createVariable('v_advec_qt', 'f4', ('levels','time',)) +writefile_v_advec_qt_var[:] = v_advec_qt[:,start_t_index:] +writefile_v_advec_qt_var.units = 'kg kg^-1 s^-1' +writefile_v_advec_qt_var.description = 'prescribed q_t tendency due to vertical advection' + + +#close processed input file +writefile_fid.close() + +#close raw input file +nc_fid.close() diff --git a/scm/etc/scripts/plot_configs/MOSAiC-AMPS.ini b/scm/etc/scripts/plot_configs/MOSAiC-AMPS.ini new file mode 100644 index 000000000..0ce84096a --- /dev/null +++ b/scm/etc/scripts/plot_configs/MOSAiC-AMPS.ini @@ -0,0 +1,63 @@ +scm_datasets = output_MOSAiC-AMPS_SCM_RRFS_v1beta/output.nc, output_MOSAiC-AMPS_SCM_GFS_v17_p8/output.nc, output_MOSAiC-AMPS_SCM_GFS_v16/output.nc +scm_datasets_labels = RRFS_v1beta, GFSv17p8, GFSv16 +plot_dir = plots_MOSAiC-AMPS_all_suites/ +obs_file = ../data/raw_case_input/MOSAiC_31Oct20190Z_raw.nc +obs_compare = True +plot_ind_datasets = True +time_series_resample = False + +[time_slices] + [[active]] + start = 2019, 11, 1, 0 + end = 2019, 11, 2, 0 + +[time_snapshots] + +[plots] + [[profiles_mean]] + vars = ql, qc, qi, qv, T, dT_dt_pbl, T_force_tend, dT_dt_conv, dT_dt_micro, dT_dt_lwrad, dT_dt_phys, qv_force_tend, dq_dt_pbl, dq_dt_shalconv, dq_dt_micro, dq_dt_phys, dq_dt_nonphys, rad_cloud_iwp, rad_cloud_swp, rad_cloud_rwp, rad_cloud_lwp + vars_labels = 'cloud water mixing ratio ($g$ $kg^{-1}$)', 'total cloud water mixing ratio ($g$ $kg^{-1}$)', 'ice+snow+graup mixing ratio ($g$ $kg^{-1}$)', 'specific humidity ($g$ $kg^{-1}$)', 'T (K)', 'PBL tendency (K/day)', 'force (K/day)', 'conv. tendency (K/day)', 'microphysics tendency (K/day)', 'LW tendency (K/day)', 'PHYS (K/day)', 'force (kg/kg/day)', 'PBL tendency (kg/kg/day)', 'ShalConv tendency (kg/kg/day)', 'microphysics tendency (kg/kg/day)', 'PHYS (kg/kg/day)', 'NONPHYS (kg/kg/day)', 'IWC (g/m3)', 'SWC (g/m3)', 'RWC (g/m3)', 'LWC (g/m3)' + vert_axis = pres_l + vert_axis_label = 'average pressure (Pa)' + y_inverted = True + y_log = False +# y_min_option = min #min, max, val (if val, add y_min = float value) + y_min_option = val #min, max, val (if val, add y_min = float value) + y_min = 70000.0 #min, max, val (if val, add y_min = float value) + y_max_option = max #min, max, val (if val, add y_max = float value) + conversion_factor = 1000.0, 1000.0, 1000.0, 1000.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 + + [[profiles_mean_multi]] + [[[T_forcing]]] + vars = T_force_tend, dT_dt_pbl, dT_dt_conv, dT_dt_micro, dT_dt_lwrad + vars_labels = 'force', 'PBL', 'Conv', 'MP', 'LW' + x_label = 'K/day' + [[[QV_forcing]]] + vars = qv_force_tend, dq_dt_pbl, dq_dt_shalconv, dq_dt_micro, dq_dt_phys, dq_dt_nonphys + vars_labels = 'force', 'PBL', 'ShalConv', 'MP', 'PHYS', 'NONPHYS' + x_label = 'kg/kg/day' + [[[conv_tendencies]]] + vars = dT_dt_deepconv, dT_dt_shalconv + vars_labels = 'deep', 'shallow' + x_label = 'K/day' + + [[profiles_instant]] + + [[time_series]] + vars = 'pres_s','lhf','shf','tprcp_rate_inst','t2m','q2m','u10m','v10m','gflux','sfc_dwn_lw','tsfc' + vars_labels = 'surface pressure (Pa)','latent heat flux ($W$ $m^{-2}$)','sensible heat flux ($W$ $m^{-2}$)','surface rainfall rate ($mm$ $hr{-1}$)','2m temperature ($K$)','2m specific humidity ($g$ $kg{-1}$)','10m zonal wind ($m$ $s{-1}$)','10m meridional wind ($m$ $s{-1}$)','ground flux ($W$ $m{-2}$)','downward longwave flux ($W$ $m{-2}$)','surface temperature ($K$)' + + [[contours]] + vars = qv, T, h_advec_qt, h_advec_thil, qi, ql + vars_labels = 'Water Vapor ($g$ $kg^{-1}$)','Temperature ($K$)','Horizontal total water advection ($g$ $kg^{-1}$ $s^{-1}$)','Horizontal thetail advection ($K$ $s^{-1}$)','QI ($g$ $kg^{-1}$)','QL ($g$ $kg^{-1}$)' + vert_axis = pres_l + vert_axis_label = 'p (Pa)' + y_inverted = True + y_log = False + y_min_option = val #min, max, val (if val, add y_min = float value) + y_min = 10000.0 + y_max_option = val #min, max, val (if val, add y_max = float value) + y_max = 100000.0 + x_ticks_num = 10 + y_ticks_num = 10 + conversion_factor = 1000.0, 1.0, 1.0, 1.0, 1000.0, 1000.0 diff --git a/scm/etc/scripts/plot_configs/MOSAiC-SS.ini b/scm/etc/scripts/plot_configs/MOSAiC-SS.ini new file mode 100644 index 000000000..82672321c --- /dev/null +++ b/scm/etc/scripts/plot_configs/MOSAiC-SS.ini @@ -0,0 +1,65 @@ +scm_datasets = output_MOSAiC-SS_SCM_RRFS_v1beta/output.nc, output_MOSAiC-SS_SCM_GFS_v17_p8/output.nc, output_MOSAiC-SS_SCM_GFS_v16/output.nc +##scm_datasets = output_MOSAiC-SS_SCM_GFS_v17_p8/output.nc, output_MOSAiC-SS_SCM_GFS_v16/output.nc +##scm_datasets_labels = GFSv17p8, GFSv16 +scm_datasets_labels = RRFS_v1beta, GFSv17p8, GFSv16 +plot_dir = plots_MOSAiC-SS_all_suites/ +obs_file = ../data/raw_case_input/MOSAiC_2Mar20200Z_raw.nc +obs_compare = True +plot_ind_datasets = True +time_series_resample = False + +[time_slices] + [[active]] + start = 2020, 3, 4, 0 + end = 2020, 3, 5, 0 + +[time_snapshots] + +[plots] + [[profiles_mean]] + vars = ql, qc, qi, qv, T, dT_dt_pbl, T_force_tend, dT_dt_conv, dT_dt_micro, dT_dt_lwrad, dT_dt_phys, qv_force_tend, dq_dt_pbl, dq_dt_shalconv, dq_dt_micro, dq_dt_phys, dq_dt_nonphys, rad_cloud_iwp, rad_cloud_swp, rad_cloud_rwp, rad_cloud_lwp + vars_labels = 'cloud water mixing ratio ($g$ $kg^{-1}$)', 'total cloud water mixing ratio ($g$ $kg^{-1}$)', 'ice+snow+graup mixing ratio ($g$ $kg^{-1}$)', 'specific humidity ($g$ $kg^{-1}$)', 'T (K)', 'PBL tendency (K/day)', 'force (K/day)', 'conv. tendency (K/day)', 'microphysics tendency (K/day)', 'LW tendency (K/day)', 'PHYS (K/day)', 'force (kg/kg/day)', 'PBL tendency (kg/kg/day)', 'ShalConv tendency (kg/kg/day)', 'microphysics tendency (kg/kg/day)', 'PHYS (kg/kg/day)', 'NONPHYS (kg/kg/day)', 'IWC (g/m3)', 'SWC (g/m3)', 'RWC (g/m3)', 'LWC (g/m3)' + vert_axis = pres_l + vert_axis_label = 'average pressure (Pa)' + y_inverted = True + y_log = False +# y_min_option = min #min, max, val (if val, add y_min = float value) + y_min_option = val #min, max, val (if val, add y_min = float value) + y_min = 70000.0 #min, max, val (if val, add y_min = float value) + y_max_option = max #min, max, val (if val, add y_max = float value) + conversion_factor = 1000.0, 1000.0, 1000.0, 1000.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0, 1.0 + + [[profiles_mean_multi]] + [[[T_forcing]]] + vars = T_force_tend, dT_dt_pbl, dT_dt_conv, dT_dt_micro, dT_dt_lwrad + vars_labels = 'force', 'PBL', 'Conv', 'MP', 'LW' + x_label = 'K/day' + [[[QV_forcing]]] + vars = qv_force_tend, dq_dt_pbl, dq_dt_shalconv, dq_dt_micro, dq_dt_phys, dq_dt_nonphys + vars_labels = 'force', 'PBL', 'ShalConv', 'MP', 'PHYS', 'NONPHYS' + x_label = 'kg/kg/day' + [[[conv_tendencies]]] + vars = dT_dt_deepconv, dT_dt_shalconv + vars_labels = 'deep', 'shallow' + x_label = 'K/day' + + [[profiles_instant]] + + [[time_series]] + vars = 'pres_s','lhf','shf','tprcp_rate_inst','t2m','q2m','u10m','v10m','gflux','sfc_dwn_lw','tsfc' + vars_labels = 'surface pressure (Pa)','latent heat flux ($W$ $m^{-2}$)','sensible heat flux ($W$ $m^{-2}$)','surface rainfall rate ($mm$ $hr{-1}$)','2m temperature ($K$)','2m specific humidity ($g$ $kg{-1}$)','10m zonal wind ($m$ $s{-1}$)','10m meridional wind ($m$ $s{-1}$)','ground flux ($W$ $m{-2}$)','downward longwave flux ($W$ $m{-2}$)','surface temperature ($K$)' + + [[contours]] + vars = qv, T, h_advec_qt, h_advec_thil, qi, ql + vars_labels = 'Water Vapor ($g$ $kg^{-1}$)','Temperature ($K$)','Horizontal total water advection ($g$ $kg^{-1}$ $s^{-1}$)','Horizontal thetail advection ($K$ $s^{-1}$)','QI ($g$ $kg^{-1}$)','QL ($g$ $kg^{-1}$)' + vert_axis = pres_l + vert_axis_label = 'p (Pa)' + y_inverted = True + y_log = False + y_min_option = val #min, max, val (if val, add y_min = float value) + y_min = 10000.0 + y_max_option = val #min, max, val (if val, add y_max = float value) + y_max = 100000.0 + x_ticks_num = 10 + y_ticks_num = 10 + conversion_factor = 1000.0, 1.0, 1.0, 1.0, 1000.0, 1000.0 diff --git a/scm/etc/scripts/scm_analysis.py b/scm/etc/scripts/scm_analysis.py index 34c85c529..d6516dc7a 100755 --- a/scm/etc/scripts/scm_analysis.py +++ b/scm/etc/scripts/scm_analysis.py @@ -856,6 +856,8 @@ def replace_fill_with_nan(nc_ds, var_name, var, group, time_diag, pres_l, datase obs_dict = sro.read_LASSO_obs(obs_file, time_slices, date_inst) elif('gabls3' in case_name.strip()): obs_dict = sro.read_gabls3_obs(obs_file, time_slices, date_inst) + elif('MOSAiC' in case_name.strip()): + obs_dict = sro.read_MOSAiC_obs(obs_file, time_slices, date_inst) try: os.makedirs(plot_dir) @@ -1378,7 +1380,7 @@ def replace_fill_with_nan(nc_ds, var_name, var, group, time_diag, pres_l, datase else: y_max_val = profiles_mean['y_max'] y_lim_val = [y_min_val, y_max_val] - + #plot mean profiles for k in range(len(profiles_mean['vars'])): #get the python variable associated with the vars listed in the config file diff --git a/scm/etc/scripts/scm_read_obs.py b/scm/etc/scripts/scm_read_obs.py index 59ac43c34..ac6b80100 100644 --- a/scm/etc/scripts/scm_read_obs.py +++ b/scm/etc/scripts/scm_read_obs.py @@ -6,6 +6,71 @@ import math import forcing_file_common as ffc +def read_MOSAiC_obs(obs_file, time_slices, date): + obs_time_slice_indices = [] + + obs_fid = Dataset(obs_file, 'r') + + obs_year = obs_fid.variables['year'][:] + obs_month = obs_fid.variables['month'][:] + obs_day = obs_fid.variables['day'][:] + obs_hour = obs_fid.variables['hour'][:] + obs_time = obs_fid.variables['time_offset'][:] + + obs_date = [] + for i in range(obs_hour.size): + obs_date.append(datetime.datetime(obs_year[i], obs_month[i], obs_day[i], obs_hour[i], 0, 0, 0)) + obs_date = np.array(obs_date) + + for time_slice in time_slices: + start_date = datetime.datetime(time_slices[time_slice]['start'][0], time_slices[time_slice]['start'][1],time_slices[time_slice]['start'][2], time_slices[time_slice]['start'][3], time_slices[time_slice]['start'][4]) + end_date = datetime.datetime(time_slices[time_slice]['end'][0], time_slices[time_slice]['end'][1],time_slices[time_slice]['end'][2], time_slices[time_slice]['end'][3], time_slices[time_slice]['end'][4]) + start_date_index = np.where(obs_date == start_date)[0][0] + end_date_index = np.where(obs_date == end_date)[0][0] + obs_time_slice_indices.append([start_date_index, end_date_index]) + +#print(start_date, end_date, start_date_index, end_date_index, obs_date[start_date_index], obs_date[end_date_index]) + + #find the index corresponding to the start of the simulations + obs_start_index = np.where(obs_date == date[0][0])[0] + obs_time = obs_time - obs_time[obs_start_index] + + obs_pres_l = obs_fid.variables['levels'][:]*100.0 #pressure levels in mb + + obs_T = obs_fid.variables['T'][:] + obs_q = obs_fid.variables['q'][:] + obs_qi= obs_fid.variables['qi'][:] + obs_ql= obs_fid.variables['ql'][:] + obs_u = obs_fid.variables['u'][:] + obs_v = obs_fid.variables['v'][:] + obs_rad_net_srf = obs_fid.variables['rad_net_srf'][:] + obs_lw_dn_srf = obs_fid.variables['lw_dn_srf'][:] + obs_tsk = obs_fid.variables['T_skin'][:] + obs_shf = obs_fid.variables['SH'][:] + obs_lhf = obs_fid.variables['LH'][:] + obs_t2m = obs_fid.variables['T_srf'][:] + obs_q2m = obs_fid.variables['q_srf'][:] + + obs_time_h = obs_time/3600.0 + + Rd = 287.0 + Rv = 461.0 + + e_s = 6.1078*np.exp(17.2693882*(obs_T - 273.16)/(obs_T - 35.86))*100.0 #Tetens formula produces e_s in mb (convert to Pa) + e = obs_q*obs_pres_l/(obs_q + (Rd/Rv)*(1.0 - obs_q)) #compute vapor pressure from specific humidity + obs_rh = np.clip(e/e_s, 0.0, 1.0) + + return_dict = {'year': obs_year, 'month': obs_month, 'day': obs_day, 'hour': obs_hour, + 'time': obs_time, 'date': obs_date, 'time_slice_indices': obs_time_slice_indices, + 'pres_l': obs_pres_l, 'T': obs_T, 'q': obs_q, 'rh': obs_rh, 'u': obs_u, 'v': obs_v, 'shf': obs_shf, + 'lhf': obs_lhf, 't2m': obs_t2m, 'q2m': obs_q2m, 'time_h': obs_time_h, 'tsfc': obs_tsk, + 'qv': obs_q, 'qi': obs_qi, 'ql': obs_ql, 'rad_net_srf': obs_rad_net_srf, 'sfc_dwn_lw': obs_lw_dn_srf} +# 'lwp': obs_lwp, 'T_force_tend': obs_T_forcing, 'qv_force_tend': obs_q_forcing} + + obs_fid.close() + + return return_dict + def read_twpice_obs(obs_file, time_slices, date): obs_time_slice_indices = [] @@ -337,4 +402,4 @@ def read_gabls3_obs(obs_file, time_slices, date): 'sfc_dwn_sw': obs_sw_dn, 'sfc_up_sw': obs_sw_up, 'sfc_rad_net_land': obs_sfc_rad_net, 'gflux': -1*obs_gflux, 't2m':obs_t2m, 'q2m':obs_q2m, 'ustar':obs_ustar,'u10m':obs_u10m, 'v10m':obs_v10m, 'hpbl':obs_hpbl, 'tsfc':obs_tsk} - return return_dict \ No newline at end of file + return return_dict From dd673f222aa9204672d0b287fbb9e4d3593d3ac5 Mon Sep 17 00:00:00 2001 From: Grant Firl Date: Thu, 11 Jul 2024 10:36:22 -0400 Subject: [PATCH 04/40] add dephy_converter.py --- scm/etc/scripts/dephy_converter.py | 1241 ++++++++++++++++++++++++++++ 1 file changed, 1241 insertions(+) create mode 100755 scm/etc/scripts/dephy_converter.py diff --git a/scm/etc/scripts/dephy_converter.py b/scm/etc/scripts/dephy_converter.py new file mode 100755 index 000000000..63595540c --- /dev/null +++ b/scm/etc/scripts/dephy_converter.py @@ -0,0 +1,1241 @@ +#!/usr/bin/env python + +import argparse +import logging +import f90nml +import os +from netCDF4 import Dataset +import numpy as np +from datetime import datetime, timedelta + + +############################################################################### +# Global settings # +############################################################################### + +# Path to the directory containing processed case input files +CASE_NML_DIR = '../case_config' + +# Path to the directory containing processed case input files +PROCESSED_CASE_DIR = '../../data/processed_case_input' + +# For developers: set logging level to DEBUG for additional output +LOGLEVEL = logging.DEBUG +#LOGLEVEL = logging.INFO + +DEFAULT_MISSING_VALUE = -9999.0 +DEFAULT_NUDGING_TIMESCALE = 7200.0 #s + +############################################################################### +# Command line arguments # +############################################################################### + +parser = argparse.ArgumentParser() +parser.add_argument('-n', '--case_name', help='name of case', required=True) +parser.add_argument('-a', '--use_area', help='use column_area namelist attribute as forcing_scale', action='store_true') + + +######################################################################################## +# +######################################################################################## +def parse_arguments(): + """Parse command line arguments""" + args = parser.parse_args() + case_name = args.case_name + use_area = args.use_area + + + return (case_name, use_area) + +######################################################################################## +# +######################################################################################## +def setup_logging(): + """Sets up the logging module.""" + logging.basicConfig(format='%(levelname)s: %(message)s', level=LOGLEVEL) + +class Case_Data(object): + def __init__(self, name, missing_value, time, levels, lat, lon, height, theta_il, qt, ql, qi, u, v, tke, ozone, \ + p_surf, T_surf, w_ls, omega, u_g, v_g, u_nudge, v_nudge, T_nudge, thil_nudge, qt_nudge, \ + dT_dt_rad, h_advec_thil, v_advec_thil, h_advec_qt, v_advec_qt, sh_flux_sfc, lh_flux_sfc): + self._name = name + self._missing_value = missing_value + self._time = time + self._levels = levels + self._lat = lat + self._lon = lon + self._height = height + self._theta_il = theta_il + self._qt = qt + self._ql = ql + self._qi = qi + self._u = u + self._v = v + self._tke = tke + self._ozone = ozone + self._p_surf = p_surf + self._T_surf = T_surf + self._w_ls = w_ls + self._omega = omega + self._u_g = u_g + self._v_g = v_g + self._u_nudge = u_nudge + self._v_nudge = v_nudge + self._T_nudge = T_nudge + self._thil_nudge = thil_nudge + self._qt_nudge = qt_nudge + self._dT_dt_rad = dT_dt_rad + self._h_advec_thil = h_advec_thil + self._v_advec_thil = v_advec_thil + self._h_advec_qt = h_advec_qt + self._v_advec_qt = v_advec_qt + self._sh_flux_sfc = sh_flux_sfc + self._lh_flux_sfc = lh_flux_sfc + + def __repr__(self): + return "Case_Data \n Globals: \n" \ + " name:% s \n" \ + " missing_value:% s \n" \ + " Dimensions: \n" \ + " time:% s \n" \ + " levels: % s \n" \ + " Scalars: \n" \ + " lat: % s \n" \ + " lon: % s \n" \ + " Initial: \n" \ + " height: % s \n" \ + " theta_il: % s \n" \ + " qt: % s \n" \ + " ql: % s \n" \ + " qi: % s \n" \ + " u: % s \n" \ + " v: % s \n" \ + " tke: %s \n" \ + " ozone: %s \n" \ + " Forcing: \n" \ + " p_surf: %s \n" \ + " T_surf: %s \n" \ + " w_ls (time avg): %s \n" \ + " omega (time avg): %s \n" \ + " u_g (time avg): %s \n" \ + " v_g (time avg): %s \n" \ + " u_nudge (time avg): %s \n" \ + " v_nudge (time avg): %s \n" \ + " T_nudge (time avg): %s \n" \ + " thil_nudge (time avg): %s \n" \ + " qt_nudge (time avg): %s \n" \ + " dT_dt_rad (time avg): %s \n" \ + " h_advec_thil (time avg): %s \n" \ + " v_advec_thil (time avg): %s \n" \ + " h_advec_qt (time avg): %s \n" \ + " v_advec_qt (time avg): %s \n" \ + " sh_flux_sfc: %s \n" \ + " lh_flux_sfc: %s \n" \ + % (self._name, self._missing_value, self._time, self._levels, + self._lat, self._lon, self._height, self._theta_il, + self._qt, self._ql, self._qi, self._u, self._v, + self._tke, self._ozone, + self._p_surf, self._T_surf, np.mean(self._w_ls, axis=1), + np.mean(self._omega, axis=1), np.mean(self._u_g, axis=1), + np.mean(self._v_g, axis=1), np.mean(self._u_nudge, axis=1), + np.mean(self._v_nudge, axis=1), np.mean(self._T_nudge, axis=1), + np.mean(self._thil_nudge, axis=1),np.mean(self._qt_nudge, axis=1), + np.mean(self._dT_dt_rad, axis=1), + np.mean(self._h_advec_thil, axis=1),np.mean(self._v_advec_thil, axis=1), + np.mean(self._h_advec_qt, axis=1),np.mean(self._v_advec_qt, axis=1), + self._sh_flux_sfc, self._lh_flux_sfc) + +def get_case_nml(case_name): + """Returns case configuration Fortran namelist""" + + filename = os.path.join(CASE_NML_DIR, case_name + '.nml') + + print(filename) + + error = False + nml = '' + if (os.path.exists(filename)): + nml = f90nml.read(filename) + else: + error = True + + return (nml, error) + +def get_case_data(case_name): + """Returns proprietery CCPP SCM case data in NetCDF Dataset format""" + + #TODO: need to handle LSM ICs + + filename = os.path.join(PROCESSED_CASE_DIR, case_name + '.nc') + + error = False + try: + nc_fid = Dataset(filename , 'r') + except: + error = True + + if (not error): + #read global variables + try: + missing_value = nc_fid.getncattr('missing_value') + except: + missing_value = DEFAULT_MISSING_VALUE + + time = nc_fid.variables['time'][:] + levels = nc_fid.variables['levels'][:] + + #read variables from scalar group + scalars_grp = nc_fid.groups['scalars'] + lat = scalars_grp.variables['lat'][:] + lon = scalars_grp.variables['lon'][:] + + #read variables from initial group + initial_grp = nc_fid.groups['initial'] + height = initial_grp.variables['height'][:] + theta_il = initial_grp.variables['thetail'][:] + qt = initial_grp.variables['qt'][:] + ql = initial_grp.variables['ql'][:] + qi = initial_grp.variables['qi'][:] + u = initial_grp.variables['u'][:] + v = initial_grp.variables['v'][:] + tke = initial_grp.variables['tke'][:] + ozone = initial_grp.variables['ozone'][:] + + #read variables from forcing group + forcing_grp = nc_fid.groups['forcing'] + p_surf = forcing_grp.variables['p_surf'][:] + T_surf = forcing_grp.variables['T_surf'][:] + w_ls = forcing_grp.variables['w_ls'][:] + omega = forcing_grp.variables['omega'][:] + u_g = forcing_grp.variables['u_g'][:] + v_g = forcing_grp.variables['v_g'][:] + u_nudge = forcing_grp.variables['u_nudge'][:] + v_nudge = forcing_grp.variables['v_nudge'][:] + T_nudge = forcing_grp.variables['T_nudge'][:] + thil_nudge = forcing_grp.variables['thil_nudge'][:] + qt_nudge = forcing_grp.variables['qt_nudge'][:] + dT_dt_rad = forcing_grp.variables['dT_dt_rad'][:] + h_advec_thil = forcing_grp.variables['h_advec_thetail'][:] + v_advec_thil = forcing_grp.variables['v_advec_thetail'][:] + h_advec_qt = forcing_grp.variables['h_advec_qt'][:] + v_advec_qt = forcing_grp.variables['v_advec_qt'][:] + try: + sh_flux_sfc = forcing_grp.variables['sh_flux_sfc'][:] + except KeyError: + sh_flux_sfc = '' + try: + lh_flux_sfc = forcing_grp.variables['lh_flux_sfc'][:] + except KeyError: + lh_flux_sfc = '' + + nc_fid.close() + + case_data = Case_Data(case_name, missing_value, time, levels, lat, lon, + height, theta_il, qt, ql, qi, u, v, tke, ozone, + p_surf, T_surf, w_ls, omega, u_g, v_g, + u_nudge, v_nudge, T_nudge, thil_nudge, qt_nudge, + dT_dt_rad, h_advec_thil, v_advec_thil, h_advec_qt, + v_advec_qt, sh_flux_sfc, lh_flux_sfc) + + return(case_data, error) + +def write_SCM_case_file(case_nml, case_data, use_area): + """Write all data to a netCDF file in the DEPHY-SCM format""" + + #TODO: need to handle LSM ICs + + # Working types + wp = np.float64 + wi = np.int32 + + # Local switches + forcing_on = 1 + forcing_off = 0 + + nml_filename = os.path.join(CASE_NML_DIR, case_nml['case_config']['case_name'] + '.nml') + + # Output file + com = 'mkdir -p ' + PROCESSED_CASE_DIR + logging.info(com) + os.system(com) + fileOUT = os.path.join(PROCESSED_CASE_DIR, case_nml['case_config']['case_name'] + '_SCM_driver.nc') + + nc_file = Dataset(fileOUT, 'w', format='NETCDF3_CLASSIC') + nc_file.description = "Case data for {} from CCPP SCM".format(case_nml['case_config']['case_name']) + + nc_file.missing_value = case_data._missing_value + + #not all namelists will have minutes, set to 0 if nml doesn't have + try: + minute = case_nml['case_config']['minute'] + except KeyError: + minute = 0 + + start_date = datetime(case_nml['case_config']['year'],case_nml['case_config']['month'],case_nml['case_config']['day'],case_nml['case_config']['hour'],minute,0) + start_date_string = start_date.strftime("%Y-%m-%d %H:%M:%S") + runtime = case_nml['case_config']['runtime'] + delta = timedelta(seconds=runtime) + end_date = start_date + delta + end_date_string = end_date.strftime("%Y-%m-%d %H:%M:%S") + loc_string = str(case_data._lon) + "E" + str(case_data._lat) + "N" + case_string = case_nml['case_config']['case_name'] + '_' + start_date_string + '_' + loc_string + + logging.debug('Case string: {}'.format(case_string)) + logging.debug('Case start date: {}'.format(start_date)) + logging.debug('Case duration: {}'.format(delta)) + logging.debug('Case end date: {}'.format(end_date)) + + if (case_nml['case_config']['sfc_type'] == 0): + surface_string = 'ocean' + elif (case_nml['case_config']['sfc_type'] == 1): + surface_string = 'land' + elif (case_nml['case_config']['sfc_type'] == 2): + surface_string = 'ice' + + + #DEPHY v1 format specifies the global attributes in this order. Some attributes are rewritten below after the order is established in the file. + nc_file.case = case_string + nc_file.title = 'Forcing and Initial Conditions for ' + case_string + nc_file.reference = 'https://dtcenter.org/sites/default/files/paragraph/scm-ccpp-guide-v6-0-0.pdf' + nc_file.author = 'Grant J. Firl and Dustin Swales' + nc_file.version = 'Created on ' + datetime.today().strftime('%Y-%m-%d %H:%M:%S') + nc_file.format_version = 'DEPHY SCM format version 1' + nc_file.modifications = '' + nc_file.script = os.path.basename(__file__) + nc_file.comment = 'converted from ' + case_nml['case_config']['case_name'] + '.nc' + nc_file.start_date = start_date_string + nc_file.end_date = end_date_string + + if (use_area and case_nml['case_config']['column_area']): + nc_file.forcing_scale = case_nml['case_config']['column_area'] + else: + nc_file.forcing_scale = -1 + + nc_file.adv_ta = forcing_off + nc_file.adv_qv = forcing_off + nc_file.adv_ua = forcing_off #no mom_forcing_type implemented this (providing pre-calculated advective terms for u) + nc_file.adv_va = forcing_off #no mom_forcing_type implemented this (providing pre-calculated advective terms for v) + nc_file.adv_theta = forcing_off + nc_file.adv_thetal = forcing_off + nc_file.adv_qt = forcing_off + nc_file.adv_rv = forcing_off + nc_file.adv_rt = forcing_off + nc_file.radiation = "on" #not implemented in CCPP SCM - controlled by CCPP SDF and/or namelist + nc_file.forc_wap = forcing_off + nc_file.forc_wa = forcing_off + nc_file.forc_geo = forcing_off + nc_file.nudging_ua = forcing_off + nc_file.nudging_va = forcing_off + nc_file.nudging_ta = forcing_off + nc_file.nudging_theta = forcing_off + nc_file.nudging_thetal = forcing_off + nc_file.nudging_qv = forcing_off + nc_file.nudging_qt = forcing_off + nc_file.nudging_rv = forcing_off + nc_file.nudging_rt = forcing_off + nc_file.zh_nudging_ta = forcing_off + nc_file.zh_nudging_theta = forcing_off + nc_file.zh_nudging_thetal = forcing_off + nc_file.zh_nudging_qv = forcing_off + nc_file.zh_nudging_qt = forcing_off + nc_file.zh_nudging_rv = forcing_off + nc_file.zh_nudging_rt = forcing_off + nc_file.zh_nudging_ua = forcing_off + nc_file.zh_nudging_va = forcing_off + nc_file.pa_nudging_ta = forcing_off + nc_file.pa_nudging_theta = forcing_off + nc_file.pa_nudging_thetal = forcing_off + nc_file.pa_nudging_qv = forcing_off + nc_file.pa_nudging_qt = forcing_off + nc_file.pa_nudging_rv = forcing_off + nc_file.pa_nudging_rt = forcing_off + nc_file.pa_nudging_ua = forcing_off + nc_file.pa_nudging_va = forcing_off + # + nc_file.surface_type = surface_string + nc_file.surface_forcing_temp = 'none' + nc_file.surface_forcing_moisture = 'none' + nc_file.surface_forcing_wind = 'none' + + #rewrite forc_wa, forc_wap, forc_geo, nudging_ua, nudging_va depending on mom_forcing_type provided in case_config nml + if (case_nml['case_config']['mom_forcing_type'] == 2): + #CCPP SCM proprietery forcing interprets mom_forcing_type = 2 as calculating vertical advective terms from provided vertical velocity AND applying geostrophic winds + + #CCPP SCM proprietery cases could have either w or omega available (or both); use omega by default? + w_ls_avail = True if np.any(case_data._w_ls[:,:]) else False + omega_avail = True if np.any(case_data._omega[:,:]) else False + if omega_avail: + nc_file.forc_wap = forcing_on + nc_file.forc_wa = forcing_off + elif w_ls_avail: + nc_file.forc_wap = forcing_off + nc_file.forc_wa = forcing_on + else: + message = 'The case namelist ({0}) specifies the momentum variables should be forced using vertical velocity (through mom_forcing = 2), but neither w_ls or omega have nonzero values'.format(nml_filename) + logging.info(message) + nc_file.forc_wap = forcing_off + nc_file.forc_wa = forcing_off + #logging.critical(message) + #raise Exception(message) + + geostrophic_avail = True if (np.any(case_data._u_g[:,:]) or np.any(case_data._v_g[:,:])) else False + if geostrophic_avail: + nc_file.forc_geo = forcing_on + else: + message = 'The case namelist ({0}) specifies the momentum variables should be forced using geostrophic winds (through mom_forcing = 2), but neither u_g or v_g have nonzero values'.format(nml_filename) + logging.info(message) + nc_file.forc_geo = forcing_off + #logging.critical(message) + #raise Exception(message) + nc_file.nudging_ua = forcing_off + nc_file.nudging_va = forcing_off + + elif (case_nml['case_config']['mom_forcing_type'] == 3): + #CCPP SCM proprietery forcing interprets mom_forcing_type = 3 as calculating momentum forcing as nudging toward u and v profiles (only) + + nc_file.forc_wa = forcing_off + nc_file.forc_wap = forcing_off + nc_file.forc_geo = forcing_off + + u_nudge_avail = True if np.any(case_data._u_nudge[:,:]) else False + v_nudge_avail = True if np.any(case_data._v_nudge[:,:]) else False + relax_time_avail = True if case_nml['case_config']['relax_time'] else False + if relax_time_avail: + relax_time = case_nml['case_config']['relax_time'] + else: + relax_time = DEFAULT_NUDGING_TIMESCALE + message = 'The case namelist ({0}) specifies the momentum variables should be forced using nudging (through mom_forcing = 3), but relax_time was not provided -- using default value of {1}s '.format(nml_filename, DEFAULT_NUDGING_TIMESCALE) + logging.info(message) + + nc_file.nudging_ua = forcing_on*relax_time + nc_file.nudging_va = forcing_on*relax_time + + if (case_nml['case_config']['thermo_forcing_type'] == 1): + #total advective forcing + radiative heating + nc_file.adv_thetal = forcing_on + nc_file.adv_qt = forcing_on + #nc_file.radiation = 'tend' #radiation isn't turned off in the CCPP SCM through the forcing + elif (case_nml['case_config']['thermo_forcing_type'] == 2): + #horizontal advective forcing + (radiative heating) + vertical velocity + nc_file.adv_thetal = forcing_on + nc_file.adv_qt = forcing_on + #nc_file.radiation = 'tend' #radiation isn't turned off in the CCPP SCM through the forcing + + w_ls_avail = True if np.any(case_data._w_ls[:,:]) else False + omega_avail = True if np.any(case_data._omega[:,:]) else False + if omega_avail: + nc_file.forc_wap = forcing_on + nc_file.forc_wa = forcing_off + elif w_ls_avail: + nc_file.forc_wap = forcing_off + nc_file.forc_wa = forcing_on + else: + message = 'The case namelist ({0}) specifies the thermo variables should be forced using vertical velocity (through thermo_forcing = 2), but neither w_ls or omega have nonzero values'.format(nml_filename) + logging.info(message) + nc_file.forc_wap = forcing_off + nc_file.forc_wa = forcing_off + #logging.critical(message) + #raise Exception(message) + + elif (case_nml['case_config']['thermo_forcing_type'] == 3): + #nudging + vertical velocity + + T_nudge_avail = True if np.any(case_data._T_nudge[:,:]) else False + qt_nudge_avail = True if np.any(case_data._qt_nudge[:,:]) else False + relax_time_avail = True if case_nml['case_config']['relax_time'] else False + if relax_time_avail: + relax_time = case_nml['case_config']['relax_time'] + else: + relax_time = DEFAULT_NUDGING_TIMESCALE + message = 'The case namelist ({0}) specifies the thermo variables should be forced using nudging (through thermo_forcing = 3), but relax_time was not provided -- using default value of {1}s '.format(nml_filename, DEFAULT_NUDGING_TIMESCALE) + logging.info(message) + + nc_file.nudging_ta = forcing_on*relax_time + nc_file.nudging_qt = forcing_on*relax_time + + w_ls_avail = True if np.any(case_data._w_ls[:,:]) else False + omega_avail = True if np.any(case_data._omega[:,:]) else False + if omega_avail: + nc_file.forc_wap = forcing_on + nc_file.forc_wa = forcing_off + elif w_ls_avail: + nc_file.forc_wap = forcing_off + nc_file.forc_wa = forcing_on + else: + message = 'The case namelist ({0}) specifies the thermo variables should be forced using vertical velocity (through thermo_forcing = 2), but neither w_ls or omega have nonzero values'.format(nml_filename) + logging.info(message) + nc_file.forc_wap = forcing_off + nc_file.forc_wa = forcing_off + #logging.critical(message) + #raise Exception(message) + + if (case_nml['case_config']['sfc_flux_spec']): + nc_file.surface_forcing_temp = 'kinematic' + nc_file.surface_forcing_moisture = 'kinematic' + nc_file.surface_forcing_wind = 'z0' + else: + nc_file.surface_forcing_temp = 'ts' + nc_file.surface_forcing_wind = 'z0' + + time_dim = nc_file.createDimension('time', case_data._time.shape[0]) + timei_dim = nc_file.createDimension('t0', 1) + lev_dim = nc_file.createDimension('lev', case_data._levels.shape[0]) + + # + timei_var = nc_file.createVariable('t0', wp, ('t0')) + timei_var.units = 'seconds since ' + start_date_string + timei_var.standard_name = 'Initial time' + timei_var.calendar = 'gregorian' + timei_var[:] = 0.0 + # + timef_var = nc_file.createVariable('time', wp, ('time')) + timef_var.units = 'seconds since ' + start_date_string + timef_var.standard_name = 'Forcing time' + timef_var.calendar = 'gregorian' + timef_var[:] = case_data._time[:] + # + lev_var = nc_file.createVariable('lev', wp, ('lev')) + lev_var.units = 'Pa' + lev_var.standard_name = 'pressure' + lev_var[:] = case_data._levels[:] + + # + lon_var = nc_file.createVariable('lon', wp, ('time')) + lon_var.units = 'degrees_east' + lon_var.standard_name = 'longitude' + lon_var[:] = case_data._lon + + # + lat_var = nc_file.createVariable('lat', wp, ('time')) + lat_var.units = 'degrees_north' + lat_var.standard_name = 'latitude' + lat_var[:] = case_data._lat + + # + thetal_var = nc_file.createVariable('thetal', wp, ('t0','lev')) + thetal_var.units = 'K' + thetal_var.standard_name = 'air_liquid_potential_temperature' + thetal_var[:] = case_data._theta_il[:] + + # + qt_var = nc_file.createVariable('qt', wp, ('t0','lev')) + qt_var.units = 'kg kg-1' + qt_var.standard_name = 'mass_fraction_of_water_in_air' + qt_var[:] = case_data._qt[:] + + # + u_var = nc_file.createVariable('ua', wp, ('t0','lev')) + u_var.units = 'm s-1' + u_var.standard_name = 'eastward_wind' + u_var[:] = case_data._u[:] + + # + v_var = nc_file.createVariable('va', wp, ('t0','lev')) + v_var.units = 'm s-1' + v_var.standard_name = 'northward_wind' + v_var[:] = case_data._v[:] + + # + p_var = nc_file.createVariable('pa', wp, ('t0','lev')) + p_var.units = 'Pa' + p_var.standard_name = 'air_pressure' + p_var[:] = case_data._levels[:] + + # + z_var = nc_file.createVariable('zh', wp, ('t0','lev')) + z_var.units = 'm' + z_var.standard_name = 'height' + z_var[:] = case_data._height[:] + + # + ps_var = nc_file.createVariable('ps', wp, ('t0')) + ps_var.units = 'Pa' + ps_var.standard_name = 'surface_air_pressure' + ps_var[:] = case_data._p_surf[0] + + # + ql_var = nc_file.createVariable('ql', wp, ('t0','lev')) + ql_var.units = 'kg kg-1' + ql_var.standard_name = 'mass_fraction_of_cloud_liquid_water_in_air' + ql_var[:] = case_data._ql[:] + + # + qi_var = nc_file.createVariable('qi', wp, ('t0','lev')) + qi_var.units = 'kg kg-1' + qi_var.standard_name = 'mass_fraction_of_cloud_ice_water_in_air' + qi_var[:] = case_data._qi[:] + + # + tke_var = nc_file.createVariable('tke', wp, ('t0','lev')) + tke_var.units = 'm2 s-2' + tke_var.standard_name = 'specific_turbulent_kinetic_energy' + tke_var[:] = case_data._tke[:] + + # + ozone_var = nc_file.createVariable('o3', wp, ('t0','lev')) + ozone_var.units = 'kg kg-1' + ozone_var.standard_name = 'mole_fraction_of_ozone_in_air' + ozone_var[:] = case_data._ozone[:] + + if (nc_file.adv_ta == forcing_on): + message = 'adv_ta is turned on, but is not implemented in the proprietery CCPP SCM case format and cannot be used.' + logging.critical() + raise Exception(message) + # tnta_adv_var = nc_file.createVariable('tnta_adv', wp, ('time','lev')) + # tnta_adv_var.units = 'K s-1' + # tnta_adv_var.standard_name = 'tendency_of_air_temperature_due_to_advection' + # tnta_adv_var[:] = np.swapaxes(case_data._tnta_adv[:],0,1) + + if (nc_file.adv_qv == forcing_on): + message = 'adv_qv is turned on, but is not implemented in the proprietery CCPP SCM case format and cannot be used.' + logging.critical() + raise Exception(message) + # tnqv_adv_var = nc_file.createVariable('tnqv_adv', wp, ('time','lev')) + # tnqv_adv_var.units = 'kg kg-1 s-1' + # tnqv_adv_var.standard_name = 'tendency_of_specific_humidity_due_to_advection' + # tnqv_adv_var[:] = np.swapaxes(case_data._tnqv_adv[:],0,1) + + if (nc_file.adv_ua == forcing_on): + message = 'adv_ua is turned on, but is not implemented in the proprietery CCPP SCM case format and cannot be used.' + logging.critical() + raise Exception(message) + # tnua_adv_var = nc_file.createVariable('tnua_adv', wp, ('time','lev')) + # tnua_adv_var.units = 'm s-2' + # tnua_adv_var.standard_name = 'tendency_of_eastward_wind_due_to_advection' + # tnua_adv_var[:] = np.swapaxes(case_data._tnua_adv[:],0,1) + + if (nc_file.adv_va == forcing_on): + message = 'adv_va is turned on, but is not implemented in the proprietery CCPP SCM case format and cannot be used.' + logging.critical() + raise Exception(message) + # tnva_adv_var = nc_file.createVariable('tnva_adv', wp, ('time','lev')) + # tnva_adv_var.units = 'm s-2' + # tnva_adv_var.standard_name = 'tendency_of_northward_wind_due_to_advection' + # tnva_adv_var[:] = np.swapaxes(case_data._tnva_adv[:],0,1) + + if (nc_file.adv_theta == forcing_on): + message = 'adv_theta is turned on, but is not implemented in the proprietery CCPP SCM case format and cannot be used.' + logging.critical() + raise Exception(message) + # tntheta_adv_var = nc_file.createVariable('tntheta_adv', wp, ('time','lev')) + # tntheta_adv_var.units = 'K s-1' + # tntheta_adv_var.standard_name = 'tendency_of_air_potential_temperature_due_to_advection' + # tntheta_adv_var[:] = np.swapaxes(case_data._tntheta_adv[:],0,1) + + if (nc_file.adv_thetal == forcing_on): + tnthetal_adv_var = nc_file.createVariable('tnthetal_adv', wp, ('time','lev')) + tnthetal_adv_var.units = 'K s-1' + tnthetal_adv_var.standard_name = 'tendency_of_air_liquid_potential_temperature_due_to_advection' + tnthetal_adv_var[:] = np.swapaxes(case_data._h_advec_thil[:] + case_data._v_advec_thil[:],0,1) + + if (nc_file.adv_qt == forcing_on): + tnqt_adv_var = nc_file.createVariable('tnqt_adv', wp, ('time','lev')) + tnqt_adv_var.units = 'kg kg-1 s-1' + tnqt_adv_var.standard_name = 'tendency_of_mass_fraction_of_water_in_air_due_to_advection' + tnqt_adv_var[:] = np.swapaxes(case_data._h_advec_qt[:] + case_data._v_advec_qt[:],0,1) + + if (nc_file.adv_rv == forcing_on): + message = 'adv_rv is turned on, but is not implemented in the proprietery CCPP SCM case format and cannot be used.' + logging.critical() + raise Exception(message) + # tnrv_adv_var = nc_file.createVariable('tnrv_adv', wp, ('time','lev')) + # tnrv_adv_var.units = 'kg kg-1 s-1' + # tnrv_adv_var.standard_name = 'tendency_of_humidity_mixing_ratio_due_to_advection' + # tnrv_adv_var[:] = np.swapaxes(case_data._tnrv_adv[:],0,1) + + if (nc_file.adv_rt == forcing_on): + message = 'adv_rt is turned on, but is not implemented in the proprietery CCPP SCM case format and cannot be used.' + logging.critical() + raise Exception(message) + # tnrt_adv_var = nc_file.createVariable('tnrt_adv', wp, ('time','lev')) + # tnrt_adv_var.units = 'kg kg-1 s-1' + # tnrt_adv_var.standard_name = 'tendency_of_water_mixing_ratio_due_to_advection' + # tnrt_adv_var[:] = np.swapaxes(case_data._tnrt_adv[:],0,1) + + if (nc_file.forc_wap == forcing_on): + wap_var = nc_file.createVariable('wap', wp, ('time','lev')) + wap_var.units = 'Pa s-1' + wap_var.standard_name = 'lagrangian_tendency_of_air_pressure' + wap_var[:] = np.swapaxes(case_data._omega[:],0,1) + elif (nc_file.forc_wa == forcing_on): + wa_var = nc_file.createVariable('wa', wp, ('time','lev')) + wa_var.units = 'm s-1' + wa_var.standard_name = 'upward_air_velocity' + wa_var[:] = np.swapaxes(case_data._w_ls[:],0,1) + + if (nc_file.forc_geo == forcing_on): + ug_var = nc_file.createVariable('ug', wp, ('time','lev')) + ug_var.units = 'm s-1' + ug_var.standard_name = 'geostrophic_eastward_wind' + ug_var[:] = np.swapaxes(case_data._u_g[:],0,1) + + vg_var = nc_file.createVariable('vg', wp, ('time','lev')) + vg_var.units = 'm s-1' + vg_var.standard_name = 'geostrophic_northward_wind' + vg_var[:] = np.swapaxes(case_data._v_g[:],0,1) + + if (nc_file.nudging_ua == forcing_on): + ua_nud_var = nc_file.createVariable('ua_nud', wp, ('time','lev')) + ua_nud_var.units = 'm s-1' + ua_nud_var.standard_name = 'nudging_eastward_wind' + ua_nud_var[:] = np.swapaxes(case_data._u_nudge[:],0,1) + + if (nc_file.nudging_va == forcing_on): + va_nud_var = nc_file.createVariable('va_nud', wp, ('time','lev')) + va_nud_var.units = 'm s-1' + va_nud_var.standard_name = 'nudging_northward_wind' + va_nud_var[:] = np.swapaxes(case_data._v_nudge[:],0,1) + + if (nc_file.nudging_ta == forcing_on): + ta_nud_var = nc_file.createVariable('ta_nud', wp, ('time','lev')) + ta_nud_var.units = 'K' + ta_nud_var.standard_name = 'nudging_air_temperature' + ta_nud_var[:] = np.swapaxes(case_data._T_nudge[:],0,1) + + if (nc_file.nudging_qt == forcing_on): + qt_nud_var = nc_file.createVariable('qt_nud', wp, ('time','lev')) + qt_nud_var.units = 'kg kg-1' + qt_nud_var.standard_name = 'nudging_mass_fraction_of_water_in_air' + qt_nud_var[:] = np.swapaxes(case_data._qt_nudge[:],0,1) + + nc_file.close() + + return(fileOUT) + +def write_SCM_nml_file(case_nml): + filename = os.path.join(CASE_NML_DIR, case_nml['case_config']['case_name'] + '_dephy.nml') + + #Go through existing case namelist and only add necessary items to new DEPHY-based namelist + + #add _dephy to case (temporary - to differentiate from old format case) + int_dict = {'case_name':case_nml['case_config']['case_name']+'_dephy', + 'input_type':1} + + nml_keys = case_nml['case_config'].todict().keys() + if ('npz_type' in nml_keys): + int_dict['npz_type'] = case_nml['case_config']['npz_type'] + if int_dict['npz_type'] == 'input' and 'vert_coord_file' in nml_keys: + int_dict['vert_coord_file'] = case_nml['case_config']['vert_coord_file'] + + if ('dt' in nml_keys): + int_dict['dt'] = case_nml['case_config']['dt'] + + #runtime is in netCDF file + + if ('output_dir' in nml_keys): + int_dict['output_dir'] = case_nml['case_config']['output_dir'] + + if ('model_ics' in nml_keys): + int_dict['model_ics'] = case_nml['case_config']['model_ics'] + + if ('lsm_ics' in nml_keys): + int_dict['lsm_ics'] = case_nml['case_config']['lsm_ics'] + + if ('do_spinup' in nml_keys): + int_dict['do_spinup'] = case_nml['case_config']['do_spinup'] + + if ('spinup_timesteps' in nml_keys): + int_dict['spinup_timesteps'] = case_nml['case_config']['spinup_timesteps'] + + if ('C_RES' in nml_keys): + int_dict['C_RES'] = case_nml['case_config']['C_RES'] + + #relax_time is in netCDF file + + #sfc_type is in netCDF file + + #sfc_flux_spec is in netCDF file + + if ('sfc_roughness_length_cm' in nml_keys): + int_dict['sfc_roughness_length_cm'] = case_nml['case_config']['sfc_roughness_length_cm'] + + if ('reference_profile_choice' in nml_keys): + int_dict['reference_profile_choice'] = case_nml['case_config']['reference_profile_choice'] + + if ('column_area' in nml_keys): + int_dict['column_area'] = case_nml['case_config']['column_area'] + + nml_dict = {'case_config':int_dict} + + nml = f90nml.namelist.Namelist(nml_dict) + + #print(nml) + nml.write(filename) + + return(filename) + +######################################################################################## +# +######################################################################################## +def write_SCM_case_file_UFS(state, surface, oro, forcing, case, date, vertical_forcing): + """Write all data to a netCDF file in the DEPHY-SCM format""" + + # Working types + wp = np.float64 + wi = np.int32 + + # Local switches + forcing_on = 1 + forcing_off = 0 + + # Output file + com = 'mkdir -p ' + PROCESSED_CASE_DIR + print(com) + os.system(com) + fileOUT = os.path.join(PROCESSED_CASE_DIR, case + '_SCM_driver.nc') + + nc_file = Dataset(fileOUT, 'w', format='NETCDF3_CLASSIC') + nc_file.description = "FV3GFS model profile input (UFS forcings)" + + nc_file.missing_value = missing_value + + start_date = datetime(date["year"],date["month"],date["day"],date["hour"],date["minute"],date["second"]) + + # + # Create surface type string (Saved as GLOBAL attribute) + # + if surface["slmsk"] > 1.5: + surface_string = 'ice' + elif surface["slmsk"] > 0.5: + surface_string = 'land' + else: + surface_string = 'ocean' + + # + # Global file attributes. + # + runtime = timedelta(seconds=forcing['time'][-1]) + end_date = start_date + runtime + end_date_string = end_date.strftime("%Y-%m-%d %H:%M:%S") + start_date_string = start_date.strftime("%Y-%m-%d %H:%M:%S") + # + loc_string = str(round(surface["lon"],2)) + "E" + str(round(surface["lat"],2)) + "N" + case_string = 'UFS_' + start_date_string + '_' + loc_string + # + nc_file.case = case_string + nc_file.title = 'Forcing and Initial Conditions for ' + case_string + nc_file.reference = 'https://dtcenter.org/sites/default/files/paragraph/scm-ccpp-guide-v6-0-0.pdf' + nc_file.author = 'Grant J. Firl and Dustin Swales' + nc_file.version = 'Created on ' + datetime.today().strftime('%Y-%m-%d %H:%M:%S') + nc_file.format_version = 'DEPHY SCM format version 1' + nc_file.modifications = '' + nc_file.script = os.path.basename(__file__) + nc_file.comment = '' + nc_file.start_date = start_date_string + nc_file.end_date = end_date_string + nc_file.forcing_scale = -1 + nc_file.radiation = "off" + nc_file.adv_ta = forcing_off + nc_file.adv_qv = forcing_off + nc_file.adv_ua = forcing_off + nc_file.adv_va = forcing_off + nc_file.adv_theta = forcing_off + nc_file.adv_thetal = forcing_off + nc_file.adv_qt = forcing_off + nc_file.adv_rv = forcing_off + nc_file.adv_rt = forcing_off + if (vertical_forcing == 2): + nc_file.forc_wa = forcing_on + else: + nc_file.forc_wa = forcing_off + nc_file.forc_wap = forcing_off + nc_file.forc_geo = forcing_off + nc_file.nudging_ua = forcing_off + nc_file.nudging_va = forcing_off + nc_file.nudging_ta = forcing_off + nc_file.nudging_theta = forcing_off + nc_file.nudging_thetal = forcing_off + nc_file.nudging_qv = forcing_off + nc_file.nudging_qt = forcing_off + nc_file.nudging_rv = forcing_off + nc_file.nudging_rt = forcing_off + nc_file.zh_nudging_ta = forcing_off + nc_file.zh_nudging_theta = forcing_off + nc_file.zh_nudging_thetal = forcing_off + nc_file.zh_nudging_qv = forcing_off + nc_file.zh_nudging_qt = forcing_off + nc_file.zh_nudging_rv = forcing_off + nc_file.zh_nudging_rt = forcing_off + nc_file.zh_nudging_ua = forcing_off + nc_file.zh_nudging_va = forcing_off + nc_file.pa_nudging_ta = forcing_off + nc_file.pa_nudging_theta = forcing_off + nc_file.pa_nudging_thetal = forcing_off + nc_file.pa_nudging_qv = forcing_off + nc_file.pa_nudging_qt = forcing_off + nc_file.pa_nudging_rv = forcing_off + nc_file.pa_nudging_rt = forcing_off + nc_file.pa_nudging_ua = forcing_off + nc_file.pa_nudging_va = forcing_off + # + nc_file.surface_type = surface_string + # + nc_file.adv_ta = forcing_on + nc_file.adv_qv = forcing_on + nc_file.adv_ua = forcing_on + nc_file.adv_va = forcing_on + # + nc_file.surface_forcing_temp = 'none' + nc_file.surface_forcing_moisture = 'none' + nc_file.surface_forcing_wind = 'none' + nc_file.surface_forcing_lsm = 'none' #'noah' #'noahmp' #'ruc' + nc_file.surface_forcing_lsm = 'lsm' + # Set file dimension + time_dim = nc_file.createDimension('time', len(forcing['time'])) + timei_dim = nc_file.createDimension('t0', 1) + lev_dim = nc_file.createDimension('lev', state["nlevs"]) + soil_dim = nc_file.createDimension('nsoil', len(surface["stc"])) + snow_dim = nc_file.createDimension('nsnow', len(surface["snicexy"])) + nslsnw_dim = nc_file.createDimension('nsoil_plus_nsnow',len(surface["snicexy"]) + len(surface["stc"])) + ice_dim = nc_file.createDimension('nice', len(surface["tiice"])) + + # + timei_var = nc_file.createVariable('t0', wp, ('t0')) + timei_var.units = 'seconds since ' + start_date_string + timei_var.standard_name = 'Initial time' + timei_var.calendar = 'gregorian' + timei_var[:] = 0.0 + # + timef_var = nc_file.createVariable('time', wp, ('time')) + timef_var.units = 'seconds since ' + start_date_string + timef_var.standard_name = 'Forcing time' + timef_var.calendar = 'gregorian' + timef_var[:] = forcing['time'] + # + lev_var = nc_file.createVariable('lev', wp, ('lev')) + lev_var.units = 'm' + lev_var.standard_name = 'height' + lev_var[:] = 0.0 + + # + lon_var = nc_file.createVariable('lon', wp, ('time')) + lon_var.units = 'degrees_east' + lon_var.standard_name = 'longitude' + lon_var[:] = surface["lon"] + + # + lat_var = nc_file.createVariable('lat', wp, ('time')) + lat_var.units = 'degrees_north' + lat_var.standard_name = 'latitude' + lat_var[:] = surface["lat"] + + # + soil_depth_var = nc_file.createVariable('soil_depth', wp, ('nsoil')) + soil_depth_var.units = 'm' + soil_depth_var.standard_name = 'depth of bottom of soil layers' + soil_depth_var[:] = [0.1,0.4,1.0,2.0] + # + theta_oro = nc_file.createVariable('theta_oro',wp, ('t0')) + theta_oro.units = "deg" + theta_oro.standard_name = "angle with respect to east of maximum subgrid orographic variations" + theta_oro[:] = oro["theta"] + # + z0_var = nc_file.createVariable('zorl', wp, ('time')) + z0_var.units = "cm" + z0_var.standard_name = 'surface_roughness_length_for_momentum_in_air' + z0_var[:] = surface["z0"] + # + zorlw_var = nc_file.createVariable('zorlw', wp, ('t0')) + zorlw_var.units = "cm" + zorlw_var.standard_name = "surface roughness length over ocean" + zorlw_var[:] = surface["z0"] + # + zorll_var = nc_file.createVariable('zorll', wp, ('t0')) + zorll_var.units = "cm" + zorll_var.standard_name = "surface roughness length over land" + zorll_var[:] = surface["zorll"] + # + zorli_var = nc_file.createVariable('zorli', wp, ('t0')) + zorli_var.units = "cm" + zorli_var.standard_name = "surface roughness length over ice" + zorli_var[:] = surface["zorli"] + # + zorlwav_var = nc_file.createVariable('zorlwav', wp, ('time')) + zorlwav_var.units = "cm" + zorlwav_var.standard_name = 'surface_roughness_length_from_wave_model' + zorlwav_var[:] = surface["zorlw"] + + # + # Variables to be output to SCM input file. Only fields that come directly from forcing, + # surface, state, and oro. Fields that get renamed are done above. + # + dict = {} + dict.update(date) + dict.update(surface) + dict.update(state) + dict.update(oro) + dict.update(forcing) + + ######################################################################################## + # + # Dictonary format: + # {"name": "", "type", "dimd": (), "units": "", "desc": ""} + # + ######################################################################################## + var_dict = [{"name": "orog", "type":wp, "dimd": ('t0' ), "units": "m", "desc": "surface_altitude"},\ + {"name": "zh", "type":wp, "dimd": ('t0', 'lev'), "units": "m", "desc": "height"},\ + {"name": "pa", "type":wp, "dimd": ('t0', 'lev'), "units": "Pa", "desc": "air_pressure"}, \ + {"name": "ta", "type":wp, "dimd": ('t0', 'lev'), "units": "K", "desc": "air_temperature"}, \ + {"name": "theta", "type":wp, "dimd": ('t0', 'lev'), "units": "K", "desc": "air_potential_temperature"}, \ + {"name": "thetal", "type":wp, "dimd": ('t0', 'lev'), "units": "K", "desc": "air_liquid_potential_temperature"}, \ + {"name": "rv", "type":wp, "dimd": ('t0', 'lev'), "units": "kg kg-1", "desc": "humidity_mixing_ratio"}, \ + {"name": "rl", "type":wp, "dimd": ('t0', 'lev'), "units": "kg kg-1", "desc": "cloud_liquid_water_mixing_ratio"}, \ + {"name": "ri", "type":wp, "dimd": ('t0', 'lev'), "units": "kg kg-1", "desc": "cloud_ice_water_mixing_ratio"}, \ + {"name": "rt", "type":wp, "dimd": ('t0', 'lev'), "units": "kg kg-1", "desc": "water_mixing_ratio"}, \ + {"name": "qv", "type":wp, "dimd": ('t0', 'lev'), "units": "kg kg-1", "desc": "specific_humidity"}, \ + {"name": "ql", "type":wp, "dimd": ('t0', 'lev'), "units": "kg kg-1", "desc": "mass_fraction_of_cloud_liquid_water_in_air"}, \ + {"name": "qi", "type":wp, "dimd": ('t0', 'lev'), "units": "kg kg-1", "desc": "mass_fraction_of_cloud_ice_water_in_air", "default_value": 0.0}, \ + {"name": "qt", "type":wp, "dimd": ('t0', 'lev'), "units": "kg kg-1", "desc": "mass_fraction_of_water_in_air"}, \ + {"name": "hur", "type":wp, "dimd": ('t0', 'lev'), "units": "%", "desc": "relative_humidity"}, \ + {"name": "tke", "type":wp, "dimd": ('t0', 'lev'), "units": "m2 s-2", "desc": "specific_turbulen_kinetic_energy", "default_value": 0.0}, \ + {"name": "ua", "type":wp, "dimd": ('t0', 'lev'), "units": "m s-1", "desc": "eastward_wind"}, \ + {"name": "va", "type":wp, "dimd": ('t0', 'lev'), "units": "m s-1", "desc": "northward_wind"}, \ + {"name": "ts", "type":wp, "dimd": ('t0' ), "units": "K", "desc": "surface_temperature"},\ + {"name": "tskin", "type":wp, "dimd": ('t0' ), "units": "K", "desc": "surface_skin_temperature"}, \ + {"name": "ps", "type":wp, "dimd": ('t0' ), "units": "Pa", "desc": "surface_air_pressure"}, \ + {"name": "beta", "type":wp, "dimd": ('t0' ), "units": "m", "desc": "soil_water_stress_factor"}, \ + {"name": "mrsos", "type":wp, "dimd": ('t0' ), "units": "kg m-2", "desc": "mass_content_of_water_in_soil_layer"}, \ + {"name": "o3", "type":wp, "dimd": ('t0', 'lev'), "units": "kg kg-1", "desc": "mole_fraction_of_ozone_in_air"}, \ + {"name": "sza", "type":wp, "dimd": ('t0' ), "units": "degree", "desc": "solar_zenith_angle"}, \ + {"name": "io", "type":wp, "dimd": ('t0' ), "units": "W m-2", "desc": "solar_irradiance"}, \ + {"name": "alb", "type":wp, "dimd": ('t0' ), "units": "1", "desc": "surface_albedo"}, \ + {"name": "emis", "type":wp, "dimd": ('t0' ), "units": "1", "desc": "surface_longwave_emissivity"}, \ + {"name": "slmsk", "type":wp, "dimd": ('t0' ), "units": "none", "desc": "land_sea_ice_mask"}] + # + var_frc = [{"name": "zh_forc", "type":wp, "dimd": ('time', 'lev'), "units": "m", "desc": "height_forcing","default_value": 1.},\ + {"name": "pa_forc", "type":wp, "dimd": ('time', 'lev'), "units": "Pa", "desc": "air_pressure_forcing"}, \ + {"name": "wa", "type":wp, "dimd": ('time', 'lev'), "units": "m s-1", "desc": "upward_air_velocity"}, \ + {"name": "wap", "type":wp, "dimd": ('time', 'lev'), "units": "Pa s-1", "desc": "lagrangian_tendency_of_air_pressure"}, \ + {"name": "ug", "type":wp, "dimd": ('time', 'lev'), "units": "m s-1", "desc": "geostrophic_eastward_wind"}, \ + {"name": "vg", "type":wp, "dimd": ('time', 'lev'), "units": "m s-1", "desc": "geostrophic_northward_wind"}, \ + {"name": "tnua_adv", "type":wp, "dimd": ('time', 'lev'), "units": "m s-2", "desc": "tendency_of_eastward_wind_due_to_advection"},\ + {"name": "tnva_adv", "type":wp, "dimd": ('time', 'lev'), "units": "m s-2", "desc": "tendency_of_northward_wind_due_to_advection"}, \ + {"name": "tnta_adv", "type":wp, "dimd": ('time', 'lev'), "units": "K s-1", "desc": "tendency_of_air_temperature_due_to_advection"}, \ + {"name": "tntheta_adv", "type":wp, "dimd": ('time', 'lev'), "units": "K s-1", "desc": "tendency_of_air_potential_temperature_due_to_advection"}, \ + {"name": "tnthetal_adv", "type":wp, "dimd": ('time', 'lev'), "units": "K s-1", "desc": "tendency_of_air_liquid_potential_temperature_due_to_advection"}, \ + {"name": "tnqv_adv", "type":wp, "dimd": ('time', 'lev'), "units": "kg kg-1 s-1", "desc": "tendency_of_specific_humidity_due_to_advection"},\ + {"name": "tnqt_adv", "type":wp, "dimd": ('time', 'lev'), "units": "kg kg-1 s-1", "desc": "tendency_of_mass_fraction_of_water_in_air_due_to_advection"},\ + {"name": "tnrv_adv", "type":wp, "dimd": ('time', 'lev'), "units": "kg kg-1 s-1", "desc": "tendency_of_humidity_mixing_ratio_due_to_advection"},\ + {"name": "tnrt_adv", "type":wp, "dimd": ('time', 'lev'), "units": "kg kg-1 s-1", "desc": "tendency_of_water_mixing_ratio_due_to_advection"},\ + {"name": "tnta_rad", "type":wp, "dimd": ('time', 'lev'), "units": "K s-1", "desc": "tendency_of_air_temperature_due_to_radiative_heating"}, \ + {"name": "tntheta_rad", "type":wp, "dimd": ('time', 'lev'), "units": "K s-1", "desc": "tendency_of_potential_air_temperature_due_to_radiative_heating"}, \ + {"name": "tnthetal_rad", "type":wp, "dimd": ('time', 'lev'), "units": "K s-1", "desc": "tendency_of_air_liquid_potential_temperature_due_to_radiative_heating"}, \ + {"name": "ta_nud", "type":wp, "dimd": ('time', 'lev'), "units": "K", "desc": "nudging_air_temperature"}, \ + {"name": "theta_nud", "type":wp, "dimd": ('time', 'lev'), "units": "K", "desc": "nudging_air_potential_temperature"}, \ + {"name": "thetal_nud", "type":wp, "dimd": ('time', 'lev'), "units": "K", "desc": "nudging_air_liquid_potential_temperature"}, \ + {"name": "qt_nud", "type":wp, "dimd": ('time', 'lev'), "units": "kg kg-1", "desc": "nudging_mass_fraction_of_water_in_air"}, \ + {"name": "rv_nud", "type":wp, "dimd": ('time', 'lev'), "units": "m s-1", "desc": "nudging_humidity_mixing_ratio"}, \ + {"name": "rt_nud", "type":wp, "dimd": ('time', 'lev'), "units": "m s-1", "desc": "nudging_water_mixing_ratio"}, \ + {"name": "ua_nud", "type":wp, "dimd": ('time', 'lev'), "units": "m s-1", "desc": "nudging_eastward_wind"}, \ + {"name": "va_nud", "type":wp, "dimd": ('time', 'lev'), "units": "m s-1", "desc": "nudging_northward_wind"}, \ + {"name": "hfss", "type":wp, "dimd": ('time' ), "units": "W m-2", "desc": "surface_upward_sensible_heat_flux"}, \ + {"name": "hfls", "type":wp, "dimd": ('time' ), "units": "W m-2", "desc": "surface_upward_latent_heat_flux"}, \ + {"name": "wpthetap_s", "type":wp, "dimd": ('time' ), "units": "K m s-1", "desc": "surface_upward_potential_temperature_flux"}, \ + {"name": "wpqvp_s", "type":wp, "dimd": ('time' ), "units": "m s-1", "desc": "surface_upward_specific_humidity_flux"}, \ + {"name": "wpqtp_s", "type":wp, "dimd": ('time' ), "units": "m s-1", "desc": "surface_upward_water_mass_fraction_flux"}, \ + {"name": "wprvp_s", "type":wp, "dimd": ('time' ), "units": "m s-1", "desc": "surface_upward_humidity_mixing_ratio_flux"}, \ + {"name": "wprtp_s", "type":wp, "dimd": ('time' ), "units": "m s-1", "desc": "surface_upward_water_mixing_ratio_flux"}, \ + {"name": "ts_forc", "type":wp, "dimd": ('time' ), "units": "K", "desc": "forcing_surface_temperature"},\ + {"name": "ps_forc", "type":wp, "dimd": ('time' ), "units": "Pa", "desc": "forcing_surface_air_pressure"},\ + {"name": "uustar", "type":wp, "dimd": ('time' ), "units": "m s-1", "desc": "surface_friction_velocity"}, \ + {"name": "z0h", "type":wp, "dimd": ('time' ), "units": "m", "desc": "surface_roughness_length_for_heat_in_air"}, \ + {"name": "z0q", "type":wp, "dimd": ('time' ), "units": "m", "desc": "surface_roughness_length_for_humidity_in_air"}, \ + {"name": "mrsos_forc", "type":wp, "dimd": ('time' ), "units": "kg m-2", "desc": "forcing_mass_content_of_water_in_soil_layer"}] + + # + var_oro = [{"name": "area", "type":wp, "dimd": ('t0'), "units": "m2", "desc": "grid_cell_area"},\ + {"name": "stddev", "type":wp, "dimd": ('t0'), "units": "m", "desc": "standard deviation of subgrid orography"}, \ + {"name": "convexity", "type":wp, "dimd": ('t0'), "units": "none", "desc": "convexity of subgrid orography"}, \ + {"name": "oa1", "type":wp, "dimd": ('t0'), "units": "none", "desc": "assymetry of subgrid orography 1"}, \ + {"name": "oa2", "type":wp, "dimd": ('t0'), "units": "none", "desc": "assymetry of subgrid orography 2"}, \ + {"name": "oa3", "type":wp, "dimd": ('t0'), "units": "none", "desc": "assymetry of subgrid orography 3"}, \ + {"name": "oa4", "type":wp, "dimd": ('t0'), "units": "none", "desc": "assymetry of subgrid orography 4"}, \ + {"name": "ol1", "type":wp, "dimd": ('t0'), "units": "none", "desc": "fraction of grid box with subgrid orography higher than critical height 1"}, \ + {"name": "ol2", "type":wp, "dimd": ('t0'), "units": "none", "desc": "fraction of grid box with subgrid orography higher than critical height 2"}, \ + {"name": "ol3", "type":wp, "dimd": ('t0'), "units": "none", "desc": "fraction of grid box with subgrid orography higher than critical height 3"}, \ + {"name": "ol4", "type":wp, "dimd": ('t0'), "units": "none", "desc": "fraction of grid box with subgrid orography higher than critical height 4"}, \ + {"name": "sigma", "type":wp, "dimd": ('t0'), "units": "none", "desc": "slope of subgrid orography"}, \ + {"name": "gamma", "type":wp, "dimd": ('t0'), "units": "none", "desc": "anisotropy of subgrid orography"}, \ + {"name": "elvmax", "type":wp, "dimd": ('t0'), "units": "m", "desc": "maximum of subgrid orography"}, \ + {"name": "oro", "type":wp, "dimd": ('t0'), "units": "m", "desc": "orography"}, \ + {"name": "oro_uf", "type":wp, "dimd": ('t0'), "units": "m", "desc": "unfiltered orography"}, \ + {"name": "landfrac", "type":wp, "dimd": ('t0'), "units": "none", "desc": "fraction of horizontal grid area occupied by land"}, \ + {"name": "lakefrac", "type":wp, "dimd": ('t0'), "units": "none", "desc": "fraction of horizontal grid area occupied by lake", "default_value":0}, \ + {"name": "lakedepth", "type":wp, "dimd": ('t0'), "units": "none", "desc": "lake depth", "default_value":0}] + # + var_nsst = [{"name": "tref", "type":wp, "dimd": ('t0'), "units": "K", "desc": "sea surface reference temperature for NSST"}, \ + {"name": "z_c", "type":wp, "dimd": ('t0'), "units": "m", "desc": "sub-layer cooling thickness for NSST"}, \ + {"name": "c_0", "type":wp, "dimd": ('t0'), "units": "none", "desc": "coefficient 1 to calculate d(Tz)/d(Ts) for NSST"}, \ + {"name": "c_d", "type":wp, "dimd": ('t0'), "units": "nonw", "desc": "coefficient 2 to calculate d(Tz)/d(Ts) for NSST"}, \ + {"name": "w_0", "type":wp, "dimd": ('t0'), "units": "none", "desc": "coefficient 3 to calculate d(Tz)/d(Ts) for NSST"}, \ + {"name": "w_d", "type":wp, "dimd": ('t0'), "units": "none", "desc": "coefficient 4 to calculate d(Tz)/d(Ts) for NSST"}, \ + {"name": "xt", "type":wp, "dimd": ('t0'), "units": "K m", "desc": "heat content in diurnal thermocline layer for NSST"}, \ + {"name": "xs", "type":wp, "dimd": ('t0'), "units": "ppt m", "desc": "salinity content in diurnal thermocline layer for NSST"}, \ + {"name": "xu", "type":wp, "dimd": ('t0'), "units": "m2 s-1", "desc": "u-current in diurnal thermocline layer for NSST"}, \ + {"name": "xv", "type":wp, "dimd": ('t0'), "units": "m2 s-1", "desc": "v-current in diurnal thermocline layer for NSST"}, \ + {"name": "xz", "type":wp, "dimd": ('t0'), "units": "m", "desc": "thickness of diurnal thermocline layer for NSST"}, \ + {"name": "zm" , "type":wp, "dimd": ('t0'), "units": "m", "desc": "thickness of ocean mixed layer for NSST"}, \ + {"name": "xtts", "type":wp, "dimd": ('t0'), "units": "m", "desc": "sensitivity of diurnal thermocline layer heat content to surface temperature [d(xt)/d(ts)] for NSST"},\ + {"name": "xzts", "type":wp, "dimd": ('t0'), "units": "m K-1", "desc": "sensitivity of diurnal thermocline layer thickness to surface temperature [d(xz)/d(ts)] for NSST"}, \ + {"name": "d_conv", "type":wp, "dimd": ('t0'), "units": "m", "desc": "thickness of free convection layer for NSST"}, \ + {"name": "ifd", "type":wp, "dimd": ('t0'), "units": "none", "desc": "index to start DTM run for NSST"}, \ + {"name": "dt_cool", "type":wp, "dimd": ('t0'), "units": "K", "desc": "sub-layer cooling amount for NSST"}, \ + {"name": "qrain", "type":wp, "dimd": ('t0'), "units": "W m-2", "desc": "sensible heat due to rainfall for NSST"}] + # + var_frgd = [{"name": "tiice", "type":wp, "dimd": ('t0','nice'), "units": "K", "desc": "sea ice internal temperature"}] + # + var_noah = [{"name": "vegsrc", "type":wi, "dimd": ('t0'), "units": "none", "desc": "vegetation source (1-2)", "default_value": 1}, \ + {"name": "tsfco", "type":wp, "dimd": ('t0'), "units": "K", "desc": "sea/skin/ice surface temperature"}, \ + {"name": "weasd", "type":wp, "dimd": ('t0'), "units": "mm", "desc": "water equivalent accumulated snow depth"}, \ + {"name": "tg3", "type":wp, "dimd": ('t0'), "units": "K", "desc": "deep soil temperature"}, \ + {"name": "alvsf", "type":wp, "dimd": ('t0'), "units": "none", "desc": "60 degree vis albedo with strong cosz dependency"}, \ + {"name": "alnsf", "type":wp, "dimd": ('t0'), "units": "none", "desc": "60 degree nir albedo with strong cosz dependency"}, \ + {"name": "alvwf", "type":wp, "dimd": ('t0'), "units": "none", "desc": "60 degree vis albedo with weak cosz dependency"}, \ + {"name": "alnwf", "type":wp, "dimd": ('t0'), "units": "none", "desc": "60 degree nir albedo with weak cosz dependency"}, \ + {"name": "facsf", "type":wp, "dimd": ('t0'), "units": "none", "desc": "fractional coverage with strong cosz dependency"}, \ + {"name": "facwf", "type":wp, "dimd": ('t0'), "units": "none", "desc": "fractional coverage with weak cosz dependency"}, \ + {"name": "vegfrac", "type":wp, "dimd": ('t0'), "units": "none", "desc": "vegetation fraction"}, \ + {"name": "canopy", "type":wp, "dimd": ('t0'), "units": "kg m-2", "desc": "amount of water stored in canopy"}, \ + {"name": "f10m", "type":wp, "dimd": ('t0'), "units": "none", "desc": "ratio of sigma level 1 wind and 10m wind"}, \ + {"name": "t2m", "type":wp, "dimd": ('t0'), "units": "K", "desc": "2-meter absolute temperature"}, \ + {"name": "q2m", "type":wp, "dimd": ('t0'), "units": "kg kg-1", "desc": "2-meter specific humidity"}, \ + {"name": "vegtyp", "type":wi, "dimd": ('t0'), "units": "none", "desc": "vegetation type (1-12)"}, \ + {"name": "soiltyp", "type":wi, "dimd": ('t0'), "units": "none", "desc": "soil type (1-12)"}, \ + {"name": "scolor", "type":wp, "dimd": ('t0'), "units": "none", "desc": "soil color"}, \ + {"name": "ffmm", "type":wp, "dimd": ('t0'), "units": "none", "desc": "Monin-Obukhov similarity function for momentum"}, \ + {"name": "ffhh", "type":wp, "dimd": ('t0'), "units": "none", "desc": "Monin-Obukhov similarity function for heat"}, \ + {"name": "hice", "type":wp, "dimd": ('t0'), "units": "m", "desc": "sea ice thickness"}, \ + {"name": "fice", "type":wp, "dimd": ('t0'), "units": "none", "desc": "ice fraction"}, \ + {"name": "tisfc", "type":wp, "dimd": ('t0'), "units": "K", "desc": "ice surface temperature"}, \ + {"name": "tprcp", "type":wp, "dimd": ('t0'), "units": "m", "desc": "instantaneous total precipitation amount"}, \ + {"name": "srflag", "type":wp, "dimd": ('t0'), "units": "none", "desc": "snow/rain flag for precipitation"}, \ + {"name": "snowd", "type":wp, "dimd": ('t0'), "units": "mm", "desc": "water equivalent snow depth"}, \ + {"name": "shdmin", "type":wp, "dimd": ('t0'), "units": "none", "desc": "minimum vegetation fraction"}, \ + {"name": "shdmax", "type":wp, "dimd": ('t0'), "units": "none", "desc": "maximum vegetation fraction"}, \ + {"name": "slopetyp", "type":wi, "dimd": ('t0'), "units": "none", "desc": "slope type (1-9)"}, \ + {"name": "snoalb", "type":wp, "dimd": ('t0'), "units": "none", "desc": "maximum snow albedo"}, \ + {"name": "sncovr", "type":wp, "dimd": ('t0'), "units": "none", "desc": "surface snow area fraction"}, \ + {"name": "tsfcl", "type":wp, "dimd": ('t0'), "units": "K", "desc": "surface skin temperature over land"}, \ + {"name": "stc", "type":wp, "dimd": ('t0','nsoil'), "units": "K", "desc": "initial profile of soil liquid moisture"}, \ + {"name": "smc", "type":wp, "dimd": ('t0','nsoil'), "units": "kg", "desc": "initial profile of soil moisture"}, \ + {"name": "slc", "type":wp, "dimd": ('t0','nsoil'), "units": "kg", "desc": "initial profile of soil temperature"}] + # + var_noahmp=[{"name": "tvxy", "type":wp, "dimd": ('t0'), "units": "K", "desc": "vegetation temperature for NoahMP"}, \ + {"name": "tgxy", "type":wp, "dimd": ('t0'), "units": "K", "desc": "ground temperature for NoahMP"}, \ + {"name": "tahxy", "type":wp, "dimd": ('t0'), "units": "K", "desc": "canopy air temperature for NoahMP"}, \ + {"name": "canicexy", "type":wp, "dimd": ('t0'), "units": "mm", "desc": "canopy intercepted ice mass for NoahMP"}, \ + {"name": "canliqxy", "type":wp, "dimd": ('t0'), "units": "mm", "desc": "canopy intercepted liquid water for NoahMP"}, \ + {"name": "eahxy", "type":wp, "dimd": ('t0'), "units": "Pa", "desc": "canopy air vapor pressure for NoahMP"}, \ + {"name": "cmxy", "type":wp, "dimd": ('t0'), "units": "none", "desc": "surface drag coefficient for momentum for NoahMP"}, \ + {"name": "chxy", "type":wp, "dimd": ('t0'), "units": "none", "desc": "surface exchange coeff heat & moisture for NoahMP"}, \ + {"name": "fwetxy", "type":wp, "dimd": ('t0'), "units": "none", "desc": "area fraction of canopy that is wetted/snowed for NoahMP"}, \ + {"name": "sneqvoxy", "type":wp, "dimd": ('t0'), "units": "mm", "desc": "snow mass at previous time step for NoahMP"}, \ + {"name": "alboldxy", "type":wp, "dimd": ('t0'), "units": "none", "desc": "snow albedo at previous time step for NoahMP"}, \ + {"name": "qsnowxy", "type":wp, "dimd": ('t0'), "units": "mm s-1", "desc": "snow precipitation rate at surface for NoahMP"}, \ + {"name": "wslakexy", "type":wp, "dimd": ('t0'), "units": "mm", "desc": "lake water storage for NoahMP"}, \ + {"name": "taussxy", "type":wp, "dimd": ('t0'), "units": "none", "desc": "non-dimensional snow age for NoahMP"}, \ + {"name": "waxy", "type":wp, "dimd": ('t0'), "units": "mm", "desc": "water storage in aquifer for NoahMP"}, \ + {"name": "wtxy", "type":wp, "dimd": ('t0'), "units": "mm", "desc": "water storage in aquifer and saturated soil for NoahMP"}, \ + {"name": "zwtxy", "type":wp, "dimd": ('t0'), "units": "m", "desc": "water table depth for NoahMP"}, \ + {"name": "xlaixy", "type":wp, "dimd": ('t0'), "units": "none", "desc": "leaf area index for NoahMP"}, \ + {"name": "xsaixy", "type":wp, "dimd": ('t0'), "units": "none", "desc": "stem area index for NoahMP"}, \ + {"name": "lfmassxy", "type":wp, "dimd": ('t0'), "units": "g m-2", "desc": "leaf mass for NoahMP"}, \ + {"name": "stmassxy", "type":wp, "dimd": ('t0'), "units": "g m-2", "desc": "stem mass for NoahMP"}, \ + {"name": "rtmassxy", "type":wp, "dimd": ('t0'), "units": "g m-2", "desc": "fine root mass for NoahMP"}, \ + {"name": "woodxy", "type":wp, "dimd": ('t0'), "units": "g m-2", "desc": "wood mass including woody roots for NoahMP"}, \ + {"name": "stblcpxy", "type":wp, "dimd": ('t0'), "units": "g m-2", "desc": "stable carbon in deep soil for NoahMP"}, \ + {"name": "fastcpxy", "type":wp, "dimd": ('t0'), "units": "g m-2", "desc": "short-lived carbon in shallow soil for NoahMP"}, \ + {"name": "smcwtdxy", "type":wp, "dimd": ('t0'), "units": "m3 m-3", "desc": "soil water content between the bottom of the soil and the water table for NoahMP"}, \ + {"name": "deeprechxy", "type":wp, "dimd": ('t0'), "units": "m", "desc": "recharge to or from the water table when deep for NoahMP"}, \ + {"name": "rechxy", "type":wp, "dimd": ('t0'), "units": "m", "desc": "recharge to or from the water table when shallow for NoahMP"}, \ + {"name": "snowxy", "type":wp, "dimd": ('t0'), "units": "none", "desc": "number of snow layers for NoahMP"}, \ + {"name": "snicexy", "type":wp, "dimd": ('t0','nsnow'), "units": "mm", "desc": "initial profile of snow layer ice"}, \ + {"name": "snliqxy", "type":wp, "dimd": ('t0','nsnow'), "units": "mm", "desc": "initial profile of snow layer liquid"}, \ + {"name": "tsnoxy", "type":wp, "dimd": ('t0','nsnow'), "units": "K", "desc": "initial profile of snow layer temperature"}, \ + {"name": "smoiseq", "type":wp, "dimd": ('t0','nsoil'), "units": "m3 m-3", "desc": "initial profile of equilibrium soil water content"}, \ + {"name": "zsnsoxy", "type":wp, "dimd": ('t0','nsoil_plus_nsnow'), "units": "m","desc": "layer bottom depth from snow surface"}] + # + var_ruc = [{"name": "wetness", "type":wp, "dimd": ('t0'), "units": "none", "desc": "normalized soil wetness for RUC LSM"}, \ + {"name": "lai", "type":wp, "dimd": ('t0'), "units": "none", "desc": "leaf area index for RUC LSM"}, \ + {"name": "clw_surf_land", "type":wp, "dimd": ('t0'), "units": "kg kg-1", "desc": "cloud condensed water mixing ratio at surface over land for RUC LSM"},\ + {"name": "clw_surf_ice", "type":wp, "dimd": ('t0'), "units": "kg kg-1", "desc": "cloud condensed water mixing ratio at surface over ice for RUC LSM"},\ + {"name": "qwv_surf_land", "type":wp, "dimd": ('t0'), "units": "kg kg-1", "desc": "water vapor mixing ratio at surface over land for RUC LSM"},\ + {"name": "qwv_surf_ice", "type":wp, "dimd": ('t0'), "units": "kg kg-1", "desc": "water vapor mixing ratio at surface over ice for RUC LSM"},\ + {"name": "tsnow_land", "type":wp, "dimd": ('t0'), "units": "K", "desc": "snow temperature at the bottom of the first snow layer over land for RUC LSM"},\ + {"name": "tsnow_ice", "type":wp, "dimd": ('t0'), "units": "K", "desc": "snow temperature at the bottom of the first snow layer over ice for RUC LSM"},\ + {"name": "snowfall_acc_land","type":wp, "dimd": ('t0'), "units": "kg m-2", "desc": "run-total snow accumulation on the ground over land for RUC LSM"},\ + {"name": "snowfall_acc_ice", "type":wp, "dimd": ('t0'), "units": "kg m-2", "desc": "run-total snow accumulation on the ground over ice for RUC LSM"},\ + {"name": "sfalb_lnd", "type":wp, "dimd": ('t0'), "units": "none", "desc": "surface albedo over land for RUC LSM"},\ + {"name": "sfalb_lnd_bck", "type":wp, "dimd": ('t0'), "units": "none", "desc": "surface snow-free albedo over land for RUC LSM"},\ + {"name": "sfalb_ice", "type":wp, "dimd": ('t0'), "units": "none", "desc": "surface albedo over ice for RUC LSM"},\ + {"name": "emis_lnd", "type":wp, "dimd": ('t0'), "units": "none", "desc": "surface emissivity over land for RUC LSM"},\ + {"name": "emis_ice", "type":wp, "dimd": ('t0'), "units": "none", "desc": "surface emissivity over ice for RUC LSM"}, \ + {"name": "tslb", "type":wp, "dimd": ('t0','nsoil'), "units": "K", "desc": "soil temperature for RUC LSM"}, \ + {"name": "smois", "type":wp, "dimd": ('t0','nsoil'), "units": "none", "desc": "volume fraction of soil moisture for RUC LSM"}, \ + {"name": "sh2o", "type":wp, "dimd": ('t0','nsoil'), "units": "none", "desc": "volume fraction of unfrozen soil moisture for RUC LSM"}, \ + {"name": "smfr", "type":wp, "dimd": ('t0','nsoil'), "units": "none", "desc": "volume fraction of frozen soil moisture for RUC LSM"}, + {"name": "flfr", "type":wp, "dimd": ('t0','nsoil'), "units": "none", "desc": "flag for frozen soil physics for RUC LSM"}] + + # + var_dict.extend(var_frc) + var_dict.extend(var_oro) + var_dict.extend(var_nsst) + var_dict.extend(var_frgd) + var_dict.extend(var_ruc) + var_dict.extend(var_noah) + var_dict.extend(var_noahmp) + + # + for var in var_dict: + if (var["name"] in dict): + var_temp = nc_file.createVariable(var["name"], var["type"], var["dimd"]) + var_temp.units = var["units"] + var_temp.standard_name = var["desc"] + var_temp[:] = dict[var["name"]] + elif "default_value" in var: + var_temp = nc_file.createVariable(var["name"], var["type"], var["dimd"]) + var_temp.units = var["units"] + var_temp.standard_name = var["desc"] + var_temp[:] = var["default_value"] + if "override" in var: + var_temp[:] = var["default_value"] + # + # Close file + # + nc_file.close() + + return(fileOUT) + +######################################################################################## +# +######################################################################################## +def main(): + setup_logging() + + #read in arguments + (case_name, use_area) = parse_arguments() + + (case_nml, error) = get_case_nml(case_name) + if (error): + message = 'The directory {0} does not contain a config file for case {1}'.format(CASE_NML_DIR, case_name) + logging.critical(message) + raise Exception(message) + else: + logging.info(case_nml) + + (case_data, error) = get_case_data(case_name) + if (error): + message = 'The directory {0} does not contain a data file for case {1}'.format(PROCESSED_CASE_DIR, case_name) + logging.critical(message) + raise Exception(message) + else: + logging.debug(case_data) + + fileOUT = write_SCM_case_file(case_nml, case_data, use_area) + logging.debug("Created {}".format(fileOUT)) + + write_SCM_nml_file(case_nml) + #logging.debug("Created {}".format(nmlOUT)) + +if __name__ == '__main__': + main() From 19aea49617b13c27c74dfe5504b4e0f640c11928 Mon Sep 17 00:00:00 2001 From: Grant Firl Date: Thu, 18 Jul 2024 16:46:17 -0400 Subject: [PATCH 05/40] working version (at least for bomex) --- scm/etc/scripts/dephy_converter.py | 78 ++++++++++++++++++++++++------ scm/src/run_scm.py | 2 +- scm/src/scm_forcing.F90 | 2 +- scm/src/scm_input.F90 | 18 +++---- 4 files changed, 75 insertions(+), 25 deletions(-) diff --git a/scm/etc/scripts/dephy_converter.py b/scm/etc/scripts/dephy_converter.py index 63595540c..fb32c2aa6 100755 --- a/scm/etc/scripts/dephy_converter.py +++ b/scm/etc/scripts/dephy_converter.py @@ -258,7 +258,7 @@ def write_SCM_case_file(case_nml, case_data, use_area): com = 'mkdir -p ' + PROCESSED_CASE_DIR logging.info(com) os.system(com) - fileOUT = os.path.join(PROCESSED_CASE_DIR, case_nml['case_config']['case_name'] + '_SCM_driver.nc') + fileOUT = os.path.join(PROCESSED_CASE_DIR, case_nml['case_config']['case_name'] + '_dephy' + '_SCM_driver.nc') nc_file = Dataset(fileOUT, 'w', format='NETCDF3_CLASSIC') nc_file.description = "Case data for {} from CCPP SCM".format(case_nml['case_config']['case_name']) @@ -469,14 +469,6 @@ def write_SCM_case_file(case_nml, case_data, use_area): #logging.critical(message) #raise Exception(message) - if (case_nml['case_config']['sfc_flux_spec']): - nc_file.surface_forcing_temp = 'kinematic' - nc_file.surface_forcing_moisture = 'kinematic' - nc_file.surface_forcing_wind = 'z0' - else: - nc_file.surface_forcing_temp = 'ts' - nc_file.surface_forcing_wind = 'z0' - time_dim = nc_file.createDimension('time', case_data._time.shape[0]) timei_dim = nc_file.createDimension('t0', 1) lev_dim = nc_file.createDimension('lev', case_data._levels.shape[0]) @@ -577,6 +569,21 @@ def write_SCM_case_file(case_nml, case_data, use_area): ozone_var.standard_name = 'mole_fraction_of_ozone_in_air' ozone_var[:] = case_data._ozone[:] + ps_forc_var = nc_file.createVariable('ps_forc', wp, ('time')) + ps_forc_var.units = 'Pa' + ps_forc_var.standard_name = 'forcing_surface_air_pressure' + ps_forc_var[:] = case_data._p_surf[:] + + pa_forc_var = nc_file.createVariable('pa_forc', wp, ('time','lev')) + pa_forc_var.units = 'Pa' + pa_forc_var.standard_name = 'air_pressure_forcing' + pa_forc_var[:] = case_data._levels[:] + + zh_forc_var = nc_file.createVariable('zh_forc', wp, ('time','lev')) + zh_forc_var.units = 'm' + zh_forc_var.standard_name = 'height_forcing' + zh_forc_var[:] = case_data._height[:] + if (nc_file.adv_ta == forcing_on): message = 'adv_ta is turned on, but is not implemented in the proprietery CCPP SCM case format and cannot be used.' logging.critical() @@ -674,30 +681,73 @@ def write_SCM_case_file(case_nml, case_data, use_area): vg_var.standard_name = 'geostrophic_northward_wind' vg_var[:] = np.swapaxes(case_data._v_g[:],0,1) - if (nc_file.nudging_ua == forcing_on): + if (nc_file.nudging_ua != forcing_off): ua_nud_var = nc_file.createVariable('ua_nud', wp, ('time','lev')) ua_nud_var.units = 'm s-1' ua_nud_var.standard_name = 'nudging_eastward_wind' ua_nud_var[:] = np.swapaxes(case_data._u_nudge[:],0,1) - if (nc_file.nudging_va == forcing_on): + if (nc_file.nudging_va != forcing_off): va_nud_var = nc_file.createVariable('va_nud', wp, ('time','lev')) va_nud_var.units = 'm s-1' va_nud_var.standard_name = 'nudging_northward_wind' va_nud_var[:] = np.swapaxes(case_data._v_nudge[:],0,1) - if (nc_file.nudging_ta == forcing_on): + if (nc_file.nudging_ta != forcing_off): ta_nud_var = nc_file.createVariable('ta_nud', wp, ('time','lev')) ta_nud_var.units = 'K' ta_nud_var.standard_name = 'nudging_air_temperature' ta_nud_var[:] = np.swapaxes(case_data._T_nudge[:],0,1) - if (nc_file.nudging_qt == forcing_on): + if (nc_file.nudging_qt != forcing_off): qt_nud_var = nc_file.createVariable('qt_nud', wp, ('time','lev')) qt_nud_var.units = 'kg kg-1' qt_nud_var.standard_name = 'nudging_mass_fraction_of_water_in_air' qt_nud_var[:] = np.swapaxes(case_data._qt_nudge[:],0,1) + if (case_nml['case_config']['sfc_flux_spec']): + nc_file.surface_forcing_temp = 'kinematic' + nc_file.surface_forcing_moisture = 'kinematic' + nc_file.surface_forcing_wind = 'z0' + + wpthetap_s_var = nc_file.createVariable('wpthetap_s', wp, ('time')) + wpthetap_s_var.units = 'K m s-1' + wpthetap_s_var.standard_name = 'surface_upward_potential_temperature_flux' + wpthetap_s_var[:] = case_data._sh_flux_sfc[:] + + wpqtp_s_var = nc_file.createVariable('wpqvp_s', wp, ('time')) + wpqtp_s_var.units = 'kg kg-1 m s-1' + wpqtp_s_var.standard_name = 'surface_upward_specific_humidity_flux' + wpqtp_s_var[:] = case_data._lh_flux_sfc[:] + + z0_var = nc_file.createVariable('z0', wp, ('time')) + z0_var.units = 'm' + z0_var.standard_name = 'surface_roughness_length_for_momentum_in_air' + z0_var[:] = case_nml['case_config']['sfc_roughness_length_cm']*1.0E-2 + + + ts_var = nc_file.createVariable('ts_forc', wp, ('time')) + ts_var.units = 'K' + ts_var.standard_name = 'forcing_surface_temperature' + if np.any(case_data._T_surf[:]): + ts_var[:] = case_data._T_surf[:] + else: + ts_var[:] = case_data._missing_value + + else: + nc_file.surface_forcing_temp = 'ts' + nc_file.surface_forcing_wind = 'z0' + + z0_var = nc_file.createVariable('z0', wp, ('time')) + z0_var.units = 'm' + z0_var.standard_name = 'surface_roughness_length_for_momentum_in_air' + z0_var[:] = case_nml['case_config']['sfc_roughness_length_cm']*1.0E-2 + + ts_var = nc_file.createVariable('ts_forc', wp, ('time')) + ts_var.units = 'K' + ts_var.standard_name = 'forcing_surface_temperature' + ts_var[:] = case_data._T_surf[:] + nc_file.close() return(fileOUT) @@ -760,7 +810,7 @@ def write_SCM_nml_file(case_nml): nml = f90nml.namelist.Namelist(nml_dict) #print(nml) - nml.write(filename) + nml.write(filename, force=True) return(filename) diff --git a/scm/src/run_scm.py b/scm/src/run_scm.py index b499fafac..6c2cb20d8 100755 --- a/scm/src/run_scm.py +++ b/scm/src/run_scm.py @@ -498,7 +498,7 @@ def setup_rundir(self): nc_fid = Dataset(os.path.join(SCM_ROOT, self._case_data_dir) + '/' + self._case + '_SCM_driver.nc' , 'r') surfaceForcing = nc_fid.getncattr('surface_forcing_temp') nc_fid.close() - if (surfaceForcing.lower() == 'flux' or surfaceForcing.lower() == 'surface_flux'): + if (surfaceForcing.lower() == 'kinematic' or surfaceForcing.lower() == 'surface_flux'): surface_flux_spec = True except KeyError: # if not using DEPHY format, check to see if surface fluxes are specified in the case configuration file (default is False) diff --git a/scm/src/scm_forcing.F90 b/scm/src/scm_forcing.F90 index ad7a47b4f..2d4258ab6 100644 --- a/scm/src/scm_forcing.F90 +++ b/scm/src/scm_forcing.F90 @@ -155,7 +155,7 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) scm_input%input_omega(scm_input%input_ntimes,:), scm_state%pres_l(i,:), scm_state%n_levels, & omega_bracket(1,:), top_index, 3) if (top_index < scm_state%n_levels .and. top_index > 0) then - w_ls_bracket(1,top_index+1:scm_state%n_levels) = 0.0!w_ls_bracket(1,top_index) + omega_bracket(1,top_index+1:scm_state%n_levels) = 0.0!w_ls_bracket(1,top_index) end if scm_state%omega(i,:) = omega_bracket(1,:) end do diff --git a/scm/src/scm_input.F90 b/scm/src/scm_input.F90 index cc3effcd5..73f277717 100644 --- a/scm/src/scm_input.F90 +++ b/scm/src/scm_input.F90 @@ -2399,7 +2399,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) end if end do else - scm_input%input_k_T_nudge = 1 + scm_input%input_k_T_nudge(:) = 1 end if else if (nudging_theta > 0) then !assume no cloud water since there is no associate [ql,qi]_nudge in the input? @@ -2425,7 +2425,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) end if end do else - scm_input%input_k_thil_nudge = 1 + scm_input%input_k_thil_nudge(:) = 1 end if else if (nudging_thetal > 0) then !assume no cloud water since there is no associate [ql,qi]_nudge in the input? @@ -2451,7 +2451,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) end if end do else - scm_input%input_k_thil_nudge = 1 + scm_input%input_k_thil_nudge(:) = 1 end if end if @@ -2478,7 +2478,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) end if end do else - scm_input%input_k_qt_nudge = 1 + scm_input%input_k_qt_nudge(:) = 1 end if else if (nudging_qt > 0) then do i=1, input_n_forcing_times @@ -2503,7 +2503,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) end if end do else - scm_input%input_k_qt_nudge = 1 + scm_input%input_k_qt_nudge(:) = 1 end if else if (nudging_rv > 0) then do i=1, input_n_forcing_times @@ -2531,7 +2531,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) end if end do else - scm_input%input_k_qt_nudge = 1 + scm_input%input_k_qt_nudge(:) = 1 end if else if (nudging_rt > 0) then do i=1, input_n_forcing_times @@ -2559,7 +2559,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) end if end do else - scm_input%input_k_qt_nudge = 1 + scm_input%input_k_qt_nudge(:) = 1 end if end if @@ -2586,7 +2586,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) end if end do else - scm_input%input_k_u_nudge = 1 + scm_input%input_k_u_nudge(:) = 1 end if end if @@ -2613,7 +2613,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) end if end do else - scm_input%input_k_v_nudge = 1 + scm_input%input_k_v_nudge(:) = 1 end if end if From b25af2145b879866570791bbc27b8d4c88d793a5 Mon Sep 17 00:00:00 2001 From: Grant Firl Date: Fri, 19 Jul 2024 14:18:04 -0400 Subject: [PATCH 06/40] only add vertical advective forcing if forc_w or forc_wap are not on --- scm/etc/scripts/dephy_converter.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/scm/etc/scripts/dephy_converter.py b/scm/etc/scripts/dephy_converter.py index fb32c2aa6..b559824fd 100755 --- a/scm/etc/scripts/dephy_converter.py +++ b/scm/etc/scripts/dephy_converter.py @@ -633,13 +633,19 @@ def write_SCM_case_file(case_nml, case_data, use_area): tnthetal_adv_var = nc_file.createVariable('tnthetal_adv', wp, ('time','lev')) tnthetal_adv_var.units = 'K s-1' tnthetal_adv_var.standard_name = 'tendency_of_air_liquid_potential_temperature_due_to_advection' - tnthetal_adv_var[:] = np.swapaxes(case_data._h_advec_thil[:] + case_data._v_advec_thil[:],0,1) + if (nc_file.forc_wap == forcing_on or nc_file.forc_wa == forcing_on): + tnthetal_adv_var[:] = np.swapaxes(case_data._h_advec_thil[:],0,1) + else: + tnthetal_adv_var[:] = np.swapaxes(case_data._h_advec_thil[:] + case_data._v_advec_thil[:],0,1) if (nc_file.adv_qt == forcing_on): tnqt_adv_var = nc_file.createVariable('tnqt_adv', wp, ('time','lev')) tnqt_adv_var.units = 'kg kg-1 s-1' tnqt_adv_var.standard_name = 'tendency_of_mass_fraction_of_water_in_air_due_to_advection' - tnqt_adv_var[:] = np.swapaxes(case_data._h_advec_qt[:] + case_data._v_advec_qt[:],0,1) + if (nc_file.forc_wap == forcing_on or nc_file.forc_wa == forcing_on): + tnqt_adv_var[:] = np.swapaxes(case_data._h_advec_qt[:],0,1) + else: + tnqt_adv_var[:] = np.swapaxes(case_data._h_advec_qt[:] + case_data._v_advec_qt[:],0,1) if (nc_file.adv_rv == forcing_on): message = 'adv_rv is turned on, but is not implemented in the proprietery CCPP SCM case format and cannot be used.' From cc937f5dadb7d6d7c5312cdb0959f03c7597e761 Mon Sep 17 00:00:00 2001 From: Grant Firl Date: Wed, 24 Jul 2024 16:44:41 -0400 Subject: [PATCH 07/40] add surface variables and updated case_config namelists --- scm/etc/case_config/LASSO_2016051812.nml | 23 +- scm/etc/case_config/LASSO_2016051812_MSDA.nml | 23 +- scm/etc/case_config/LASSO_2016051812_VARA.nml | 23 +- scm/etc/case_config/LASSO_20180514_s02.nml | 23 +- scm/etc/case_config/LASSO_20180522_s02.nml | 23 +- scm/etc/case_config/LASSO_20180606_s02.nml | 23 +- scm/etc/case_config/LASSO_20180618_s02.nml | 23 +- scm/etc/case_config/LASSO_20180619_s02.nml | 23 +- scm/etc/case_config/LASSO_20180705_s02.nml | 23 +- scm/etc/case_config/LASSO_20180707_s02.nml | 23 +- scm/etc/case_config/LASSO_20180709_s02.nml | 23 +- scm/etc/case_config/LASSO_20180712_s02.nml | 23 +- scm/etc/case_config/LASSO_20180731_s02.nml | 23 +- scm/etc/case_config/LASSO_20180911_s02.nml | 23 +- scm/etc/case_config/LASSO_20180914_s02.nml | 23 +- scm/etc/case_config/LASSO_20180916_s02.nml | 23 +- scm/etc/case_config/LASSO_20180917_s02.nml | 23 +- scm/etc/case_config/LASSO_20180918_s02.nml | 23 +- scm/etc/case_config/LASSO_20181002_s02.nml | 23 +- scm/etc/case_config/arm_sgp_summer_1997_A.nml | 23 +- scm/etc/case_config/arm_sgp_summer_1997_B.nml | 23 +- scm/etc/case_config/arm_sgp_summer_1997_C.nml | 23 +- scm/etc/case_config/arm_sgp_summer_1997_R.nml | 23 +- scm/etc/case_config/arm_sgp_summer_1997_S.nml | 23 +- scm/etc/case_config/arm_sgp_summer_1997_T.nml | 23 +- scm/etc/case_config/arm_sgp_summer_1997_U.nml | 23 +- scm/etc/case_config/arm_sgp_summer_1997_X.nml | 23 +- scm/etc/case_config/astex.nml | 23 +- scm/etc/case_config/bomex.nml | 23 +- scm/etc/case_config/gabls3.nml | 29 +- scm/etc/case_config/gabls3_noahmp.nml | 29 +- scm/etc/case_config/gabls3_ruc.nml | 29 +- scm/etc/case_config/twpice.nml | 23 +- scm/etc/scripts/dephy_converter.py | 2231 +++++++++++++---- scm/src/scm_input.F90 | 308 +-- 35 files changed, 2156 insertions(+), 1160 deletions(-) diff --git a/scm/etc/case_config/LASSO_2016051812.nml b/scm/etc/case_config/LASSO_2016051812.nml index 75eff16b8..31df86d63 100644 --- a/scm/etc/case_config/LASSO_2016051812.nml +++ b/scm/etc/case_config/LASSO_2016051812.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'LASSO_2016051812', -runtime = 54000, -thermo_forcing_type = 2, -mom_forcing_type = 3, -relax_time = 7200.0, -sfc_flux_spec = .true., -sfc_roughness_length_cm = 10.0 -sfc_type = 1, -reference_profile_choice = 2, -year = 2016, -month = 5, -day = 18, -hour = 12, -column_area = 2.0E9, -$end +&case_config + case_name = 'LASSO_2016051812' + column_area = 2000000000.0 + input_type = 1 + reference_profile_choice = 2 + sfc_roughness_length_cm = 10.0 +/ diff --git a/scm/etc/case_config/LASSO_2016051812_MSDA.nml b/scm/etc/case_config/LASSO_2016051812_MSDA.nml index 900c70b9e..ec6edbf08 100644 --- a/scm/etc/case_config/LASSO_2016051812_MSDA.nml +++ b/scm/etc/case_config/LASSO_2016051812_MSDA.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'LASSO_2016051812_MSDA', -runtime = 54000, -thermo_forcing_type = 2, -mom_forcing_type = 3, -relax_time = 7200.0, -sfc_flux_spec = .true., -sfc_roughness_length_cm = 10.0 -sfc_type = 1, -reference_profile_choice = 2, -year = 2016, -month = 5, -day = 18, -hour = 12, -column_area = 2.0E9, -$end +&case_config + case_name = 'LASSO_2016051812_MSDA' + column_area = 2000000000.0 + input_type = 1 + reference_profile_choice = 2 + sfc_roughness_length_cm = 10.0 +/ diff --git a/scm/etc/case_config/LASSO_2016051812_VARA.nml b/scm/etc/case_config/LASSO_2016051812_VARA.nml index 2f0374372..139278616 100644 --- a/scm/etc/case_config/LASSO_2016051812_VARA.nml +++ b/scm/etc/case_config/LASSO_2016051812_VARA.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'LASSO_2016051812_VARA', -runtime = 54000, -thermo_forcing_type = 2, -mom_forcing_type = 3, -relax_time = 7200.0, -sfc_flux_spec = .true., -sfc_roughness_length_cm = 10.0 -sfc_type = 1, -reference_profile_choice = 2, -year = 2016, -month = 5, -day = 18, -hour = 12, -column_area = 2.0E9, -$end +&case_config + case_name = 'LASSO_2016051812_VARA' + column_area = 2000000000.0 + input_type = 1 + reference_profile_choice = 2 + sfc_roughness_length_cm = 10.0 +/ diff --git a/scm/etc/case_config/LASSO_20180514_s02.nml b/scm/etc/case_config/LASSO_20180514_s02.nml index 432c77ed1..61f9a7f3e 100644 --- a/scm/etc/case_config/LASSO_20180514_s02.nml +++ b/scm/etc/case_config/LASSO_20180514_s02.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'LASSO_20180514_s02', -runtime = 54000, -thermo_forcing_type = 2, -mom_forcing_type = 3, -relax_time = 7200.0, -sfc_flux_spec = .true., -sfc_roughness_length_cm = 10.0 -sfc_type = 1, -reference_profile_choice = 2, -year = 2018, -month = 5, -day = 14, -hour = 12, -column_area = 2.0E9, -$end +&case_config + case_name = 'LASSO_20180514_s02' + column_area = 2000000000.0 + input_type = 1 + reference_profile_choice = 2 + sfc_roughness_length_cm = 10.0 +/ diff --git a/scm/etc/case_config/LASSO_20180522_s02.nml b/scm/etc/case_config/LASSO_20180522_s02.nml index 4f69ef9b1..2a561bbb4 100644 --- a/scm/etc/case_config/LASSO_20180522_s02.nml +++ b/scm/etc/case_config/LASSO_20180522_s02.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'LASSO_20180522_s02', -runtime = 54000, -thermo_forcing_type = 2, -mom_forcing_type = 3, -relax_time = 7200.0, -sfc_flux_spec = .true., -sfc_roughness_length_cm = 10.0 -sfc_type = 1, -reference_profile_choice = 2, -year = 2018, -month = 5, -day = 22, -hour = 12, -column_area = 2.0E9, -$end +&case_config + case_name = 'LASSO_20180522_s02' + column_area = 2000000000.0 + input_type = 1 + reference_profile_choice = 2 + sfc_roughness_length_cm = 10.0 +/ diff --git a/scm/etc/case_config/LASSO_20180606_s02.nml b/scm/etc/case_config/LASSO_20180606_s02.nml index feeadc334..2e8a13eb4 100644 --- a/scm/etc/case_config/LASSO_20180606_s02.nml +++ b/scm/etc/case_config/LASSO_20180606_s02.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'LASSO_20180606_s02', -runtime = 54000, -thermo_forcing_type = 2, -mom_forcing_type = 3, -relax_time = 7200.0, -sfc_flux_spec = .true., -sfc_roughness_length_cm = 10.0 -sfc_type = 1, -reference_profile_choice = 2, -year = 2018, -month = 6, -day = 06, -hour = 12, -column_area = 2.0E9, -$end +&case_config + case_name = 'LASSO_20180606_s02' + column_area = 2000000000.0 + input_type = 1 + reference_profile_choice = 2 + sfc_roughness_length_cm = 10.0 +/ diff --git a/scm/etc/case_config/LASSO_20180618_s02.nml b/scm/etc/case_config/LASSO_20180618_s02.nml index a5b261a3c..1a609b659 100644 --- a/scm/etc/case_config/LASSO_20180618_s02.nml +++ b/scm/etc/case_config/LASSO_20180618_s02.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'LASSO_20180618_s02', -runtime = 54000, -thermo_forcing_type = 2, -mom_forcing_type = 3, -relax_time = 7200.0, -sfc_flux_spec = .true., -sfc_roughness_length_cm = 10.0 -sfc_type = 1, -reference_profile_choice = 2, -year = 2018, -month = 6, -day = 18, -hour = 12, -column_area = 2.0E9, -$end +&case_config + case_name = 'LASSO_20180618_s02' + column_area = 2000000000.0 + input_type = 1 + reference_profile_choice = 2 + sfc_roughness_length_cm = 10.0 +/ diff --git a/scm/etc/case_config/LASSO_20180619_s02.nml b/scm/etc/case_config/LASSO_20180619_s02.nml index e32bc294d..33c6c1981 100644 --- a/scm/etc/case_config/LASSO_20180619_s02.nml +++ b/scm/etc/case_config/LASSO_20180619_s02.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'LASSO_20180619_s02', -runtime = 54000, -thermo_forcing_type = 2, -mom_forcing_type = 3, -relax_time = 7200.0, -sfc_flux_spec = .true., -sfc_roughness_length_cm = 10.0 -sfc_type = 1, -reference_profile_choice = 2, -year = 2018, -month = 6, -day = 19, -hour = 12, -column_area = 2.0E9, -$end +&case_config + case_name = 'LASSO_20180619_s02' + column_area = 2000000000.0 + input_type = 1 + reference_profile_choice = 2 + sfc_roughness_length_cm = 10.0 +/ diff --git a/scm/etc/case_config/LASSO_20180705_s02.nml b/scm/etc/case_config/LASSO_20180705_s02.nml index 5648360e8..fac051533 100644 --- a/scm/etc/case_config/LASSO_20180705_s02.nml +++ b/scm/etc/case_config/LASSO_20180705_s02.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'LASSO_20180705_s02', -runtime = 54000, -thermo_forcing_type = 2, -mom_forcing_type = 3, -relax_time = 7200.0, -sfc_flux_spec = .true., -sfc_roughness_length_cm = 10.0 -sfc_type = 1, -reference_profile_choice = 2, -year = 2018, -month = 7, -day = 05, -hour = 12, -column_area = 2.0E9, -$end +&case_config + case_name = 'LASSO_20180705_s02' + column_area = 2000000000.0 + input_type = 1 + reference_profile_choice = 2 + sfc_roughness_length_cm = 10.0 +/ diff --git a/scm/etc/case_config/LASSO_20180707_s02.nml b/scm/etc/case_config/LASSO_20180707_s02.nml index af73e1d62..2df38195d 100644 --- a/scm/etc/case_config/LASSO_20180707_s02.nml +++ b/scm/etc/case_config/LASSO_20180707_s02.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'LASSO_20180707_s02', -runtime = 54000, -thermo_forcing_type = 2, -mom_forcing_type = 3, -relax_time = 7200.0, -sfc_flux_spec = .true., -sfc_roughness_length_cm = 10.0 -sfc_type = 1, -reference_profile_choice = 2, -year = 2018, -month = 7, -day = 07, -hour = 12, -column_area = 2.0E9, -$end +&case_config + case_name = 'LASSO_20180707_s02' + column_area = 2000000000.0 + input_type = 1 + reference_profile_choice = 2 + sfc_roughness_length_cm = 10.0 +/ diff --git a/scm/etc/case_config/LASSO_20180709_s02.nml b/scm/etc/case_config/LASSO_20180709_s02.nml index ac68594cd..5fd786d63 100644 --- a/scm/etc/case_config/LASSO_20180709_s02.nml +++ b/scm/etc/case_config/LASSO_20180709_s02.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'LASSO_20180709_s02', -runtime = 54000, -thermo_forcing_type = 2, -mom_forcing_type = 3, -relax_time = 7200.0, -sfc_flux_spec = .true., -sfc_roughness_length_cm = 10.0 -sfc_type = 1, -reference_profile_choice = 2, -year = 2018, -month = 7, -day = 09, -hour = 12, -column_area = 2.0E9, -$end +&case_config + case_name = 'LASSO_20180709_s02' + column_area = 2000000000.0 + input_type = 1 + reference_profile_choice = 2 + sfc_roughness_length_cm = 10.0 +/ diff --git a/scm/etc/case_config/LASSO_20180712_s02.nml b/scm/etc/case_config/LASSO_20180712_s02.nml index 6917a1851..7aa611c0a 100644 --- a/scm/etc/case_config/LASSO_20180712_s02.nml +++ b/scm/etc/case_config/LASSO_20180712_s02.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'LASSO_20180712_s02', -runtime = 54000, -thermo_forcing_type = 2, -mom_forcing_type = 3, -relax_time = 7200.0, -sfc_flux_spec = .true., -sfc_roughness_length_cm = 10.0 -sfc_type = 1, -reference_profile_choice = 2, -year = 2018, -month = 7, -day = 12, -hour = 12, -column_area = 2.0E9, -$end +&case_config + case_name = 'LASSO_20180712_s02' + column_area = 2000000000.0 + input_type = 1 + reference_profile_choice = 2 + sfc_roughness_length_cm = 10.0 +/ diff --git a/scm/etc/case_config/LASSO_20180731_s02.nml b/scm/etc/case_config/LASSO_20180731_s02.nml index 6ac93bbad..654037d69 100644 --- a/scm/etc/case_config/LASSO_20180731_s02.nml +++ b/scm/etc/case_config/LASSO_20180731_s02.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'LASSO_20180731_s02', -runtime = 54000, -thermo_forcing_type = 2, -mom_forcing_type = 3, -relax_time = 7200.0, -sfc_flux_spec = .true., -sfc_roughness_length_cm = 10.0 -sfc_type = 1, -reference_profile_choice = 2, -year = 2018, -month = 7, -day = 31, -hour = 12, -column_area = 2.0E9, -$end +&case_config + case_name = 'LASSO_20180731_s02' + column_area = 2000000000.0 + input_type = 1 + reference_profile_choice = 2 + sfc_roughness_length_cm = 10.0 +/ diff --git a/scm/etc/case_config/LASSO_20180911_s02.nml b/scm/etc/case_config/LASSO_20180911_s02.nml index e4fc92955..68e9fcb43 100644 --- a/scm/etc/case_config/LASSO_20180911_s02.nml +++ b/scm/etc/case_config/LASSO_20180911_s02.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'LASSO_20180911_s02', -runtime = 54000, -thermo_forcing_type = 2, -mom_forcing_type = 3, -relax_time = 7200.0, -sfc_flux_spec = .true., -sfc_roughness_length_cm = 10.0 -sfc_type = 1, -reference_profile_choice = 2, -year = 2018, -month = 9, -day = 11, -hour = 12, -column_area = 2.0E9, -$end +&case_config + case_name = 'LASSO_20180911_s02' + column_area = 2000000000.0 + input_type = 1 + reference_profile_choice = 2 + sfc_roughness_length_cm = 10.0 +/ diff --git a/scm/etc/case_config/LASSO_20180914_s02.nml b/scm/etc/case_config/LASSO_20180914_s02.nml index 66d28362d..6a6c834c6 100644 --- a/scm/etc/case_config/LASSO_20180914_s02.nml +++ b/scm/etc/case_config/LASSO_20180914_s02.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'LASSO_20180914_s02', -runtime = 54000, -thermo_forcing_type = 2, -mom_forcing_type = 3, -relax_time = 7200.0, -sfc_flux_spec = .true., -sfc_roughness_length_cm = 10.0 -sfc_type = 1, -reference_profile_choice = 2, -year = 2018, -month = 9, -day = 14, -hour = 12, -column_area = 2.0E9, -$end +&case_config + case_name = 'LASSO_20180914_s02' + column_area = 2000000000.0 + input_type = 1 + reference_profile_choice = 2 + sfc_roughness_length_cm = 10.0 +/ diff --git a/scm/etc/case_config/LASSO_20180916_s02.nml b/scm/etc/case_config/LASSO_20180916_s02.nml index 6197652b8..3e486717f 100644 --- a/scm/etc/case_config/LASSO_20180916_s02.nml +++ b/scm/etc/case_config/LASSO_20180916_s02.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'LASSO_20180916_s02', -runtime = 54000, -thermo_forcing_type = 2, -mom_forcing_type = 3, -relax_time = 7200.0, -sfc_flux_spec = .true., -sfc_roughness_length_cm = 10.0 -sfc_type = 1, -reference_profile_choice = 2, -year = 2018, -month = 9, -day = 16, -hour = 12, -column_area = 2.0E9, -$end +&case_config + case_name = 'LASSO_20180916_s02' + column_area = 2000000000.0 + input_type = 1 + reference_profile_choice = 2 + sfc_roughness_length_cm = 10.0 +/ diff --git a/scm/etc/case_config/LASSO_20180917_s02.nml b/scm/etc/case_config/LASSO_20180917_s02.nml index 896a32225..0ff786d1b 100644 --- a/scm/etc/case_config/LASSO_20180917_s02.nml +++ b/scm/etc/case_config/LASSO_20180917_s02.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'LASSO_20180917_s02', -runtime = 54000, -thermo_forcing_type = 2, -mom_forcing_type = 3, -relax_time = 7200.0, -sfc_flux_spec = .true., -sfc_roughness_length_cm = 10.0 -sfc_type = 1, -reference_profile_choice = 2, -year = 2018, -month = 9, -day = 17, -hour = 12, -column_area = 2.0E9, -$end +&case_config + case_name = 'LASSO_20180917_s02' + column_area = 2000000000.0 + input_type = 1 + reference_profile_choice = 2 + sfc_roughness_length_cm = 10.0 +/ diff --git a/scm/etc/case_config/LASSO_20180918_s02.nml b/scm/etc/case_config/LASSO_20180918_s02.nml index 09deb06aa..383cad945 100644 --- a/scm/etc/case_config/LASSO_20180918_s02.nml +++ b/scm/etc/case_config/LASSO_20180918_s02.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'LASSO_20180918_s02', -runtime = 54000, -thermo_forcing_type = 2, -mom_forcing_type = 3, -relax_time = 7200.0, -sfc_flux_spec = .true., -sfc_roughness_length_cm = 10.0 -sfc_type = 1, -reference_profile_choice = 2, -year = 2018, -month = 9, -day = 18, -hour = 12, -column_area = 2.0E9, -$end +&case_config + case_name = 'LASSO_20180918_s02' + column_area = 2000000000.0 + input_type = 1 + reference_profile_choice = 2 + sfc_roughness_length_cm = 10.0 +/ diff --git a/scm/etc/case_config/LASSO_20181002_s02.nml b/scm/etc/case_config/LASSO_20181002_s02.nml index b63d206de..9a10ff357 100644 --- a/scm/etc/case_config/LASSO_20181002_s02.nml +++ b/scm/etc/case_config/LASSO_20181002_s02.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'LASSO_20181002_s02', -runtime = 54000, -thermo_forcing_type = 2, -mom_forcing_type = 3, -relax_time = 7200.0, -sfc_flux_spec = .true., -sfc_roughness_length_cm = 10.0 -sfc_type = 1, -reference_profile_choice = 2, -year = 2018, -month = 10, -day = 02, -hour = 12, -column_area = 2.0E9, -$end +&case_config + case_name = 'LASSO_20181002_s02' + column_area = 2000000000.0 + input_type = 1 + reference_profile_choice = 2 + sfc_roughness_length_cm = 10.0 +/ diff --git a/scm/etc/case_config/arm_sgp_summer_1997_A.nml b/scm/etc/case_config/arm_sgp_summer_1997_A.nml index 375d0c4cb..912c3ba2f 100644 --- a/scm/etc/case_config/arm_sgp_summer_1997_A.nml +++ b/scm/etc/case_config/arm_sgp_summer_1997_A.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'arm_sgp_summer_1997_A', -runtime = 345600, -thermo_forcing_type = 1, -mom_forcing_type = 3, -relax_time = 7200.0, -sfc_flux_spec = .true., -sfc_roughness_length_cm = 10.0 -sfc_type = 1, -reference_profile_choice = 2, -year = 1997, -month = 6, -day = 26, -hour = 23, -column_area = 2.0E9, -$end +&case_config + case_name = 'arm_sgp_summer_1997_A' + column_area = 2000000000.0 + input_type = 1 + reference_profile_choice = 2 + sfc_roughness_length_cm = 10.0 +/ diff --git a/scm/etc/case_config/arm_sgp_summer_1997_B.nml b/scm/etc/case_config/arm_sgp_summer_1997_B.nml index 0ac151cc4..f72393b48 100644 --- a/scm/etc/case_config/arm_sgp_summer_1997_B.nml +++ b/scm/etc/case_config/arm_sgp_summer_1997_B.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'arm_sgp_summer_1997_B', -runtime = 432000, -thermo_forcing_type = 1, -mom_forcing_type = 3, -relax_time = 7200.0, -sfc_flux_spec = .true., -sfc_roughness_length_cm = 10.0 -sfc_type = 1, -reference_profile_choice = 2, -year = 1997, -month = 7, -day = 7, -hour = 23, -column_area = 2.0E9, -$end +&case_config + case_name = 'arm_sgp_summer_1997_B' + column_area = 2000000000.0 + input_type = 1 + reference_profile_choice = 2 + sfc_roughness_length_cm = 10.0 +/ diff --git a/scm/etc/case_config/arm_sgp_summer_1997_C.nml b/scm/etc/case_config/arm_sgp_summer_1997_C.nml index ace0b4dd2..4ed84bab0 100644 --- a/scm/etc/case_config/arm_sgp_summer_1997_C.nml +++ b/scm/etc/case_config/arm_sgp_summer_1997_C.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'arm_sgp_summer_1997_C', -runtime = 432000, -thermo_forcing_type = 1, -mom_forcing_type = 3, -relax_time = 7200.0, -sfc_flux_spec = .true., -sfc_roughness_length_cm = 10.0 -sfc_type = 1, -reference_profile_choice = 2, -year = 1997, -month = 7, -day = 12, -hour = 23, -column_area = 2.0E9, -$end +&case_config + case_name = 'arm_sgp_summer_1997_C' + column_area = 2000000000.0 + input_type = 1 + reference_profile_choice = 2 + sfc_roughness_length_cm = 10.0 +/ diff --git a/scm/etc/case_config/arm_sgp_summer_1997_R.nml b/scm/etc/case_config/arm_sgp_summer_1997_R.nml index c3da579ce..79632258b 100644 --- a/scm/etc/case_config/arm_sgp_summer_1997_R.nml +++ b/scm/etc/case_config/arm_sgp_summer_1997_R.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'arm_sgp_summer_1997_R', -runtime = 345600, -thermo_forcing_type = 1, -mom_forcing_type = 3, -relax_time = 7200.0, -sfc_flux_spec = .true., -sfc_roughness_length_cm = 10.0 -sfc_type = 1, -reference_profile_choice = 2, -year = 1997, -month = 6, -day = 18, -hour = 23, -column_area = 2.0E9, -$end +&case_config + case_name = 'arm_sgp_summer_1997_R' + column_area = 2000000000.0 + input_type = 1 + reference_profile_choice = 2 + sfc_roughness_length_cm = 10.0 +/ diff --git a/scm/etc/case_config/arm_sgp_summer_1997_S.nml b/scm/etc/case_config/arm_sgp_summer_1997_S.nml index ba26818be..25f21da4c 100644 --- a/scm/etc/case_config/arm_sgp_summer_1997_S.nml +++ b/scm/etc/case_config/arm_sgp_summer_1997_S.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'arm_sgp_summer_1997_S', -runtime = 345600, -thermo_forcing_type = 1, -mom_forcing_type = 3, -relax_time = 7200.0, -sfc_flux_spec = .true., -sfc_roughness_length_cm = 10.0 -sfc_type = 1, -reference_profile_choice = 2, -year = 1997, -month = 6, -day = 22, -hour = 23, -column_area = 2.0E9, -$end +&case_config + case_name = 'arm_sgp_summer_1997_S' + column_area = 2000000000.0 + input_type = 1 + reference_profile_choice = 2 + sfc_roughness_length_cm = 10.0 +/ diff --git a/scm/etc/case_config/arm_sgp_summer_1997_T.nml b/scm/etc/case_config/arm_sgp_summer_1997_T.nml index d68aaa82a..6b5cc9f3f 100644 --- a/scm/etc/case_config/arm_sgp_summer_1997_T.nml +++ b/scm/etc/case_config/arm_sgp_summer_1997_T.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'arm_sgp_summer_1997_T', -runtime = 259200, -thermo_forcing_type = 1, -mom_forcing_type = 3, -relax_time = 7200.0, -sfc_flux_spec = .true., -sfc_roughness_length_cm = 10.0 -sfc_type = 1, -reference_profile_choice = 2, -year = 1997, -month = 6, -day = 30, -hour = 23, -column_area = 2.0E9, -$end +&case_config + case_name = 'arm_sgp_summer_1997_T' + column_area = 2000000000.0 + input_type = 1 + reference_profile_choice = 2 + sfc_roughness_length_cm = 10.0 +/ diff --git a/scm/etc/case_config/arm_sgp_summer_1997_U.nml b/scm/etc/case_config/arm_sgp_summer_1997_U.nml index 2d599f4f8..1abc438f5 100644 --- a/scm/etc/case_config/arm_sgp_summer_1997_U.nml +++ b/scm/etc/case_config/arm_sgp_summer_1997_U.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'arm_sgp_summer_1997_U', -runtime = 345600, -thermo_forcing_type = 1, -mom_forcing_type = 3, -relax_time = 7200.0, -sfc_flux_spec = .true., -sfc_roughness_length_cm = 10.0 -sfc_type = 1, -reference_profile_choice = 2, -year = 1997, -month = 7, -day = 4, -hour = 23, -column_area = 2.0E9, -$end +&case_config + case_name = 'arm_sgp_summer_1997_U' + column_area = 2000000000.0 + input_type = 1 + reference_profile_choice = 2 + sfc_roughness_length_cm = 10.0 +/ diff --git a/scm/etc/case_config/arm_sgp_summer_1997_X.nml b/scm/etc/case_config/arm_sgp_summer_1997_X.nml index cc90d4b91..b207a781f 100644 --- a/scm/etc/case_config/arm_sgp_summer_1997_X.nml +++ b/scm/etc/case_config/arm_sgp_summer_1997_X.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'arm_sgp_summer_1997_X', -runtime = 2505600, -thermo_forcing_type = 1, -mom_forcing_type = 3, -relax_time = 7200.0, -sfc_flux_spec = .true., -sfc_roughness_length_cm = 10.0 -sfc_type = 1, -reference_profile_choice = 2, -year = 1997, -month = 6, -day = 18, -hour = 23, -column_area = 2.0E9, -$end +&case_config + case_name = 'arm_sgp_summer_1997_X' + column_area = 2000000000.0 + input_type = 1 + reference_profile_choice = 2 + sfc_roughness_length_cm = 10.0 +/ diff --git a/scm/etc/case_config/astex.nml b/scm/etc/case_config/astex.nml index 3a9e99a3b..1cfb03bfb 100644 --- a/scm/etc/case_config/astex.nml +++ b/scm/etc/case_config/astex.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'astex', -runtime = 144000, -thermo_forcing_type = 2, -mom_forcing_type = 2, -relax_time = 7200.0, -sfc_flux_spec = .false., -sfc_type = 0, -sfc_roughness_length_cm = 0.02, -reference_profile_choice = 1, -year = 1992, -month = 6, -day = 13, -hour = 0, -column_area = 3.7E5, -$end +&case_config + case_name = 'astex' + column_area = 370000.0 + input_type = 1 + reference_profile_choice = 1 + sfc_roughness_length_cm = 0.02 +/ diff --git a/scm/etc/case_config/bomex.nml b/scm/etc/case_config/bomex.nml index 093c31353..e6f68378a 100644 --- a/scm/etc/case_config/bomex.nml +++ b/scm/etc/case_config/bomex.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'bomex', -runtime = 21600, -thermo_forcing_type = 2, -mom_forcing_type = 3, -relax_time = 7200.0, -sfc_flux_spec = .true., -sfc_roughness_length_cm = 0.012, -sfc_type = 0, -reference_profile_choice = 1, -year = 1969, -month = 6, -day = 22, -hour = 13, -column_area = 2.0E9, -$end +&case_config + case_name = 'bomex' + column_area = 2000000000.0 + input_type = 1 + reference_profile_choice = 1 + sfc_roughness_length_cm = 0.012 +/ diff --git a/scm/etc/case_config/gabls3.nml b/scm/etc/case_config/gabls3.nml index 727b9eced..0e48db674 100644 --- a/scm/etc/case_config/gabls3.nml +++ b/scm/etc/case_config/gabls3.nml @@ -1,19 +1,10 @@ -$case_config -case_name = 'gabls3', -runtime = 86400, -thermo_forcing_type = 2, -mom_forcing_type = 2, -relax_time = 7200.0, -sfc_flux_spec = .false., -lsm_ics = .true., -do_spinup = .true., -spinup_timesteps = 12, -sfc_roughness_length_cm = 15.0, -sfc_type = 1, -reference_profile_choice = 2, -year = 2006, -month = 7, -day = 1, -hour = 12, -column_area = 1.45E8, -$end +&case_config + case_name = 'gabls3' + column_area = 145000000.0 + do_spinup = .true. + input_type = 1 + lsm_ics = .true. + reference_profile_choice = 2 + sfc_roughness_length_cm = 15.0 + spinup_timesteps = 12 +/ diff --git a/scm/etc/case_config/gabls3_noahmp.nml b/scm/etc/case_config/gabls3_noahmp.nml index 5775d65f5..4b7267352 100644 --- a/scm/etc/case_config/gabls3_noahmp.nml +++ b/scm/etc/case_config/gabls3_noahmp.nml @@ -1,19 +1,10 @@ -$case_config -case_name = 'gabls3_noahmp', -runtime = 86400, -thermo_forcing_type = 2, -mom_forcing_type = 2, -relax_time = 7200.0, -sfc_flux_spec = .false., -lsm_ics = .true., -do_spinup = .true., -spinup_timesteps = 12, -sfc_roughness_length_cm = 15.0, -sfc_type = 1, -reference_profile_choice = 2, -year = 2006, -month = 7, -day = 1, -hour = 12, -column_area = 1.45E8, -$end +&case_config + case_name = 'gabls3_noahmp' + column_area = 145000000.0 + do_spinup = .true. + input_type = 1 + lsm_ics = .true. + reference_profile_choice = 2 + sfc_roughness_length_cm = 15.0 + spinup_timesteps = 12 +/ diff --git a/scm/etc/case_config/gabls3_ruc.nml b/scm/etc/case_config/gabls3_ruc.nml index a13a4dcf0..4a1ff01da 100644 --- a/scm/etc/case_config/gabls3_ruc.nml +++ b/scm/etc/case_config/gabls3_ruc.nml @@ -1,19 +1,10 @@ -$case_config -case_name = 'gabls3_ruc', -runtime = 86400, -thermo_forcing_type = 2, -mom_forcing_type = 2, -relax_time = 7200.0, -sfc_flux_spec = .false., -lsm_ics = .true., -do_spinup = .true., -spinup_timesteps = 12, -sfc_roughness_length_cm = 15.0, -sfc_type = 1, -reference_profile_choice = 2, -year = 2006, -month = 7, -day = 1, -hour = 12, -column_area = 1.45E8, -$end +&case_config + case_name = 'gabls3_ruc' + column_area = 145000000.0 + do_spinup = .true. + input_type = 1 + lsm_ics = .true. + reference_profile_choice = 2 + sfc_roughness_length_cm = 15.0 + spinup_timesteps = 12 +/ diff --git a/scm/etc/case_config/twpice.nml b/scm/etc/case_config/twpice.nml index 23a5ceea0..bd3374c36 100644 --- a/scm/etc/case_config/twpice.nml +++ b/scm/etc/case_config/twpice.nml @@ -1,16 +1,7 @@ -$case_config -case_name = 'twpice', -runtime = 2138400, -thermo_forcing_type = 2, -mom_forcing_type = 3, -relax_time = 7200.0, -sfc_flux_spec = .false., -sfc_type = 0, -sfc_roughness_length_cm = 0.02, -reference_profile_choice = 1, -year = 2006, -month = 1, -day = 19, -hour = 3, -column_area = 2.0E9, -$end +&case_config + case_name = 'twpice' + column_area = 2000000000.0 + input_type = 1 + reference_profile_choice = 1 + sfc_roughness_length_cm = 0.02 +/ diff --git a/scm/etc/scripts/dephy_converter.py b/scm/etc/scripts/dephy_converter.py index b559824fd..42b745d00 100755 --- a/scm/etc/scripts/dephy_converter.py +++ b/scm/etc/scripts/dephy_converter.py @@ -55,17 +55,159 @@ def setup_logging(): logging.basicConfig(format='%(levelname)s: %(message)s', level=LOGLEVEL) class Case_Data(object): - def __init__(self, name, missing_value, time, levels, lat, lon, height, theta_il, qt, ql, qi, u, v, tke, ozone, \ + def __init__(self, name, missing_value, time, levels, soil_depth, lat, lon, slmsk, vegsrc, vegtyp, soiltyp, \ + scolor, slopetyp, tsfco, vegfrac, shdmin, shdmax, canopy, hice, fice, tisfc, snowd, snoalb, tg3, \ + uustar, alvsf, alnsf, alvwf, alnwf, facsf, facwf, weasd, f10m, t2m, q2m, ffmm, ffhh, \ + tprcp, srflag, sncovr, tsfcl, zorl, zorll, zorli, zorlw, zorlwav, tvxy, tgxy, tahxy, canicexy, canliqxy, eahxy, \ + cmxy, chxy, fwetxy, sneqvoxy, alboldxy, qsnowxy, wslakexy, taussxy, waxy, wtxy, zwtxy, xlaixy, xsaixy, \ + lfmassxy, stmassxy, rtmassxy, woodxy, stblcpxy, fastcpxy, smcwtdxy, deeprechxy, rechxy, snowxy, \ + wetness, clw_surf_land, clw_surf_ice, qwv_surf_land, qwv_surf_ice, tsnow_land, tsnow_ice, \ + snowfallac_land, snowfallac_ice, sncovr_ice, sfalb_lnd, sfalb_lnd_bck, emis_ice, lai, area, \ + stddev, convexity, oa1, oa2, oa3, oa4, ol1, ol2, ol3, ol4, theta_oro, gamma, sigma, elvmax, \ + oro, oro_uf, landfrac, lakefrac, lakedepth, tref, z_c, c_0, c_d, w_0, w_d, xt, xs, xu, xv, xz, zm, \ + xtts, xzts, d_conv, ifd, dt_cool, qrain, height, theta_il, t,\ + qt, ql, qi, u, v, tke, ozone, stc, smc, slc, snicexy, snliqxy, tsnoxy, smoiseq, zsnsoxy, tiice, \ + tslb, smois, sh2o, smfr, flfr, \ p_surf, T_surf, w_ls, omega, u_g, v_g, u_nudge, v_nudge, T_nudge, thil_nudge, qt_nudge, \ dT_dt_rad, h_advec_thil, v_advec_thil, h_advec_qt, v_advec_qt, sh_flux_sfc, lh_flux_sfc): self._name = name self._missing_value = missing_value + #dimensions self._time = time self._levels = levels + self._soil_depth = soil_depth + #scalars self._lat = lat self._lon = lon + #NOAH LSM scalars + self._slmsk = slmsk + self._vegsrc = vegsrc + self._vegtyp = vegtyp + self._soiltyp = soiltyp + self._scolor = scolor + self._slopetyp = slopetyp + self._tsfco = tsfco + self._vegfrac = vegfrac + self._shdmin = shdmin + self._shdmax = shdmax + self._canopy = canopy + self._hice = hice + self._fice = fice + self._tisfc = tisfc + self._snowd = snowd + self._snoalb = snoalb + self._tg3 = tg3 + self._uustar = uustar + self._alvsf = alvsf + self._alnsf = alnsf + self._alvwf = alvwf + self._alnwf = alnwf + self._facsf = facsf + self._facwf = facwf + self._weasd = weasd + self._f10m = f10m + self._t2m = t2m + self._q2m = q2m + self._ffmm = ffmm + self._ffhh = ffhh + self._tprcp = tprcp + self._srflag = srflag + self._sncovr = sncovr + self._tsfcl = tsfcl + self._zorl = zorl + self._zorll = zorll + self._zorli = zorli + self._zorlw = zorlw + self._zorlwav = zorlwav + self._area = area + #NOAHMP scalars + self._tvxy = tvxy + self._tgxy = tgxy + self._tahxy = tahxy + self._canicexy = canicexy + self._canliqxy = canliqxy + self._eahxy = eahxy + self._cmxy = cmxy + self._chxy = chxy + self._fwetxy = fwetxy + self._sneqvoxy = sneqvoxy + self._alboldxy = alboldxy + self._qsnowxy = qsnowxy + self._wslakexy = wslakexy + self._taussxy = taussxy + self._waxy = waxy + self._wtxy = wtxy + self._zwtxy = zwtxy + self._xlaixy = xlaixy + self._xsaixy = xsaixy + self._lfmassxy = lfmassxy + self._stmassxy = stmassxy + self._rtmassxy = rtmassxy + self._woodxy = woodxy + self._stblcpxy = stblcpxy + self._fastcpxy = fastcpxy + self._smcwtdxy = smcwtdxy + self._deeprechxy = deeprechxy + self._rechxy = rechxy + self._snowxy = snowxy + #RUC LSM scalars + self._wetness = wetness + self._clw_surf_land = clw_surf_land + self._clw_surf_ice = clw_surf_ice + self._qwv_surf_land = qwv_surf_land + self._qwv_surf_ice = qwv_surf_ice + self._tsnow_land = tsnow_land + self._tsnow_ice = tsnow_ice + self._snowfallac_land = snowfallac_land + self._snowfallac_ice = snowfallac_ice + self._sncovr_ice = sncovr_ice + self._sfalb_lnd = sfalb_lnd + self._sfalb_lnd_bck = sfalb_lnd_bck + self._emis_ice = emis_ice + self._lai = lai + #orographic variables + self._stddev = stddev + self._convexity = convexity + self._oa1 = oa1 + self._oa2 = oa2 + self._oa3 = oa3 + self._oa4 = oa4 + self._ol1 = ol1 + self._ol2 = ol2 + self._ol3 = ol3 + self._ol4 = ol4 + self._theta_oro = theta_oro + self._gamma = gamma + self._sigma = sigma + self._elvmax = elvmax + self._oro = oro + self._oro_uf = oro_uf + self._landfrac = landfrac + self._lakefrac = lakefrac + self._lakedepth = lakedepth + #NSST vars + self._tref = tref + self._z_c = z_c + self._c_0 = c_0 + self._c_d = c_d + self._w_0 = w_0 + self._w_d = w_d + self._xt = xt + self._xs = xs + self._xu = xu + self._xv = xv + self._xz = xz + self._zm = zm + self._xtts = xtts + self._xzts = xzts + self._d_conv = d_conv + self._ifd = ifd + self._dt_cool = dt_cool + self._qrain = qrain + #initial conditions (profiles for t0) self._height = height self._theta_il = theta_il + self._t = t self._qt = qt self._ql = ql self._qi = qi @@ -73,8 +215,24 @@ def __init__(self, name, missing_value, time, levels, lat, lon, height, theta_il self._v = v self._tke = tke self._ozone = ozone + self._stc = stc + self._smc = smc + self._slc = slc + self._snicexy = snicexy + self._snliqxy = snliqxy + self._tsnoxy = tsnoxy + self._smoiseq = smoiseq + self._zsnsoxy = zsnsoxy + self._tiice = tiice + self._tslb = tslb + self._smois = smois + self._sh2o = sh2o + self._smfr = smfr + self._flfr = flfr + #time series self._p_surf = p_surf self._T_surf = T_surf + #2D forcing vars (vert, time) self._w_ls = w_ls self._omega = omega self._u_g = u_g @@ -99,12 +257,134 @@ def __repr__(self): " Dimensions: \n" \ " time:% s \n" \ " levels: % s \n" \ + " soil_depth: % s \n" \ " Scalars: \n" \ " lat: % s \n" \ " lon: % s \n" \ + " area: % s \n" \ + " slmsk: % s \n" \ + " vegsrc: % s \n" \ + " vegtyp: % s \n" \ + " soiltyp: % s \n" \ + " scolor: % s \n" \ + " slopetyp: % s \n" \ + " tsfco: % s \n" \ + " vegfrac: % s \n" \ + " shdmin: % s \n" \ + " shdmax: % s \n" \ + " canopy: % s \n" \ + " hice: % s \n" \ + " fice: % s \n" \ + " tisfc: % s \n" \ + " snowd: % s \n" \ + " snoalb: % s \n" \ + " tg3: % s \n" \ + " uustar: % s \n" \ + " alvsf: % s \n" \ + " alnsf: % s \n" \ + " alvwf: % s \n" \ + " alnwf: % s \n" \ + " facsf: % s \n" \ + " facwf: % s \n" \ + " weasd: % s \n" \ + " f10m: % s \n" \ + " t2m: % s \n" \ + " q2m: % s \n" \ + " ffmm: % s \n" \ + " ffhh: % s \n" \ + " tprcp: % s \n" \ + " srflag: % s \n" \ + " sncovr: % s \n" \ + " tsfcl: % s \n" \ + " zorl: % s \n" \ + " zorll: % s \n" \ + " zorli: % s \n" \ + " zorlw: % s \n" \ + " zorlwav: % s \n" \ + " tvxy: % s \n" \ + " tgxy: % s \n" \ + " tahxy: % s \n" \ + " canicexy: % s \n" \ + " canliqxy: % s \n" \ + " eahxy: % s \n" \ + " cmxy: % s \n" \ + " chxy: % s \n" \ + " fwetxy: % s \n" \ + " sneqvoxy: % s \n" \ + " alboldxy: % s \n" \ + " qsnowxy: % s \n" \ + " wslakexy: % s \n" \ + " taussxy: % s \n" \ + " waxy: % s \n" \ + " wtxy: % s \n" \ + " zwtxy: % s \n" \ + " xlaixy: % s \n" \ + " xsaixy: % s \n" \ + " lfmassxy: % s \n" \ + " stmassxy: % s \n" \ + " rtmassxy: % s \n" \ + " woodxy: % s \n" \ + " stblcpxy: % s \n" \ + " fastcpxy: % s \n" \ + " smcwtdxy: % s \n" \ + " deeprechxy: % s \n" \ + " rechxy: % s \n" \ + " snowxy: % s \n" \ + " wetness: % s \n" \ + " clw_surf_land: % s \n" \ + " clw_surf_ice: % s \n" \ + " qwv_surf_land: % s \n" \ + " qwv_surf_ice: % s \n" \ + " tsnow_land: % s \n" \ + " tsnow_ice: % s \n" \ + " snowfallac_land: % s \n" \ + " snowfallac_ice: % s \n" \ + " sncovr_ice: % s \n" \ + " sfalb_lnd: % s \n" \ + " sfalb_lnd_bck: % s \n" \ + " emis_ice: % s \n" \ + " lai: % s \n" \ + " stddev: % s \n" \ + " convexity: % s \n" \ + " oa1: % s \n" \ + " oa2: % s \n" \ + " oa3: % s \n" \ + " oa4: % s \n" \ + " ol1: % s \n" \ + " ol2: % s \n" \ + " ol3: % s \n" \ + " ol4: % s \n" \ + " theta_oro: % s \n" \ + " gamma: % s \n" \ + " sigma: % s \n" \ + " elvmax: % s \n" \ + " oro: % s \n" \ + " oro_uf: % s \n" \ + " landfrac: % s \n" \ + " lakefrac: % s \n" \ + " lakedepth: % s \n" \ + " tref: % s \n" \ + " z_c: % s \n" \ + " c_0: % s \n" \ + " c_d: % s \n" \ + " w_0: % s \n" \ + " w_d: % s \n" \ + " xt: % s \n" \ + " xs: % s \n" \ + " xu: % s \n" \ + " xv: % s \n" \ + " xz: % s \n" \ + " zm: % s \n" \ + " xtts: % s \n" \ + " xzts: % s \n" \ + " d_conv: % s \n" \ + " ifd: % s \n" \ + " dt_cool: % s \n" \ + " qrain: % s \n" \ " Initial: \n" \ " height: % s \n" \ " theta_il: % s \n" \ + " t: % s \n" \ " qt: % s \n" \ " ql: % s \n" \ " qi: % s \n" \ @@ -112,6 +392,20 @@ def __repr__(self): " v: % s \n" \ " tke: %s \n" \ " ozone: %s \n" \ + " stc: %s \n" \ + " smc: %s \n" \ + " slc: %s \n" \ + " snicexy: % s \n" \ + " snliqxy: % s \n" \ + " tsnoxy: % s \n" \ + " smoiseq: % s \n" \ + " zsnsoxy: % s \n" \ + " tiice: % s \n" \ + " tslb: % s \n" \ + " smois: % s \n" \ + " sh2o: % s \n" \ + " smfr: % s \n" \ + " flfr: % s \n" \ " Forcing: \n" \ " p_surf: %s \n" \ " T_surf: %s \n" \ @@ -132,9 +426,27 @@ def __repr__(self): " sh_flux_sfc: %s \n" \ " lh_flux_sfc: %s \n" \ % (self._name, self._missing_value, self._time, self._levels, - self._lat, self._lon, self._height, self._theta_il, + self._soil_depth, self._lat, self._lon, self._area, self._slmsk, self._vegsrc, + self._vegtyp, self._soiltyp, self._scolor, + self._slopetyp, self._tsfco, self._vegfrac, self._shdmin, + self._shdmax, self._canopy, self._hice, self._fice, self._tisfc, self._snowd, self._snoalb, + self._tg3, self._uustar, self._alvsf, self._alnsf, self._alvwf, self._alnwf, self._facsf, self._facwf, + self._weasd, self._f10m, self._t2m, self._q2m, self._ffmm, self._ffhh, + self._tprcp, self._srflag, self._sncovr, self._tsfcl, self._zorl, self._zorll, self._zorli, self._zorlw, self._zorlwav, + self._tvxy, self._tgxy, self._tahxy, self._canicexy, self._canliqxy, self._eahxy, + self._cmxy, self._chxy, self._fwetxy, self._sneqvoxy, self._alboldxy, self._qsnowxy, self._wslakexy, self._taussxy, + self._waxy, self._wtxy, self._zwtxy, self._xlaixy, self._xsaixy, self._lfmassxy, self._stmassxy, self._rtmassxy, + self._woodxy, self._stblcpxy, self._fastcpxy, self._smcwtdxy, self._deeprechxy, self._rechxy, self._snowxy, + self._wetness, self._clw_surf_land, self._clw_surf_ice, self._qwv_surf_land, self._qwv_surf_ice, self._tsnow_land, self._tsnow_ice, + self._snowfallac_land, self._snowfallac_ice, self._sncovr_ice, self._sfalb_lnd, self._sfalb_lnd_bck, self._emis_ice, self._lai, + self._stddev, self._convexity, self._oa1, self._oa2, self._oa3, self._oa4, self._ol1, self._ol2, self._ol3, self._ol4, + self._theta_oro, self._gamma, self._sigma, self._elvmax, self._oro, self._oro_uf, self._landfrac, self._lakefrac, self._lakedepth, + self._tref, self._z_c, self._c_0, self._c_d, self._w_0, self._w_d, self._xt, self._xs, self._xu, self._xv, self._xz, self._zm, + self._xtts, self._xzts, self._d_conv, self._ifd, self._dt_cool, self._qrain, + self._height, self._theta_il, self._t, self._qt, self._ql, self._qi, self._u, self._v, - self._tke, self._ozone, + self._tke, self._ozone, self._stc, self._smc, self._slc, self._snicexy, self._snliqxy, self._tsnoxy, + self._smoiseq, self._zsnsoxy, self._tiice, self._tslb, self._smois, self._sh2o, self._smfr, self._flfr, self._p_surf, self._T_surf, np.mean(self._w_ls, axis=1), np.mean(self._omega, axis=1), np.mean(self._u_g, axis=1), np.mean(self._v_g, axis=1), np.mean(self._u_nudge, axis=1), @@ -183,16 +495,513 @@ def get_case_data(case_name): time = nc_fid.variables['time'][:] levels = nc_fid.variables['levels'][:] + try: + soil_depth = nc_fid.variables['soil_depth'][:] + except KeyError: + soil_depth = [missing_value] #read variables from scalar group scalars_grp = nc_fid.groups['scalars'] lat = scalars_grp.variables['lat'][:] lon = scalars_grp.variables['lon'][:] - + try: + slmsk = scalars_grp.variables['slmsk'][:] + except KeyError: + slmsk = missing_value + try: + vegsrc = scalars_grp.variables['vegsrc'][:] + except KeyError: + vegsrc = missing_value + try: + vegtyp = scalars_grp.variables['vegtyp'][:] + except KeyError: + vegtyp = missing_value + try: + soiltyp = scalars_grp.variables['soiltyp'][:] + except KeyError: + soiltyp = missing_value + try: + scolor = scalars_grp.variables['scolor'][:] + except KeyError: + scolor = missing_value + try: + slopetyp = scalars_grp.variables['slopetyp'][:] + except KeyError: + slopetyp = missing_value + try: + tsfco = scalars_grp.variables['tsfco'][:] + except KeyError: + tsfco = missing_value + try: + vegfrac = scalars_grp.variables['vegfrac'][:] + except KeyError: + vegfrac = missing_value + try: + shdmin = scalars_grp.variables['shdmin'][:] + except KeyError: + shdmin = missing_value + try: + shdmax = scalars_grp.variables['shdmax'][:] + except KeyError: + shdmax = missing_value + try: + canopy = scalars_grp.variables['canopy'][:] + except KeyError: + canopy = missing_value + try: + hice = scalars_grp.variables['hice'][:] + except KeyError: + hice = missing_value + try: + fice = scalars_grp.variables['fice'][:] + except KeyError: + fice = missing_value + try: + tisfc = scalars_grp.variables['tisfc'][:] + except KeyError: + tisfc = missing_value + try: + snowd = scalars_grp.variables['snowd'][:] + except KeyError: + try: + snowd = scalars_grp.variables['snwdph'][:] + except KeyError: + snowd = missing_value + try: + snoalb = scalars_grp.variables['snoalb'][:] + except KeyError: + snoalb = missing_value + try: + tg3 = scalars_grp.variables['tg3'][:] + except KeyError: + tg3 = missing_value + try: + uustar = scalars_grp.variables['uustar'][:] + except KeyError: + uustar = missing_value + try: + alvsf = scalars_grp.variables['alvsf'][:] + except KeyError: + alvsf = missing_value + try: + alnsf = scalars_grp.variables['alnsf'][:] + except KeyError: + alnsf = missing_value + try: + alvwf = scalars_grp.variables['alvwf'][:] + except KeyError: + alvwf = missing_value + try: + alnwf = scalars_grp.variables['alnwf'][:] + except KeyError: + alnwf = missing_value + try: + facsf = scalars_grp.variables['facsf'][:] + except KeyError: + facsf = missing_value + try: + facwf = scalars_grp.variables['facwf'][:] + except KeyError: + facwf = missing_value + try: + weasd = scalars_grp.variables['weasd'][:] + except KeyError: + weasd = missing_value + try: + f10m = scalars_grp.variables['f10m'][:] + except KeyError: + f10m = missing_value + try: + t2m = scalars_grp.variables['t2m'][:] + except KeyError: + t2m = missing_value + try: + q2m = scalars_grp.variables['q2m'][:] + except KeyError: + q2m = missing_value + try: + ffmm = scalars_grp.variables['ffmm'][:] + except KeyError: + ffmm = missing_value + try: + ffhh = scalars_grp.variables['ffhh'][:] + except KeyError: + ffhh = missing_value + try: + tprcp = scalars_grp.variables['tprcp'][:] + except KeyError: + tprcp = missing_value + try: + srflag = scalars_grp.variables['srflag'][:] + except KeyError: + srflag = missing_value + try: + sncovr = scalars_grp.variables['sncovr'][:] + except KeyError: + sncovr = missing_value + try: + tsfcl = scalars_grp.variables['tsfcl'][:] + except KeyError: + tsfcl = missing_value + try: + zorl = scalars_grp.variables['zorl'][:] + except KeyError: + zorl = missing_value + try: + zorll = scalars_grp.variables['zorll'][:] + except KeyError: + zorll = missing_value + try: + zorli = scalars_grp.variables['zorli'][:] + except KeyError: + zorli = missing_value + try: + zorlw = scalars_grp.variables['zorlw'][:] + except KeyError: + zorlw = missing_value + try: + zorlwav = scalars_grp.variables['zorlwav'][:] + except KeyError: + zorlwav = missing_value + try: + tvxy = scalars_grp.variables['tvxy'][:] + except KeyError: + tvxy = missing_value + try: + tgxy = scalars_grp.variables['tgxy'][:] + except KeyError: + tgxy = missing_value + try: + tahxy = scalars_grp.variables['tahxy'][:] + except KeyError: + tahxy = missing_value + try: + canicexy = scalars_grp.variables['canicexy'][:] + except KeyError: + canicexy = missing_value + try: + canliqxy = scalars_grp.variables['canliqxy'][:] + except KeyError: + canliqxy = missing_value + try: + eahxy = scalars_grp.variables['eahxy'][:] + except KeyError: + eahxy = missing_value + try: + cmxy = scalars_grp.variables['cmxy'][:] + except KeyError: + cmxy = missing_value + try: + chxy = scalars_grp.variables['chxy'][:] + except KeyError: + chxy = missing_value + try: + fwetxy = scalars_grp.variables['fwetxy'][:] + except KeyError: + fwetxy = missing_value + try: + sneqvoxy = scalars_grp.variables['sneqvoxy'][:] + except KeyError: + sneqvoxy = missing_value + try: + alboldxy = scalars_grp.variables['alboldxy'][:] + except KeyError: + alboldxy = missing_value + try: + qsnowxy = scalars_grp.variables['qsnowxy'][:] + except KeyError: + qsnowxy = missing_value + try: + wslakexy = scalars_grp.variables['wslakexy'][:] + except KeyError: + wslakexy = missing_value + try: + taussxy = scalars_grp.variables['taussxy'][:] + except KeyError: + taussxy = missing_value + try: + waxy = scalars_grp.variables['waxy'][:] + except KeyError: + waxy = missing_value + try: + wtxy = scalars_grp.variables['wtxy'][:] + except KeyError: + wtxy = missing_value + try: + zwtxy = scalars_grp.variables['zwtxy'][:] + except KeyError: + zwtxy = missing_value + try: + xlaixy = scalars_grp.variables['xlaixy'][:] + except KeyError: + xlaixy = missing_value + try: + xsaixy = scalars_grp.variables['xsaixy'][:] + except KeyError: + xsaixy = missing_value + try: + lfmassxy = scalars_grp.variables['lfmassxy'][:] + except KeyError: + lfmassxy = missing_value + try: + stmassxy = scalars_grp.variables['stmassxy'][:] + except KeyError: + stmassxy = missing_value + try: + rtmassxy = scalars_grp.variables['rtmassxy'][:] + except KeyError: + rtmassxy = missing_value + try: + woodxy = scalars_grp.variables['woodxy'][:] + except KeyError: + woodxy = missing_value + try: + stblcpxy = scalars_grp.variables['stblcpxy'][:] + except KeyError: + stblcpxy = missing_value + try: + fastcpxy = scalars_grp.variables['fastcpxy'][:] + except KeyError: + fastcpxy = missing_value + try: + smcwtdxy = scalars_grp.variables['smcwtdxy'][:] + except KeyError: + smcwtdxy = missing_value + try: + deeprechxy = scalars_grp.variables['deeprechxy'][:] + except KeyError: + deeprechxy = missing_value + try: + rechxy = scalars_grp.variables['rechxy'][:] + except KeyError: + rechxy = missing_value + try: + snowxy = scalars_grp.variables['snowxy'][:] + except KeyError: + snowxy = missing_value + try: + wetness = scalars_grp.variables['wetness'][:] + except KeyError: + wetness = missing_value + try: + clw_surf_land = scalars_grp.variables['clw_surf_land'][:] + except KeyError: + clw_surf_land = missing_value + try: + clw_surf_ice = scalars_grp.variables['clw_surf_ice'][:] + except KeyError: + clw_surf_ice = missing_value + try: + qwv_surf_land = scalars_grp.variables['qwv_surf_land'][:] + except KeyError: + qwv_surf_land = missing_value + try: + qwv_surf_ice = scalars_grp.variables['qwv_surf_ice'][:] + except KeyError: + qwv_surf_ice = missing_value + try: + tsnow_land = scalars_grp.variables['tsnow_land'][:] + except KeyError: + tsnow_land = missing_value + try: + tsnow_ice = scalars_grp.variables['tsnow_ice'][:] + except KeyError: + tsnow_ice = missing_value + try: + snowfallac_land = scalars_grp.variables['snowfallac_land'][:] + except KeyError: + snowfallac_land = missing_value + try: + snowfallac_ice = scalars_grp.variables['snowfallac_ice'][:] + except KeyError: + snowfallac_ice = missing_value + try: + sncovr_ice = scalars_grp.variables['sncovr_ice'][:] + except KeyError: + sncovr_ice = missing_value + try: + sfalb_lnd = scalars_grp.variables['sfalb_lnd'][:] + except KeyError: + sfalb_lnd = missing_value + try: + sfalb_lnd_bck = scalars_grp.variables['sfalb_lnd_bck'][:] + except KeyError: + sfalb_lnd_bck = missing_value + try: + emis_ice = scalars_grp.variables['emis_ice'][:] + except KeyError: + emis_ice = missing_value + try: + lai = scalars_grp.variables['lai'][:] + except KeyError: + lai = missing_value + try: + area = scalars_grp.variables['area'][:] + except KeyError: + area = missing_value + try: + stddev = scalars_grp.variables['stddev'][:] + except KeyError: + stddev = missing_value + try: + convexity = scalars_grp.variables['convexity'][:] + except KeyError: + convexity = missing_value + try: + oa1 = scalars_grp.variables['oa1'][:] + except KeyError: + oa1 = missing_value + try: + oa2 = scalars_grp.variables['oa2'][:] + except KeyError: + oa2 = missing_value + try: + oa3 = scalars_grp.variables['oa3'][:] + except KeyError: + oa3 = missing_value + try: + oa4 = scalars_grp.variables['oa4'][:] + except KeyError: + oa4 = missing_value + try: + ol1 = scalars_grp.variables['ol1'][:] + except KeyError: + ol1 = missing_value + try: + ol2 = scalars_grp.variables['ol2'][:] + except KeyError: + ol2 = missing_value + try: + ol3 = scalars_grp.variables['ol3'][:] + except KeyError: + ol3 = missing_value + try: + ol4 = scalars_grp.variables['ol4'][:] + except KeyError: + ol4 = missing_value + try: + theta_oro = scalars_grp.variables['theta_oro'][:] + except KeyError: + theta_oro = missing_value + try: + gamma = scalars_grp.variables['gamma'][:] + except KeyError: + gamma = missing_value + try: + sigma = scalars_grp.variables['sigma'][:] + except KeyError: + sigma = missing_value + try: + elvmax = scalars_grp.variables['elvmax'][:] + except KeyError: + elvmax = missing_value + try: + oro = scalars_grp.variables['oro'][:] + except KeyError: + oro = missing_value + try: + oro_uf = scalars_grp.variables['oro_uf'][:] + except KeyError: + oro_uf = missing_value + try: + landfrac = scalars_grp.variables['landfrac'][:] + except KeyError: + landfrac = missing_value + try: + lakefrac = scalars_grp.variables['lakefrac'][:] + except KeyError: + lakefrac = missing_value + try: + lakedepth = scalars_grp.variables['lakedepth'][:] + except KeyError: + lakedepth = missing_value + try: + tref = scalars_grp.variables['tref'][:] + except KeyError: + tref = missing_value + try: + z_c = scalars_grp.variables['z_c'][:] + except KeyError: + z_c = missing_value + try: + c_0 = scalars_grp.variables['c_0'][:] + except KeyError: + c_0 = missing_value + try: + c_d = scalars_grp.variables['c_d'][:] + except KeyError: + c_d = missing_value + try: + w_0 = scalars_grp.variables['w_0'][:] + except KeyError: + w_0 = missing_value + try: + w_d = scalars_grp.variables['w_0'][:] + except KeyError: + w_d = missing_value + try: + xt = scalars_grp.variables['xt'][:] + except KeyError: + xt = missing_value + try: + xs = scalars_grp.variables['xs'][:] + except KeyError: + xs = missing_value + try: + xu = scalars_grp.variables['xu'][:] + except KeyError: + xu = missing_value + try: + xv = scalars_grp.variables['xv'][:] + except KeyError: + xv = missing_value + try: + xz = scalars_grp.variables['xz'][:] + except KeyError: + xz = missing_value + try: + zm = scalars_grp.variables['zm'][:] + except KeyError: + zm = missing_value + try: + xtts = scalars_grp.variables['xtts'][:] + except KeyError: + xtts = missing_value + try: + xzts = scalars_grp.variables['xzts'][:] + except KeyError: + xzts = missing_value + try: + d_conv = scalars_grp.variables['d_conv'][:] + except KeyError: + d_conv = missing_value + try: + ifd = scalars_grp.variables['ifd'][:] + except KeyError: + ifd = missing_value + try: + dt_cool = scalars_grp.variables['dt_cool'][:] + except KeyError: + dt_cool = missing_value + try: + qrain = scalars_grp.variables['qrains'][:] + except KeyError: + qrain = missing_value + #read variables from initial group initial_grp = nc_fid.groups['initial'] - height = initial_grp.variables['height'][:] - theta_il = initial_grp.variables['thetail'][:] + try: + height = initial_grp.variables['height'][:] + except KeyError: + height = [missing_value] + try: + theta_il = initial_grp.variables['thetail'][:] + except KeyError: + theta_il = [missing_value] + try: + t = initial_grp.variables['temp'][:] + except KeyError: + t = [missing_value] qt = initial_grp.variables['qt'][:] ql = initial_grp.variables['ql'][:] qi = initial_grp.variables['qi'][:] @@ -200,6 +1009,62 @@ def get_case_data(case_name): v = initial_grp.variables['v'][:] tke = initial_grp.variables['tke'][:] ozone = initial_grp.variables['ozone'][:] + try: + stc = initial_grp.variables['stc'][:] + except KeyError: + stc = [missing_value] + try: + smc = initial_grp.variables['smc'][:] + except KeyError: + smc = [missing_value] + try: + slc = initial_grp.variables['slc'][:] + except KeyError: + slc = [missing_value] + try: + snicexy = initial_grp.variables['snicexy'][:] + except KeyError: + snicexy = [missing_value] + try: + snliqxy = initial_grp.variables['snliqxy'][:] + except KeyError: + snliqxy = [missing_value] + try: + tsnoxy = initial_grp.variables['tsnoxy'][:] + except KeyError: + tsnoxy = [missing_value] + try: + smoiseq = initial_grp.variables['smoiseq'][:] + except KeyError: + smoiseq = [missing_value] + try: + zsnsoxy = initial_grp.variables['zsnsoxy'][:] + except KeyError: + zsnsoxy = [missing_value] + try: + tiice = initial_grp.variables['tiice'][:] + except KeyError: + tiice = [missing_value] + try: + tslb = initial_grp.variables['tslb'][:] + except KeyError: + tslb = [missing_value] + try: + smois = initial_grp.variables['smois'][:] + except KeyError: + smois = [missing_value] + try: + sh2o = initial_grp.variables['sh2o'][:] + except KeyError: + sh2o = [missing_value] + try: + smfr = initial_grp.variables['smfr'][:] + except KeyError: + smfr = [missing_value] + try: + flfr = initial_grp.variables['flfr'][:] + except KeyError: + flfr = [missing_value] #read variables from forcing group forcing_grp = nc_fid.groups['forcing'] @@ -230,8 +1095,20 @@ def get_case_data(case_name): nc_fid.close() - case_data = Case_Data(case_name, missing_value, time, levels, lat, lon, - height, theta_il, qt, ql, qi, u, v, tke, ozone, + case_data = Case_Data(case_name, missing_value, time, levels, soil_depth, lat, lon, + slmsk, vegsrc, vegtyp, soiltyp, scolor, slopetyp, tsfco, vegfrac, shdmin, shdmax, + canopy, hice, fice, tisfc, snowd, snoalb, tg3, uustar, + alvsf, alnsf, alvwf, alnwf, facsf, facwf, weasd, f10m, t2m, q2m, ffmm, ffhh, + tprcp, srflag, sncovr, tsfcl, zorl, zorll, zorli, zorlw, zorlwav, tvxy, tgxy, tahxy, canicexy, canliqxy, eahxy, + cmxy, chxy, fwetxy, sneqvoxy, alboldxy, qsnowxy, wslakexy, taussxy, + waxy, wtxy, zwtxy, xlaixy, xsaixy, + lfmassxy, stmassxy, rtmassxy, woodxy, stblcpxy, fastcpxy, smcwtdxy, deeprechxy, rechxy, snowxy, + wetness, clw_surf_land, clw_surf_ice, qwv_surf_land, qwv_surf_ice, tsnow_land, tsnow_ice, + snowfallac_land, snowfallac_ice, sncovr_ice, sfalb_lnd, sfalb_lnd_bck, emis_ice, lai, area, + stddev, convexity, oa1, oa2, oa3, oa4, ol1, ol3, ol3, ol4, theta_oro, gamma, sigma, elvmax, oro, oro_uf, landfrac, lakefrac, lakedepth, + tref, z_c, c_0, c_d, w_0, w_d, xt, xs, xu, xv, xz, zm, xtts, xzts, d_conv, ifd, dt_cool, qrain, + height, theta_il, t, qt, ql, qi, u, v, tke, ozone, stc, smc, slc, + snicexy, snliqxy, tsnoxy, smoiseq, zsnsoxy, tiice, tslb, smois, sh2o, smfr, flfr, p_surf, T_surf, w_ls, omega, u_g, v_g, u_nudge, v_nudge, T_nudge, thil_nudge, qt_nudge, dT_dt_rad, h_advec_thil, v_advec_thil, h_advec_qt, @@ -252,6 +1129,7 @@ def write_SCM_case_file(case_nml, case_data, use_area): forcing_on = 1 forcing_off = 0 + nml_keys = case_nml['case_config'].todict().keys() nml_filename = os.path.join(CASE_NML_DIR, case_nml['case_config']['case_name'] + '.nml') # Output file @@ -285,13 +1163,22 @@ def write_SCM_case_file(case_nml, case_data, use_area): logging.debug('Case duration: {}'.format(delta)) logging.debug('Case end date: {}'.format(end_date)) - if (case_nml['case_config']['sfc_type'] == 0): - surface_string = 'ocean' - elif (case_nml['case_config']['sfc_type'] == 1): - surface_string = 'land' - elif (case_nml['case_config']['sfc_type'] == 2): + if (case_nml['case_config']['sfc_type'] > 1.5): surface_string = 'ice' + elif (case_nml['case_config']['sfc_type'] > 0.5): + surface_string = 'land' + else: + surface_string = 'ocean' + #override case nml with LSM/model data + if ('lsm_ics' in nml_keys): + if (case_nml['case_config']['lsm_ics']): + if (case_data._slmsk > 1.5): + surface_string = 'ice' + elif (case_data._slmsk > 0.5): + surface_string = 'land' + else: + surface_string = 'ocean' #DEPHY v1 format specifies the global attributes in this order. Some attributes are rewritten below after the order is established in the file. nc_file.case = case_string @@ -356,6 +1243,7 @@ def write_SCM_case_file(case_nml, case_data, use_area): nc_file.surface_forcing_temp = 'none' nc_file.surface_forcing_moisture = 'none' nc_file.surface_forcing_wind = 'none' + nc_file.surface_forcing_lsm = 'none' #rewrite forc_wa, forc_wap, forc_geo, nudging_ua, nudging_va depending on mom_forcing_type provided in case_config nml if (case_nml['case_config']['mom_forcing_type'] == 2): @@ -473,6 +1361,23 @@ def write_SCM_case_file(case_nml, case_data, use_area): timei_dim = nc_file.createDimension('t0', 1) lev_dim = nc_file.createDimension('lev', case_data._levels.shape[0]) + if ('lsm_ics' in nml_keys or 'model_ics' in nml_keys): + nc_file.surface_forcing_lsm = 'lsm' + if (('lsm_ics' in nml_keys and case_nml['case_config']['lsm_ics']) or ('model_ics' in nml_keys and case_nml['case_config']['model_ics'])): + if (case_data._soil_depth[0] != case_data._missing_value): + soil_dim = nc_file.createDimension('nsoil', case_data._soil_depth.shape[0]) + else: + message = 'LSM ICs are expected from the case_nml file, but no soil depth is provided.' + logging.critical(message) + raise Exception(message) + + if (case_data._snicexy[0] != case_data._missing_value): + snow_dim = nc_file.createDimension('nsnow', case_data._snicexy.shape[0]) + nslsnw_dim = nc_file.createDimension('nsoil_plus_nsnow',case_data._snicexy.shape[0] + case_data._soil_depth.shape[0]) + + if (case_data._tiice[0] != case_data._missing_value): + ice_dim = nc_file.createDimension('nice', case_data._tiice[0]) + # timei_var = nc_file.createVariable('t0', wp, ('t0')) timei_var.units = 'seconds since ' + start_date_string @@ -491,6 +1396,12 @@ def write_SCM_case_file(case_nml, case_data, use_area): lev_var.standard_name = 'pressure' lev_var[:] = case_data._levels[:] + if (case_data._soil_depth[0] != case_data._missing_value): + soil_depth_var = nc_file.createVariable('soil_depth', wp, ('nsoil')) + soil_depth_var.units = 'm' + soil_depth_var.standard_name = 'depth of bottom of soil layers' + soil_depth_var[:] = case_data._soil_depth[:] + # lon_var = nc_file.createVariable('lon', wp, ('time')) lon_var.units = 'degrees_east' @@ -503,11 +1414,742 @@ def write_SCM_case_file(case_nml, case_data, use_area): lat_var.standard_name = 'latitude' lat_var[:] = case_data._lat - # - thetal_var = nc_file.createVariable('thetal', wp, ('t0','lev')) - thetal_var.units = 'K' - thetal_var.standard_name = 'air_liquid_potential_temperature' - thetal_var[:] = case_data._theta_il[:] + if (case_data._slmsk != case_data._missing_value): + slmsk_var = nc_file.createVariable('slmsk', wp) + slmsk_var.units = 'none' + slmsk_var.standard_name = 'land_sea_ice_mask' + slmsk_var[:] = case_data._slmsk + + if (case_data._vegsrc != case_data._missing_value): + vegsrc_var = nc_file.createVariable('vegsrc', wp) + vegsrc_var.units = 'none' + vegsrc_var.standard_name = 'vegetation source (1-2)' + vegsrc_var[:] = case_data._vegsrc + + if (case_data._vegtyp != case_data._missing_value): + vegtyp_var = nc_file.createVariable('vegtyp', wp) + vegtyp_var.units = 'none' + vegtyp_var.standard_name = 'vegetation type (1-12)' + vegtyp_var[:] = case_data._vegtyp + + if (case_data._soiltyp != case_data._missing_value): + soiltyp_var = nc_file.createVariable('soiltyp', wp) + soiltyp_var.units = 'none' + soiltyp_var.standard_name = 'soil type (1-12)' + soiltyp_var[:] = case_data._soiltyp + + if (case_data._scolor != case_data._missing_value): + scolor_var = nc_file.createVariable('scolor', wp) + scolor_var.units = 'none' + scolor_var.standard_name = 'soil color' + scolor_var[:] = case_data._scolor + + if (case_data._slopetyp != case_data._missing_value): + slopetyp_var = nc_file.createVariable('slopetyp', wp) + slopetyp_var.units = 'none' + slopetyp_var.standard_name = 'slope type (1-9)' + slopetyp_var[:] = case_data._slopetyp + + if (case_data._tsfco != case_data._missing_value): + tsfco_var = nc_file.createVariable('tsfco', wp) + tsfco_var.units = 'none' + tsfco_var.standard_name = 'slope type (1-9)' + tsfco_var[:] = case_data._tsfco + + if (case_data._vegfrac != case_data._missing_value): + vegfrac_var = nc_file.createVariable('vegfrac', wp) + vegfrac_var.units = 'none' + vegfrac_var.standard_name = 'slope type (1-9)' + vegfrac_var[:] = case_data._vegfrac + + if (case_data._shdmin != case_data._missing_value): + shdmin_var = nc_file.createVariable('shdmin', wp) + shdmin_var.units = 'none' + shdmin_var.standard_name = 'slope type (1-9)' + shdmin_var[:] = case_data._shdmin + + if (case_data._shdmax != case_data._missing_value): + shdmax_var = nc_file.createVariable('shdmax', wp) + shdmax_var.units = 'none' + shdmax_var.standard_name = 'slope type (1-9)' + shdmax_var[:] = case_data._shdmax + + if (case_data._canopy != case_data._missing_value): + canopy_var = nc_file.createVariable('canopy', wp) + canopy_var.units = 'kg m-2' + canopy_var.standard_name = 'amount of water stored in canopy' + canopy_var[:] = case_data._canopy + + if (case_data._hice != case_data._missing_value): + hice_var = nc_file.createVariable('hice', wp) + hice_var.units = 'm' + hice_var.standard_name = 'sea ice thickness' + hice_var[:] = case_data._hice + + if (case_data._fice != case_data._missing_value): + fice_var = nc_file.createVariable('fice', wp) + fice_var.units = 'none' + fice_var.standard_name = 'ice fraction' + fice_var[:] = case_data._fice + + if (case_data._tisfc != case_data._missing_value): + tisfc_var = nc_file.createVariable('tisfc', wp) + tisfc_var.units = 'K' + tisfc_var.standard_name = 'ice surface temperature' + tisfc_var[:] = case_data._tisfc + + if (case_data._snowd != case_data._missing_value): + snowd_var = nc_file.createVariable('snowd', wp) + snowd_var.units = 'mm' + snowd_var.standard_name = 'water equivalent snow depth' + snowd_var[:] = case_data._snowd + + if (case_data._snoalb != case_data._missing_value): + snoalb_var = nc_file.createVariable('snoalb', wp) + snoalb_var.units = 'none' + snoalb_var.standard_name = 'maximum snow albedo' + snoalb_var[:] = case_data._snoalb + + if (case_data._tg3 != case_data._missing_value): + tg3_var = nc_file.createVariable('tg3', wp) + tg3_var.units = 'K' + tg3_var.standard_name = 'deep soil temperature' + tg3_var[:] = case_data._tg3 + + if (case_data._uustar != case_data._missing_value): + uustar_var = nc_file.createVariable('uustar', wp) + uustar_var.units = 'm s-1' + uustar_var.standard_name = 'surface_friction_velocity' + uustar_var[:] = case_data._uustar + + if (case_data._alvsf != case_data._missing_value): + alvsf_var = nc_file.createVariable('alvsf', wp) + alvsf_var.units = 'none' + alvsf_var.standard_name = '60 degree vis albedo with strong cosz dependency' + alvsf_var[:] = case_data._alvsf + + if (case_data._alnsf != case_data._missing_value): + alnsf_var = nc_file.createVariable('alnsf', wp) + alnsf_var.units = 'none' + alnsf_var.standard_name = '60 degree nir albedo with strong cosz dependency' + alnsf_var[:] = case_data._alnsf + + if (case_data._alvwf != case_data._missing_value): + alvwf_var = nc_file.createVariable('alvwf', wp) + alvwf_var.units = 'none' + alvwf_var.standard_name = '60 degree vis albedo with weak cosz dependency' + alvwf_var[:] = case_data._alvwf + + if (case_data._alnwf != case_data._missing_value): + alnwf_var = nc_file.createVariable('alnwf', wp) + alnwf_var.units = 'none' + alnwf_var.standard_name = '60 degree nir albedo with weak cosz dependency' + alnwf_var[:] = case_data._alnwf + + if (case_data._facsf != case_data._missing_value): + facsf_var = nc_file.createVariable('facsf', wp) + facsf_var.units = 'none' + facsf_var.standard_name = 'fractional coverage with strong cosz dependency' + facsf_var[:] = case_data._facsf + + if (case_data._facwf != case_data._missing_value): + facwf_var = nc_file.createVariable('facwf', wp) + facwf_var.units = 'none' + facwf_var.standard_name = 'fractional coverage with weak cosz dependency' + facwf_var[:] = case_data._facwf + + if (case_data._weasd != case_data._missing_value): + weasd_var = nc_file.createVariable('weasd', wp) + weasd_var.units = 'mm' + weasd_var.standard_name = 'water equivalent accumulated snow depth' + weasd_var[:] = case_data._weasd + + if (case_data._f10m != case_data._missing_value): + f10m_var = nc_file.createVariable('f10m', wp) + f10m_var.units = 'none' + f10m_var.standard_name = 'ratio of sigma level 1 wind and 10m wind' + f10m_var[:] = case_data._f10m + + if (case_data._t2m != case_data._missing_value): + t2m_var = nc_file.createVariable('t2m', wp) + t2m_var.units = 'K' + t2m_var.standard_name = '2-meter absolute temperature' + t2m_var[:] = case_data._t2m + + if (case_data._q2m != case_data._missing_value): + q2m_var = nc_file.createVariable('q2m', wp) + q2m_var.units = 'kg kg-1' + q2m_var.standard_name = '2-meter specific humidity' + q2m_var[:] = case_data._q2m + + if (case_data._ffmm != case_data._missing_value): + ffmm_var = nc_file.createVariable('ffmm', wp) + ffmm_var.units = 'none' + ffmm_var.standard_name = 'Monin-Obukhov similarity function for momentum' + ffmm_var[:] = case_data._ffmm + + if (case_data._ffhh != case_data._missing_value): + ffhh_var = nc_file.createVariable('ffhh', wp) + ffhh_var.units = 'none' + ffhh_var.standard_name = 'Monin-Obukhov similarity function for heat' + ffhh_var[:] = case_data._ffhh + + if (case_data._tprcp != case_data._missing_value): + tprcp_var = nc_file.createVariable('tprcp', wp) + tprcp_var.units = 'm' + tprcp_var.standard_name = 'instantaneous total precipitation amount' + tprcp_var[:] = case_data._tprcp + + if (case_data._srflag != case_data._missing_value): + srflag_var = nc_file.createVariable('srflag', wp) + srflag_var.units = 'none' + srflag_var.standard_name = 'snow/rain flag for precipitation' + srflag_var[:] = case_data._srflag + + if (case_data._sncovr != case_data._missing_value): + sncovr_var = nc_file.createVariable('sncovr', wp) + sncovr_var.units = 'none' + sncovr_var.standard_name = 'surface snow area fraction' + sncovr_var[:] = case_data._sncovr + + if (case_data._tsfcl != case_data._missing_value): + tsfcl_var = nc_file.createVariable('tsfcl', wp) + tsfcl_var.units = 'K' + tsfcl_var.standard_name = 'surface skin temperature over land' + tsfcl_var[:] = case_data._tsfcl + + if (case_data._zorl != case_data._missing_value): + zorl_var = nc_file.createVariable('zorl', wp) + zorl_var.units = 'cm' + zorl_var.standard_name = 'surface roughness length' + zorl_var[:] = case_data._zorl + + if (case_data._zorll != case_data._missing_value): + zorll_var = nc_file.createVariable('zorll', wp) + zorll_var.units = 'cm' + zorll_var.standard_name = 'surface roughness length over land' + zorll_var[:] = case_data._zorll + + if (case_data._zorli != case_data._missing_value): + zorli_var = nc_file.createVariable('zorli', wp) + zorli_var.units = 'cm' + zorli_var.standard_name = 'surface roughness length over ice' + zorli_var[:] = case_data._zorli + + if (case_data._zorlw != case_data._missing_value): + zorlw_var = nc_file.createVariable('zorlw', wp) + zorlw_var.units = 'cm' + zorlw_var.standard_name = 'surface roughness length over ocean' + zorlw_var[:] = case_data._zorlw + + if (case_data._zorlwav != case_data._missing_value): + zorlwav_var = nc_file.createVariable('zorlwav', wp) + zorlwav_var.units = 'cm' + zorlwav_var.standard_name = 'surface_roughness_length_from_wave_model' + zorlwav_var[:] = case_data._zorlwav + + if (case_data._tvxy != case_data._missing_value): + tvxy_var = nc_file.createVariable('tvxy', wp) + tvxy_var.units = 'K' + tvxy_var.standard_name = 'vegetation temperature for NoahMP' + tvxy_var[:] = case_data._tvxy + + if (case_data._tgxy != case_data._missing_value): + tgxy_var = nc_file.createVariable('tgxy', wp) + tgxy_var.units = 'K' + tgxy_var.standard_name = 'ground temperature for NoahMP' + tgxy_var[:] = case_data._tgxy + + if (case_data._tahxy != case_data._missing_value): + tahxy_var = nc_file.createVariable('tahxy', wp) + tahxy_var.units = 'K' + tahxy_var.standard_name = 'canopy air temperature for NoahMP' + tahxy_var[:] = case_data._tahxy + + if (case_data._canicexy != case_data._missing_value): + canicexy_var = nc_file.createVariable('canicexy', wp) + canicexy_var.units = 'mm' + canicexy_var.standard_name = 'canopy intercepted ice mass for NoahMP' + canicexy_var[:] = case_data._canicexy + + if (case_data._canliqxy != case_data._missing_value): + canliqxy_var = nc_file.createVariable('canliqxy', wp) + canliqxy_var.units = 'mm' + canliqxy_var.standard_name = 'canopy intercepted liquid water for NoahMP' + canliqxy_var[:] = case_data._canliqxy + + if (case_data._eahxy != case_data._missing_value): + eahxy_var = nc_file.createVariable('eahxy', wp) + eahxy_var.units = 'Pa' + eahxy_var.standard_name = 'canopy air vapor pressure for NoahMP' + eahxy_var[:] = case_data._eahxy + + if (case_data._cmxy != case_data._missing_value): + cmxy_var = nc_file.createVariable('cmxy', wp) + cmxy_var.units = 'none' + cmxy_var.standard_name = 'surface drag coefficient for momentum for NoahMP' + cmxy_var[:] = case_data._cmxy + + if (case_data._chxy != case_data._missing_value): + chxy_var = nc_file.createVariable('chxy', wp) + chxy_var.units = 'none' + chxy_var.standard_name = 'surface exchange coeff heat & moisture for NoahMP' + chxy_var[:] = case_data._chxy + + if (case_data._fwetxy != case_data._missing_value): + fwetxy_var = nc_file.createVariable('fwetxy', wp) + fwetxy_var.units = 'none' + fwetxy_var.standard_name = 'area fraction of canopy that is wetted/snowed for NoahMP' + fwetxy_var[:] = case_data._fwetxy + + if (case_data._sneqvoxy != case_data._missing_value): + sneqvoxy_var = nc_file.createVariable('sneqvoxy', wp) + sneqvoxy_var.units = 'mm' + sneqvoxy_var.standard_name = 'snow mass at previous time step for NoahMP' + sneqvoxy_var[:] = case_data._sneqvoxy + + if (case_data._alboldxy != case_data._missing_value): + alboldxy_var = nc_file.createVariable('alboldxy', wp) + alboldxy_var.units = 'none' + alboldxy_var.standard_name = 'snow albedo at previous time step for NoahMP' + alboldxy_var[:] = case_data._alboldxy + + if (case_data._qsnowxy != case_data._missing_value): + qsnowxy_var = nc_file.createVariable('qsnowxy', wp) + qsnowxy_var.units = 'mm s-1' + qsnowxy_var.standard_name = 'snow precipitation rate at surface for NoahMP' + qsnowxy_var[:] = case_data._qsnowxy + + if (case_data._wslakexy != case_data._missing_value): + wslakexy_var = nc_file.createVariable('wslakexy', wp) + wslakexy_var.units = 'mm' + wslakexy_var.standard_name = 'lake water storage for NoahMP' + wslakexy_var[:] = case_data._wslakexy + + if (case_data._taussxy != case_data._missing_value): + taussxy_var = nc_file.createVariable('taussxy', wp) + taussxy_var.units = 'none' + taussxy_var.standard_name = 'non-dimensional snow age for NoahMP' + taussxy_var[:] = case_data._taussxy + + + if (case_data._waxy != case_data._missing_value): + waxy_var = nc_file.createVariable('waxy', wp) + waxy_var.units = 'mm' + waxy_var.standard_name = 'water storage in aquifer for NoahMP' + waxy_var[:] = case_data._waxy + + if (case_data._wtxy != case_data._missing_value): + wtxy_var = nc_file.createVariable('wtxy', wp) + wtxy_var.units = 'mm' + wtxy_var.standard_name = 'ater storage in aquifer and saturated soil for NoahMP' + wtxy_var[:] = case_data._wtxy + + if (case_data._zwtxy != case_data._missing_value): + zwtxy_var = nc_file.createVariable('zwtxy', wp) + zwtxy_var.units = 'm' + zwtxy_var.standard_name = 'water table depth for NoahMP' + zwtxy_var[:] = case_data._zwtxy + + if (case_data._xlaixy != case_data._missing_value): + xlaixy_var = nc_file.createVariable('xlaixy', wp) + xlaixy_var.units = 'none' + xlaixy_var.standard_name = 'leaf area index for NoahMP' + xlaixy_var[:] = case_data._xlaixy + + if (case_data._xsaixy != case_data._missing_value): + xsaixy_var = nc_file.createVariable('xsaixy', wp) + xsaixy_var.units = 'none' + xsaixy_var.standard_name = 'stem area index for NoahMP' + xsaixy_var[:] = case_data._xsaixy + + if (case_data._lfmassxy != case_data._missing_value): + lfmassxy_var = nc_file.createVariable('lfmassxy', wp) + lfmassxy_var.units = 'g m-2' + lfmassxy_var.standard_name = 'leaf mass for NoahMP' + lfmassxy_var[:] = case_data._lfmassxy + + if (case_data._stmassxy != case_data._missing_value): + stmassxy_var = nc_file.createVariable('stmassxy', wp) + stmassxy_var.units = 'g m-2' + stmassxy_var.standard_name = 'stem mass for NoahMP' + stmassxy_var[:] = case_data._stmassxy + + if (case_data._rtmassxy != case_data._missing_value): + rtmassxy_var = nc_file.createVariable('rtmassxy', wp) + rtmassxy_var.units = 'g m-2' + rtmassxy_var.standard_name = 'fine root mass for NoahMP' + rtmassxy_var[:] = case_data._rtmassxy + + if (case_data._woodxy != case_data._missing_value): + woodxy_var = nc_file.createVariable('woodxy', wp) + woodxy_var.units = 'g m-2' + woodxy_var.standard_name = 'wood mass including woody roots for NoahMP' + woodxy_var[:] = case_data._woodxy + + if (case_data._stblcpxy != case_data._missing_value): + stblcpxy_var = nc_file.createVariable('stblcpxy', wp) + stblcpxy_var.units = 'g m-2' + stblcpxy_var.standard_name = 'stable carbon in deep soil for NoahMP' + stblcpxy_var[:] = case_data._stblcpxy + + if (case_data._fastcpxy != case_data._missing_value): + fastcpxy_var = nc_file.createVariable('fastcpxy', wp) + fastcpxy_var.units = 'g m-2' + fastcpxy_var.standard_name = 'short-lived carbon in shallow soil for NoahMP' + fastcpxy_var[:] = case_data._fastcpxy + + if (case_data._smcwtdxy != case_data._missing_value): + smcwtdxy_var = nc_file.createVariable('smcwtdxy', wp) + smcwtdxy_var.units = 'm3 m-3' + smcwtdxy_var.standard_name = 'oil water content between the bottom of the soil and the water table for NoahMP' + smcwtdxy_var[:] = case_data._smcwtdxy + + if (case_data._deeprechxy != case_data._missing_value): + deeprechxy_var = nc_file.createVariable('deeprechxy', wp) + deeprechxy_var.units = 'm' + deeprechxy_var.standard_name = 'echarge to or from the water table when deep for NoahMP' + deeprechxy_var[:] = case_data._deeprechxy + + if (case_data._rechxy != case_data._missing_value): + rechxy_var = nc_file.createVariable('rechxy', wp) + rechxy_var.units = 'm' + rechxy_var.standard_name = 'recharge to or from the water table when shallow for NoahMP' + rechxy_var[:] = case_data._rechxy + + if (case_data._snowxy != case_data._missing_value): + snowxy_var = nc_file.createVariable('snowxy', wp) + snowxy_var.units = 'none' + snowxy_var.standard_name = 'number of snow layers for NoahMP' + snowxy_var[:] = case_data._snowxy + + if (case_data._wetness != case_data._missing_value): + wetness_var = nc_file.createVariable('wetness', wp) + wetness_var.units = 'none' + wetness_var.standard_name = 'normalized soil wetness for RUC LSM' + wetness_var[:] = case_data._wetness + + if (case_data._clw_surf_land != case_data._missing_value): + clw_surf_land_var = nc_file.createVariable('clw_surf_land', wp) + clw_surf_land_var.units = 'kg kg-1' + clw_surf_land_var.standard_name = 'cloud condensed water mixing ratio at surface over land for RUC LSM' + clw_surf_land_var[:] = case_data._clw_surf_land + + if (case_data._clw_surf_ice != case_data._missing_value): + clw_surf_ice_var = nc_file.createVariable('clw_surf_ice', wp) + clw_surf_ice_var.units = 'kg kg-1' + clw_surf_ice_var.standard_name = 'cloud condensed water mixing ratio at surface over ice for RUC LSM' + clw_surf_ice_var[:] = case_data._clw_surf_ice + + if (case_data._qwv_surf_land != case_data._missing_value): + qwv_surf_land_var = nc_file.createVariable('qwv_surf_land', wp) + qwv_surf_land_var.units = 'kg kg-1' + qwv_surf_land_var.standard_name = 'water vapor mixing ratio at surface over land for RUC LSM' + qwv_surf_land_var[:] = case_data._qwv_surf_land + + if (case_data._qwv_surf_ice != case_data._missing_value): + qwv_surf_ice_var = nc_file.createVariable('qwv_surf_ice', wp) + qwv_surf_ice_var.units = 'kg kg-1' + qwv_surf_ice_var.standard_name = 'water vapor mixing ratio at surface over ice for RUC LSM' + qwv_surf_ice_var[:] = case_data._qwv_surf_ice + + if (case_data._tsnow_land != case_data._missing_value): + tsnow_land_var = nc_file.createVariable('tsnow_land', wp) + tsnow_land_var.units = 'K' + tsnow_land_var.standard_name = 'snow temperature at the bottom of the first snow layer over land for RUC LSM' + tsnow_land_var[:] = case_data._tsnow_land + + if (case_data._tsnow_ice != case_data._missing_value): + tsnow_ice_var = nc_file.createVariable('tsnow_ice', wp) + tsnow_ice_var.units = 'K' + tsnow_ice_var.standard_name = 'snow temperature at the bottom of the first snow layer over land for RUC LSM' + tsnow_ice_var[:] = case_data._tsnow_ice + + if (case_data._snowfallac_land != case_data._missing_value): + snowfallac_land_var = nc_file.createVariable('snowfallac_land', wp) + snowfallac_land_var.units = 'kg m-2' + snowfallac_land_var.standard_name = 'run-total snow accumulation on the ground over land for RUC LSM' + snowfallac_land_var[:] = case_data._snowfallac_land + + if (case_data._snowfallac_ice != case_data._missing_value): + snowfallac_ice_var = nc_file.createVariable('snowfallac_ice', wp) + snowfallac_ice_var.units = 'kg m-2' + snowfallac_ice_var.standard_name = 'run-total snow accumulation on the ground over land for RUC LSM' + snowfallac_ice_var[:] = case_data._snowfallac_ice + + if (case_data._sncovr_ice != case_data._missing_value): + sncovr_ice_var = nc_file.createVariable('sncovr_ice', wp) + sncovr_ice_var.units = 'none' + sncovr_ice_var.standard_name = 'surface snow area fraction over ice' + sncovr_ice_var[:] = case_data._sncovr_ice + + if (case_data._sfalb_lnd != case_data._missing_value): + sfalb_lnd_var = nc_file.createVariable('sfalb_lnd', wp) + sfalb_lnd_var.units = 'none' + sfalb_lnd_var.standard_name = 'surface albedo over land for RUC LSM' + sfalb_lnd_var[:] = case_data._sfalb_lnd + + if (case_data._sfalb_lnd_bck != case_data._missing_value): + sfalb_lnd_bck_var = nc_file.createVariable('sfalb_lnd_bckß', wp) + sfalb_lnd_bck_var.units = 'none' + sfalb_lnd_bck_var.standard_name = 'surface snow-free albedo over land for RUC LSM' + sfalb_lnd_bck_var[:] = case_data._sfalb_lnd_bck + + if (case_data._emis_ice != case_data._missing_value): + emis_ice_var = nc_file.createVariable('emis_ice', wp) + emis_ice_var.units = 'none' + emis_ice_var.standard_name = 'surface emissivity over ice for RUC LSM' + emis_ice_var[:] = case_data._emis_ice + + if (case_data._lai != case_data._missing_value): + lai_var = nc_file.createVariable('lai', wp) + lai_var.units = 'none' + lai_var.standard_name = 'leaf area index for RUC LSM' + lai_var[:] = case_data._lai + + area_var = nc_file.createVariable('area', wp) + area_var.units = 'm2' + area_var.standard_name = 'grid cell area' + if ('column_area' in nml_keys and case_nml['case_config']['column_area']): + area_var[:] = case_nml['case_config']['column_area'] + message = 'Since column_area was supplied in the case namelist, it will be used instead of the data from the case data file (if it exists).' + logging.info(message) + elif (case_data._area != case_data._missing_value): + area_var[:] = case_data._area + + if (case_data._stddev != case_data._missing_value): + stddev_var = nc_file.createVariable('stddev', wp) + stddev_var.units = 'm' + stddev_var.standard_name = 'standard deviation of subgrid orography' + stddev_var[:] = case_data._stddev + + if (case_data._convexity != case_data._missing_value): + convexity_var = nc_file.createVariable('convexity', wp) + convexity_var.units = 'none' + convexity_var.standard_name = 'convexity of subgrid orography' + convexity_var[:] = case_data._convexity + + if (case_data._oa1 != case_data._missing_value): + oa1_var = nc_file.createVariable('oa1', wp) + oa1_var.units = 'none' + oa1_var.standard_name = 'assymetry of subgrid orography 1' + oa1_var[:] = case_data._oa1 + + if (case_data._oa2 != case_data._missing_value): + oa2_var = nc_file.createVariable('oa2', wp) + oa2_var.units = 'none' + oa2_var.standard_name = 'assymetry of subgrid orography 2' + oa2_var[:] = case_data._oa2 + + if (case_data._oa3 != case_data._missing_value): + oa3_var = nc_file.createVariable('oa3', wp) + oa3_var.units = 'none' + oa3_var.standard_name = 'assymetry of subgrid orography 3' + oa3_var[:] = case_data._oa3 + + if (case_data._oa4 != case_data._missing_value): + oa4_var = nc_file.createVariable('oa4', wp) + oa4_var.units = 'none' + oa4_var.standard_name = 'assymetry of subgrid orography 4' + oa4_var[:] = case_data._oa4 + + if (case_data._ol1 != case_data._missing_value): + ol1_var = nc_file.createVariable('ol1', wp) + ol1_var.units = 'none' + ol1_var.standard_name = 'fraction of grid box with subgrid orography higher than critical height 1' + ol1_var[:] = case_data._ol1 + + if (case_data._ol2 != case_data._missing_value): + ol2_var = nc_file.createVariable('ol2', wp) + ol2_var.units = 'none' + ol2_var.standard_name = 'fraction of grid box with subgrid orography higher than critical height 2' + ol2_var[:] = case_data._ol2 + + if (case_data._ol3 != case_data._missing_value): + ol3_var = nc_file.createVariable('ol3', wp) + ol3_var.units = 'none' + ol3_var.standard_name = 'fraction of grid box with subgrid orography higher than critical height 3' + ol3_var[:] = case_data._ol3 + + if (case_data._ol4 != case_data._missing_value): + ol4_var = nc_file.createVariable('ol4', wp) + ol4_var.units = 'none' + ol4_var.standard_name = 'fraction of grid box with subgrid orography higher than critical height 4' + ol4_var[:] = case_data._ol4 + + if (case_data._theta_oro != case_data._missing_value): + theta_oro_var = nc_file.createVariable('theta_oro', wp) + theta_oro_var.units = 'deg' + theta_oro_var.standard_name = 'angle with respect to east of maximum subgrid orographic variations' + theta_oro_var[:] = case_data._theta_oro + + if (case_data._gamma != case_data._missing_value): + gamma_var = nc_file.createVariable('gamma', wp) + gamma_var.units = 'none' + gamma_var.standard_name = 'anisotropy of subgrid orography' + gamma_var[:] = case_data._gamma + + if (case_data._sigma != case_data._missing_value): + sigma_var = nc_file.createVariable('sigma', wp) + sigma_var.units = 'none' + sigma_var.standard_name = 'slope of subgrid orography' + sigma_var[:] = case_data._sigma + + if (case_data._elvmax != case_data._missing_value): + elvmax_var = nc_file.createVariable('elvmax', wp) + elvmax_var.units = 'm' + elvmax_var.standard_name = 'maximum of subgrid orography' + elvmax_var[:] = case_data._elvmax + + if (case_data._oro != case_data._missing_value): + oro_var = nc_file.createVariable('oro', wp) + oro_var.units = 'm' + oro_var.standard_name = 'orography' + oro_var[:] = case_data._oro + + if (case_data._oro_uf != case_data._missing_value): + oro_uf_var = nc_file.createVariable('oro_uf', wp) + oro_uf_var.units = 'm' + oro_uf_var.standard_name = 'unfiltered orography' + oro_uf_var[:] = case_data._oro_uf + + if (case_data._landfrac != case_data._missing_value): + landfrac_var = nc_file.createVariable('landfrac', wp) + landfrac_var.units = 'none' + landfrac_var.standard_name = 'fraction of horizontal grid area occupied by land' + landfrac_var[:] = case_data._landfrac + + if (case_data._lakefrac != case_data._missing_value): + lakefrac_var = nc_file.createVariable('lakefrac', wp) + lakefrac_var.units = 'none' + lakefrac_var.standard_name = 'fraction of horizontal grid area occupied by lake' + lakefrac_var[:] = case_data._lakefrac + + if (case_data._lakedepth != case_data._missing_value): + lakedepth_var = nc_file.createVariable('lakedepth', wp) + lakedepth_var.units = 'none' + lakedepth_var.standard_name = 'lake depth' + lakedepth_var[:] = case_data._lakedepth + + if (case_data._tref != case_data._missing_value): + tref_var = nc_file.createVariable('tref', wp) + tref_var.units = 'K' + tref_var.standard_name = 'sea surface reference temperature for NSST' + tref_var[:] = case_data._tref + + if (case_data._z_c != case_data._missing_value): + z_c_var = nc_file.createVariable('z_c', wp) + z_c_var.units = 'm' + z_c_var.standard_name = 'sub-layer cooling thickness for NSST' + z_c_var[:] = case_data._z_c + + if (case_data._c_0 != case_data._missing_value): + c_0_var = nc_file.createVariable('c_0', wp) + c_0_var.units = 'none' + c_0_var.standard_name = 'coefficient 1 to calculate d(Tz)/d(Ts) for NSST' + c_0_var[:] = case_data._c_0 + + if (case_data._c_d != case_data._missing_value): + c_d_var = nc_file.createVariable('c_d', wp) + c_d_var.units = 'none' + c_d_var.standard_name = 'coefficient 2 to calculate d(Tz)/d(Ts) for NSST' + c_d_var[:] = case_data._c_d + + if (case_data._w_0!= case_data._missing_value): + w_0_var = nc_file.createVariable('w_0', wp) + w_0_var.units = 'none' + w_0_var.standard_name = 'coefficient 3 to calculate d(Tz)/d(Ts) for NSST' + w_0_var[:] = case_data._w_0 + + if (case_data._w_d != case_data._missing_value): + w_d_var = nc_file.createVariable('w_d', wp) + w_d_var.units = 'none' + w_d_var.standard_name = 'coefficient 4 to calculate d(Tz)/d(Ts) for NSST' + w_d_var[:] = case_data._w_d + + if (case_data._xt != case_data._missing_value): + xt_var = nc_file.createVariable('xt', wp) + xt_var.units = 'K m' + xt_var.standard_name = 'heat content in diurnal thermocline layer for NSST' + xt_var[:] = case_data._xt + + if (case_data._xs != case_data._missing_value): + xs_var = nc_file.createVariable('xs', wp) + xs_var.units = 'ppt m' + xs_var.standard_name = 'salinity content in diurnal thermocline layer for NSST' + xs_var[:] = case_data._xs + + if (case_data._xu != case_data._missing_value): + xu_var = nc_file.createVariable('xu', wp) + xu_var.units = 'm2 s-1' + xu_var.standard_name = 'u-current in diurnal thermocline layer for NSST' + xu_var[:] = case_data._xu + + if (case_data._xv != case_data._missing_value): + xv_var = nc_file.createVariable('xv', wp) + xv_var.units = 'm2 s-1' + xv_var.standard_name = 'v-current in diurnal thermocline layer for NSST' + xv_var[:] = case_data._xv + + if (case_data._xz != case_data._missing_value): + xz_var = nc_file.createVariable('xz', wp) + xz_var.units = 'm' + xz_var.standard_name = 'thickness of diurnal thermocline layer for NSST' + xz_var[:] = case_data._xz + + if (case_data._zm != case_data._missing_value): + zm_var = nc_file.createVariable('zm', wp) + zm_var.units = 'm' + zm_var.standard_name = 'thickness of ocean mixed layer for NSST' + zm_var[:] = case_data._zm + + if (case_data._xtts != case_data._missing_value): + xtts_var = nc_file.createVariable('xtts', wp) + xtts_var.units = 'm' + xtts_var.standard_name = 'sensitivity of diurnal thermocline layer heat content to surface temperature [d(xt)/d(ts)] for NSST' + xtts_var[:] = case_data._xtts + + if (case_data._xzts != case_data._missing_value): + xzts_var = nc_file.createVariable('xzts', wp) + xzts_var.units = 'm K-1' + xzts_var.standard_name = 'sensitivity of diurnal thermocline layer thickness to surface temperature [d(xz)/d(ts)] for NSST' + xzts_var[:] = case_data._xzts + + if (case_data._d_conv != case_data._missing_value): + d_conv_var = nc_file.createVariable('d_conv', wp) + d_conv_var.units = 'm' + d_conv_var.standard_name = 'thickness of free convection layer for NSST' + d_conv_var[:] = case_data._d_conv + + if (case_data._ifd != case_data._missing_value): + ifd_var = nc_file.createVariable('ifd', wp) + ifd_var.units = 'none' + ifd_var.standard_name = 'index to start DTM run for NSST' + ifd_var[:] = case_data._ifd + + if (case_data._dt_cool != case_data._missing_value): + dt_cool_var = nc_file.createVariable('dt_cool', wp) + dt_cool_var.units = 'K' + dt_cool_var.standard_name = 'sub-layer cooling amount for NSST' + dt_cool_var[:] = case_data._dt_cool + + if (case_data._qrain != case_data._missing_value): + qrain_var = nc_file.createVariable('qrain', wp) + qrain_var.units = 'W m-2' + qrain_var.standard_name = 'sensible heat due to rainfall for NSST' + qrain_var[:] = case_data._qrain + + if (case_data._theta_il[0] != case_data._missing_value): + thetal_var = nc_file.createVariable('thetal', wp, ('t0','lev')) + thetal_var.units = 'K' + thetal_var.standard_name = 'air_liquid_potential_temperature' + thetal_var[:] = case_data._theta_il[:] + + if (case_data._t[0] != case_data._missing_value): + t_var = nc_file.createVariable('t', wp, ('t0','lev')) + t_var.units = 'K' + t_var.standard_name = 'absolute temperature' + t_var[:] = case_data._t[:] # qt_var = nc_file.createVariable('qt', wp, ('t0','lev')) @@ -569,6 +2211,90 @@ def write_SCM_case_file(case_nml, case_data, use_area): ozone_var.standard_name = 'mole_fraction_of_ozone_in_air' ozone_var[:] = case_data._ozone[:] + if (case_data._stc[0] != case_data._missing_value): + stc_var = nc_file.createVariable('stc', wp, ('t0','nsoil')) + stc_var.units = 'K' + stc_var.standard_name = 'initial profile of soil temperature' + stc_var[:] = case_data._stc[:] + + if (case_data._smc[0] != case_data._missing_value): + smc_var = nc_file.createVariable('smc', wp, ('t0','nsoil')) + smc_var.units = 'kg' + smc_var.standard_name = 'initial profile of soil moisture' + smc_var[:] = case_data._smc[:] + + if (case_data._slc[0] != case_data._missing_value): + slc_var = nc_file.createVariable('slc', wp, ('t0','nsoil')) + slc_var.units = 'kg' + slc_var.standard_name = 'initial profile of soil liquid moisture' + slc_var[:] = case_data._slc[:] + + if (case_data._snicexy[0] != case_data._missing_value): + snicexy_var = nc_file.createVariable('snicexy', wp, ('t0','nsnow')) + snicexy_var.units = 'mm' + snicexy_var.standard_name = 'initial profile of snow layer ice' + snicexy_var[:] = case_data._snicexy[:] + + if (case_data._snliqxy[0] != case_data._missing_value): + snliqxy_var = nc_file.createVariable('snliqxy', wp, ('t0','nsnow')) + snliqxy_var.units = 'mm' + snliqxy_var.standard_name = 'initial profile of snow layer liquid' + snliqxy_var[:] = case_data._snliqxy[:] + + if (case_data._tsnoxy[0] != case_data._missing_value): + tsnoxy_var = nc_file.createVariable('tsnoxy', wp, ('t0','nsnow')) + tsnoxy_var.units = 'K' + tsnoxy_var.standard_name = 'initial profile of snow layer temperature' + tsnoxy_var[:] = case_data._tsnoxy[:] + + if (case_data._smoiseq[0] != case_data._missing_value): + smoiseq_var = nc_file.createVariable('smoiseq', wp, ('t0','nsoil')) + smoiseq_var.units = 'm3 m-3' + smoiseq_var.standard_name = 'initial profile of equilibrium soil water content' + smoiseq_var[:] = case_data._smoiseq[:] + + if (case_data._zsnsoxy[0] != case_data._missing_value): + zsnsoxy_var = nc_file.createVariable('zsnxosy', wp, ('t0','nsoil_plus_nsnow')) + zsnsoxy_var.units = 'm' + zsnsoxy_var.standard_name = 'layer bottom depth from snow surface' + zsnsoxy_var[:] = case_data._zsnsoxy[:] + + if (case_data._tiice[0] != case_data._missing_value): + tiice_var = nc_file.createVariable('tiice', wp, ('t0','nice')) + tiice_var.units = 'K' + tiice_var.standard_name = 'sea ice internal temperature' + tiice_var[:] = case_data._tiice[:] + + if (case_data._tslb[0] != case_data._missing_value): + tslb_var = nc_file.createVariable('tslb', wp, ('t0','nsoil')) + tslb_var.units = 'K' + tslb_var.standard_name = 'soil temperature for RUC LSM' + tslb_var[:] = case_data._tslb[:] + + if (case_data._smois[0] != case_data._missing_value): + smois_var = nc_file.createVariable('smois', wp, ('t0','nsoil')) + smois_var.units = 'none' + smois_var.standard_name = 'volume fraction of soil moisture for RUC LSM' + smois_var[:] = case_data._smois[:] + + if (case_data._sh2o[0] != case_data._missing_value): + sh2o_var = nc_file.createVariable('sh2o', wp, ('t0','nsoil')) + sh2o_var.units = 'none' + sh2o_var.standard_name = 'volume fraction of unfrozen soil moisture for RUC LSM' + sh2o_var[:] = case_data._sh2o[:] + + if (case_data._smfr[0] != case_data._missing_value): + smfr_var = nc_file.createVariable('smfr', wp, ('t0','nsoil')) + smfr_var.units = 'none' + smfr_var.standard_name = 'volume fraction of frozen soil moisture for RUC LSM' + smfr_var[:] = case_data._smfr[:] + + if (case_data._flfr[0] != case_data._missing_value): + flfr_var = nc_file.createVariable('flfr', wp, ('t0','nsoil')) + flfr_var.units = 'none' + flfr_var.standard_name = 'flag for frozen soil physics for RUC LSM' + flfr_var[:] = case_data._flfr[:] + ps_forc_var = nc_file.createVariable('ps_forc', wp, ('time')) ps_forc_var.units = 'Pa' ps_forc_var.standard_name = 'forcing_surface_air_pressure' @@ -739,20 +2465,21 @@ def write_SCM_case_file(case_nml, case_data, use_area): ts_var[:] = case_data._T_surf[:] else: ts_var[:] = case_data._missing_value - else: - nc_file.surface_forcing_temp = 'ts' - nc_file.surface_forcing_wind = 'z0' - - z0_var = nc_file.createVariable('z0', wp, ('time')) - z0_var.units = 'm' - z0_var.standard_name = 'surface_roughness_length_for_momentum_in_air' - z0_var[:] = case_nml['case_config']['sfc_roughness_length_cm']*1.0E-2 - - ts_var = nc_file.createVariable('ts_forc', wp, ('time')) - ts_var.units = 'K' - ts_var.standard_name = 'forcing_surface_temperature' - ts_var[:] = case_data._T_surf[:] + if (nc_file.surface_forcing_lsm != 'lsm'): + + nc_file.surface_forcing_temp = 'ts' + nc_file.surface_forcing_wind = 'z0' + + z0_var = nc_file.createVariable('z0', wp, ('time')) + z0_var.units = 'm' + z0_var.standard_name = 'surface_roughness_length_for_momentum_in_air' + z0_var[:] = case_nml['case_config']['sfc_roughness_length_cm']*1.0E-2 + + ts_var = nc_file.createVariable('ts_forc', wp, ('time')) + ts_var.units = 'K' + ts_var.standard_name = 'forcing_surface_temperature' + ts_var[:] = case_data._T_surf[:] nc_file.close() @@ -820,448 +2547,6 @@ def write_SCM_nml_file(case_nml): return(filename) -######################################################################################## -# -######################################################################################## -def write_SCM_case_file_UFS(state, surface, oro, forcing, case, date, vertical_forcing): - """Write all data to a netCDF file in the DEPHY-SCM format""" - - # Working types - wp = np.float64 - wi = np.int32 - - # Local switches - forcing_on = 1 - forcing_off = 0 - - # Output file - com = 'mkdir -p ' + PROCESSED_CASE_DIR - print(com) - os.system(com) - fileOUT = os.path.join(PROCESSED_CASE_DIR, case + '_SCM_driver.nc') - - nc_file = Dataset(fileOUT, 'w', format='NETCDF3_CLASSIC') - nc_file.description = "FV3GFS model profile input (UFS forcings)" - - nc_file.missing_value = missing_value - - start_date = datetime(date["year"],date["month"],date["day"],date["hour"],date["minute"],date["second"]) - - # - # Create surface type string (Saved as GLOBAL attribute) - # - if surface["slmsk"] > 1.5: - surface_string = 'ice' - elif surface["slmsk"] > 0.5: - surface_string = 'land' - else: - surface_string = 'ocean' - - # - # Global file attributes. - # - runtime = timedelta(seconds=forcing['time'][-1]) - end_date = start_date + runtime - end_date_string = end_date.strftime("%Y-%m-%d %H:%M:%S") - start_date_string = start_date.strftime("%Y-%m-%d %H:%M:%S") - # - loc_string = str(round(surface["lon"],2)) + "E" + str(round(surface["lat"],2)) + "N" - case_string = 'UFS_' + start_date_string + '_' + loc_string - # - nc_file.case = case_string - nc_file.title = 'Forcing and Initial Conditions for ' + case_string - nc_file.reference = 'https://dtcenter.org/sites/default/files/paragraph/scm-ccpp-guide-v6-0-0.pdf' - nc_file.author = 'Grant J. Firl and Dustin Swales' - nc_file.version = 'Created on ' + datetime.today().strftime('%Y-%m-%d %H:%M:%S') - nc_file.format_version = 'DEPHY SCM format version 1' - nc_file.modifications = '' - nc_file.script = os.path.basename(__file__) - nc_file.comment = '' - nc_file.start_date = start_date_string - nc_file.end_date = end_date_string - nc_file.forcing_scale = -1 - nc_file.radiation = "off" - nc_file.adv_ta = forcing_off - nc_file.adv_qv = forcing_off - nc_file.adv_ua = forcing_off - nc_file.adv_va = forcing_off - nc_file.adv_theta = forcing_off - nc_file.adv_thetal = forcing_off - nc_file.adv_qt = forcing_off - nc_file.adv_rv = forcing_off - nc_file.adv_rt = forcing_off - if (vertical_forcing == 2): - nc_file.forc_wa = forcing_on - else: - nc_file.forc_wa = forcing_off - nc_file.forc_wap = forcing_off - nc_file.forc_geo = forcing_off - nc_file.nudging_ua = forcing_off - nc_file.nudging_va = forcing_off - nc_file.nudging_ta = forcing_off - nc_file.nudging_theta = forcing_off - nc_file.nudging_thetal = forcing_off - nc_file.nudging_qv = forcing_off - nc_file.nudging_qt = forcing_off - nc_file.nudging_rv = forcing_off - nc_file.nudging_rt = forcing_off - nc_file.zh_nudging_ta = forcing_off - nc_file.zh_nudging_theta = forcing_off - nc_file.zh_nudging_thetal = forcing_off - nc_file.zh_nudging_qv = forcing_off - nc_file.zh_nudging_qt = forcing_off - nc_file.zh_nudging_rv = forcing_off - nc_file.zh_nudging_rt = forcing_off - nc_file.zh_nudging_ua = forcing_off - nc_file.zh_nudging_va = forcing_off - nc_file.pa_nudging_ta = forcing_off - nc_file.pa_nudging_theta = forcing_off - nc_file.pa_nudging_thetal = forcing_off - nc_file.pa_nudging_qv = forcing_off - nc_file.pa_nudging_qt = forcing_off - nc_file.pa_nudging_rv = forcing_off - nc_file.pa_nudging_rt = forcing_off - nc_file.pa_nudging_ua = forcing_off - nc_file.pa_nudging_va = forcing_off - # - nc_file.surface_type = surface_string - # - nc_file.adv_ta = forcing_on - nc_file.adv_qv = forcing_on - nc_file.adv_ua = forcing_on - nc_file.adv_va = forcing_on - # - nc_file.surface_forcing_temp = 'none' - nc_file.surface_forcing_moisture = 'none' - nc_file.surface_forcing_wind = 'none' - nc_file.surface_forcing_lsm = 'none' #'noah' #'noahmp' #'ruc' - nc_file.surface_forcing_lsm = 'lsm' - # Set file dimension - time_dim = nc_file.createDimension('time', len(forcing['time'])) - timei_dim = nc_file.createDimension('t0', 1) - lev_dim = nc_file.createDimension('lev', state["nlevs"]) - soil_dim = nc_file.createDimension('nsoil', len(surface["stc"])) - snow_dim = nc_file.createDimension('nsnow', len(surface["snicexy"])) - nslsnw_dim = nc_file.createDimension('nsoil_plus_nsnow',len(surface["snicexy"]) + len(surface["stc"])) - ice_dim = nc_file.createDimension('nice', len(surface["tiice"])) - - # - timei_var = nc_file.createVariable('t0', wp, ('t0')) - timei_var.units = 'seconds since ' + start_date_string - timei_var.standard_name = 'Initial time' - timei_var.calendar = 'gregorian' - timei_var[:] = 0.0 - # - timef_var = nc_file.createVariable('time', wp, ('time')) - timef_var.units = 'seconds since ' + start_date_string - timef_var.standard_name = 'Forcing time' - timef_var.calendar = 'gregorian' - timef_var[:] = forcing['time'] - # - lev_var = nc_file.createVariable('lev', wp, ('lev')) - lev_var.units = 'm' - lev_var.standard_name = 'height' - lev_var[:] = 0.0 - - # - lon_var = nc_file.createVariable('lon', wp, ('time')) - lon_var.units = 'degrees_east' - lon_var.standard_name = 'longitude' - lon_var[:] = surface["lon"] - - # - lat_var = nc_file.createVariable('lat', wp, ('time')) - lat_var.units = 'degrees_north' - lat_var.standard_name = 'latitude' - lat_var[:] = surface["lat"] - - # - soil_depth_var = nc_file.createVariable('soil_depth', wp, ('nsoil')) - soil_depth_var.units = 'm' - soil_depth_var.standard_name = 'depth of bottom of soil layers' - soil_depth_var[:] = [0.1,0.4,1.0,2.0] - # - theta_oro = nc_file.createVariable('theta_oro',wp, ('t0')) - theta_oro.units = "deg" - theta_oro.standard_name = "angle with respect to east of maximum subgrid orographic variations" - theta_oro[:] = oro["theta"] - # - z0_var = nc_file.createVariable('zorl', wp, ('time')) - z0_var.units = "cm" - z0_var.standard_name = 'surface_roughness_length_for_momentum_in_air' - z0_var[:] = surface["z0"] - # - zorlw_var = nc_file.createVariable('zorlw', wp, ('t0')) - zorlw_var.units = "cm" - zorlw_var.standard_name = "surface roughness length over ocean" - zorlw_var[:] = surface["z0"] - # - zorll_var = nc_file.createVariable('zorll', wp, ('t0')) - zorll_var.units = "cm" - zorll_var.standard_name = "surface roughness length over land" - zorll_var[:] = surface["zorll"] - # - zorli_var = nc_file.createVariable('zorli', wp, ('t0')) - zorli_var.units = "cm" - zorli_var.standard_name = "surface roughness length over ice" - zorli_var[:] = surface["zorli"] - # - zorlwav_var = nc_file.createVariable('zorlwav', wp, ('time')) - zorlwav_var.units = "cm" - zorlwav_var.standard_name = 'surface_roughness_length_from_wave_model' - zorlwav_var[:] = surface["zorlw"] - - # - # Variables to be output to SCM input file. Only fields that come directly from forcing, - # surface, state, and oro. Fields that get renamed are done above. - # - dict = {} - dict.update(date) - dict.update(surface) - dict.update(state) - dict.update(oro) - dict.update(forcing) - - ######################################################################################## - # - # Dictonary format: - # {"name": "", "type", "dimd": (), "units": "", "desc": ""} - # - ######################################################################################## - var_dict = [{"name": "orog", "type":wp, "dimd": ('t0' ), "units": "m", "desc": "surface_altitude"},\ - {"name": "zh", "type":wp, "dimd": ('t0', 'lev'), "units": "m", "desc": "height"},\ - {"name": "pa", "type":wp, "dimd": ('t0', 'lev'), "units": "Pa", "desc": "air_pressure"}, \ - {"name": "ta", "type":wp, "dimd": ('t0', 'lev'), "units": "K", "desc": "air_temperature"}, \ - {"name": "theta", "type":wp, "dimd": ('t0', 'lev'), "units": "K", "desc": "air_potential_temperature"}, \ - {"name": "thetal", "type":wp, "dimd": ('t0', 'lev'), "units": "K", "desc": "air_liquid_potential_temperature"}, \ - {"name": "rv", "type":wp, "dimd": ('t0', 'lev'), "units": "kg kg-1", "desc": "humidity_mixing_ratio"}, \ - {"name": "rl", "type":wp, "dimd": ('t0', 'lev'), "units": "kg kg-1", "desc": "cloud_liquid_water_mixing_ratio"}, \ - {"name": "ri", "type":wp, "dimd": ('t0', 'lev'), "units": "kg kg-1", "desc": "cloud_ice_water_mixing_ratio"}, \ - {"name": "rt", "type":wp, "dimd": ('t0', 'lev'), "units": "kg kg-1", "desc": "water_mixing_ratio"}, \ - {"name": "qv", "type":wp, "dimd": ('t0', 'lev'), "units": "kg kg-1", "desc": "specific_humidity"}, \ - {"name": "ql", "type":wp, "dimd": ('t0', 'lev'), "units": "kg kg-1", "desc": "mass_fraction_of_cloud_liquid_water_in_air"}, \ - {"name": "qi", "type":wp, "dimd": ('t0', 'lev'), "units": "kg kg-1", "desc": "mass_fraction_of_cloud_ice_water_in_air", "default_value": 0.0}, \ - {"name": "qt", "type":wp, "dimd": ('t0', 'lev'), "units": "kg kg-1", "desc": "mass_fraction_of_water_in_air"}, \ - {"name": "hur", "type":wp, "dimd": ('t0', 'lev'), "units": "%", "desc": "relative_humidity"}, \ - {"name": "tke", "type":wp, "dimd": ('t0', 'lev'), "units": "m2 s-2", "desc": "specific_turbulen_kinetic_energy", "default_value": 0.0}, \ - {"name": "ua", "type":wp, "dimd": ('t0', 'lev'), "units": "m s-1", "desc": "eastward_wind"}, \ - {"name": "va", "type":wp, "dimd": ('t0', 'lev'), "units": "m s-1", "desc": "northward_wind"}, \ - {"name": "ts", "type":wp, "dimd": ('t0' ), "units": "K", "desc": "surface_temperature"},\ - {"name": "tskin", "type":wp, "dimd": ('t0' ), "units": "K", "desc": "surface_skin_temperature"}, \ - {"name": "ps", "type":wp, "dimd": ('t0' ), "units": "Pa", "desc": "surface_air_pressure"}, \ - {"name": "beta", "type":wp, "dimd": ('t0' ), "units": "m", "desc": "soil_water_stress_factor"}, \ - {"name": "mrsos", "type":wp, "dimd": ('t0' ), "units": "kg m-2", "desc": "mass_content_of_water_in_soil_layer"}, \ - {"name": "o3", "type":wp, "dimd": ('t0', 'lev'), "units": "kg kg-1", "desc": "mole_fraction_of_ozone_in_air"}, \ - {"name": "sza", "type":wp, "dimd": ('t0' ), "units": "degree", "desc": "solar_zenith_angle"}, \ - {"name": "io", "type":wp, "dimd": ('t0' ), "units": "W m-2", "desc": "solar_irradiance"}, \ - {"name": "alb", "type":wp, "dimd": ('t0' ), "units": "1", "desc": "surface_albedo"}, \ - {"name": "emis", "type":wp, "dimd": ('t0' ), "units": "1", "desc": "surface_longwave_emissivity"}, \ - {"name": "slmsk", "type":wp, "dimd": ('t0' ), "units": "none", "desc": "land_sea_ice_mask"}] - # - var_frc = [{"name": "zh_forc", "type":wp, "dimd": ('time', 'lev'), "units": "m", "desc": "height_forcing","default_value": 1.},\ - {"name": "pa_forc", "type":wp, "dimd": ('time', 'lev'), "units": "Pa", "desc": "air_pressure_forcing"}, \ - {"name": "wa", "type":wp, "dimd": ('time', 'lev'), "units": "m s-1", "desc": "upward_air_velocity"}, \ - {"name": "wap", "type":wp, "dimd": ('time', 'lev'), "units": "Pa s-1", "desc": "lagrangian_tendency_of_air_pressure"}, \ - {"name": "ug", "type":wp, "dimd": ('time', 'lev'), "units": "m s-1", "desc": "geostrophic_eastward_wind"}, \ - {"name": "vg", "type":wp, "dimd": ('time', 'lev'), "units": "m s-1", "desc": "geostrophic_northward_wind"}, \ - {"name": "tnua_adv", "type":wp, "dimd": ('time', 'lev'), "units": "m s-2", "desc": "tendency_of_eastward_wind_due_to_advection"},\ - {"name": "tnva_adv", "type":wp, "dimd": ('time', 'lev'), "units": "m s-2", "desc": "tendency_of_northward_wind_due_to_advection"}, \ - {"name": "tnta_adv", "type":wp, "dimd": ('time', 'lev'), "units": "K s-1", "desc": "tendency_of_air_temperature_due_to_advection"}, \ - {"name": "tntheta_adv", "type":wp, "dimd": ('time', 'lev'), "units": "K s-1", "desc": "tendency_of_air_potential_temperature_due_to_advection"}, \ - {"name": "tnthetal_adv", "type":wp, "dimd": ('time', 'lev'), "units": "K s-1", "desc": "tendency_of_air_liquid_potential_temperature_due_to_advection"}, \ - {"name": "tnqv_adv", "type":wp, "dimd": ('time', 'lev'), "units": "kg kg-1 s-1", "desc": "tendency_of_specific_humidity_due_to_advection"},\ - {"name": "tnqt_adv", "type":wp, "dimd": ('time', 'lev'), "units": "kg kg-1 s-1", "desc": "tendency_of_mass_fraction_of_water_in_air_due_to_advection"},\ - {"name": "tnrv_adv", "type":wp, "dimd": ('time', 'lev'), "units": "kg kg-1 s-1", "desc": "tendency_of_humidity_mixing_ratio_due_to_advection"},\ - {"name": "tnrt_adv", "type":wp, "dimd": ('time', 'lev'), "units": "kg kg-1 s-1", "desc": "tendency_of_water_mixing_ratio_due_to_advection"},\ - {"name": "tnta_rad", "type":wp, "dimd": ('time', 'lev'), "units": "K s-1", "desc": "tendency_of_air_temperature_due_to_radiative_heating"}, \ - {"name": "tntheta_rad", "type":wp, "dimd": ('time', 'lev'), "units": "K s-1", "desc": "tendency_of_potential_air_temperature_due_to_radiative_heating"}, \ - {"name": "tnthetal_rad", "type":wp, "dimd": ('time', 'lev'), "units": "K s-1", "desc": "tendency_of_air_liquid_potential_temperature_due_to_radiative_heating"}, \ - {"name": "ta_nud", "type":wp, "dimd": ('time', 'lev'), "units": "K", "desc": "nudging_air_temperature"}, \ - {"name": "theta_nud", "type":wp, "dimd": ('time', 'lev'), "units": "K", "desc": "nudging_air_potential_temperature"}, \ - {"name": "thetal_nud", "type":wp, "dimd": ('time', 'lev'), "units": "K", "desc": "nudging_air_liquid_potential_temperature"}, \ - {"name": "qt_nud", "type":wp, "dimd": ('time', 'lev'), "units": "kg kg-1", "desc": "nudging_mass_fraction_of_water_in_air"}, \ - {"name": "rv_nud", "type":wp, "dimd": ('time', 'lev'), "units": "m s-1", "desc": "nudging_humidity_mixing_ratio"}, \ - {"name": "rt_nud", "type":wp, "dimd": ('time', 'lev'), "units": "m s-1", "desc": "nudging_water_mixing_ratio"}, \ - {"name": "ua_nud", "type":wp, "dimd": ('time', 'lev'), "units": "m s-1", "desc": "nudging_eastward_wind"}, \ - {"name": "va_nud", "type":wp, "dimd": ('time', 'lev'), "units": "m s-1", "desc": "nudging_northward_wind"}, \ - {"name": "hfss", "type":wp, "dimd": ('time' ), "units": "W m-2", "desc": "surface_upward_sensible_heat_flux"}, \ - {"name": "hfls", "type":wp, "dimd": ('time' ), "units": "W m-2", "desc": "surface_upward_latent_heat_flux"}, \ - {"name": "wpthetap_s", "type":wp, "dimd": ('time' ), "units": "K m s-1", "desc": "surface_upward_potential_temperature_flux"}, \ - {"name": "wpqvp_s", "type":wp, "dimd": ('time' ), "units": "m s-1", "desc": "surface_upward_specific_humidity_flux"}, \ - {"name": "wpqtp_s", "type":wp, "dimd": ('time' ), "units": "m s-1", "desc": "surface_upward_water_mass_fraction_flux"}, \ - {"name": "wprvp_s", "type":wp, "dimd": ('time' ), "units": "m s-1", "desc": "surface_upward_humidity_mixing_ratio_flux"}, \ - {"name": "wprtp_s", "type":wp, "dimd": ('time' ), "units": "m s-1", "desc": "surface_upward_water_mixing_ratio_flux"}, \ - {"name": "ts_forc", "type":wp, "dimd": ('time' ), "units": "K", "desc": "forcing_surface_temperature"},\ - {"name": "ps_forc", "type":wp, "dimd": ('time' ), "units": "Pa", "desc": "forcing_surface_air_pressure"},\ - {"name": "uustar", "type":wp, "dimd": ('time' ), "units": "m s-1", "desc": "surface_friction_velocity"}, \ - {"name": "z0h", "type":wp, "dimd": ('time' ), "units": "m", "desc": "surface_roughness_length_for_heat_in_air"}, \ - {"name": "z0q", "type":wp, "dimd": ('time' ), "units": "m", "desc": "surface_roughness_length_for_humidity_in_air"}, \ - {"name": "mrsos_forc", "type":wp, "dimd": ('time' ), "units": "kg m-2", "desc": "forcing_mass_content_of_water_in_soil_layer"}] - - # - var_oro = [{"name": "area", "type":wp, "dimd": ('t0'), "units": "m2", "desc": "grid_cell_area"},\ - {"name": "stddev", "type":wp, "dimd": ('t0'), "units": "m", "desc": "standard deviation of subgrid orography"}, \ - {"name": "convexity", "type":wp, "dimd": ('t0'), "units": "none", "desc": "convexity of subgrid orography"}, \ - {"name": "oa1", "type":wp, "dimd": ('t0'), "units": "none", "desc": "assymetry of subgrid orography 1"}, \ - {"name": "oa2", "type":wp, "dimd": ('t0'), "units": "none", "desc": "assymetry of subgrid orography 2"}, \ - {"name": "oa3", "type":wp, "dimd": ('t0'), "units": "none", "desc": "assymetry of subgrid orography 3"}, \ - {"name": "oa4", "type":wp, "dimd": ('t0'), "units": "none", "desc": "assymetry of subgrid orography 4"}, \ - {"name": "ol1", "type":wp, "dimd": ('t0'), "units": "none", "desc": "fraction of grid box with subgrid orography higher than critical height 1"}, \ - {"name": "ol2", "type":wp, "dimd": ('t0'), "units": "none", "desc": "fraction of grid box with subgrid orography higher than critical height 2"}, \ - {"name": "ol3", "type":wp, "dimd": ('t0'), "units": "none", "desc": "fraction of grid box with subgrid orography higher than critical height 3"}, \ - {"name": "ol4", "type":wp, "dimd": ('t0'), "units": "none", "desc": "fraction of grid box with subgrid orography higher than critical height 4"}, \ - {"name": "sigma", "type":wp, "dimd": ('t0'), "units": "none", "desc": "slope of subgrid orography"}, \ - {"name": "gamma", "type":wp, "dimd": ('t0'), "units": "none", "desc": "anisotropy of subgrid orography"}, \ - {"name": "elvmax", "type":wp, "dimd": ('t0'), "units": "m", "desc": "maximum of subgrid orography"}, \ - {"name": "oro", "type":wp, "dimd": ('t0'), "units": "m", "desc": "orography"}, \ - {"name": "oro_uf", "type":wp, "dimd": ('t0'), "units": "m", "desc": "unfiltered orography"}, \ - {"name": "landfrac", "type":wp, "dimd": ('t0'), "units": "none", "desc": "fraction of horizontal grid area occupied by land"}, \ - {"name": "lakefrac", "type":wp, "dimd": ('t0'), "units": "none", "desc": "fraction of horizontal grid area occupied by lake", "default_value":0}, \ - {"name": "lakedepth", "type":wp, "dimd": ('t0'), "units": "none", "desc": "lake depth", "default_value":0}] - # - var_nsst = [{"name": "tref", "type":wp, "dimd": ('t0'), "units": "K", "desc": "sea surface reference temperature for NSST"}, \ - {"name": "z_c", "type":wp, "dimd": ('t0'), "units": "m", "desc": "sub-layer cooling thickness for NSST"}, \ - {"name": "c_0", "type":wp, "dimd": ('t0'), "units": "none", "desc": "coefficient 1 to calculate d(Tz)/d(Ts) for NSST"}, \ - {"name": "c_d", "type":wp, "dimd": ('t0'), "units": "nonw", "desc": "coefficient 2 to calculate d(Tz)/d(Ts) for NSST"}, \ - {"name": "w_0", "type":wp, "dimd": ('t0'), "units": "none", "desc": "coefficient 3 to calculate d(Tz)/d(Ts) for NSST"}, \ - {"name": "w_d", "type":wp, "dimd": ('t0'), "units": "none", "desc": "coefficient 4 to calculate d(Tz)/d(Ts) for NSST"}, \ - {"name": "xt", "type":wp, "dimd": ('t0'), "units": "K m", "desc": "heat content in diurnal thermocline layer for NSST"}, \ - {"name": "xs", "type":wp, "dimd": ('t0'), "units": "ppt m", "desc": "salinity content in diurnal thermocline layer for NSST"}, \ - {"name": "xu", "type":wp, "dimd": ('t0'), "units": "m2 s-1", "desc": "u-current in diurnal thermocline layer for NSST"}, \ - {"name": "xv", "type":wp, "dimd": ('t0'), "units": "m2 s-1", "desc": "v-current in diurnal thermocline layer for NSST"}, \ - {"name": "xz", "type":wp, "dimd": ('t0'), "units": "m", "desc": "thickness of diurnal thermocline layer for NSST"}, \ - {"name": "zm" , "type":wp, "dimd": ('t0'), "units": "m", "desc": "thickness of ocean mixed layer for NSST"}, \ - {"name": "xtts", "type":wp, "dimd": ('t0'), "units": "m", "desc": "sensitivity of diurnal thermocline layer heat content to surface temperature [d(xt)/d(ts)] for NSST"},\ - {"name": "xzts", "type":wp, "dimd": ('t0'), "units": "m K-1", "desc": "sensitivity of diurnal thermocline layer thickness to surface temperature [d(xz)/d(ts)] for NSST"}, \ - {"name": "d_conv", "type":wp, "dimd": ('t0'), "units": "m", "desc": "thickness of free convection layer for NSST"}, \ - {"name": "ifd", "type":wp, "dimd": ('t0'), "units": "none", "desc": "index to start DTM run for NSST"}, \ - {"name": "dt_cool", "type":wp, "dimd": ('t0'), "units": "K", "desc": "sub-layer cooling amount for NSST"}, \ - {"name": "qrain", "type":wp, "dimd": ('t0'), "units": "W m-2", "desc": "sensible heat due to rainfall for NSST"}] - # - var_frgd = [{"name": "tiice", "type":wp, "dimd": ('t0','nice'), "units": "K", "desc": "sea ice internal temperature"}] - # - var_noah = [{"name": "vegsrc", "type":wi, "dimd": ('t0'), "units": "none", "desc": "vegetation source (1-2)", "default_value": 1}, \ - {"name": "tsfco", "type":wp, "dimd": ('t0'), "units": "K", "desc": "sea/skin/ice surface temperature"}, \ - {"name": "weasd", "type":wp, "dimd": ('t0'), "units": "mm", "desc": "water equivalent accumulated snow depth"}, \ - {"name": "tg3", "type":wp, "dimd": ('t0'), "units": "K", "desc": "deep soil temperature"}, \ - {"name": "alvsf", "type":wp, "dimd": ('t0'), "units": "none", "desc": "60 degree vis albedo with strong cosz dependency"}, \ - {"name": "alnsf", "type":wp, "dimd": ('t0'), "units": "none", "desc": "60 degree nir albedo with strong cosz dependency"}, \ - {"name": "alvwf", "type":wp, "dimd": ('t0'), "units": "none", "desc": "60 degree vis albedo with weak cosz dependency"}, \ - {"name": "alnwf", "type":wp, "dimd": ('t0'), "units": "none", "desc": "60 degree nir albedo with weak cosz dependency"}, \ - {"name": "facsf", "type":wp, "dimd": ('t0'), "units": "none", "desc": "fractional coverage with strong cosz dependency"}, \ - {"name": "facwf", "type":wp, "dimd": ('t0'), "units": "none", "desc": "fractional coverage with weak cosz dependency"}, \ - {"name": "vegfrac", "type":wp, "dimd": ('t0'), "units": "none", "desc": "vegetation fraction"}, \ - {"name": "canopy", "type":wp, "dimd": ('t0'), "units": "kg m-2", "desc": "amount of water stored in canopy"}, \ - {"name": "f10m", "type":wp, "dimd": ('t0'), "units": "none", "desc": "ratio of sigma level 1 wind and 10m wind"}, \ - {"name": "t2m", "type":wp, "dimd": ('t0'), "units": "K", "desc": "2-meter absolute temperature"}, \ - {"name": "q2m", "type":wp, "dimd": ('t0'), "units": "kg kg-1", "desc": "2-meter specific humidity"}, \ - {"name": "vegtyp", "type":wi, "dimd": ('t0'), "units": "none", "desc": "vegetation type (1-12)"}, \ - {"name": "soiltyp", "type":wi, "dimd": ('t0'), "units": "none", "desc": "soil type (1-12)"}, \ - {"name": "scolor", "type":wp, "dimd": ('t0'), "units": "none", "desc": "soil color"}, \ - {"name": "ffmm", "type":wp, "dimd": ('t0'), "units": "none", "desc": "Monin-Obukhov similarity function for momentum"}, \ - {"name": "ffhh", "type":wp, "dimd": ('t0'), "units": "none", "desc": "Monin-Obukhov similarity function for heat"}, \ - {"name": "hice", "type":wp, "dimd": ('t0'), "units": "m", "desc": "sea ice thickness"}, \ - {"name": "fice", "type":wp, "dimd": ('t0'), "units": "none", "desc": "ice fraction"}, \ - {"name": "tisfc", "type":wp, "dimd": ('t0'), "units": "K", "desc": "ice surface temperature"}, \ - {"name": "tprcp", "type":wp, "dimd": ('t0'), "units": "m", "desc": "instantaneous total precipitation amount"}, \ - {"name": "srflag", "type":wp, "dimd": ('t0'), "units": "none", "desc": "snow/rain flag for precipitation"}, \ - {"name": "snowd", "type":wp, "dimd": ('t0'), "units": "mm", "desc": "water equivalent snow depth"}, \ - {"name": "shdmin", "type":wp, "dimd": ('t0'), "units": "none", "desc": "minimum vegetation fraction"}, \ - {"name": "shdmax", "type":wp, "dimd": ('t0'), "units": "none", "desc": "maximum vegetation fraction"}, \ - {"name": "slopetyp", "type":wi, "dimd": ('t0'), "units": "none", "desc": "slope type (1-9)"}, \ - {"name": "snoalb", "type":wp, "dimd": ('t0'), "units": "none", "desc": "maximum snow albedo"}, \ - {"name": "sncovr", "type":wp, "dimd": ('t0'), "units": "none", "desc": "surface snow area fraction"}, \ - {"name": "tsfcl", "type":wp, "dimd": ('t0'), "units": "K", "desc": "surface skin temperature over land"}, \ - {"name": "stc", "type":wp, "dimd": ('t0','nsoil'), "units": "K", "desc": "initial profile of soil liquid moisture"}, \ - {"name": "smc", "type":wp, "dimd": ('t0','nsoil'), "units": "kg", "desc": "initial profile of soil moisture"}, \ - {"name": "slc", "type":wp, "dimd": ('t0','nsoil'), "units": "kg", "desc": "initial profile of soil temperature"}] - # - var_noahmp=[{"name": "tvxy", "type":wp, "dimd": ('t0'), "units": "K", "desc": "vegetation temperature for NoahMP"}, \ - {"name": "tgxy", "type":wp, "dimd": ('t0'), "units": "K", "desc": "ground temperature for NoahMP"}, \ - {"name": "tahxy", "type":wp, "dimd": ('t0'), "units": "K", "desc": "canopy air temperature for NoahMP"}, \ - {"name": "canicexy", "type":wp, "dimd": ('t0'), "units": "mm", "desc": "canopy intercepted ice mass for NoahMP"}, \ - {"name": "canliqxy", "type":wp, "dimd": ('t0'), "units": "mm", "desc": "canopy intercepted liquid water for NoahMP"}, \ - {"name": "eahxy", "type":wp, "dimd": ('t0'), "units": "Pa", "desc": "canopy air vapor pressure for NoahMP"}, \ - {"name": "cmxy", "type":wp, "dimd": ('t0'), "units": "none", "desc": "surface drag coefficient for momentum for NoahMP"}, \ - {"name": "chxy", "type":wp, "dimd": ('t0'), "units": "none", "desc": "surface exchange coeff heat & moisture for NoahMP"}, \ - {"name": "fwetxy", "type":wp, "dimd": ('t0'), "units": "none", "desc": "area fraction of canopy that is wetted/snowed for NoahMP"}, \ - {"name": "sneqvoxy", "type":wp, "dimd": ('t0'), "units": "mm", "desc": "snow mass at previous time step for NoahMP"}, \ - {"name": "alboldxy", "type":wp, "dimd": ('t0'), "units": "none", "desc": "snow albedo at previous time step for NoahMP"}, \ - {"name": "qsnowxy", "type":wp, "dimd": ('t0'), "units": "mm s-1", "desc": "snow precipitation rate at surface for NoahMP"}, \ - {"name": "wslakexy", "type":wp, "dimd": ('t0'), "units": "mm", "desc": "lake water storage for NoahMP"}, \ - {"name": "taussxy", "type":wp, "dimd": ('t0'), "units": "none", "desc": "non-dimensional snow age for NoahMP"}, \ - {"name": "waxy", "type":wp, "dimd": ('t0'), "units": "mm", "desc": "water storage in aquifer for NoahMP"}, \ - {"name": "wtxy", "type":wp, "dimd": ('t0'), "units": "mm", "desc": "water storage in aquifer and saturated soil for NoahMP"}, \ - {"name": "zwtxy", "type":wp, "dimd": ('t0'), "units": "m", "desc": "water table depth for NoahMP"}, \ - {"name": "xlaixy", "type":wp, "dimd": ('t0'), "units": "none", "desc": "leaf area index for NoahMP"}, \ - {"name": "xsaixy", "type":wp, "dimd": ('t0'), "units": "none", "desc": "stem area index for NoahMP"}, \ - {"name": "lfmassxy", "type":wp, "dimd": ('t0'), "units": "g m-2", "desc": "leaf mass for NoahMP"}, \ - {"name": "stmassxy", "type":wp, "dimd": ('t0'), "units": "g m-2", "desc": "stem mass for NoahMP"}, \ - {"name": "rtmassxy", "type":wp, "dimd": ('t0'), "units": "g m-2", "desc": "fine root mass for NoahMP"}, \ - {"name": "woodxy", "type":wp, "dimd": ('t0'), "units": "g m-2", "desc": "wood mass including woody roots for NoahMP"}, \ - {"name": "stblcpxy", "type":wp, "dimd": ('t0'), "units": "g m-2", "desc": "stable carbon in deep soil for NoahMP"}, \ - {"name": "fastcpxy", "type":wp, "dimd": ('t0'), "units": "g m-2", "desc": "short-lived carbon in shallow soil for NoahMP"}, \ - {"name": "smcwtdxy", "type":wp, "dimd": ('t0'), "units": "m3 m-3", "desc": "soil water content between the bottom of the soil and the water table for NoahMP"}, \ - {"name": "deeprechxy", "type":wp, "dimd": ('t0'), "units": "m", "desc": "recharge to or from the water table when deep for NoahMP"}, \ - {"name": "rechxy", "type":wp, "dimd": ('t0'), "units": "m", "desc": "recharge to or from the water table when shallow for NoahMP"}, \ - {"name": "snowxy", "type":wp, "dimd": ('t0'), "units": "none", "desc": "number of snow layers for NoahMP"}, \ - {"name": "snicexy", "type":wp, "dimd": ('t0','nsnow'), "units": "mm", "desc": "initial profile of snow layer ice"}, \ - {"name": "snliqxy", "type":wp, "dimd": ('t0','nsnow'), "units": "mm", "desc": "initial profile of snow layer liquid"}, \ - {"name": "tsnoxy", "type":wp, "dimd": ('t0','nsnow'), "units": "K", "desc": "initial profile of snow layer temperature"}, \ - {"name": "smoiseq", "type":wp, "dimd": ('t0','nsoil'), "units": "m3 m-3", "desc": "initial profile of equilibrium soil water content"}, \ - {"name": "zsnsoxy", "type":wp, "dimd": ('t0','nsoil_plus_nsnow'), "units": "m","desc": "layer bottom depth from snow surface"}] - # - var_ruc = [{"name": "wetness", "type":wp, "dimd": ('t0'), "units": "none", "desc": "normalized soil wetness for RUC LSM"}, \ - {"name": "lai", "type":wp, "dimd": ('t0'), "units": "none", "desc": "leaf area index for RUC LSM"}, \ - {"name": "clw_surf_land", "type":wp, "dimd": ('t0'), "units": "kg kg-1", "desc": "cloud condensed water mixing ratio at surface over land for RUC LSM"},\ - {"name": "clw_surf_ice", "type":wp, "dimd": ('t0'), "units": "kg kg-1", "desc": "cloud condensed water mixing ratio at surface over ice for RUC LSM"},\ - {"name": "qwv_surf_land", "type":wp, "dimd": ('t0'), "units": "kg kg-1", "desc": "water vapor mixing ratio at surface over land for RUC LSM"},\ - {"name": "qwv_surf_ice", "type":wp, "dimd": ('t0'), "units": "kg kg-1", "desc": "water vapor mixing ratio at surface over ice for RUC LSM"},\ - {"name": "tsnow_land", "type":wp, "dimd": ('t0'), "units": "K", "desc": "snow temperature at the bottom of the first snow layer over land for RUC LSM"},\ - {"name": "tsnow_ice", "type":wp, "dimd": ('t0'), "units": "K", "desc": "snow temperature at the bottom of the first snow layer over ice for RUC LSM"},\ - {"name": "snowfall_acc_land","type":wp, "dimd": ('t0'), "units": "kg m-2", "desc": "run-total snow accumulation on the ground over land for RUC LSM"},\ - {"name": "snowfall_acc_ice", "type":wp, "dimd": ('t0'), "units": "kg m-2", "desc": "run-total snow accumulation on the ground over ice for RUC LSM"},\ - {"name": "sfalb_lnd", "type":wp, "dimd": ('t0'), "units": "none", "desc": "surface albedo over land for RUC LSM"},\ - {"name": "sfalb_lnd_bck", "type":wp, "dimd": ('t0'), "units": "none", "desc": "surface snow-free albedo over land for RUC LSM"},\ - {"name": "sfalb_ice", "type":wp, "dimd": ('t0'), "units": "none", "desc": "surface albedo over ice for RUC LSM"},\ - {"name": "emis_lnd", "type":wp, "dimd": ('t0'), "units": "none", "desc": "surface emissivity over land for RUC LSM"},\ - {"name": "emis_ice", "type":wp, "dimd": ('t0'), "units": "none", "desc": "surface emissivity over ice for RUC LSM"}, \ - {"name": "tslb", "type":wp, "dimd": ('t0','nsoil'), "units": "K", "desc": "soil temperature for RUC LSM"}, \ - {"name": "smois", "type":wp, "dimd": ('t0','nsoil'), "units": "none", "desc": "volume fraction of soil moisture for RUC LSM"}, \ - {"name": "sh2o", "type":wp, "dimd": ('t0','nsoil'), "units": "none", "desc": "volume fraction of unfrozen soil moisture for RUC LSM"}, \ - {"name": "smfr", "type":wp, "dimd": ('t0','nsoil'), "units": "none", "desc": "volume fraction of frozen soil moisture for RUC LSM"}, - {"name": "flfr", "type":wp, "dimd": ('t0','nsoil'), "units": "none", "desc": "flag for frozen soil physics for RUC LSM"}] - - # - var_dict.extend(var_frc) - var_dict.extend(var_oro) - var_dict.extend(var_nsst) - var_dict.extend(var_frgd) - var_dict.extend(var_ruc) - var_dict.extend(var_noah) - var_dict.extend(var_noahmp) - - # - for var in var_dict: - if (var["name"] in dict): - var_temp = nc_file.createVariable(var["name"], var["type"], var["dimd"]) - var_temp.units = var["units"] - var_temp.standard_name = var["desc"] - var_temp[:] = dict[var["name"]] - elif "default_value" in var: - var_temp = nc_file.createVariable(var["name"], var["type"], var["dimd"]) - var_temp.units = var["units"] - var_temp.standard_name = var["desc"] - var_temp[:] = var["default_value"] - if "override" in var: - var_temp[:] = var["default_value"] - # - # Close file - # - nc_file.close() - - return(fileOUT) - ######################################################################################## # ######################################################################################## diff --git a/scm/src/scm_input.F90 b/scm/src/scm_input.F90 index 73f277717..1b2dab265 100644 --- a/scm/src/scm_input.F90 +++ b/scm/src/scm_input.F90 @@ -1162,6 +1162,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) real(kind=sp) :: exner, exner_inv, rho, elapsed_sec, missing_value_eps real(kind=dp) :: rinc(5) integer :: jdat(1:8), idat(1:8) !(yr, mon, day, t-zone, hr, min, sec, mil-sec) + logical :: needed_for_lsm_ics, needed_for_model_ics integer :: input_n_init_times, input_n_forcing_times, input_n_lev, input_n_snow, input_n_ice, input_n_soil @@ -1302,15 +1303,16 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) input_ri (input_n_lev, input_n_init_times), & input_rh (input_n_lev, input_n_init_times), & input_tke (input_n_lev, input_n_init_times), & + input_ozone (input_n_lev, input_n_init_times), & stat=allocate_status) if (trim(input_surfaceForcingLSM) == "lsm") then !if model ICs are included in the file scm_state%lsm_ics = .true. + endif !variables with vertical extent - allocate(input_ozone (input_n_lev, input_n_init_times), & - input_stc (input_n_soil, input_n_init_times), & + allocate(input_stc (input_n_soil, input_n_init_times), & input_smc (input_n_soil, input_n_init_times), & input_slc (input_n_soil, input_n_init_times), & input_snicexy (input_n_snow, input_n_init_times), & @@ -1452,8 +1454,12 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) input_sfalb_ice ( input_n_init_times), & input_emis_ice ( input_n_init_times), & stat=allocate_status) - end if - + + needed_for_lsm_ics = .False. + needed_for_model_ics = .False. + if (scm_state%lsm_ics .or. trim(input_surfaceForcingLSM) == "lsm") needed_for_lsm_ics = .True. + if (scm_state%model_ics) needed_for_model_ics = .True. + !> - Read in the initial profiles. call NetCDF_read_var(ncid, "pa", .True., input_pres) call NetCDF_read_var(ncid, "zh", .True., input_height) @@ -1477,53 +1483,53 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) call NetCDF_read_var(ncid, "ri", .False., input_ri) call NetCDF_read_var(ncid, "hur", .False., input_rh) - call NetCDF_read_var(ncid, "tke", .True., input_tke) + call NetCDF_read_var(ncid, "tke", .False., input_tke) - if (trim(input_surfaceForcingLSM) == "lsm") then - call NetCDF_read_var(ncid, "o3", .True., input_ozone) - call NetCDF_read_var(ncid, "area", .True., input_area) + + call NetCDF_read_var(ncid, "o3", .False., input_ozone) + call NetCDF_read_var(ncid, "area", .False., input_area) - !orographic parameters - call NetCDF_read_var(ncid, "stddev", .True., input_stddev) - call NetCDF_read_var(ncid, "convexity", .True., input_convexity) - call NetCDF_read_var(ncid, "oa1", .True., input_oa1) - call NetCDF_read_var(ncid, "oa2", .True., input_oa2) - call NetCDF_read_var(ncid, "oa3", .True., input_oa3) - call NetCDF_read_var(ncid, "oa4", .True., input_oa4) - call NetCDF_read_var(ncid, "ol1", .True., input_ol1) - call NetCDF_read_var(ncid, "ol2", .True., input_ol2) - call NetCDF_read_var(ncid, "ol3", .True., input_ol3) - call NetCDF_read_var(ncid, "ol4", .True., input_ol4) - call NetCDF_read_var(ncid, "theta_oro", .True., input_theta_oro) - call NetCDF_read_var(ncid, "gamma", .True., input_gamma) - call NetCDF_read_var(ncid, "sigma", .True., input_sigma) - call NetCDF_read_var(ncid, "elvmax", .True., input_elvmax) - call NetCDF_read_var(ncid, "oro", .True., input_oro) - call NetCDF_read_var(ncid, "oro_uf", .True., input_oro_uf) - call NetCDF_read_var(ncid, "landfrac", .True., input_landfrac) - call NetCDF_read_var(ncid, "lakefrac", .True., input_lakefrac) - call NetCDF_read_var(ncid, "lakedepth", .True., input_lakedepth) + !orographic parameters + call NetCDF_read_var(ncid, "stddev", needed_for_model_ics, input_stddev) + call NetCDF_read_var(ncid, "convexity", needed_for_model_ics, input_convexity) + call NetCDF_read_var(ncid, "oa1", needed_for_model_ics, input_oa1) + call NetCDF_read_var(ncid, "oa2", needed_for_model_ics, input_oa2) + call NetCDF_read_var(ncid, "oa3", needed_for_model_ics, input_oa3) + call NetCDF_read_var(ncid, "oa4", needed_for_model_ics, input_oa4) + call NetCDF_read_var(ncid, "ol1", needed_for_model_ics, input_ol1) + call NetCDF_read_var(ncid, "ol2", needed_for_model_ics, input_ol2) + call NetCDF_read_var(ncid, "ol3", needed_for_model_ics, input_ol3) + call NetCDF_read_var(ncid, "ol4", needed_for_model_ics, input_ol4) + call NetCDF_read_var(ncid, "theta_oro", needed_for_model_ics, input_theta_oro) + call NetCDF_read_var(ncid, "gamma", needed_for_model_ics, input_gamma) + call NetCDF_read_var(ncid, "sigma", needed_for_model_ics, input_sigma) + call NetCDF_read_var(ncid, "elvmax", needed_for_model_ics, input_elvmax) + call NetCDF_read_var(ncid, "oro", needed_for_model_ics, input_oro) + call NetCDF_read_var(ncid, "oro_uf", needed_for_model_ics, input_oro_uf) + call NetCDF_read_var(ncid, "landfrac", needed_for_model_ics, input_landfrac) + call NetCDF_read_var(ncid, "lakefrac", needed_for_model_ics, input_lakefrac) + call NetCDF_read_var(ncid, "lakedepth", needed_for_model_ics, input_lakedepth) - !NSST variables - call NetCDF_read_var(ncid, "tref", .True., input_tref) - call NetCDF_read_var(ncid, "z_c", .True., input_z_c) - call NetCDF_read_var(ncid, "c_0", .True., input_c_0) - call NetCDF_read_var(ncid, "c_d", .True., input_c_d) - call NetCDF_read_var(ncid, "w_0", .True., input_w_0) - call NetCDF_read_var(ncid, "w_d", .True., input_w_d) - call NetCDF_read_var(ncid, "xt", .True., input_xt) - call NetCDF_read_var(ncid, "xs", .True., input_xs) - call NetCDF_read_var(ncid, "xu", .True., input_xu) - call NetCDF_read_var(ncid, "xv", .True., input_xv) - call NetCDF_read_var(ncid, "xz", .True., input_xz) - call NetCDF_read_var(ncid, "zm", .True., input_zm) - call NetCDF_read_var(ncid, "xtts", .True., input_xtts) - call NetCDF_read_var(ncid, "xzts", .True., input_xzts) - call NetCDF_read_var(ncid, "d_conv", .True., input_d_conv) - call NetCDF_read_var(ncid, "ifd", .True., input_ifd) - call NetCDF_read_var(ncid, "dt_cool", .True., input_dt_cool) - call NetCDF_read_var(ncid, "qrain", .True., input_qrain) - end if + !NSST variables + call NetCDF_read_var(ncid, "tref", needed_for_model_ics, input_tref) + call NetCDF_read_var(ncid, "z_c", needed_for_model_ics, input_z_c) + call NetCDF_read_var(ncid, "c_0", needed_for_model_ics, input_c_0) + call NetCDF_read_var(ncid, "c_d", needed_for_model_ics, input_c_d) + call NetCDF_read_var(ncid, "w_0", needed_for_model_ics, input_w_0) + call NetCDF_read_var(ncid, "w_d", needed_for_model_ics, input_w_d) + call NetCDF_read_var(ncid, "xt", needed_for_model_ics, input_xt) + call NetCDF_read_var(ncid, "xs", needed_for_model_ics, input_xs) + call NetCDF_read_var(ncid, "xu", needed_for_model_ics, input_xu) + call NetCDF_read_var(ncid, "xv", needed_for_model_ics, input_xv) + call NetCDF_read_var(ncid, "xz", needed_for_model_ics, input_xz) + call NetCDF_read_var(ncid, "zm", needed_for_model_ics, input_zm) + call NetCDF_read_var(ncid, "xtts", needed_for_model_ics, input_xtts) + call NetCDF_read_var(ncid, "xzts", needed_for_model_ics, input_xzts) + call NetCDF_read_var(ncid, "d_conv", needed_for_model_ics, input_d_conv) + call NetCDF_read_var(ncid, "ifd", needed_for_model_ics, input_ifd) + call NetCDF_read_var(ncid, "dt_cool", needed_for_model_ics, input_dt_cool) + call NetCDF_read_var(ncid, "qrain", needed_for_model_ics, input_qrain) + !> - Allocate the forcing variables. @@ -1645,106 +1651,108 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) ! ! Surface forcing Model LSM ICs ! - if (trim(input_surfaceForcingLSM) == "lsm") then - call NetCDF_read_var(ncid, "stc", .True., input_stc) - call NetCDF_read_var(ncid, "smc", .True., input_smc) - call NetCDF_read_var(ncid, "slc", .True., input_slc) - call NetCDF_read_var(ncid, "snicexy", .True., input_snicexy) - call NetCDF_read_var(ncid, "snliqxy", .True., input_snliqxy) - call NetCDF_read_var(ncid, "tsnoxy", .True., input_tsnoxy ) - call NetCDF_read_var(ncid, "smoiseq", .True., input_smoiseq) - call NetCDF_read_var(ncid, "zsnsoxy", .True., input_zsnsoxy) - call NetCDF_read_var(ncid, "tiice", .True., input_tiice) - call NetCDF_read_var(ncid, "tslb", .True., input_tslb ) - call NetCDF_read_var(ncid, "smois", .True., input_smois) - call NetCDF_read_var(ncid, "sh2o", .True., input_sh2o ) - call NetCDF_read_var(ncid, "smfr", .True., input_smfr ) - call NetCDF_read_var(ncid, "flfr", .True., input_flfr ) + + call NetCDF_read_var(ncid, "stc", .False., input_stc) + call NetCDF_read_var(ncid, "smc", .False., input_smc) + call NetCDF_read_var(ncid, "slc", .False., input_slc) + + call NetCDF_read_var(ncid, "tiice", .False., input_tiice) - call NetCDF_read_var(ncid, "vegsrc", .True., input_vegsrc ) - call NetCDF_read_var(ncid, "vegtyp", .True., input_vegtyp ) - call NetCDF_read_var(ncid, "soiltyp", .True., input_soiltyp ) - call NetCDF_read_var(ncid, "scolor", .True., input_scolor) - call NetCDF_read_var(ncid, "slopetyp", .True., input_slopetype) - call NetCDF_read_var(ncid, "tsfco", .True., input_tsfco) - call NetCDF_read_var(ncid, "vegfrac", .True., input_vegfrac) - call NetCDF_read_var(ncid, "shdmin", .True., input_shdmin) - call NetCDF_read_var(ncid, "shdmax", .True., input_shdmax) - call NetCDF_read_var(ncid, "slmsk", .True., input_slmsk) - call NetCDF_read_var(ncid, "canopy", .True., input_canopy) - call NetCDF_read_var(ncid, "hice", .True., input_hice) - call NetCDF_read_var(ncid, "fice", .True., input_fice) - call NetCDF_read_var(ncid, "tisfc", .True., input_tisfc) - call NetCDF_read_var(ncid, "snowd", .True., input_snwdph) - call NetCDF_read_var(ncid, "snoalb", .True., input_snoalb) - call NetCDF_read_var(ncid, "tg3", .True., input_tg3) - call NetCDF_read_var(ncid, "uustar", .True., input_uustar) - call NetCDF_read_var(ncid, "alvsf", .True., input_alvsf) - call NetCDF_read_var(ncid, "alnsf", .True., input_alnsf) - call NetCDF_read_var(ncid, "alvwf", .True., input_alvwf) - call NetCDF_read_var(ncid, "alnwf", .True., input_alnwf) - call NetCDF_read_var(ncid, "facsf", .True., input_facsf) - call NetCDF_read_var(ncid, "facwf", .True., input_facwf) - call NetCDF_read_var(ncid, "weasd", .True., input_weasd) - call NetCDF_read_var(ncid, "f10m", .True., input_f10m) - call NetCDF_read_var(ncid, "t2m", .True., input_t2m) - call NetCDF_read_var(ncid, "q2m", .True., input_q2m) - call NetCDF_read_var(ncid, "ffmm", .True., input_ffmm) - call NetCDF_read_var(ncid, "ffhh", .True., input_ffhh) - call NetCDF_read_var(ncid, "tprcp", .True., input_tprcp) - call NetCDF_read_var(ncid, "srflag", .True., input_srflag) - call NetCDF_read_var(ncid, "sncovr", .True., input_sncovr) - call NetCDF_read_var(ncid, "tsfcl", .True., input_tsfcl) - call NetCDF_read_var(ncid, "zorll", .True., input_zorll) - call NetCDF_read_var(ncid, "zorli", .True., input_zorli) - call NetCDF_read_var(ncid, "zorlw", .True., input_zorlw) + call NetCDF_read_var(ncid, "vegsrc", .False., input_vegsrc ) + call NetCDF_read_var(ncid, "vegtyp", .False., input_vegtyp ) + call NetCDF_read_var(ncid, "soiltyp", .False., input_soiltyp ) + call NetCDF_read_var(ncid, "scolor", .False., input_scolor) + call NetCDF_read_var(ncid, "slopetyp", .False., input_slopetype) + call NetCDF_read_var(ncid, "tsfco", .False., input_tsfco) + call NetCDF_read_var(ncid, "vegfrac", .False., input_vegfrac) + call NetCDF_read_var(ncid, "shdmin", .False., input_shdmin) + call NetCDF_read_var(ncid, "shdmax", .False., input_shdmax) + call NetCDF_read_var(ncid, "slmsk", .False., input_slmsk) + call NetCDF_read_var(ncid, "canopy", .False., input_canopy) + call NetCDF_read_var(ncid, "hice", .False., input_hice) + call NetCDF_read_var(ncid, "fice", .False., input_fice) + call NetCDF_read_var(ncid, "tisfc", .False., input_tisfc) + call NetCDF_read_var(ncid, "snowd", .False., input_snwdph) + call NetCDF_read_var(ncid, "snoalb", .False., input_snoalb) + call NetCDF_read_var(ncid, "tg3", .False., input_tg3) + call NetCDF_read_var(ncid, "uustar", .False., input_uustar) + call NetCDF_read_var(ncid, "alvsf", .False., input_alvsf) + call NetCDF_read_var(ncid, "alnsf", .False., input_alnsf) + call NetCDF_read_var(ncid, "alvwf", .False., input_alvwf) + call NetCDF_read_var(ncid, "alnwf", .False., input_alnwf) + call NetCDF_read_var(ncid, "facsf", .False., input_facsf) + call NetCDF_read_var(ncid, "facwf", .False., input_facwf) + call NetCDF_read_var(ncid, "weasd", .False., input_weasd) + call NetCDF_read_var(ncid, "f10m", .False., input_f10m) + call NetCDF_read_var(ncid, "t2m", .False., input_t2m) + call NetCDF_read_var(ncid, "q2m", .False., input_q2m) + call NetCDF_read_var(ncid, "ffmm", .False., input_ffmm) + call NetCDF_read_var(ncid, "ffhh", .False., input_ffhh) + call NetCDF_read_var(ncid, "tprcp", .False., input_tprcp) + call NetCDF_read_var(ncid, "srflag", .False., input_srflag) + call NetCDF_read_var(ncid, "sncovr", .False., input_sncovr) + call NetCDF_read_var(ncid, "tsfcl", .False., input_tsfcl) + call NetCDF_read_var(ncid, "zorll", .False., input_zorll) + call NetCDF_read_var(ncid, "zorli", .False., input_zorli) + call NetCDF_read_var(ncid, "zorlw", .False., input_zorlw) - !NoahMP parameters - call NetCDF_read_var(ncid, "tvxy", .False., input_tvxy) - call NetCDF_read_var(ncid, "tgxy", .False., input_tgxy) - call NetCDF_read_var(ncid, "tahxy", .False., input_tahxy) - call NetCDF_read_var(ncid, "canicexy", .False., input_canicexy) - call NetCDF_read_var(ncid, "canliqxy", .False., input_canliqxy) - call NetCDF_read_var(ncid, "eahxy", .False., input_eahxy) - call NetCDF_read_var(ncid, "cmxy", .False., input_cmxy) - call NetCDF_read_var(ncid, "chxy", .False., input_chxy) - call NetCDF_read_var(ncid, "fwetxy", .False., input_fwetxy) - call NetCDF_read_var(ncid, "sneqvoxy", .False., input_sneqvoxy) - call NetCDF_read_var(ncid, "alboldxy", .False., input_alboldxy) - call NetCDF_read_var(ncid, "qsnowxy", .False., input_qsnowxy) - call NetCDF_read_var(ncid, "wslakexy", .False., input_wslakexy) - call NetCDF_read_var(ncid, "taussxy", .False., input_taussxy) - call NetCDF_read_var(ncid, "waxy", .False., input_waxy) - call NetCDF_read_var(ncid, "wtxy", .False., input_wtxy) - call NetCDF_read_var(ncid, "zwtxy", .False., input_zwtxy) - call NetCDF_read_var(ncid, "xlaixy", .False., input_xlaixy) - call NetCDF_read_var(ncid, "xsaixy", .False., input_xsaixy) - call NetCDF_read_var(ncid, "lfmassxy", .False., input_lfmassxy) - call NetCDF_read_var(ncid, "stmassxy", .False., input_stmassxy) - call NetCDF_read_var(ncid, "rtmassxy", .False., input_rtmassxy) - call NetCDF_read_var(ncid, "woodxy", .False., input_woodxy) - call NetCDF_read_var(ncid, "stblcpxy", .False., input_stblcpxy) - call NetCDF_read_var(ncid, "fastcpxy", .False., input_fastcpxy) - call NetCDF_read_var(ncid, "smcwtdxy", .False., input_smcwtdxy) - call NetCDF_read_var(ncid, "deeprechxy",.False., input_deeprechxy) - call NetCDF_read_var(ncid, "rechxy", .False., input_rechxy) - call NetCDF_read_var(ncid, "snowxy", .False., input_snowxy) - !RUC LSM variables - call NetCDF_read_var(ncid, "wetness", .False., input_wetness) - call NetCDF_read_var(ncid, "clw_surf_land", .False., input_clw_surf_land) - call NetCDF_read_var(ncid, "clw_surf_ice", .False., input_clw_surf_ice) - call NetCDF_read_var(ncid, "qwv_surf_land", .False., input_qwv_surf_land) - call NetCDF_read_var(ncid, "qwv_surf_ice", .False., input_qwv_surf_ice) - call NetCDF_read_var(ncid, "tsnow_land", .False., input_tsnow_land) - call NetCDF_read_var(ncid, "tsnow_ice", .False., input_tsnow_ice) - call NetCDF_read_var(ncid, "snowfallac_land", .False., input_snowfallac_land) - call NetCDF_read_var(ncid, "snowfallac_ice", .False., input_snowfallac_ice) - call NetCDF_read_var(ncid, "sncovr_ice", .False., input_sncovr_ice) - call NetCDF_read_var(ncid, "sfalb_lnd", .False., input_sfalb_lnd) - call NetCDF_read_var(ncid, "sfalb_lnd_bck", .False., input_sfalb_lnd_bck) - call NetCDF_read_var(ncid, "emis_ice", .False., input_emis_ice) - call NetCDF_read_var(ncid, "lai", .False., input_lai) - end if + !NoahMP parameters + call NetCDF_read_var(ncid, "snicexy", .False., input_snicexy) + call NetCDF_read_var(ncid, "snliqxy", .False., input_snliqxy) + call NetCDF_read_var(ncid, "tsnoxy", .False., input_tsnoxy ) + call NetCDF_read_var(ncid, "smoiseq", .False., input_smoiseq) + call NetCDF_read_var(ncid, "zsnsoxy", .False., input_zsnsoxy) + + call NetCDF_read_var(ncid, "tvxy", .False., input_tvxy) + call NetCDF_read_var(ncid, "tgxy", .False., input_tgxy) + call NetCDF_read_var(ncid, "tahxy", .False., input_tahxy) + call NetCDF_read_var(ncid, "canicexy", .False., input_canicexy) + call NetCDF_read_var(ncid, "canliqxy", .False., input_canliqxy) + call NetCDF_read_var(ncid, "eahxy", .False., input_eahxy) + call NetCDF_read_var(ncid, "cmxy", .False., input_cmxy) + call NetCDF_read_var(ncid, "chxy", .False., input_chxy) + call NetCDF_read_var(ncid, "fwetxy", .False., input_fwetxy) + call NetCDF_read_var(ncid, "sneqvoxy", .False., input_sneqvoxy) + call NetCDF_read_var(ncid, "alboldxy", .False., input_alboldxy) + call NetCDF_read_var(ncid, "qsnowxy", .False., input_qsnowxy) + call NetCDF_read_var(ncid, "wslakexy", .False., input_wslakexy) + call NetCDF_read_var(ncid, "taussxy", .False., input_taussxy) + call NetCDF_read_var(ncid, "waxy", .False., input_waxy) + call NetCDF_read_var(ncid, "wtxy", .False., input_wtxy) + call NetCDF_read_var(ncid, "zwtxy", .False., input_zwtxy) + call NetCDF_read_var(ncid, "xlaixy", .False., input_xlaixy) + call NetCDF_read_var(ncid, "xsaixy", .False., input_xsaixy) + call NetCDF_read_var(ncid, "lfmassxy", .False., input_lfmassxy) + call NetCDF_read_var(ncid, "stmassxy", .False., input_stmassxy) + call NetCDF_read_var(ncid, "rtmassxy", .False., input_rtmassxy) + call NetCDF_read_var(ncid, "woodxy", .False., input_woodxy) + call NetCDF_read_var(ncid, "stblcpxy", .False., input_stblcpxy) + call NetCDF_read_var(ncid, "fastcpxy", .False., input_fastcpxy) + call NetCDF_read_var(ncid, "smcwtdxy", .False., input_smcwtdxy) + call NetCDF_read_var(ncid, "deeprechxy",.False., input_deeprechxy) + call NetCDF_read_var(ncid, "rechxy", .False., input_rechxy) + call NetCDF_read_var(ncid, "snowxy", .False., input_snowxy) + !RUC LSM variables + call NetCDF_read_var(ncid, "tslb", .False., input_tslb ) + call NetCDF_read_var(ncid, "smois", .False., input_smois) + call NetCDF_read_var(ncid, "sh2o", .False., input_sh2o ) + call NetCDF_read_var(ncid, "smfr", .False., input_smfr ) + call NetCDF_read_var(ncid, "flfr", .False., input_flfr ) + call NetCDF_read_var(ncid, "wetness", .False., input_wetness) + call NetCDF_read_var(ncid, "clw_surf_land", .False., input_clw_surf_land) + call NetCDF_read_var(ncid, "clw_surf_ice", .False., input_clw_surf_ice) + call NetCDF_read_var(ncid, "qwv_surf_land", .False., input_qwv_surf_land) + call NetCDF_read_var(ncid, "qwv_surf_ice", .False., input_qwv_surf_ice) + call NetCDF_read_var(ncid, "tsnow_land", .False., input_tsnow_land) + call NetCDF_read_var(ncid, "tsnow_ice", .False., input_tsnow_ice) + call NetCDF_read_var(ncid, "snowfallac_land", .False., input_snowfallac_land) + call NetCDF_read_var(ncid, "snowfallac_ice", .False., input_snowfallac_ice) + call NetCDF_read_var(ncid, "sncovr_ice", .False., input_sncovr_ice) + call NetCDF_read_var(ncid, "sfalb_lnd", .False., input_sfalb_lnd) + call NetCDF_read_var(ncid, "sfalb_lnd_bck", .False., input_sfalb_lnd_bck) + call NetCDF_read_var(ncid, "emis_ice", .False., input_emis_ice) + call NetCDF_read_var(ncid, "lai", .False., input_lai) + call check(NF90_CLOSE(NCID=ncid),"nf90_close()") @@ -2259,8 +2267,8 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) !set all individual w forcing controls to .true. until finer control is available from the input file scm_state%force_sub_for_T = .true. scm_state%force_sub_for_qv = .true. - scm_state%force_sub_for_u = .true. - scm_state%force_sub_for_v = .true. + !scm_state%force_sub_for_u = .true. + !scm_state%force_sub_for_v = .true. else if (forc_w > 0) then do i=1, input_n_forcing_times scm_input%input_w_ls(i,:) = input_force_w(:,i) @@ -2270,8 +2278,8 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) !set all individual w forcing controls to .true. until finer control is available from the input file scm_state%force_sub_for_T = .true. scm_state%force_sub_for_qv = .true. - scm_state%force_sub_for_u = .true. - scm_state%force_sub_for_v = .true. + ! scm_state%force_sub_for_u = .true. + ! scm_state%force_sub_for_v = .true. end if if (forc_geo > 0) then From 02f10bb988a34c8a64338bf937a63024051d7a6c Mon Sep 17 00:00:00 2001 From: Dustin Swales Date: Thu, 25 Jul 2024 22:05:46 +0000 Subject: [PATCH 08/40] Changes for CLM lake to work in CCPP SCM --- .gitmodules | 4 ++-- ccpp/physics | 2 +- scm/src/scm_type_defs.F90 | 10 ++++++++-- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.gitmodules b/.gitmodules index dc0798c32..6c2c7ba23 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,8 +4,8 @@ branch = main [submodule "ccpp-physics"] path = ccpp/physics - url = https://github.com/NCAR/ccpp-physics - branch = main + url = https://github.com/dustinswales/ccpp-physics + branch = hotfix/clmlake_in_scm [submodule "CMakeModules"] path = CMakeModules url = https://github.com/noaa-emc/CMakeModules diff --git a/ccpp/physics b/ccpp/physics index 3a1969102..bafa77c26 160000 --- a/ccpp/physics +++ b/ccpp/physics @@ -1 +1 @@ -Subproject commit 3a19691021b779748f4b448d3f21ab381fcc6c6e +Subproject commit bafa77c2602970bea54db917a05a5ea8c122651c diff --git a/scm/src/scm_type_defs.F90 b/scm/src/scm_type_defs.F90 index 01629bacf..737ecb6e2 100644 --- a/scm/src/scm_type_defs.F90 +++ b/scm/src/scm_type_defs.F90 @@ -1064,7 +1064,7 @@ subroutine physics_set(physics, scm_input, scm_state) ! ! Orographical data (2D) ! - if (scm_state%model_ics) then + if (scm_state%model_ics .or. scm_state%lsm_ics) then write(0,'(a)') "Setting internal physics variables from the orographic section of the case input file (scalars)..." call conditionally_set_var(scm_input%input_stddev, physics%Sfcprop%hprime(i,1), "stddev", .true., missing_var(1)) call conditionally_set_var(scm_input%input_convexity, physics%Sfcprop%hprime(i,2), "convexity", .true., missing_var(2)) @@ -1202,8 +1202,14 @@ subroutine physics_set(physics, scm_input, scm_state) ! ! Derive physics quantities using surface model ICs. ! + print*,"SWALES SCM: scm_state%model_ics = ",scm_state%model_ics + print*,"SWALES SCM: scm_state%lsm_ics = ",scm_state%lsm_ics + print*,"SWALES SCM: physics%Sfcprop%stype(i) = ",physics%Sfcprop%stype(i) + print*,"SWALES SCM: physics%Sfcprop%lakefrac(i) = ",physics%Sfcprop%lakefrac(i) + print*,"SWALES SCM: physics%Sfcprop%oro_uf(i) = ",physics%Sfcprop%oro_uf(i) + print*,"SWALES SCM: min_lake_orog = ",min_lake_orog if(scm_state%model_ics .or. scm_state%lsm_ics) then - if (physics%Sfcprop%stype(i) == 14 .or. physics%Sfcprop%stype(i)+0.5 <= 0) then + if (physics%Sfcprop%stype(i) == 14 .or. physics%Sfcprop%stype(i) <= 0) then physics%Sfcprop%landfrac(i) = real_zero physics%Sfcprop%stype(i) = 0 if (physics%Sfcprop%lakefrac(i) > real_zero) then From 81868055d2a02ac6094d17a9ef51dcde0c49b3bf Mon Sep 17 00:00:00 2001 From: Dustin Swales Date: Fri, 26 Jul 2024 14:38:06 +0000 Subject: [PATCH 09/40] Omission from previous commit --- scm/src/scm_type_defs.F90 | 6 ------ 1 file changed, 6 deletions(-) diff --git a/scm/src/scm_type_defs.F90 b/scm/src/scm_type_defs.F90 index 737ecb6e2..9a0dafe36 100644 --- a/scm/src/scm_type_defs.F90 +++ b/scm/src/scm_type_defs.F90 @@ -1202,12 +1202,6 @@ subroutine physics_set(physics, scm_input, scm_state) ! ! Derive physics quantities using surface model ICs. ! - print*,"SWALES SCM: scm_state%model_ics = ",scm_state%model_ics - print*,"SWALES SCM: scm_state%lsm_ics = ",scm_state%lsm_ics - print*,"SWALES SCM: physics%Sfcprop%stype(i) = ",physics%Sfcprop%stype(i) - print*,"SWALES SCM: physics%Sfcprop%lakefrac(i) = ",physics%Sfcprop%lakefrac(i) - print*,"SWALES SCM: physics%Sfcprop%oro_uf(i) = ",physics%Sfcprop%oro_uf(i) - print*,"SWALES SCM: min_lake_orog = ",min_lake_orog if(scm_state%model_ics .or. scm_state%lsm_ics) then if (physics%Sfcprop%stype(i) == 14 .or. physics%Sfcprop%stype(i) <= 0) then physics%Sfcprop%landfrac(i) = real_zero From 9389555510870080e93954b816238767beb07564 Mon Sep 17 00:00:00 2001 From: Dustin Swales Date: Fri, 26 Jul 2024 14:39:36 +0000 Subject: [PATCH 10/40] Updated physics --- ccpp/physics | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ccpp/physics b/ccpp/physics index bafa77c26..f2d31ef43 160000 --- a/ccpp/physics +++ b/ccpp/physics @@ -1 +1 @@ -Subproject commit bafa77c2602970bea54db917a05a5ea8c122651c +Subproject commit f2d31ef4368f1d9f9dce57278be6779b0683b7b4 From bb03b342066aabff793f1a21c694a06974aa3597 Mon Sep 17 00:00:00 2001 From: Dustin Swales Date: Fri, 26 Jul 2024 14:49:44 +0000 Subject: [PATCH 11/40] update physics hash --- ccpp/physics | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ccpp/physics b/ccpp/physics index f2d31ef43..bafa77c26 160000 --- a/ccpp/physics +++ b/ccpp/physics @@ -1 +1 @@ -Subproject commit f2d31ef4368f1d9f9dce57278be6779b0683b7b4 +Subproject commit bafa77c2602970bea54db917a05a5ea8c122651c From 9de60958725e038448e7fd9666e5e1eaacab669f Mon Sep 17 00:00:00 2001 From: Dustin Swales Date: Fri, 26 Jul 2024 15:07:37 +0000 Subject: [PATCH 12/40] Doh --- ccpp/framework | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ccpp/framework b/ccpp/framework index ccfefcd0b..0f8232724 160000 --- a/ccpp/framework +++ b/ccpp/framework @@ -1 +1 @@ -Subproject commit ccfefcd0b426e011f94137031d5f7c2a4dda2659 +Subproject commit 0f8232724975c13289cad390c9a71fa2c6a9bff4 From 5d2c49e947ca7ee827a18e7c1c4cc2ecb400cd90 Mon Sep 17 00:00:00 2001 From: Grant Firl Date: Tue, 30 Jul 2024 13:06:36 -0400 Subject: [PATCH 13/40] move landfrac/lakefrac/lakedepth out of IF statement to preserve working LSM IC-only cases (like GABLS3) (#13) --- scm/src/scm_type_defs.F90 | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/scm/src/scm_type_defs.F90 b/scm/src/scm_type_defs.F90 index 9a0dafe36..64c4289c0 100644 --- a/scm/src/scm_type_defs.F90 +++ b/scm/src/scm_type_defs.F90 @@ -1064,7 +1064,7 @@ subroutine physics_set(physics, scm_input, scm_state) ! ! Orographical data (2D) ! - if (scm_state%model_ics .or. scm_state%lsm_ics) then + if (scm_state%model_ics) then write(0,'(a)') "Setting internal physics variables from the orographic section of the case input file (scalars)..." call conditionally_set_var(scm_input%input_stddev, physics%Sfcprop%hprime(i,1), "stddev", .true., missing_var(1)) call conditionally_set_var(scm_input%input_convexity, physics%Sfcprop%hprime(i,2), "convexity", .true., missing_var(2)) @@ -1082,10 +1082,7 @@ subroutine physics_set(physics, scm_input, scm_state) call conditionally_set_var(scm_input%input_elvmax, physics%Sfcprop%hprime(i,14), "elvmax", .true., missing_var(14)) call conditionally_set_var(scm_input%input_oro, physics%Sfcprop%oro(i), "oro", .true., missing_var(15)) call conditionally_set_var(scm_input%input_oro_uf, physics%Sfcprop%oro_uf(i), "oro_uf", (physics%Model%do_ugwp .and. physics%Model%nmtvr == 14), missing_var(16)) - call conditionally_set_var(scm_input%input_landfrac, physics%Sfcprop%landfrac(i), "landfrac", physics%Model%frac_grid, missing_var(17)) - call conditionally_set_var(scm_input%input_lakefrac, physics%Sfcprop%lakefrac(i), "lakefrac", (physics%Model%lkm == 1), missing_var(18)) - call conditionally_set_var(scm_input%input_lakedepth, physics%Sfcprop%lakedepth(i), "lakedepth", (physics%Model%lkm == 1), missing_var(19)) - + n = 19 if ( i==1 .and. ANY( missing_var(1:n) ) ) then write(0,'(a)') "INPUT CHECK: Some missing input data was found related to (potentially non-required) orography and gravity wave drag parameters. This may lead to crashes or other strange behavior." @@ -1097,6 +1094,20 @@ subroutine physics_set(physics, scm_input, scm_state) missing_var = .false. end if + ! Variables found in orographic dataset but needed for non-orographic reasons (e.g. lake model, fractional grid) + call conditionally_set_var(scm_input%input_landfrac, physics%Sfcprop%landfrac(i), "landfrac", physics%Model%frac_grid, missing_var(1)) + call conditionally_set_var(scm_input%input_lakefrac, physics%Sfcprop%lakefrac(i), "lakefrac", (physics%Model%lkm == 1), missing_var(2)) + call conditionally_set_var(scm_input%input_lakedepth, physics%Sfcprop%lakedepth(i), "lakedepth", (physics%Model%lkm == 1), missing_var(3)) + n = 3 + if ( i==1 .and. ANY( missing_var(1:n) ) ) then + write(0,'(a)') "INPUT CHECK: Some missing input data was found related to (potentially non-required) lake-related or fractional grid-related variables. This may lead to crashes or other strange behavior." + write(0,'(a)') "Check scm_type_defs.F90/physics_set to see the names of variables that are missing, corresponding to the following indices:" + do j=1, n + if (missing_var(j)) write(0,'(a,i0)') "variable index ",j + end do + end if + missing_var = .false. + ! ! Surface data (2D) ! From 3ba2954545084e25fd9cbcc44155db141b22bf61 Mon Sep 17 00:00:00 2001 From: Grant Firl Date: Wed, 31 Jul 2024 13:04:12 -0400 Subject: [PATCH 14/40] add COMBLE case configuration and changes to scm_input.F90 to work with non-conforming COMBLE case DEPHY file --- scm/etc/case_config/COMBLE.nml | 9 +++++ scm/src/scm_input.F90 | 61 ++++++++++++++++++++++++++++++---- 2 files changed, 64 insertions(+), 6 deletions(-) create mode 100644 scm/etc/case_config/COMBLE.nml diff --git a/scm/etc/case_config/COMBLE.nml b/scm/etc/case_config/COMBLE.nml new file mode 100644 index 000000000..c408cd88a --- /dev/null +++ b/scm/etc/case_config/COMBLE.nml @@ -0,0 +1,9 @@ +$case_config +case_name = 'COMBLE', +input_type = 1 +lsm_ics = .false., +do_spinup = .false., +spinup_timesteps = 0, +reference_profile_choice = 2, +column_area = 1.45E8, +$end diff --git a/scm/src/scm_input.F90 b/scm/src/scm_input.F90 index 1b2dab265..1ab41cdfa 100644 --- a/scm/src/scm_input.F90 +++ b/scm/src/scm_input.F90 @@ -1158,11 +1158,12 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) integer :: ncid, varID, allocate_status, ierr, i, k integer :: active_lon, active_lat, active_init_time CHARACTER(LEN=nf90_max_name) :: tmpName + CHARACTER(LEN=nf90_max_name) :: tmpUnits real(kind=sp), parameter :: p0 = 100000.0 real(kind=sp) :: exner, exner_inv, rho, elapsed_sec, missing_value_eps real(kind=dp) :: rinc(5) integer :: jdat(1:8), idat(1:8) !(yr, mon, day, t-zone, hr, min, sec, mil-sec) - logical :: needed_for_lsm_ics, needed_for_model_ics + logical :: needed_for_lsm_ics, needed_for_model_ics, lev_in_altitude integer :: input_n_init_times, input_n_forcing_times, input_n_lev, input_n_snow, input_n_ice, input_n_soil @@ -1182,7 +1183,17 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) call check(NF90_INQUIRE_DIMENSION(ncid, varID, tmpName, input_n_lev),"nf90_inq_dim(lev)") !Check whether long_name = 'altitude', units='m' OR long_name = 'pressure', units='Pa'? !It may not matter, because 'lev' may not be needed when the IC pressure and height are BOTH already provided - + call check(NF90_INQ_VARID(ncid,"lev",varID),"nf90_inq_varid(lev)") + call check(NF90_GET_ATT(ncid, varID, "units", tmpUnits),"nf90_get_att(units)") + if (adjustl(trim(tmpUnits)) == 'pa' .or. adjustl(trim(tmpUnits)) == 'Pa') then + lev_in_altitude = .false. + else if (adjustl(trim(tmpUnits)) == 'm') then + lev_in_altitude = .true. + else + write(0,'(a,i0,a)') "The variable 'lev' in the case data file had units different than 'm', 'pa', or 'Pa', but it is expected to be altitude in m or pressure in Pa. Stopping..." + STOP + end if + !### TO BE USED IF DEPHY-SCM can be extended to include model ICs ### !possible dimensions (if using model ICs) ierr = NF90_INQ_DIMID(ncid,"nsoil",varID) @@ -1461,8 +1472,31 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) if (scm_state%model_ics) needed_for_model_ics = .True. !> - Read in the initial profiles. - call NetCDF_read_var(ncid, "pa", .True., input_pres) - call NetCDF_read_var(ncid, "zh", .True., input_height) + + if (lev_in_altitude) then + call NetCDF_read_var(ncid, "pa", .True., input_pres) + !zh could be defined in addition to lev, use if so + call NetCDF_read_var(ncid, "zh", .False., input_height) + if (input_height(1,1) == missing_value) then + do i=1, input_n_init_times + do k=1, input_n_lev + input_height(k,i) = input_lev(k) + end do + end do + end if + else + call NetCDF_read_var(ncid, "zh", .True., input_height) + !pa could be defined in addition to lev, use if so + call NetCDF_read_var(ncid, "pa", .False., input_pres) + if (input_pres(1,1) == missing_value) then + do i=1, input_n_init_times + do k=1, input_n_lev + input_pres(k,i) = input_lev(k) + end do + end do + end if + end if + call NetCDF_read_var(ncid, "ps", .True., input_pres_surf) call NetCDF_read_var(ncid, "ua", .True., input_u) call NetCDF_read_var(ncid, "va", .True., input_v) @@ -1580,8 +1614,23 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) call NetCDF_read_var(ncid, "lat", .True., input_lat) call NetCDF_read_var(ncid, "lon", .True., input_lon) call NetCDF_read_var(ncid, "ps_forc", .True., input_force_pres_surf) - call NetCDF_read_var(ncid, "zh_forc", .True., input_force_height) - call NetCDF_read_var(ncid, "pa_forc", .True., input_force_pres) + !zh_forc and pa_forc should be present according to the DEPHY standard; if not, assume that zh_forc = input_height and pa_forc = input_pres + call NetCDF_read_var(ncid, "zh_forc", .False., input_force_height) + if (input_force_height(1,1) == missing_value) then + do i=1, input_n_forcing_times + do k=1, input_n_lev + input_force_height(k,i) = input_height(k,1) + end do + end do + end if + call NetCDF_read_var(ncid, "pa_forc", .False., input_force_pres) + if (input_force_pres(1,1) == missing_value) then + do i=1, input_n_forcing_times + do k=1, input_n_lev + input_force_pres(k,i) = input_pres(k,1) + end do + end do + end if !conditionally read forcing vars (or set to missing); if the global attribute is set to expect a variable and it doesn't exist, stop the model call NetCDF_conditionally_read_var(adv_u, "adv_ua", "tnua_adv", trim(adjustl(scm_state%case_name))//'.nc', ncid, input_force_u_adv) From 7eae6383bc49bbbb426a7b3fc5a7dd2e8c009420 Mon Sep 17 00:00:00 2001 From: Grant Firl Date: Thu, 1 Aug 2024 15:40:53 -0400 Subject: [PATCH 15/40] update and convert MOSAiC cases to DEPHY format; allow both surfaceforcingT to be true and surfaceforcinglsm to be true - ingests LSM data and a forcing surface T --- scm/etc/case_config/MOSAiC-AMPS.nml | 25 +++---- scm/etc/case_config/MOSAiC-SS.nml | 25 +++---- .../MOSAiC_AMPS_forcing_file_generator.py | 68 ++++++++++++++----- .../MOSAiC_SS_forcing_file_generator.py | 68 ++++++++++++++----- scm/etc/scripts/dephy_converter.py | 27 ++++---- scm/src/scm_input.F90 | 4 +- 6 files changed, 136 insertions(+), 81 deletions(-) mode change 100644 => 100755 scm/etc/scripts/MOSAiC_AMPS_forcing_file_generator.py mode change 100644 => 100755 scm/etc/scripts/MOSAiC_SS_forcing_file_generator.py diff --git a/scm/etc/case_config/MOSAiC-AMPS.nml b/scm/etc/case_config/MOSAiC-AMPS.nml index ca3148a9f..bbcbdf46e 100644 --- a/scm/etc/case_config/MOSAiC-AMPS.nml +++ b/scm/etc/case_config/MOSAiC-AMPS.nml @@ -1,17 +1,8 @@ -$case_config -case_name = 'MOSAiC-AMPS', -runtime = 604800.0, -thermo_forcing_type = 2, -mom_forcing_type = 3, -relax_time = 3600.0, -sfc_flux_spec = .false., -sfc_type = 2, -sfc_roughness_length_cm = 0.02, -reference_profile_choice = 1, -year = 2019, -month = 10, -day = 31, -hour = 0, -column_area = 2.0E9, -lsm_ics = .true., -$end +&case_config + case_name = 'MOSAiC-AMPS' + column_area = 2000000000.0 + input_type = 1 + lsm_ics = .true. + reference_profile_choice = 1 + sfc_roughness_length_cm = 0.02 +/ diff --git a/scm/etc/case_config/MOSAiC-SS.nml b/scm/etc/case_config/MOSAiC-SS.nml index a2f5caa81..ec995e675 100644 --- a/scm/etc/case_config/MOSAiC-SS.nml +++ b/scm/etc/case_config/MOSAiC-SS.nml @@ -1,17 +1,8 @@ -$case_config -case_name = 'MOSAiC-SS', -runtime = 604800.0, -thermo_forcing_type = 2, -mom_forcing_type = 3, -relax_time = 3600.0, -sfc_flux_spec = .false., -sfc_type = 2, -sfc_roughness_length_cm = 0.02, -reference_profile_choice = 1, -year = 2020, -month = 3, -day = 2, -hour = 0, -column_area = 2.0E9, -lsm_ics = .true., -$end +&case_config + case_name = 'MOSAiC-SS' + column_area = 2000000000.0 + input_type = 1 + lsm_ics = .true. + reference_profile_choice = 1 + sfc_roughness_length_cm = 0.02 +/ diff --git a/scm/etc/scripts/MOSAiC_AMPS_forcing_file_generator.py b/scm/etc/scripts/MOSAiC_AMPS_forcing_file_generator.py old mode 100644 new mode 100755 index cfbb2d2ba..b2c5a9381 --- a/scm/etc/scripts/MOSAiC_AMPS_forcing_file_generator.py +++ b/scm/etc/scripts/MOSAiC_AMPS_forcing_file_generator.py @@ -146,6 +146,9 @@ #height = ffc.get_height_from_pres(T_abs[:,0],levels,z_sfc) #the following variables are not in this forcing file, but are included in other cases +soil_depth = np.zeros(4,dtype=float) +soil_depth[:] = [0.1, 0.4, 1.0, 2.0] + #rad_heating = nc_fid.variables['dT_dt_rad'][:] #K/s #rad_heating = np.swapaxes(rad_heating, 0, 1) #swap the time and levels axis rad_heating = np.zeros((levels.size,time.size),dtype=float) @@ -163,29 +166,31 @@ smc = 0.33 slc = 0.33 hice = 0.3 -slmsk = 2.0 +slmsk = 2.0 #sea ice tsfco = T_surf[start_t_index] -weasd = 200.0 +weasd = 200.0 #mm water equivalent snow depth fice = 1.0 tisfc = tsfco snwdph = 2.e-4 tg3 = 271.35 zorl = 15.0 -alvsf = 0.23 -alnsf = 0.23 -alvwf = 0.23 -alnwf = 0.23 -facsf = 0.5055632 -facwf = 0.4944368 +alvsf = 0.06 +alnsf = 0.06 +alvwf = 0.06 +alnwf = 0.06 +facsf = 0.0 +facwf = 0.0 vegfrac = 0.0 canopy = 0.0 -vegtyp = 10 -soiltyp = 12 +vegtyp = 0 +soiltyp = 0 +scolor = 1 uustar = 0.3828793 -shdmin = 0.01 -shdmax = 0.8 +shdmin = 0.0 +shdmax = 0.0 slopetyp = 1 -snoalb = 0.7287961 +snoalb = 0.0 +sncovr = 1.0 # Open ozone file #f = open('../../data/raw_case_input/twpice_CRM_ozone.txt', 'r') @@ -237,6 +242,12 @@ writefile_levels_var.units = 'Pa' writefile_levels_var.description = 'pressure levels' +writefile_soil_depth_dim = writefile_fid.createDimension('soil_depth', None) +writefile_soil_depth_var = writefile_fid.createVariable('soil_depth', 'f4', ('soil_depth',)) +writefile_soil_depth_var[:] = soil_depth[:] +writefile_soil_depth_var.units = 'm' +writefile_soil_depth_var.description = 'soil depth' + writefile_ice_thickness_dim = writefile_fid.createDimension('ice_thickness', None) writefile_ice_thickness_var = writefile_fid.createVariable('ice_thickness', 'f4', ('ice_thickness',)) writefile_ice_thickness_var[:] = ice_thickness @@ -302,6 +313,21 @@ writefile_zorl_var.units = 'cm' writefile_zorl_var.description = 'composite surface roughness length' +writefile_zorll_var = writefile_scalar_grp.createVariable('zorll', 'f4') +writefile_zorll_var[:] = zorl +writefile_zorll_var.units = 'cm' +writefile_zorll_var.description = 'surface roughness length over land' + +writefile_zorlw_var = writefile_scalar_grp.createVariable('zorlw', 'f4') +writefile_zorlw_var[:] = zorl +writefile_zorlw_var.units = 'cm' +writefile_zorlw_var.description = 'surface roughness length over ocean' + +writefile_zorli_var = writefile_scalar_grp.createVariable('zorli', 'f4') +writefile_zorli_var[:] = zorl +writefile_zorli_var.units = 'cm' +writefile_zorli_var.description = 'surface roughness length over ice' + writefile_alvsf_var = writefile_scalar_grp.createVariable('alvsf', 'f4') writefile_alvsf_var[:] = alvsf writefile_alvsf_var.units = '' @@ -352,6 +378,11 @@ writefile_soiltyp_var.units = '' writefile_soiltyp_var.description = 'soil type 1-12' +writefile_scolor_var = writefile_scalar_grp.createVariable('scolor', 'f4') +writefile_scolor_var[:] = scolor +writefile_scolor_var.units = '' +writefile_scolor_var.description = 'soil color' + writefile_uustar_var = writefile_scalar_grp.createVariable('uustar', 'f4') writefile_uustar_var[:] = uustar writefile_uustar_var.units = 'm s-1' @@ -377,6 +408,11 @@ writefile_snoalb_var.units = '1' writefile_snoalb_var.description = 'maximum snow albedo' +writefile_sncovr_var = writefile_scalar_grp.createVariable('sncovr', 'f4') +writefile_sncovr_var[:] = sncovr +writefile_sncovr_var.units = '1' +writefile_sncovr_var.description = 'surface snow area fraction' + #initial group writefile_height_var = writefile_initial_grp.createVariable('height', 'f4', ('levels',)) @@ -389,17 +425,17 @@ writefile_tiice_var.units = 'K' writefile_tiice_var.description = 'initial profile of sea ice internal temperature' -writefile_stc_var = writefile_initial_grp.createVariable('stc', 'f4') +writefile_stc_var = writefile_initial_grp.createVariable('stc', 'f4', ('soil_depth',)) writefile_stc_var[:] = stc writefile_stc_var.units = 'K' writefile_stc_var.description = 'initial profile of sea ice internal temperature' -writefile_smc_var = writefile_initial_grp.createVariable('smc', 'f4') +writefile_smc_var = writefile_initial_grp.createVariable('smc', 'f4', ('soil_depth',)) writefile_smc_var[:] = smc writefile_smc_var.units = 'm3 m-3' writefile_smc_var.description = 'initial profile of soil moisture' -writefile_slc_var = writefile_initial_grp.createVariable('slc', 'f4') +writefile_slc_var = writefile_initial_grp.createVariable('slc', 'f4', ('soil_depth',)) writefile_slc_var[:] = slc writefile_slc_var.units = 'm3 m-3' writefile_slc_var.description = 'initial profile of soil liquid water' diff --git a/scm/etc/scripts/MOSAiC_SS_forcing_file_generator.py b/scm/etc/scripts/MOSAiC_SS_forcing_file_generator.py old mode 100644 new mode 100755 index 918eea33e..514c4dfe2 --- a/scm/etc/scripts/MOSAiC_SS_forcing_file_generator.py +++ b/scm/etc/scripts/MOSAiC_SS_forcing_file_generator.py @@ -146,6 +146,9 @@ #height = ffc.get_height_from_pres(T_abs[:,0],levels,z_sfc) #the following variables are not in this forcing file, but are included in other cases +soil_depth = np.zeros(4,dtype=float) +soil_depth[:] = [0.1, 0.4, 1.0, 2.0] + #rad_heating = nc_fid.variables['dT_dt_rad'][:] #K/s #rad_heating = np.swapaxes(rad_heating, 0, 1) #swap the time and levels axis rad_heating = np.zeros((levels.size,time.size),dtype=float) @@ -163,29 +166,31 @@ smc = 0.33 slc = 0.33 hice = 0.3 -slmsk = 2.0 +slmsk = 2.0 #sea ice tsfco = T_surf[start_t_index] -weasd = 200.0 +weasd = 200.0 #mm water equivalent snow depth fice = 1.0 tisfc = tsfco snwdph = 2.e-4 tg3 = 271.35 zorl = 15.0 -alvsf = 0.23 -alnsf = 0.23 -alvwf = 0.23 -alnwf = 0.23 -facsf = 0.5055632 -facwf = 0.4944368 +alvsf = 0.06 +alnsf = 0.06 +alvwf = 0.06 +alnwf = 0.06 +facsf = 0.0 +facwf = 0.0 vegfrac = 0.0 canopy = 0.0 -vegtyp = 10 -soiltyp = 12 +vegtyp = 0 +soiltyp = 0 +scolor = 1 uustar = 0.3828793 -shdmin = 0.01 -shdmax = 0.8 +shdmin = 0.0 +shdmax = 0.0 slopetyp = 1 -snoalb = 0.7287961 +snoalb = 0.0 +sncovr = 1.0 # Open ozone file #f = open('../../data/raw_case_input/twpice_CRM_ozone.txt', 'r') @@ -237,6 +242,12 @@ writefile_levels_var.units = 'Pa' writefile_levels_var.description = 'pressure levels' +writefile_soil_depth_dim = writefile_fid.createDimension('soil_depth', None) +writefile_soil_depth_var = writefile_fid.createVariable('soil_depth', 'f4', ('soil_depth',)) +writefile_soil_depth_var[:] = soil_depth[:] +writefile_soil_depth_var.units = 'm' +writefile_soil_depth_var.description = 'soil depth' + writefile_ice_thickness_dim = writefile_fid.createDimension('ice_thickness', None) writefile_ice_thickness_var = writefile_fid.createVariable('ice_thickness', 'f4', ('ice_thickness',)) writefile_ice_thickness_var[:] = ice_thickness @@ -302,6 +313,21 @@ writefile_zorl_var.units = 'cm' writefile_zorl_var.description = 'composite surface roughness length' +writefile_zorll_var = writefile_scalar_grp.createVariable('zorll', 'f4') +writefile_zorll_var[:] = zorl +writefile_zorll_var.units = 'cm' +writefile_zorll_var.description = 'surface roughness length over land' + +writefile_zorlw_var = writefile_scalar_grp.createVariable('zorlw', 'f4') +writefile_zorlw_var[:] = zorl +writefile_zorlw_var.units = 'cm' +writefile_zorlw_var.description = 'surface roughness length over ocean' + +writefile_zorli_var = writefile_scalar_grp.createVariable('zorli', 'f4') +writefile_zorli_var[:] = zorl +writefile_zorli_var.units = 'cm' +writefile_zorli_var.description = 'surface roughness length over ice' + writefile_alvsf_var = writefile_scalar_grp.createVariable('alvsf', 'f4') writefile_alvsf_var[:] = alvsf writefile_alvsf_var.units = '' @@ -352,6 +378,11 @@ writefile_soiltyp_var.units = '' writefile_soiltyp_var.description = 'soil type 1-12' +writefile_scolor_var = writefile_scalar_grp.createVariable('scolor', 'f4') +writefile_scolor_var[:] = scolor +writefile_scolor_var.units = '' +writefile_scolor_var.description = 'soil color' + writefile_uustar_var = writefile_scalar_grp.createVariable('uustar', 'f4') writefile_uustar_var[:] = uustar writefile_uustar_var.units = 'm s-1' @@ -377,6 +408,11 @@ writefile_snoalb_var.units = '1' writefile_snoalb_var.description = 'maximum snow albedo' +writefile_sncovr_var = writefile_scalar_grp.createVariable('sncovr', 'f4') +writefile_sncovr_var[:] = sncovr +writefile_sncovr_var.units = '1' +writefile_sncovr_var.description = 'surface snow area fraction' + #initial group writefile_height_var = writefile_initial_grp.createVariable('height', 'f4', ('levels',)) @@ -389,17 +425,17 @@ writefile_tiice_var.units = 'K' writefile_tiice_var.description = 'initial profile of sea ice internal temperature' -writefile_stc_var = writefile_initial_grp.createVariable('stc', 'f4') +writefile_stc_var = writefile_initial_grp.createVariable('stc', 'f4', ('soil_depth',)) writefile_stc_var[:] = stc writefile_stc_var.units = 'K' writefile_stc_var.description = 'initial profile of sea ice internal temperature' -writefile_smc_var = writefile_initial_grp.createVariable('smc', 'f4') +writefile_smc_var = writefile_initial_grp.createVariable('smc', 'f4', ('soil_depth',)) writefile_smc_var[:] = smc writefile_smc_var.units = 'm3 m-3' writefile_smc_var.description = 'initial profile of soil moisture' -writefile_slc_var = writefile_initial_grp.createVariable('slc', 'f4') +writefile_slc_var = writefile_initial_grp.createVariable('slc', 'f4', ('soil_depth',)) writefile_slc_var[:] = slc writefile_slc_var.units = 'm3 m-3' writefile_slc_var.description = 'initial profile of soil liquid water' diff --git a/scm/etc/scripts/dephy_converter.py b/scm/etc/scripts/dephy_converter.py index 42b745d00..4dba44be8 100755 --- a/scm/etc/scripts/dephy_converter.py +++ b/scm/etc/scripts/dephy_converter.py @@ -1376,7 +1376,7 @@ def write_SCM_case_file(case_nml, case_data, use_area): nslsnw_dim = nc_file.createDimension('nsoil_plus_nsnow',case_data._snicexy.shape[0] + case_data._soil_depth.shape[0]) if (case_data._tiice[0] != case_data._missing_value): - ice_dim = nc_file.createDimension('nice', case_data._tiice[0]) + ice_dim = nc_file.createDimension('nice', case_data._tiice.shape[0]) # timei_var = nc_file.createVariable('t0', wp, ('t0')) @@ -2466,20 +2466,19 @@ def write_SCM_case_file(case_nml, case_data, use_area): else: ts_var[:] = case_data._missing_value else: - if (nc_file.surface_forcing_lsm != 'lsm'): - - nc_file.surface_forcing_temp = 'ts' - nc_file.surface_forcing_wind = 'z0' - - z0_var = nc_file.createVariable('z0', wp, ('time')) - z0_var.units = 'm' - z0_var.standard_name = 'surface_roughness_length_for_momentum_in_air' - z0_var[:] = case_nml['case_config']['sfc_roughness_length_cm']*1.0E-2 + nc_file.surface_forcing_temp = 'ts' + nc_file.surface_forcing_wind = 'z0' - ts_var = nc_file.createVariable('ts_forc', wp, ('time')) - ts_var.units = 'K' - ts_var.standard_name = 'forcing_surface_temperature' - ts_var[:] = case_data._T_surf[:] + z0_var = nc_file.createVariable('z0', wp, ('time')) + z0_var.units = 'm' + z0_var.standard_name = 'surface_roughness_length_for_momentum_in_air' + z0_var[:] = case_nml['case_config']['sfc_roughness_length_cm']*1.0E-2 + + ts_var = nc_file.createVariable('ts_forc', wp, ('time')) + ts_var.units = 'K' + ts_var.standard_name = 'forcing_surface_temperature' + ts_var[:] = case_data._T_surf[:] + nc_file.close() diff --git a/scm/src/scm_input.F90 b/scm/src/scm_input.F90 index 1ab41cdfa..2233098bf 100644 --- a/scm/src/scm_input.F90 +++ b/scm/src/scm_input.F90 @@ -2195,7 +2195,9 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) else scm_input%input_lh_flux_sfc = input_force_sfc_lat_flx(:) end if - else if (trim(input_surfaceForcingLSM) == 'lsm') then + end if + + if (trim(input_surfaceForcingLSM) == 'lsm') then !these were considered required variables above, so they should not need to be checked for missing scm_input%input_stc = input_stc(:,active_init_time) scm_input%input_smc = input_smc(:,active_init_time) From 6e449c5dbc21537008d650e111d707d529bca89f Mon Sep 17 00:00:00 2001 From: Grant Firl Date: Thu, 1 Aug 2024 16:04:53 -0400 Subject: [PATCH 16/40] add new cases to rt_test_cases.py --- test/rt_test_cases.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/test/rt_test_cases.py b/test/rt_test_cases.py index f1db91bf9..1660b48c9 100644 --- a/test/rt_test_cases.py +++ b/test/rt_test_cases.py @@ -27,6 +27,17 @@ {"case": "LASSO_2016051812", "suite": "SCM_GFS_v16"}, \ {"case": "LASSO_2016051812", "suite": "SCM_WoFS_v0"}, \ {"case": "LASSO_2016051812", "suite": "SCM_HRRR_gf"}, \ + {"case": "COMBLE", "suite": "SCM_GFS_v17_p8_ugwpv1"}, \ + {"case": "COMBLE", "suite": "SCM_GFS_v16_RRTMGP"}, \ + {"case": "COMBLE", "suite": "SCM_GFS_v16"}, \ + {"case": "COMBLE", "suite": "SCM_WoFS_v0"}, \ + {"case": "COMBLE", "suite": "SCM_HRRR_gf"}, \ + {"case": "MOSAiC-AMPS", "suite": "SCM_GFS_v17_p8_ugwpv1"}, \ + {"case": "MOSAiC-AMPS", "suite": "SCM_GFS_v16_RRTMGP"}, \ + {"case": "MOSAiC-AMPS", "suite": "SCM_GFS_v16"}, \ + {"case": "MOSAiC-AMPS", "suite": "SCM_WoFS_v0"}, \ + {"case": "MOSAiC-AMPS", "suite": "SCM_HRRR_gf"}, \ + {"case": "gabls3", "suite": "SCM_GFS_v16"}, \ #---------------------------------------------------------------------------------------------------------------------------------------------- # Unsupported suites (w/ supported cases) #---------------------------------------------------------------------------------------------------------------------------------------------- From 684448dbbe3ad5abf2213083586efd4e87d90891 Mon Sep 17 00:00:00 2001 From: Grant Firl Date: Thu, 1 Aug 2024 16:09:22 -0400 Subject: [PATCH 17/40] update get_all_static_data.sh script to grab v7.0.0-beta release assets (with new DEPHY-format processed_case_input files) --- contrib/get_all_static_data.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/get_all_static_data.sh b/contrib/get_all_static_data.sh index b0e8006dd..99c0cd4de 100755 --- a/contrib/get_all_static_data.sh +++ b/contrib/get_all_static_data.sh @@ -21,7 +21,7 @@ for file in "${data_files[@]}"; do mkdir -p $BASEDIR/scm/data/$file cd $BASEDIR/scm/data/$file echo "Retrieving $file" - wget https://github.com/NCAR/ccpp-scm/releases/download/v6.0.0/${file}.tar.gz + wget https://github.com/NCAR/ccpp-scm/releases/download/v7.0.0-beta/${file}.tar.gz tar -xf ${file}.tar.gz rm -f ${file}.tar.gz done From aa99c2dcbb19c9f7d7013837cdf9d4bff91b8fe9 Mon Sep 17 00:00:00 2001 From: Dustin Swales Date: Thu, 1 Aug 2024 21:48:43 +0000 Subject: [PATCH 18/40] Revert submodule. --- .gitmodules | 4 ++-- ccpp/physics | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index 6c2c7ba23..dc0798c32 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,8 +4,8 @@ branch = main [submodule "ccpp-physics"] path = ccpp/physics - url = https://github.com/dustinswales/ccpp-physics - branch = hotfix/clmlake_in_scm + url = https://github.com/NCAR/ccpp-physics + branch = main [submodule "CMakeModules"] path = CMakeModules url = https://github.com/noaa-emc/CMakeModules diff --git a/ccpp/physics b/ccpp/physics index fd3aae41b..62f7656eb 160000 --- a/ccpp/physics +++ b/ccpp/physics @@ -1 +1 @@ -Subproject commit fd3aae41b2012ed23b0d38f70dbe4fdede5d3aa9 +Subproject commit 62f7656ebdaa39d989413e5d285ed6d6723eb4de From 59d82e9502d8e8c4ac7eab39950fe666b97404c3 Mon Sep 17 00:00:00 2001 From: Soren Rasmussen Date: Fri, 19 Jul 2024 09:31:41 -0600 Subject: [PATCH 19/40] Installing OpenMPI, fixing ENV and LABEL warnings, splitting some commands into multiple RUN statements for quicker debugging by making the failing step easier to find Installing ccmake in cmake-curses-gui fixes some CMake issues that were occurring, unsure why. Changing venv install location, old one wasn't working. Python packages needed to be updated. Switching to parallel builds. Make sure python package f90nml can be found in paths --- docker/Dockerfile | 69 ++++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 37 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 7d0586090..85ad4d856 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,5 +1,5 @@ FROM debian:12 -MAINTAINER Michael Kavulich +LABEL maintainer="Michael Kavulich " # Set up base OS environment @@ -7,21 +7,25 @@ RUN apt-get -y update # Get "essential" tools and libraries RUN apt-get -y install build-essential \ - && apt-get -y install cmake curl git file gfortran-12 ksh m4 python3 tcsh time wget vim \ + && apt-get -y install cmake cmake-curses-gui curl git file gfortran-12 ksh m4 python3 tcsh time wget vim emacs-nox \ && apt-get -y install libnetcdf-pnetcdf-19 libnetcdff7 libnetcdf-dev libnetcdff-dev libxml2 \ - && apt-get -y install python3-pip python3.11-venv + && apt-get -y install python3-pip python3.11-venv python3-netcdf4 \ + && apt-get -y install openmpi-bin libopenmpi-dev +RUN ln -s /usr/bin/python3 /usr/bin/python -MAINTAINER Grant Firl or Michael Kavulich +# Set up python needed packages, preferred Docker method is apt-get but +# f90nml can't be installed for debian that way +RUN pip install f90nml --break-system-packages #Compiler environment variables -ENV CC /usr/bin/gcc -ENV FC /usr/bin/gfortran -ENV CXX /usr/bin/g++ -ENV F77 /usr/bin/gfortran -ENV F90 /usr/bin/gfortran +ENV CC=/usr/bin/gcc +ENV FC=/usr/bin/gfortran +ENV CXX=/usr/bin/g++ +ENV F77=/usr/bin/gfortran +ENV F90=/usr/bin/gfortran # Other necessary environment variables -ENV LD_LIBRARY_PATH /usr/lib/ +ENV LD_LIBRARY_PATH=/usr/lib/ # Set up unpriviledged user account, set up user home space and make sure user has permissions on all stuff in /comsoftware RUN groupadd comusers -g 9999 \ @@ -32,57 +36,54 @@ RUN groupadd comusers -g 9999 \ && chown -R comuser:comusers /comsoftware \ && chmod -R 6755 /comsoftware -# Link version-specific aliases (python3 will be created later with virtual environment) -RUN ln -s ~comuser/.venv/bin/python3 /usr/local/bin/python -RUN ln -s /usr/bin/gfortran-12 /usr/bin/gfortran - # all root steps completed above, now continue below as regular userID comuser USER comuser WORKDIR /home # Build NCEP libraries we need for SCM -ENV NCEPLIBS_DIR /comsoftware/nceplibs +ENV NCEPLIBS_DIR=/comsoftware/nceplibs RUN mkdir -p $NCEPLIBS_DIR/src && cd $NCEPLIBS_DIR/src \ && git clone -b v2.4.1 --recursive https://github.com/NOAA-EMC/NCEPLIBS-bacio \ && mkdir NCEPLIBS-bacio/build && cd NCEPLIBS-bacio/build \ && cmake -DCMAKE_INSTALL_PREFIX=$NCEPLIBS_DIR .. \ - && make VERBOSE=1 \ - && make install + && make VERBOSE=1 -j \ + && make install RUN cd $NCEPLIBS_DIR/src \ && git clone -b v2.3.3 --recursive https://github.com/NOAA-EMC/NCEPLIBS-sp \ && mkdir NCEPLIBS-sp/build && cd NCEPLIBS-sp/build \ && cmake -DCMAKE_INSTALL_PREFIX=$NCEPLIBS_DIR .. \ - && make VERBOSE=1 \ + && make VERBOSE=1 -j \ && make install RUN cd $NCEPLIBS_DIR/src \ && git clone -b v2.11.0 --recursive https://github.com/NOAA-EMC/NCEPLIBS-w3emc \ && mkdir NCEPLIBS-w3emc/build && cd NCEPLIBS-w3emc/build \ && cmake -DCMAKE_INSTALL_PREFIX=$NCEPLIBS_DIR .. \ - && make VERBOSE=1 \ + && make VERBOSE=1 -j \ && make install -ENV bacio_ROOT /comsoftware/nceplibs -ENV sp_ROOT /comsoftware/nceplibs -ENV w3emc_ROOT /comsoftware/nceplibs +ENV bacio_ROOT=/comsoftware/nceplibs +ENV sp_ROOT=/comsoftware/nceplibs +ENV w3emc_ROOT=/comsoftware/nceplibs -# Obtain CCPP SCM source code and static data, build code +# Obtain CCPP SCM source code, build code, and download static data RUN cd /comsoftware \ && git clone --recursive -b main https://github.com/NCAR/ccpp-scm \ - && cd /comsoftware/ccpp-scm/ \ - && ./contrib/get_all_static_data.sh \ - && ./contrib/get_thompson_tables.sh \ - && cd /comsoftware/ccpp-scm/scm \ - && mkdir bin \ - && cd bin \ + && mkdir /comsoftware/ccpp-scm/scm/bin + +RUN cd /comsoftware/ccpp-scm/scm/bin \ && cmake ../src \ - && make -j4 + && make -j + +RUN cd /comsoftware/ccpp-scm/ \ + && ./contrib/get_all_static_data.sh \ + && ./contrib/get_thompson_tables.sh # The analysis scripts have options for using LaTeX when making figure labels. -# If you would like to install LaTeK, uncomment the section below. +# If you would like to install LaTeK, uncomment the section below. # Note: This will increase the image size by 1 GB. #USER root #RUN yum -y update \ @@ -96,9 +97,3 @@ ENV SCM_ROOT=/comsoftware/ccpp-scm/ # For interactive use, vim mouse settings are infuriating RUN echo "set mouse=" > ~/.vimrc - -# Set up python virtual environment and install needed packages -ENV VIRTUAL_ENV=~/.venv -RUN python3 -m venv $VIRTUAL_ENV -ENV PATH="$VIRTUAL_ENV/bin:$PATH" -RUN pip3 install f90nml==1.4.4 netcdf4==1.6.5 From d2a41d3664cc0094a816f92e0d9cb96415686cc2 Mon Sep 17 00:00:00 2001 From: Soren Rasmussen Date: Wed, 24 Jul 2024 18:13:44 -0600 Subject: [PATCH 20/40] Changing Fortran stop statements to error stop statements. Adding github actions flag to run_scm.py so it will stop on first error --- .github/workflows/ci_test_docker.yml | 2 +- scm/src/CCPP_typedefs.F90 | 19 +- scm/src/GFS_typedefs.F90 | 134 +++++----- scm/src/run_scm.py | 136 +++++----- scm/src/scm.F90 | 86 +++---- scm/src/scm_forcing.F90 | 168 ++++++------- scm/src/scm_input.F90 | 357 +++++++++++++-------------- scm/src/scm_setup.F90 | 62 ++--- scm/src/scm_time_integration.F90 | 27 +- scm/src/scm_utils.F90 | 28 +-- scm/src/scm_vgrid.F90 | 46 ++-- 11 files changed, 534 insertions(+), 531 deletions(-) diff --git a/.github/workflows/ci_test_docker.yml b/.github/workflows/ci_test_docker.yml index e6508a00d..51991a10d 100644 --- a/.github/workflows/ci_test_docker.yml +++ b/.github/workflows/ci_test_docker.yml @@ -26,4 +26,4 @@ jobs: run: | mkdir $HOME/output chmod a+rw $HOME/output - docker run --rm -v $HOME/output:/home ${{ env.TEST_TAG }} ./run_scm.py -f ../../test/rt_test_cases.py --runtime_mult 0.1 -d + docker run --rm -v $HOME/output:/home ${{ env.TEST_TAG }} ./run_scm.py -f ../../test/rt_test_cases.py --runtime_mult 0.1 -d -a diff --git a/scm/src/CCPP_typedefs.F90 b/scm/src/CCPP_typedefs.F90 index 0b49ed010..4cfaeacd7 100644 --- a/scm/src/CCPP_typedefs.F90 +++ b/scm/src/CCPP_typedefs.F90 @@ -355,8 +355,8 @@ module CCPP_typedefs real (kind=kind_phys), pointer :: qs_lay(:,:) => null() !< real (kind=kind_phys), pointer :: q_lay(:,:) => null() !< real (kind=kind_phys), pointer :: deltaZ(:,:) => null() !< - real (kind=kind_phys), pointer :: deltaZc(:,:) => null() !< - real (kind=kind_phys), pointer :: deltaP(:,:) => null() !< + real (kind=kind_phys), pointer :: deltaZc(:,:) => null() !< + real (kind=kind_phys), pointer :: deltaP(:,:) => null() !< real (kind=kind_phys), pointer :: cloud_overlap_param(:,:) => null() !< Cloud overlap parameter real (kind=kind_phys), pointer :: cnv_cloud_overlap_param(:,:) => null() !< Convective cloud overlap parameter real (kind=kind_phys), pointer :: precip_overlap_param(:,:) => null() !< Precipitation overlap parameter @@ -373,12 +373,12 @@ module CCPP_typedefs real (kind=kind_phys), pointer :: cld_rwp(:,:) => null() !< Cloud rain water path real (kind=kind_phys), pointer :: cld_rerain(:,:) => null() !< Cloud rain effective radius real (kind=kind_phys), pointer :: precip_frac(:,:) => null() !< Precipitation fraction - real (kind=kind_phys), pointer :: cld_cnv_frac(:,:) => null() !< SGS convective cloud fraction + real (kind=kind_phys), pointer :: cld_cnv_frac(:,:) => null() !< SGS convective cloud fraction real (kind=kind_phys), pointer :: cld_cnv_lwp(:,:) => null() !< SGS convective cloud liquid water path real (kind=kind_phys), pointer :: cld_cnv_reliq(:,:) => null() !< SGS convective cloud liquid effective radius real (kind=kind_phys), pointer :: cld_cnv_iwp(:,:) => null() !< SGS convective cloud ice water path real (kind=kind_phys), pointer :: cld_cnv_reice(:,:) => null() !< SGS convective cloud ice effecive radius - real (kind=kind_phys), pointer :: cld_pbl_lwp(:,:) => null() !< SGS PBL cloud liquid water path + real (kind=kind_phys), pointer :: cld_pbl_lwp(:,:) => null() !< SGS PBL cloud liquid water path real (kind=kind_phys), pointer :: cld_pbl_reliq(:,:) => null() !< SGS PBL cloud liquid effective radius real (kind=kind_phys), pointer :: cld_pbl_iwp(:,:) => null() !< SGS PBL cloud ice water path real (kind=kind_phys), pointer :: cld_pbl_reice(:,:) => null() !< SGS PBL cloud ice effecive radius @@ -390,7 +390,7 @@ module CCPP_typedefs real (kind=kind_phys), pointer :: fluxswDOWN_allsky(:,:) => null() !< RRTMGP downward shortwave all-sky flux profile real (kind=kind_phys), pointer :: fluxswUP_clrsky(:,:) => null() !< RRTMGP upward shortwave clr-sky flux profile real (kind=kind_phys), pointer :: fluxswDOWN_clrsky(:,:) => null() !< RRTMGP downward shortwave clr-sky flux profile - real (kind=kind_phys), pointer :: sfc_emiss_byband(:,:) => null() !< + real (kind=kind_phys), pointer :: sfc_emiss_byband(:,:) => null() !< real (kind=kind_phys), pointer :: sec_diff_byband(:,:) => null() !< real (kind=kind_phys), pointer :: sfc_alb_nir_dir(:,:) => null() !< real (kind=kind_phys), pointer :: sfc_alb_nir_dif(:,:) => null() !< @@ -888,7 +888,7 @@ subroutine gfs_interstitial_setup_tracers(Interstitial, Model) Interstitial%nvdiff = Interstitial%nvdiff + 1 ENDIF if (Model%me == Model%master) write(0,*) 'nssl_settings2: nvdiff,ntrac = ', Interstitial%nvdiff, Model%ntrac - + elseif (Model%imp_physics == Model%imp_physics_wsm6) then Interstitial%nvdiff = Model%ntrac -3 if (Model%satmedmf) Interstitial%nvdiff = Interstitial%nvdiff + 1 @@ -965,8 +965,7 @@ subroutine gfs_interstitial_setup_tracers(Interstitial, Model) Interstitial%nvdiff = 9 endif else - write(0,*) "Selected microphysics scheme is not supported when coupling with chemistry" - stop + error stop "Selected microphysics scheme is not supported when coupling with chemistry" endif if (Interstitial%trans_aero) Interstitial%nvdiff = Interstitial%nvdiff + Model%ntchm if (Model%ntke > 0) Interstitial%nvdiff = Interstitial%nvdiff + 1 ! adding tke to the list @@ -1419,11 +1418,11 @@ subroutine gfs_interstitial_phys_reset (Interstitial, Model) ! Use same logic in UFS to reset Thompson extended diagnostics Interstitial%ext_diag_thompson_reset = Interstitial%max_hourly_reset ! - ! Frequency flag for computing the full radar reflectivity (water coated ice) + ! Frequency flag for computing the full radar reflectivity (water coated ice) if (Model%nsfullradar_diag<0) then Interstitial%fullradar_diag = .true. else - Interstitial%fullradar_diag = (Model%kdt == 1 .or. mod(Model%kdt, nint(Model%nsfullradar_diag/Model%dtp)) == 0) + Interstitial%fullradar_diag = (Model%kdt == 1 .or. mod(Model%kdt, nint(Model%nsfullradar_diag/Model%dtp)) == 0) end if ! diff --git a/scm/src/GFS_typedefs.F90 b/scm/src/GFS_typedefs.F90 index d8fe5f446..35f325f03 100644 --- a/scm/src/GFS_typedefs.F90 +++ b/scm/src/GFS_typedefs.F90 @@ -2,7 +2,7 @@ module GFS_typedefs use mpi_f08 use machine, only: kind_phys, kind_dbl_prec, kind_sngl_prec - + use module_radsw_parameters, only: topfsw_type, sfcfsw_type use module_radlw_parameters, only: topflw_type, sfcflw_type use h2o_def, only: levh2o, h2o_coeff @@ -541,14 +541,14 @@ module GFS_typedefs real (kind=kind_phys), pointer :: evap_lnd(:) => null() !< sfc latent heat flux over land, converted to evaporative flux real (kind=kind_phys), pointer :: hflx_lnd(:) => null() !< sfc sensible heat flux over land real (kind=kind_phys), pointer :: ep_lnd(:) => null() !< sfc up pot latent heat flux over land - real (kind=kind_phys), pointer :: t2mmp_lnd(:) => null() !< 2 meter temperature over land + real (kind=kind_phys), pointer :: t2mmp_lnd(:) => null() !< 2 meter temperature over land real (kind=kind_phys), pointer :: q2mp_lnd(:) => null() !< 2 meter spec humidity over land real (kind=kind_phys), pointer :: gflux_lnd(:) => null() !< soil heat flux over land real (kind=kind_phys), pointer :: runoff_lnd(:) => null() !< surface runoff over land real (kind=kind_phys), pointer :: drain_lnd(:) => null() !< subsurface runoff over land real (kind=kind_phys), pointer :: cmm_lnd(:) => null() !< surface drag wind speed for momentum - real (kind=kind_phys), pointer :: chh_lnd(:) => null() !< surface drag mass flux for heat and moisture - real (kind=kind_phys), pointer :: zvfun_lnd(:) => null() !< function of surface roughness length and green vegetation fraction + real (kind=kind_phys), pointer :: chh_lnd(:) => null() !< surface drag mass flux for heat and moisture + real (kind=kind_phys), pointer :: zvfun_lnd(:) => null() !< function of surface roughness length and green vegetation fraction !--- outgoing accumulated quantities real (kind=kind_phys), pointer :: rain_cpl (:) => null() !< total rain precipitation @@ -754,7 +754,7 @@ module GFS_typedefs logical :: cplaqm !< default no cplaqm collection logical :: cplchm !< default no cplchm collection logical :: cpllnd !< default no cpllnd collection - logical :: cpllnd2atm !< default no lnd->atm coupling + logical :: cpllnd2atm !< default no lnd->atm coupling logical :: rrfs_sd !< default no rrfs_sd collection logical :: use_cice_alb !< default .false. - i.e. don't use albedo imported from the ice model logical :: cpl_imp_mrg !< default no merge import with internal forcings @@ -1225,8 +1225,8 @@ module GFS_typedefs real(kind=kind_phys) :: rbcr !< Critical Richardson Number in the PBL scheme real(kind=kind_phys) :: betascu !< Tuning parameter for prog. closure shallow clouds - real(kind=kind_phys) :: betamcu !< Tuning parameter for prog. closure midlevel clouds - real(kind=kind_phys) :: betadcu !< Tuning parameter for prog. closure deep clouds + real(kind=kind_phys) :: betamcu !< Tuning parameter for prog. closure midlevel clouds + real(kind=kind_phys) :: betadcu !< Tuning parameter for prog. closure deep clouds !--- MYNN parameters/switches logical :: do_mynnedmf @@ -3075,7 +3075,7 @@ subroutine coupling_create (Coupling, IM, Model) Coupling%slmsk_cpl = clear_val !< pointer to sfcprop%slmsk endif - ! -- Coupling options to retrive land fluxes from external land component + ! -- Coupling options to retrive land fluxes from external land component if (Model%cpllnd .and. Model%cpllnd2atm) then allocate (Coupling%sncovr1_lnd (IM)) allocate (Coupling%qsurf_lnd (IM)) @@ -4003,7 +4003,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & !--- coupling parameters cplflx, cplice, cplocn2atm, cplwav, cplwav2atm, cplaqm, & cplchm, cpllnd, cpllnd2atm, cpl_imp_mrg, cpl_imp_dbg, & - rrfs_sd, use_cice_alb, & + rrfs_sd, use_cice_alb, & #ifdef IDEA_PHYS lsidea, weimer_model, f107_kp_size, f107_kp_interval, & f107_kp_skip_size, f107_kp_data_size, f107_kp_read_in_start, & @@ -4192,7 +4192,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & inquire (file=trim(fn_nml), exist=exists) if (.not. exists) then write(6,*) 'GFS_namelist_read:: namelist file: ',trim(fn_nml),' does not exist' - stop + error stop else open (unit=nlunit, file=fn_nml, action='READ', status='OLD', iostat=ios) endif @@ -4228,7 +4228,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & Model%qdiag3d = qdiag3d if (qdiag3d .and. .not. ldiag3d) then write(0,*) 'Logic error in GFS_typedefs.F90: qdiag3d requires ldiag3d' - stop + error stop endif Model%flag_for_gwd_generic_tend = .true. Model%flag_for_pbl_generic_tend = .true. @@ -4255,12 +4255,12 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & else write(0,*) 'CCPP suite simulator turned on, but error encountered loading data.' write(0,*) errmsg - stop + error stop endif if(.not. qdiag3d .and. .not. ldiag3d) then write(0,*) 'CCPP suite simulator turned on, but qdiag3d and/or ldiag3d are not set to .true.' write(0,*) errmsg - stop + error stop endif endif @@ -4340,11 +4340,11 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & ! if (naux2d>naux2dmax) then write(0,*) "Error, number of requested auxiliary 2d arrays exceeds the maximum defined in GFS_typedefs.F90" - stop + error stop endif if (naux3d>naux3dmax) then write(0,*) "Error, number of requested auxiliary 3d arrays exceeds the maximum defined in GFS_typedefs.F90" - stop + error stop endif Model%naux2d = naux2d Model%naux3d = naux3d @@ -4358,7 +4358,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & end if if (any(aux2d_time_avg) .or. any(aux3d_time_avg)) then write(0,*) "Error, the SCM has not implemented time averaging of diagnostics in GFS_typedefs.F90" - stop + error stop end if Model%fhcyc = fhcyc @@ -4397,7 +4397,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & ! Model%cplflx == .true. and Model%cplice == .false. (HAFS FV3ATM-HYCOM) if (Model%cplice .and. .not. Model%cplflx) then print *,' Logic error: Model%cplflx==.false. and Model%cplice==.true. is currently not supported - shutting down' - stop + error stop endif Model%cplocn2atm = cplocn2atm Model%cplwav = cplwav @@ -4451,7 +4451,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & Model%lsidea = lsidea if (Model%lsidea) then print *,' LSIDEA is active but needs to be reworked for FV3 - shutting down' - stop + error stop endif #ifdef IDEA_PHYS !--- integrated dynamics through earth's atmosphere @@ -4490,7 +4490,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & Model%levr = levs else if (levr > levs) then write(0,*) "Logic error, number of radiation levels (levr) cannot exceed number of model levels (levs)" - stop + error stop else Model%levr = levr endif @@ -4498,11 +4498,11 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & if (isubc_sw < 0 .or. isubc_sw > 2) then write(0,'(a,i0)') 'ERROR: shortwave cloud-sampling (isubc_sw) scheme selected not valid: ',isubc_sw - stop + error stop endif if (isubc_lw < 0 .or. isubc_lw > 2) then write(0,'(a,i0)') 'ERROR: longwave cloud-sampling (isubc_lw) scheme selected not valid: ',isubc_lw - stop + error stop endif @@ -4510,7 +4510,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & (iovr .ne. Model%iovr_max) .and. (iovr .ne. Model%iovr_dcorr) .and. & (iovr .ne. Model%iovr_exp) .and. (iovr .ne. Model%iovr_exprand)) then write(0,'(a,i0)') 'ERROR: cloud-overlap (iovr) scheme selected not valid: ',iovr - stop + error stop endif if ((isubc_sw == 0 .or. isubc_lw == 0) .and. iovr > 2 ) then @@ -4615,16 +4615,16 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & ! RRTMGP incompatible with levr /= levs if (Model%levr /= Model%levs) then write(0,*) "Logic error, RRTMGP only works with levr = levs" - stop + error stop end if ! RRTMGP LW scattering calculation not supported w/ RRTMG cloud-optics if (Model%doGP_lwscat .and. Model%doG_cldoptics) then write(0,*) "Logic error, RRTMGP Longwave cloud-scattering not supported with RRTMG cloud-optics." - stop + error stop end if if (Model%doGP_sgs_mynn .and. .not. do_mynnedmf) then write(0,*) "Logic error, RRTMGP flag doGP_sgs_mynn only works with do_mynnedmf=.true." - stop + error stop endif if (Model%doGP_sgs_cnv .or. Model%doGP_sgs_mynn) then write(0,*) "RRTMGP explicit cloud scheme being used." @@ -4635,7 +4635,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & if (Model%doGP_cldoptics_PADE .and. Model%doGP_cldoptics_LUT) then write(0,*) "Logic error, Both RRTMGP cloud-optics options cannot be selected. " - stop + error stop end if if (.not. Model%doGP_cldoptics_PADE .and. .not. Model%doGP_cldoptics_LUT .and. .not. Model%doG_cldoptics) then write(0,*) "Logic error, No option for cloud-optics scheme provided. Using RRTMG cloud-optics" @@ -4644,7 +4644,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & if (Model%rrtmgp_nGptsSW .lt. 0 .or. Model%rrtmgp_nGptsLW .lt. 0 .or. & Model%rrtmgp_nBandsSW .lt. 0 .or. Model%rrtmgp_nBandsLW .lt. 0) then write(0,*) "Logic error, RRTMGP spectral dimensions (bands/gpts) need to be provided." - stop + error stop endif else if (Model%use_LW_jacobian) then @@ -4660,7 +4660,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & if (.not.lwhtr .or. .not.swhtr) then write(0,*) "Logic error, the CCPP version of RRTMG lwrad/swrad require the output" // & " of the lw/sw heating rates to be turned on (namelist options lwhtr and swhtr)" - stop + error stop end if !--- microphysical switch @@ -4723,7 +4723,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & Model%mraerosol = mraerosol if (Model%ltaerosol .and. Model%mraerosol) then write(0,*) 'Logic error: Only one Thompson aerosol option can be true, either ltaerosol or mraerosol)' - stop + error stop end if Model%lradar = lradar Model%nsfullradar_diag = nsfullradar_diag @@ -4754,7 +4754,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & Model%rdlai = rdlai if (Model%rdlai .and. .not. Model%lsm == Model%lsm_ruc) then write(0,*) 'Logic error: rdlai = .true. only works with RUC LSM' - stop + error stop end if ! Set surface layers for CCPP physics @@ -4772,7 +4772,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & if (Model%lsm==Model%lsm_noah .or. Model%lsm==Model%lsm_noahmp) then if (Model%lsoil_lsm/=4) then write(0,*) 'Error in GFS_typedefs.F90, number of soil layers must be 4 for Noah/NoahMP' - stop + error stop end if Model%zs = (/-0.1_kind_phys, -0.4_kind_phys, -1.0_kind_phys, -2.0_kind_phys/) Model%dzs = (/ 0.1_kind_phys, 0.3_kind_phys, 0.6_kind_phys, 1.0_kind_phys/) @@ -4785,7 +4785,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & if (Model%lsm==Model%lsm_ruc) then if (Model%lsoil_lsm/=9) then write(0,*) 'Error in GFS_typedefs.F90, number of soil layers must be 9 for RUC' - stop + error stop end if end if @@ -4795,12 +4795,12 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & if (Model%lsm==Model%lsm_noah .or. Model%lsm==Model%lsm_noahmp) then if (kice/=2) then write(0,*) 'Error in GFS_typedefs.F90, number of ice model layers must be 2 for Noah/NoahMP/Noah_WRFv4' - stop + error stop end if elseif (Model%lsm==Model%lsm_ruc) then if (kice/=9) then write(0,*) 'Error in GFS_typedefs.F90, number of ice model layers must be 9 for RUC' - stop + error stop end if end if @@ -4813,7 +4813,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & if (Model%lsm==Model%lsm_noahmp) then if (lsnow_lsm/=3) then write(0,*) 'Logic error: NoahMP expects the maximum number of snow layers to be exactly 3 (see sfc_noahmp_drv.f)' - stop + error stop else Model%lsnow_lsm = lsnow_lsm ! Set lower bound for LSM model, runs from negative (above surface) to surface (zero) @@ -4843,7 +4843,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & !see GFS_MP_generic_post.F90; exticeden is only compatible with GFDL, !Thompson, or NSSL MP print *,' Using exticeden = T is only valid when using GFDL, Thompson, or NSSL microphysics.' - stop + error stop end if ! GFDL surface layer options Model%lcurr_sf = lcurr_sf @@ -4917,19 +4917,19 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & !HWRF physics suite if (hwrf_samfdeep .and. imfdeepcnv/=2) then write(*,*) 'Logic error: hwrf_samfdeep requires imfdeepcnv=2' - stop + error stop end if if (hwrf_samfshal .and. imfshalcnv/=2) then write(*,*) 'Logic error: hwrf_samfshal requires imfshalcnv=2' - stop + error stop end if Model%hwrf_samfdeep = hwrf_samfdeep Model%hwrf_samfshal = hwrf_samfshal - !--prognostic closure - moisture coupling + !--prognostic closure - moisture coupling if ((progsigma .and. imfdeepcnv/=2) .and. (progsigma .and. imfdeepcnv/=5)) then write(*,*) 'Logic error: progsigma requires imfdeepcnv=2 or 5' - stop + error stop end if Model%progsigma = progsigma Model%betascu = betascu @@ -4938,7 +4938,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & if (oz_phys .and. oz_phys_2015) then write(*,*) 'Logic error: can only use one ozone physics option (oz_phys or oz_phys_2015), not both. Exiting.' - stop + error stop end if Model%oz_phys = oz_phys Model%oz_phys_2015 = oz_phys_2015 @@ -5556,7 +5556,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & write(0,*) 'NSSL micro: error! CCN is OFF (nssl_ccn_on = F) but ntccn > 1.' write(0,*) 'Should either remove ccn_nc from field_table or set nssl_ccn_on = .true.' ENDIF - stop + error stop ENDIF Model%ntccn = -99 Model%ntccna = -99 @@ -5565,7 +5565,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & write(*,*) 'NSSL micro: error! CCN is ON but ntccn < 1. Must have ccn_nc in field_table if nssl_ccn_on=T' write(0,*) 'NSSL micro: error! CCN is ON but ntccn < 1. Must have ccn_nc in field_table if nssl_ccn_on=T' ENDIF - stop + error stop ELSE if (Model%me == Model%master) then write(*,*) 'NSSL micro: CCN is ON' @@ -5601,7 +5601,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & write(0,*) 'missing needed tracers for NSSL hail! nthl > 1 but either volume or number is not in field_table' write(0,*) 'nthv, nthnc = ', Model%nthv, Model%nthnc ENDIF - stop + error stop ENDIF ENDIF @@ -5620,21 +5620,21 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & write(*,*) 'NSSL micro: CCN is ON' ENDIF ENDIF - + ! add checks for nssl_3moment - IF ( ( Model%nssl_3moment ) ) THEN + IF ( ( Model%nssl_3moment ) ) THEN IF ( Model%ntrz < 1 ) THEN write(*,*) 'NSSL micro: 3-moment is ON, but rain_ref tracer is missing' - stop + error stop ENDIF IF ( Model%ntgz < 1 ) THEN write(*,*) 'NSSL micro: 3-moment is ON, but graupel_ref tracer is missing' - stop + error stop ENDIF IF ( nssl_hail_on ) THEN IF ( Model%nthz < 1 ) THEN write(*,*) 'NSSL micro: 3-moment is ON, but hail_ref tracer is missing' - stop + error stop ENDIF ENDIF ENDIF @@ -5646,7 +5646,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & Model%ntcw < 1 .or. Model%ntlnc < 1 & ) THEN if (Model%me == Model%master) write(0,*) 'missing needed tracers for NSSL!' - stop + error stop ENDIF @@ -5762,7 +5762,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & if (do_shoc) then if (Model%imp_physics == Model%imp_physics_thompson) then print *,'SHOC is not currently compatible with Thompson MP -- shutting down' - stop + error stop endif Model%nshoc_3d = 3 Model%nshoc_2d = 0 @@ -5781,7 +5781,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & if (Model%do_mynnedmf) then if (Model%do_shoc .or. Model%hybedmf .or. Model%satmedmf) then print *,' Logic error: MYNN EDMF cannot be run with SHOC, HEDMF or SATMEDMF' - stop + error stop end if ! Model%shal_cnv = .false. ! Model%imfshalcnv = -1 @@ -5827,14 +5827,14 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & elseif (Model%lsm == 0) then print *,' OSU no longer supported - job aborted' - stop + error stop elseif (Model%lsm == Model%lsm_noahmp) then if (Model%ivegsrc /= 1) then print *,'Vegetation type must be IGBP if Noah MP is used' - stop + error stop elseif (Model%isot /= 1) then print *,'Soil type must be STATSGO if Noah MP is used' - stop + error stop endif print *, 'New Noah MP Land Surface Model will be used' print *, 'The Physics options are' @@ -5863,7 +5863,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & print *,' add_fire_heat_flux = ',add_fire_heat_flux else print *,' Unsupported LSM type - job aborted - lsm=',Model%lsm - stop + error stop endif ! if (Model%lsm == Model%lsm_noahmp .and. Model%iopt_snf == 4) then @@ -5908,7 +5908,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & if ( (Model%imfdeepcnv == Model%imfdeepcnv_ntiedtke .or. Model%imfshalcnv == Model%imfshalcnv_ntiedtke) .and. & .not. (Model%imfdeepcnv == Model%imfdeepcnv_ntiedtke .and. Model%imfshalcnv == Model%imfshalcnv_ntiedtke) ) then write(0,*) "Logic error: if NTDK deep convection is used, must also use NTDK shallow convection (and vice versa)" - stop + error stop end if if (.not. Model%cscnv) then @@ -6048,7 +6048,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & Model%npsdelt = 2 if (nwat /= 2) then print *,' Zhao-Carr MP requires nwat to be set to 2 - job aborted' - stop + error stop end if if (Model%me == Model%master) print *,' Using Zhao/Carr/Sundqvist Microphysics' @@ -6069,7 +6069,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & Model%nseffr = 3 if (nwat /= 4) then print *,' Ferrier-Aligo MP requires nwat to be set to 4 - job aborted' - stop + error stop end if if (Model%me == Model%master) print *,' Using Ferrier-Aligo MP scheme', & ' microphysics', & @@ -6077,7 +6077,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & elseif (Model%imp_physics == Model%imp_physics_wsm6) then !WSM6 microphysics print *,' Error, WSM6 no longer supported - job aborted' - stop + error stop !Model%npdf3d = 0 !Model%num_p3d = 3 !Model%num_p2d = 1 @@ -6101,7 +6101,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & ENDIF if ( nwat /= 6+i ) then print *,' NSSL MP requires nwat to be set to ', 6+i,' - job aborted, nssl_hail_on = ',nssl_hail_on - stop + error stop end if Model%nleffr = 1 Model%nieffr = 2 @@ -6132,11 +6132,11 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & Model%nseffr = 3 if (nwat /= 6) then print *,' Thompson MP requires nwat to be set to 6 - job aborted' - stop + error stop end if if (.not. Model%effr_in) then print *,' Thompson MP requires effr_in to be set to .true. - job aborted' - stop + error stop end if if (Model%me == Model%master) print *,' Using Thompson double moment microphysics', & ' ltaerosol = ',Model%ltaerosol, & @@ -6168,7 +6168,7 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & endif if (nwat /= 6 .and. Model%fprcp >= 2) then print *,' Morrison-Gettelman MP requires nwat to be set to 6 - job aborted' - stop + error stop end if if (Model%me == Model%master) & print *,' Using Morrison-Gettelman double moment microphysics', & @@ -6208,14 +6208,14 @@ subroutine control_initialize (Model, nlunit, fn_nml, me, master, & Model%shcnvcw = .false. if (nwat /= 6) then print *,' GFDL MP requires nwat to be set to 6 - job aborted' - stop + error stop end if if (Model%me == Model%master) print *,' avg_max_length=',Model%avg_max_length if (Model%me == Model%master) print *,' Using GFDL Cloud Microphysics' else if (Model%me == Model%master) print *,'Wrong imp_physics value. Job abort.' - stop + error stop endif if(Model%ras .or. Model%cscnv) Model%cnvcld = .false. @@ -6349,7 +6349,7 @@ subroutine control_initialize_radar_tten(Model, radar_tten_limits) write(0,'(A,F12.4,A)') 'radar_tten_limits(1) = ',radar_tten_limits(1),' <-- lower limit' write(0,'(A,F12.4,A)') 'radar_tten_limits(2) = ',radar_tten_limits(2),' <-- upper limit' write(0,*) "If you do not want me to apply the prescribed tendencies, just say so! Remove fh_dfi_radar from your namelist." - stop + error stop endif else !o! Rejoice !o! Radar_tten_limits had lower and upper bounds. diff --git a/scm/src/run_scm.py b/scm/src/run_scm.py index b499fafac..35222f168 100755 --- a/scm/src/run_scm.py +++ b/scm/src/run_scm.py @@ -120,6 +120,7 @@ parser.add_argument('--n_itt_out', help='period of instantaneous output (number of timesteps)', required=False, type=int) parser.add_argument('--n_itt_diag', help='period of diagnostic output (number of timesteps)', required=False, type=int) parser.add_argument('-dt', '--timestep', help='timestep (s)', required=False, type=float) +parser.add_argument('-a', '--actions', help='if running from Github Actions this will select correct configuration', required=False, action='store_true') parser.add_argument('-v', '--verbose', help='set logging level to debug and write log to file', action='count', default=0) parser.add_argument('-f', '--file', help='name of file where SCM runs are defined') parser.add_argument('--mpi_command', help='command used to invoke the executable via MPI (including options)', required=False) @@ -190,13 +191,14 @@ def parse_arguments(): bin_dir = args.bin_dir timestep = args.timestep mpi_command = args.mpi_command - + github_actions = args.actions + if not sdf: sdf = DEFAULT_SUITE - + return (file, case, sdf, namelist, tracers, gdb, runtime, runtime_mult, docker, \ verbose, levels, npz_type, vert_coord_file, case_data_dir, n_itt_out, \ - n_itt_diag, run_dir, bin_dir, timestep, mpi_command) + n_itt_diag, run_dir, bin_dir, timestep, mpi_command, github_actions) def find_gdb(): """Detect gdb, abort if not found""" @@ -217,28 +219,28 @@ def __init__(self, case, suite, runtime, runtime_mult, levels, npz_type, vert_co """Initialize experiment. This routine does most of the work, including setting and checking the experiment configuration (namelist).""" - + self._case = case self._suite_obj = suite self._suite = suite._name self._name = case + '_' + self._suite - + self._physics_namelist = suite.namelist - + #check to see that the physics namelists exists in the right dir if not os.path.isfile(os.path.join(SCM_ROOT, PHYSICS_NAMELIST_DIR, self._physics_namelist)): message = 'The physics namelist {0} was not found'.format(os.path.join(SCM_ROOT, PHYSICS_NAMELIST_DIR, self._physics_namelist)) logging.critical(message) raise Exception(message) - + self._tracers = suite.tracers - + #check to see that the tracers exists in the right dir if not os.path.isfile(os.path.join(SCM_ROOT, TRACERS_DIR, self._tracers)): message = 'The tracer configuration {0} was not found'.format(os.path.join(TRACERS_DIR, self._tracers)) logging.critical(message) raise Exception(message) - + #check to see if the case namelists exists in the right dir self._namelist = os.path.join(SCM_ROOT, CASE_NAMELIST_DIR, self._case + '.nml') if not os.path.isfile(self._namelist): @@ -254,14 +256,14 @@ def __init__(self, case, suite, runtime, runtime_mult, levels, npz_type, vert_co self._runtime = None message = 'Namelist runtime adjustment {0} IS NOT applied'.format(self._runtime) logging.debug(message) - + if runtime_mult: self._runtime_mult = runtime_mult message = 'Existing case namelist runtime multiplied by {0}'.format(self._runtime_mult) logging.debug(message) else: self._runtime_mult = None - + if levels: self._levels = levels message = 'The number of vertical levels is set to {0}'.format(self._levels) @@ -270,7 +272,7 @@ def __init__(self, case, suite, runtime, runtime_mult, levels, npz_type, vert_co self._levels = None message = 'The number of vertical levels contained in the case configuration file is used if present, otherwise the default value in scm_input.F90 is used.' logging.debug(message) - + if npz_type: self._npz_type = npz_type message = 'The npz_type of vertical levels is set to {0}'.format(self._npz_type) @@ -294,7 +296,7 @@ def __init__(self, case, suite, runtime, runtime_mult, levels, npz_type, vert_co self._vert_coord_file = None message = 'The npz_type contained in the case configuration file is used if present, otherwise the default value in scm_input.F90 is used.' logging.debug(message) - + if case_data_dir: self._case_data_dir = case_data_dir else: @@ -304,12 +306,12 @@ def __init__(self, case, suite, runtime, runtime_mult, levels, npz_type, vert_co message = 'The case data directory {0} was not found'.format(self._case_data_dir) logging.critical(message) raise Exception(message) - + if n_itt_out: self._n_itt_out = n_itt_out else: self._n_itt_out = DEFAULT_OUTPUT_PERIOD - + if n_itt_diag: self._n_itt_diag = n_itt_diag else: @@ -319,7 +321,7 @@ def __init__(self, case, suite, runtime, runtime_mult, levels, npz_type, vert_co self._timestep = timestep else: self._timestep = suite.timestep - + @property def name(self): """Get the name of the experiment.""" @@ -339,27 +341,27 @@ def namelist(self): def namelist(self, value): """Set the case namelist of the experiment.""" self._namelist = value - + @property def case(self): """Get the case of the experiment.""" return self._case - + @name.setter def case(self, value): """Set the case of the experiment.""" self._case = value - + @property def suite(self): """Get the suite of the experiment.""" return self._suite - + @suite.setter def suite(self, value): """Set the suite of the experiment.""" self._suite = value - + @property def physics_namelist(self): """Get the physics namelist of the experiment.""" @@ -369,7 +371,7 @@ def physics_namelist(self): def physics_namelist(self, value): """Set the physics namelist of the experiment.""" self._physics_namelist = value - + @property def tracers(self): """Get the tracer file for the experiment.""" @@ -379,7 +381,7 @@ def tracers(self): def tracers(self, value): """Set the tracer file for the experiment.""" self._tracers = value - + @property def levels(self): """Get the number of vertical levels for the experiment.""" @@ -389,7 +391,7 @@ def levels(self): def levels(self, value): """Set the number of vertical levels for the experiment.""" self._levels = value - + @property def npz_type(self): """Get the vertical level type for the experiment.""" @@ -399,7 +401,7 @@ def npz_type(self): def npz_type(self, value): """Set the vertical level type for the experiment.""" self._npz_type = value - + @property def vert_coord_file(self): """Get the file containing vertical levels for the experiment.""" @@ -409,7 +411,7 @@ def vert_coord_file(self): def vert_coord_file(self, value): """Set the file containing vertical levels for the experiment.""" self._vert_coord_file = value - + @property def case_data_dir(self): """Get the case data directory for the experiment.""" @@ -419,7 +421,7 @@ def case_data_dir(self): def case_data_dir(self, value): """Set the case data directory for the experiment.""" self._case_data_dir = value - + @property def n_itt_out(self): """Get the output period (in timesteps) for the experiment.""" @@ -429,7 +431,7 @@ def n_itt_out(self): def n_itt_out(self, value): """Set the output period (in timesteps) for the experiment.""" self._n_itt_out = value - + @property def n_itt_diag(self): """Get the diagnostic period (in timesteps) for the experiment.""" @@ -439,10 +441,10 @@ def n_itt_diag(self): def n_itt_diag(self, value): """Set the diagnostic period (in timesteps) for the experiment.""" self._n_itt_diag = value - + def setup_rundir(self): """Set up run directory for this experiment.""" - + # Parse case configuration namelist and extract # - output directory # - surface_flux_spec @@ -475,7 +477,7 @@ def setup_rundir(self): case_nml['case_config']['n_itt_diag'] = self._n_itt_diag if self._timestep: case_nml['case_config']['dt'] = self._timestep - # look for the output_dir variable in the case configuration namelist and use it if it does; + # look for the output_dir variable in the case configuration namelist and use it if it does; # if it doesn't exist, create a default output directory name (from the case and suite names) and create a namelist patch try: output_dir = case_nml['case_config']['output_dir'] @@ -488,7 +490,7 @@ def setup_rundir(self): output_dir = 'output_' + self._case + '_' + self._suite + '_' + os.path.splitext(self._physics_namelist)[0] output_dir_patch_nml = {'case_config':{'output_dir':output_dir}} custom_output_dir = False - + #if using the DEPHY format, need to also check the case data file for the surfaceForcing global attribute for 'Flux' or 'surfaceFlux', which denotes prescribed surface fluxes try: input_type = case_nml['case_config']['input_type'] @@ -506,34 +508,34 @@ def setup_rundir(self): surface_flux_spec = case_nml['case_config']['sfc_flux_spec'] except KeyError: surface_flux_spec = False - + # If surface fluxes are specified for this case, use the SDF modified to use them if surface_flux_spec: logging.info('Specified surface fluxes are used for case {0}. Switching to SDF {1} from {2}'.format(self._case,'suite_' + self._suite + '_ps' + '.xml','suite_' + self._suite + '.xml')) self._suite = self._suite + '_ps' - + # Create physics_config namelist for experiment configuration file physics_config = {"physics_suite":self._suite, "physics_nml":self._physics_namelist,} physics_config_dict = {"physics_config":physics_config} physics_config_nml = f90nml.namelist.Namelist(physics_config_dict) - + # Create STANDARD_EXPERIMENT_NAMELIST in the run directory with the case configuration and physics configuration namelists logging.info('Creating experiment configuration namelist {0} in the run directory from {1} using {2} and {3} '.format(STANDARD_EXPERIMENT_NAMELIST,self._namelist,self._suite,self._physics_namelist)) - + with open(os.path.join(SCM_RUN, STANDARD_EXPERIMENT_NAMELIST), "w+") as nml_file: case_nml.write(nml_file) - + with open(os.path.join(SCM_RUN, STANDARD_EXPERIMENT_NAMELIST), "a") as nml_file: physics_config_nml.write(nml_file) - + # if using the default output dir name created in this script, patch the experiment namelist with the new output_dir variable if(not custom_output_dir): # GJF TODO: this implementation is clunky; newer versions of f90nml can handle this better, but this works with v0.19 so no need to require newer version f90nml.patch(os.path.join(SCM_RUN, STANDARD_EXPERIMENT_NAMELIST), output_dir_patch_nml, 'temp.nml') cmd = "mv {0} {1}".format('temp.nml', os.path.join(SCM_RUN, STANDARD_EXPERIMENT_NAMELIST)) execute(cmd) - + # Link physics namelist to run directory with its original name logging.debug('Linking physics namelist {0} to run directory'.format(self._physics_namelist)) if os.path.isfile(os.path.join(SCM_RUN, self._physics_namelist)): @@ -550,7 +552,7 @@ def setup_rundir(self): logging.info('Found optional prescribed surface physics namelist {0}; linking it to run directory'.format(opt_ps_nml_filename)) cmd = "ln -sf {0} {1}".format(opt_ps_nml_filename, os.path.join(SCM_RUN, self._physics_namelist)) execute(cmd) - + # Link tracer configuration to run directory with standard name logging.debug('Linking tracer configuration {0} to run directory'.format(self._tracers)) if os.path.isfile(os.path.join(SCM_RUN, self._tracers)): @@ -561,7 +563,7 @@ def setup_rundir(self): raise Exception(message) cmd = "ln -sf {0} {1}".format(os.path.join(SCM_ROOT, TRACERS_DIR, self._tracers), os.path.join(SCM_RUN, TRACERS_LINK)) execute(cmd) - + # Link case data file to run directory with original name try: input_type = case_nml['case_config']['input_type'] @@ -580,7 +582,7 @@ def setup_rundir(self): raise Exception(message) cmd = "ln -sf {0} {1}".format(os.path.join(SCM_ROOT, self._case_data_dir, case_data_netcdf_file), os.path.join(SCM_RUN, case_data_netcdf_file)) execute(cmd) - + # Link vertical coordinate file to run directory with its original name if (self._npz_type == 'input'): logging.debug('Linking vertical coordinate file {0} to run directory'.format(self._vert_coord_file)) @@ -592,7 +594,7 @@ def setup_rundir(self): raise Exception(message) cmd = "ln -sf {0} {1}".format(os.path.join(SCM_ROOT, VERT_COORD_DATA_DIR, self._vert_coord_file), os.path.join(SCM_RUN, self._vert_coord_file)) execute(cmd) - + # Link physics SDF to run directory physics_suite = 'suite_' + self._suite + '.xml' logging.debug('Linking physics suite {0} to run directory'.format(physics_suite)) @@ -604,7 +606,7 @@ def setup_rundir(self): raise Exception(message) cmd = "ln -sf {0} {1}".format(os.path.join(SCM_ROOT, PHYSICS_SUITE_DIR, physics_suite), os.path.join(SCM_RUN, physics_suite)) execute(cmd) - + # Link physics data needed for schemes to run directory logging.debug('Linking physics input data from {0} into run directory'.format(os.path.join(SCM_ROOT, PHYSICS_DATA_DIR))) for entry in os.listdir(os.path.join(SCM_ROOT, PHYSICS_DATA_DIR)): @@ -613,7 +615,7 @@ def setup_rundir(self): logging.debug('Linking file {0}'.format(entry)) cmd = 'ln -sf {0} {1}'.format(os.path.join(SCM_ROOT, PHYSICS_DATA_DIR, entry), os.path.join(SCM_RUN, entry)) execute(cmd) - + # Link reference profile data to run directory logging.debug('Linking reference profile data from {0} into run directory'.format(os.path.join(SCM_ROOT, REFERENCE_PROFILE_DIR))) for entry in REFERENCE_PROFILE_FILE_LIST: @@ -622,7 +624,7 @@ def setup_rundir(self): logging.debug('Linking file {0}'.format(entry)) cmd = 'ln -sf {0} {1}'.format(os.path.join(SCM_ROOT, REFERENCE_PROFILE_DIR, entry), os.path.join(SCM_RUN, entry)) execute(cmd) - + # Parse physics namelist and extract # - oz_phys # - oz_phys_2015 @@ -643,7 +645,7 @@ def setup_rundir(self): message = 'Logic error, both oz_phys and oz_phys_2015 are set to true in the physics namelist' logging.critical(message) raise Exception(message) - + # Link input data for oz_phys or oz_phys_2015 if os.path.exists(os.path.join(SCM_RUN, OZ_PHYS_LINK)): os.remove(os.path.join(SCM_RUN, OZ_PHYS_LINK)) @@ -655,13 +657,13 @@ def setup_rundir(self): logging.debug('Linking input data for oz_phys_2015') cmd = 'ln -sf {0} {1}'.format(os.path.join(SCM_RUN, OZ_PHYS_2015_TARGET), os.path.join(SCM_RUN, OZ_PHYS_LINK)) execute(cmd) - + # Look for do_ugwp_v1 try: do_ugwp_v1 = nml['gfs_physics_nml']['do_ugwp_v1'] except KeyError: do_ugwp_v1 = DEFAULT_DO_UGWP_V1 - + # Link the tau file if do_ugwp_v1 if do_ugwp_v1: if os.path.exists(os.path.join(SCM_RUN, TAU_LINK)): @@ -669,7 +671,7 @@ def setup_rundir(self): logging.debug('Linking input data for UGWP_v1') cmd = 'ln -sf {0} {1}'.format(os.path.join(SCM_RUN, TAU_TARGET), os.path.join(SCM_RUN, TAU_LINK)) execute(cmd) - + # Link scripts needed to run SCM analysis logging.debug('Linking analysis scripts from {0} into run directory'.format(os.path.join(SCM_ROOT, SCM_ANALYSIS_SCRIPT_DIR))) analysis_script_files = ['scm_analysis.py','configspec.ini'] @@ -679,7 +681,7 @@ def setup_rundir(self): logging.debug('Linking file {0}'.format(entry)) cmd = 'ln -sf {0} {1}'.format(os.path.join(SCM_ROOT, SCM_ANALYSIS_SCRIPT_DIR, entry), os.path.join(SCM_RUN, entry)) execute(cmd) - + # Link plot configuration files needed to run SCM analysis logging.debug('Linking plot configuration files from {0} into run directory'.format(os.path.join(SCM_ROOT, SCM_ANALYSIS_CONFIG_DIR))) for entry in os.listdir(os.path.join(SCM_ROOT, SCM_ANALYSIS_CONFIG_DIR)): @@ -688,18 +690,18 @@ def setup_rundir(self): logging.debug('Linking file {0}'.format(entry)) cmd = 'ln -sf {0} {1}'.format(os.path.join(SCM_ROOT, SCM_ANALYSIS_CONFIG_DIR, entry), os.path.join(SCM_RUN, entry)) execute(cmd) - + # Create output directory (delete existing directory) logging.debug('Creating output directory {0} in run directory'.format(output_dir)) if os.path.isdir(os.path.join(SCM_RUN, output_dir)): shutil.rmtree(os.path.join(SCM_RUN, output_dir)) os.makedirs(os.path.join(SCM_RUN, output_dir)) - + # Write experiment configuration file to output directory logging.debug('Writing experiment configuration {0}.nml to output directory'.format(self._name)) cmd = 'cp {0} {1}'.format(os.path.join(SCM_RUN, STANDARD_EXPERIMENT_NAMELIST), os.path.join(SCM_RUN, output_dir,self._name + '.nml')) execute(cmd) - + # Move executable to run dir if COPY_EXECUTABLE: logging.debug('Copying executable to run directory') @@ -709,7 +711,7 @@ def setup_rundir(self): logging.debug('Linking executable to run directory') cmd = 'ln -sf {0} {1}'.format(os.path.join(SCM_ROOT, SCM_BIN, EXECUTABLE_NAME), os.path.join(SCM_RUN, EXECUTABLE_NAME)) execute(cmd) - + #Inform user of timestep and output intervals if self._timestep: logging.info('Using {0}s as the timestep with an instantaneous output period of {1}s and a diagnostic output period of {2}s'.format( @@ -717,7 +719,7 @@ def setup_rundir(self): else: logging.info('Using the default timestep in src/scm_input.F90 with an instantaneous output period of {0}*dt and a diagnostic output period of {1}*dt'.format( case_nml['case_config']['n_itt_out'],case_nml['case_config']['n_itt_diag'])) - + return os.path.join(SCM_RUN, output_dir) def launch_executable(use_gdb, gdb, mpi_command, ignore_error = False): @@ -753,7 +755,7 @@ def launch_executable(use_gdb, gdb, mpi_command, ignore_error = False): else: time_elapsed = int(minutes)*60 + float(seconds) return (status, time_elapsed) - + def copy_outdir(exp_dir): """Copy output directory to /home for this experiment.""" dir_name = os.path.basename(exp_dir) @@ -765,8 +767,8 @@ def copy_outdir(exp_dir): def main(): (file, case, sdf, namelist, tracers, use_gdb, runtime, runtime_mult, docker, \ verbose, levels, npz_type, vert_coord_file, case_data_dir, n_itt_out, \ - n_itt_diag, run_dir, bin_dir, timestep, mpi_command) = parse_arguments() - + n_itt_diag, run_dir, bin_dir, timestep, mpi_command, github_actions) = parse_arguments() + setup_logging(verbose) global SCM_ROOT @@ -782,7 +784,7 @@ def main(): SCM_BIN = bin_dir else: SCM_BIN = os.path.join(SCM_ROOT, DEFAULT_BIN_DIR) - + global SCM_RUN if run_dir: SCM_RUN = run_dir @@ -790,10 +792,10 @@ def main(): SCM_RUN = os.path.join(SCM_ROOT, DEFAULT_RUN_DIR) if not os.path.isdir(SCM_RUN): os.makedirs(SCM_RUN) - + global EXECUTABLE EXECUTABLE = os.path.join(SCM_RUN, EXECUTABLE_NAME) - + # Debugger if use_gdb: gdb = find_gdb() @@ -844,9 +846,9 @@ def main(): logging.info('Using provided namelist for suite={0}'.format(run["suite"])) except: logging.info('Using default namelist for suite={0}'.format(run["suite"])) - + # If tracer file provided, use. Otherwise use default tracer file for this suite - try: + try: active_suite.tracers = run["tracers"] logging.info('Using provided tracer file for suite={0}'.format(run["suite"])) except: @@ -859,7 +861,7 @@ def main(): # If namelist and tracer file provided, use. Otherwise error. if ("namelist" in run) and ("tracers" in run): irun = irun + 1 - if timestep: + if timestep: active_suite = suite(run["suite"], run["tracers"], run["namelist"], timestep, -1, False) else: active_suite = suite(run["suite"], run["tracers"], run["namelist"], -1, -1, False) @@ -882,6 +884,10 @@ def main(): l_ignore_error = MULTIRUN_IGNORE_ERROR else: l_ignore_error = False + # need to correctly fail if running Github Actions + if github_actions: + l_ignore_error = False + (status, time_elapsed) = launch_executable(use_gdb, gdb, mpi_command, ignore_error = l_ignore_error) # if status == 0: diff --git a/scm/src/scm.F90 b/scm/src/scm.F90 index ff28593f0..b6ac80d4a 100644 --- a/scm/src/scm.F90 +++ b/scm/src/scm.F90 @@ -45,12 +45,12 @@ subroutine scm_main_sub() call MPI_INIT(ierr) if (ierr/=0) then write(*,*) 'An error occurred in MPI_INIT: ', ierr - stop 1 + error stop end if - fcst_mpi_comm = MPI_COMM_WORLD + fcst_mpi_comm = MPI_COMM_WORLD call get_config_nml(scm_state) - + select case(scm_state%input_type) case(0) call get_case_init(scm_state, scm_input_instance) @@ -58,9 +58,9 @@ subroutine scm_main_sub() call get_case_init_DEPHY(scm_state, scm_input_instance) case default write(*,*) 'An unrecognized specification of the input_type namelist variable is being used. Exiting...' - stop + error stop end select - + call get_reference_profile(scm_state, scm_reference) call get_FV3_vgrid(scm_input_instance, scm_state) @@ -75,15 +75,15 @@ subroutine scm_main_sub() scm_state%itt = 1 in_spinup = (scm_state%do_spinup .and. scm_state%itt <= scm_state%spinup_timesteps) - + if (in_spinup) then call set_spinup_nudging(scm_state) end if - + call interpolate_forcing(scm_input_instance, scm_state, in_spinup) call physics%create(scm_state%n_cols) - + !physics initialization section !set the array index of the time level of the state variables that the cdata @@ -97,13 +97,13 @@ subroutine scm_main_sub() case default cdata_time_index = 2 end select - + !open a logfile if (physics%Init_parm%me == physics%Init_parm%master .and. physics%Init_parm%logunit>=0) then write (logfile_name, '(A7,I0.5,A4)') 'logfile.out' open(unit=physics%Init_parm%logunit, file=trim(scm_state%output_dir)//'/'//logfile_name, action='write', status='replace') end if - + physics%Init_parm%fcst_mpi_comm = fcst_mpi_comm physics%Init_parm%levs = scm_state%n_levels physics%Init_parm%bdat(1) = scm_state%init_year @@ -126,7 +126,7 @@ subroutine scm_main_sub() physics%Init_parm%hydrostatic = .true. physics%Init_parm%restart = .false. physics%Init_parm%nwat = scm_state%nwat - + ! Allocate and initialize DDTs call GFS_suite_setup(physics%Model, physics%Statein, physics%Stateout, & physics%Sfcprop, physics%Coupling, physics%Grid, & @@ -134,7 +134,7 @@ subroutine scm_main_sub() physics%Diag, physics%Interstitial, 1, 1, & physics%Init_parm, scm_state%n_cols, scm_state%lon, & scm_state%lat, scm_state%area) - + !override radiation frequency if (scm_state%force_rad_T > 0) then !turn off radiation since it is already accounted for in the forcing @@ -142,22 +142,22 @@ subroutine scm_main_sub() physics%Model%nsswr = -1 physics%Model%nslwr = -1 end if - + !override fhzero in physics namelist if n_itt_diag is set in the case namelist if (scm_state%n_itt_diag >= 1) then physics%Model%nszero = scm_state%n_itt_diag physics%Model%fhzero = scm_state%n_itt_diag*scm_state%dt/3600.0 end if - + !check for problematic diagnostic and radiation periods if (mod(physics%Model%nszero,scm_state%n_itt_out) /= 0) then write(*,*) "***ERROR***: The diagnostic output period must be a multiple of the output period." write(*,*) "From ", adjustl(trim(scm_state%physics_nml)), ", fhzero = ",physics%Model%fhzero write(*,*) "implying a diagnostic output period of ", physics%Model%nszero*scm_state%dt, "seconds." write(*,*) "The given output period in the case configuration namelist is ", scm_state%output_period,"seconds." - STOP + error stop end if - + if (mod(physics%Model%nsswr,scm_state%n_itt_out) /= 0) then write(*,*) "***WARNING***: The shortwave radiation calling period is different than the output period." write(*,*) "From ", adjustl(trim(scm_state%physics_nml)), ", fhswr = ",physics%Model%fhswr @@ -165,7 +165,7 @@ subroutine scm_main_sub() write(*,*) "This will cause the effective output period of variables that are only given values during shortwave calls to be ",& lcm(scm_state%n_itt_out,physics%Model%nsswr)*scm_state%dt," seconds." end if - + if (mod(physics%Model%nslwr,scm_state%n_itt_out) /= 0) then write(*,*) "***WARNING***: The longwave radiation calling period is different than the output period." write(*,*) "From ", adjustl(trim(scm_state%physics_nml)), ", fhlwr = ",physics%Model%fhlwr @@ -173,14 +173,14 @@ subroutine scm_main_sub() write(*,*) "This will cause the effective output period of variables that are only given values during longwave calls to be ",& lcm(scm_state%n_itt_out,physics%Model%nslwr)*scm_state%dt," seconds." end if - + cdata%blk_no = 1 cdata%thrd_no = 1 cdata%thrd_cnt = 1 call physics%associate(scm_state) call physics%set(scm_input_instance, scm_state) - + ! When asked to calculate 3-dim. tendencies, set Stateout variables to ! Statein variables here in order to capture the first call to dycore if (physics%Model%ldiag3d) then @@ -189,7 +189,7 @@ subroutine scm_main_sub() physics%Stateout%gt0 = physics%Statein%tgrs physics%Stateout%gq0 = physics%Statein%qgrs endif - + !initialize the column's physics write(0,'(a,i0,a)') "Calling ccpp_physics_init with suite '" // trim(trim(adjustl(scm_state%physics_suite_name))) // "'" @@ -197,9 +197,9 @@ subroutine scm_main_sub() write(0,'(a,i0,a,i0)') "Called ccpp_physics_init with suite '" // trim(trim(adjustl(scm_state%physics_suite_name))) // "', ierr=", ierr if (ierr/=0) then write(*,'(a,i0,a)') 'An error occurred in ccpp_physics_init: ' // trim(cdata%errmsg) // '. Exiting...' - stop 1 + error stop end if - + physics%Model%first_time_step = .true. call output_init(scm_state, physics) @@ -212,7 +212,7 @@ subroutine scm_main_sub() scm_state%dt_now = scm_state%dt scm_state%model_time = scm_state%dt_now end if - + call interpolate_forcing(scm_input_instance, scm_state, in_spinup) if (.not. scm_state%model_ics) call calc_pres_exner_geopotential(1, scm_state) @@ -259,19 +259,19 @@ subroutine scm_main_sub() physics%Diag%dtend(i,:,idtend) = physics%Diag%dtend(i,:,idtend) & + (physics%Statein%ugrs(i,:) - physics%Stateout%gu0(i,:)) endif - + idtend = physics%Model%dtidx(physics%Model%index_of_y_wind,physics%Model%index_of_process_non_physics) if(idtend>=1) then physics%Diag%dtend(i,:,idtend) = physics%Diag%dtend(i,:,idtend) & + (physics%Statein%vgrs(i,:) - physics%Stateout%gv0(i,:)) endif - + idtend = physics%Model%dtidx(physics%Model%index_of_temperature,physics%Model%index_of_process_non_physics) if(idtend>=1) then physics%Diag%dtend(i,:,idtend) = physics%Diag%dtend(i,:,idtend) & + (physics%Statein%tgrs(i,:) - physics%Stateout%gt0(i,:)) endif - + if (physics%Model%qdiag3d) then do itrac=1,physics%Model%ntrac idtend = physics%Model%dtidx(itrac+100,physics%Model%index_of_process_non_physics) @@ -283,13 +283,13 @@ subroutine scm_main_sub() endif endif end do - + call ccpp_physics_timestep_init(cdata, suite_name=trim(adjustl(scm_state%physics_suite_name)), ierr=ierr) if (ierr/=0) then write(*,'(a,i0,a)') 'An error occurred in ccpp_physics_timestep_init: ' // trim(cdata%errmsg) // '. Exiting...' - stop 1 + error stop end if - + !--- determine if radiation diagnostics buckets need to be cleared if (nint(physics%Model%fhzero*3600) >= nint(max(physics%Model%fhswr,physics%Model%fhlwr))) then if (mod(physics%Model%kdt,physics%Model%nszero) == 1 .or. physics%Model%nszero == 1) then @@ -301,22 +301,22 @@ subroutine scm_main_sub() call physics%Diag%rad_zero (physics%Model) endif endif - + !--- determine if physics diagnostics buckets need to be cleared if (mod(physics%Model%kdt,physics%Model%nszero) == 1 .or. physics%Model%nszero == 1) then call physics%Diag%phys_zero (physics%Model) endif - + call ccpp_physics_run(cdata, suite_name=trim(adjustl(scm_state%physics_suite_name)), ierr=ierr) if (ierr/=0) then write(*,'(a,i0,a)') 'An error occurred in ccpp_physics_run: ' // trim(cdata%errmsg) // '. Exiting...' - stop 1 + error stop end if - + call ccpp_physics_timestep_finalize(cdata, suite_name=trim(adjustl(scm_state%physics_suite_name)), ierr=ierr) if (ierr/=0) then write(*,'(a,i0,a)') 'An error occurred in ccpp_physics_timestep_finalize: ' // trim(cdata%errmsg) // '. Exiting...' - stop 1 + error stop end if !the filter routine (called after the following leapfrog time step) expects time level 2 in temp_tracer to be the updated, unfiltered state after the previous time step @@ -356,9 +356,9 @@ subroutine scm_main_sub() !prepare for time loop scm_state%n_timesteps = ceiling(scm_state%runtime/scm_state%dt) + scm_state%spinup_timesteps - + scm_state%dt_now = scm_state%dt - + !if (.not. in_spinup) then physics%Model%first_time_step = .false. !end if @@ -371,7 +371,7 @@ subroutine scm_main_sub() in_spinup = .false. scm_state%itt = i - scm_state%spinup_timesteps end if - + !> - Calculate the elapsed model time. if (.not. in_spinup) then scm_state%model_time = scm_state%itt*scm_state%dt @@ -392,7 +392,7 @@ subroutine scm_main_sub() end if call interpolate_forcing(scm_input_instance, scm_state, in_spinup) - + call calc_pres_exner_geopotential(1, scm_state) !zero out diagnostics output on EVERY time step - breaks diagnostics averaged over many timesteps @@ -410,7 +410,7 @@ subroutine scm_main_sub() scm_state%state_tracer(:,:,scm_state%cloud_water_index,1) = scm_state%state_tracer(:,:,scm_state%cloud_water_index,2) scm_state%state_tracer(:,:,scm_state%ozone_index,1) = scm_state%state_tracer(:,:,scm_state%ozone_index,2) end if - + write(*,*) "itt = ",scm_state%itt write(*,*) "model time (s) = ",scm_state%model_time if (scm_state%lsm_ics .or. scm_state%model_ics) then @@ -418,7 +418,7 @@ subroutine scm_main_sub() write(*,*) "sensible heat flux (W m-2): ",physics%Interstitial%dtsfc1(1) write(*,*) "latent heat flux (W m-2): ",physics%Interstitial%dqsfc1(1) end if - + if (.not. in_spinup) then call output_append(scm_state, physics) end if @@ -428,13 +428,13 @@ subroutine scm_main_sub() if (ierr/=0) then write(*,'(a,i0,a)') 'An error occurred in ccpp_physics_finalize: ' // trim(cdata%errmsg) // '. Exiting...' - stop 1 + error stop end if - + call MPI_FINALIZE(ierr) if (ierr/=0) then write(*,*) 'An error occurred in MPI_FINALIZE: ', ierr - stop 1 + error stop end if end subroutine scm_main_sub diff --git a/scm/src/scm_forcing.F90 b/scm/src/scm_forcing.F90 index ad7a47b4f..db239aa8b 100644 --- a/scm/src/scm_forcing.F90 +++ b/scm/src/scm_forcing.F90 @@ -39,10 +39,10 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) tot_advec_theta_bracket(2,scm_state%n_levels), tot_advec_thetal_bracket(2,scm_state%n_levels), tot_advec_qv_bracket(2,scm_state%n_levels), & tot_advec_u_bracket(2,scm_state%n_levels), tot_advec_v_bracket(2,scm_state%n_levels) !< forcing terms that "bracket" around the model time real(kind=dp) :: rho - + !> \section interpolate_forcing_alg Algorithm !! @{ - + if (in_spinup) then do i=1, scm_state%n_cols scm_state%pres_surf(i) = scm_input%input_pres_surf(1) @@ -56,15 +56,15 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) end do return end if - + !> - Check for the case where the elapsed model time extends beyond the supplied forcing. if(scm_state%model_time >= scm_input%input_time(scm_input%input_ntimes)) then !> - If so, hold the forcing terms constant at the last supplied values. The forcing still needs to be interpolated to the grid. write(*,*) "The model_time has exceeded the specifed period of forcing. Forcing will now be held constant at the last & specified values." - + if(scm_state%input_type == 0) then - + !> - For all forcing terms, call interpolate_to_grid_centers from \ref utils for each variable. This subroutine returns the last vertical index calculated in case forcing terms above the case input needs to be specified. do i=1, scm_state%n_cols call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres, & @@ -107,7 +107,7 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres, & scm_input%input_v_advec_qt(scm_input%input_ntimes,:), scm_state%pres_l(i,:), scm_state%n_levels, & v_advec_qt_bracket(1,:), top_index, 3) - + !> - If the input forcing file does not reach to the model domain top, fill in values above the input forcing file domain with those from the top level. if (top_index < scm_state%n_levels .AND. top_index.GT.0) then w_ls_bracket(1,top_index+1:scm_state%n_levels) = 0.0!w_ls_bracket(1,top_index) @@ -125,7 +125,7 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) v_advec_thil_bracket(1,top_index+1:scm_state%n_levels) = v_advec_thil_bracket(1,top_index) v_advec_qt_bracket(1,top_index+1:scm_state%n_levels) = v_advec_qt_bracket(1,top_index) end if - + !> - For this case, no time interpolation is necessary; just set the forcing terms to the vertically-interpolated values. scm_state%w_ls(i,:) = w_ls_bracket(1,:) scm_state%omega(i,:) = omega_bracket(1,:) @@ -141,7 +141,7 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) scm_state%h_advec_qt(i,:) = h_advec_qt_bracket(1,:) scm_state%v_advec_thil(i,:) = v_advec_thil_bracket(1,:) scm_state%v_advec_qt(i,:) = v_advec_qt_bracket(1,:) - + !> - Set the surface parameters to the last available data. scm_state%pres_surf(i) = scm_input%input_pres_surf(scm_input%input_ntimes) scm_state%T_surf(i) = scm_input%input_T_surf(scm_input%input_ntimes) @@ -172,7 +172,7 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) scm_state%w_ls(i,:) = w_ls_bracket(1,:) end do end if - + if (scm_state%force_geo) then do i=1, scm_state%n_cols call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres_forcing(scm_input%input_ntimes,:), & @@ -187,7 +187,7 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) scm_state%v_g(i,:) = v_g_bracket(1,:) end do end if - + if (scm_state%force_adv_T == 1) then do i=1, scm_state%n_cols call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres_forcing(scm_input%input_ntimes,:), & @@ -219,7 +219,7 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) scm_state%tot_advec_thetal(i,:) = tot_advec_thetal_bracket(1,:) end do end if - + if (scm_state%force_adv_qv) then do i=1, scm_state%n_cols call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres_forcing(scm_input%input_ntimes,:), & @@ -231,7 +231,7 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) scm_state%tot_advec_qv(i,:) = tot_advec_qv_bracket(1,:) end do end if - + if (scm_state%force_adv_u) then do i=1, scm_state%n_cols call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres_forcing(scm_input%input_ntimes,:), scm_input%input_tot_advec_u(scm_input%input_ntimes,:), & @@ -242,7 +242,7 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) scm_state%tot_advec_u(i,:) = tot_advec_u_bracket(1,:) end do end if - + if (scm_state%force_adv_v) then do i=1, scm_state%n_cols call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres_forcing(scm_input%input_ntimes,:), scm_input%input_tot_advec_v(scm_input%input_ntimes,:), & @@ -253,7 +253,7 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) scm_state%tot_advec_v(i,:) = tot_advec_v_bracket(1,:) end do end if - + if (scm_state%force_nudging_t == 1) then do i=1, scm_state%n_cols call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres_forcing(scm_input%input_ntimes,:), scm_input%input_T_nudge(scm_input%input_ntimes,:), & @@ -264,7 +264,7 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) scm_state%T_nudge(i,:) = T_nudge_bracket(1,:) call find_vertical_index_pressure(scm_input%input_pres_forcing(scm_input%input_ntimes,scm_input%input_k_T_nudge(scm_input%input_ntimes)), scm_state%pres_l(i,:), scm_state%force_nudging_T_k(i)) end do - + else if (scm_state%force_nudging_T == 2 .or. scm_state%force_nudging_T == 3) then do i=1, scm_state%n_cols call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres_forcing(scm_input%input_ntimes,:), scm_input%input_thil_nudge(scm_input%input_ntimes,:), & @@ -276,7 +276,7 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) call find_vertical_index_pressure(scm_input%input_pres_forcing(scm_input%input_ntimes,scm_input%input_k_thil_nudge(scm_input%input_ntimes)), scm_state%pres_l(i,:), scm_state%force_nudging_T_k(i)) end do end if - + if (scm_state%force_nudging_qv) then do i=1, scm_state%n_cols call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres_forcing(scm_input%input_ntimes,:), scm_input%input_qt_nudge(scm_input%input_ntimes,:), & @@ -288,7 +288,7 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) call find_vertical_index_pressure(scm_input%input_pres_forcing(scm_input%input_ntimes,scm_input%input_k_qt_nudge(scm_input%input_ntimes)), scm_state%pres_l(i,:), scm_state%force_nudging_qv_k(i)) end do end if - + if (scm_state%force_nudging_u) then do i=1, scm_state%n_cols call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres_forcing(scm_input%input_ntimes,:), scm_input%input_u_nudge(scm_input%input_ntimes,:), & @@ -300,7 +300,7 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) call find_vertical_index_pressure(scm_input%input_pres_forcing(scm_input%input_ntimes,scm_input%input_k_u_nudge(scm_input%input_ntimes)), scm_state%pres_l(i,:), scm_state%force_nudging_u_k(i)) end do end if - + if (scm_state%force_nudging_v) then do i=1, scm_state%n_cols call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres_forcing(scm_input%input_ntimes,:), scm_input%input_v_nudge(scm_input%input_ntimes,:), & @@ -312,7 +312,7 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) call find_vertical_index_pressure(scm_input%input_pres_forcing(scm_input%input_ntimes,scm_input%input_k_v_nudge(scm_input%input_ntimes)), scm_state%pres_l(i,:), scm_state%force_nudging_v_k(i)) end do end if - + if (scm_state%force_rad_T == 1 .or. scm_state%force_rad_T == 2 .or. scm_state%force_rad_T == 3) then do i=1, scm_state%n_cols call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres_forcing(scm_input%input_ntimes,:), scm_input%input_dT_dt_rad(scm_input%input_ntimes,:), & @@ -323,14 +323,14 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) scm_state%dT_dt_rad(i,:) = dT_dt_rad_bracket(1,:) end do end if - + if (scm_state%surface_thermo_control == 0 .or. scm_state%surface_thermo_control == 1 .or. scm_state%surface_thermo_control == 2) then !skin temperature is needed if surface fluxes are specified (for calculating bulk Richardson number in the specified surface flux scheme) and for simple ocean scheme do i=1, scm_state%n_cols scm_state%T_surf(i) = scm_input%input_T_surf(scm_input%input_ntimes) end do end if - + if (scm_state%surface_thermo_control == 0) then do i=1, scm_state%n_cols scm_state%sh_flux(i) = scm_input%input_sh_flux_sfc_kin(scm_input%input_ntimes) @@ -344,11 +344,11 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) scm_state%lh_flux(i) = (1.0/(con_hvap*rho))*scm_input%input_lh_flux_sfc(scm_input%input_ntimes) end do end if - + do i=1, scm_state%n_cols scm_state%pres_surf(i) = scm_input%input_pres_surf(scm_input%input_ntimes) end do - + end if else !> - When the model elapsed time is within the time-frame specified by the input forcing, the forcing must be interpolated in time and space. @@ -362,9 +362,9 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) exit end if end do - + if(scm_state%input_type == 0) then - + do i=1, scm_state%n_cols !> - For all forcing terms, call interpolate_to_grid_centers from \ref utils for each variable for each time level that "bracket" around !> the current model time. This subroutine returns the last vertical index calculated in case forcing terms above the case input needs @@ -499,7 +499,7 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) scm_state%omega(i,:) = (1.0 - lifrac)*omega_bracket(1,:) + lifrac*omega_bracket(2,:) end do end if - + if (scm_state%force_w) then do i=1, scm_state%n_cols call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres_forcing(low_t_index,:), scm_input%input_w_ls(low_t_index,:), & @@ -513,7 +513,7 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) scm_state%w_ls(i,:) = (1.0 - lifrac)*w_ls_bracket(1,:) + lifrac*w_ls_bracket(2,:) end do end if - + if (scm_state%force_geo) then do i=1, scm_state%n_cols call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres_forcing(low_t_index,:), scm_input%input_u_g(low_t_index,:), & @@ -534,7 +534,7 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) scm_state%v_g(i,:) = (1.0 - lifrac)*v_g_bracket(1,:) + lifrac*v_g_bracket(2,:) end do end if - + if (scm_state%force_adv_T == 1) then do i=1, scm_state%n_cols call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres_forcing(low_t_index,:), scm_input%input_tot_advec_t(low_t_index,:), & @@ -572,7 +572,7 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) scm_state%tot_advec_thetal(i,:) = (1.0 - lifrac)*tot_advec_thetal_bracket(1,:) + lifrac*tot_advec_thetal_bracket(2,:) end do end if - + if (scm_state%force_adv_qv) then do i=1, scm_state%n_cols call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres_forcing(low_t_index,:), scm_input%input_tot_advec_qv(low_t_index,:), & @@ -586,7 +586,7 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) scm_state%tot_advec_qv(i,:) = (1.0 - lifrac)*tot_advec_qv_bracket(1,:) + lifrac*tot_advec_qv_bracket(2,:) end do end if - + if (scm_state%force_adv_u) then do i=1, scm_state%n_cols call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres_forcing(low_t_index,:), scm_input%input_tot_advec_u(low_t_index,:), & @@ -600,7 +600,7 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) scm_state%tot_advec_u(i,:) = (1.0 - lifrac)*tot_advec_u_bracket(1,:) + lifrac*tot_advec_u_bracket(2,:) end do end if - + if (scm_state%force_adv_v) then do i=1, scm_state%n_cols call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres_forcing(low_t_index,:), scm_input%input_tot_advec_v(low_t_index,:), & @@ -614,7 +614,7 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) scm_state%tot_advec_v(i,:) = (1.0 - lifrac)*tot_advec_v_bracket(1,:) + lifrac*tot_advec_v_bracket(2,:) end do end if - + if (scm_state%force_nudging_t == 1) then do i=1, scm_state%n_cols call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres_forcing(low_t_index,:), scm_input%input_T_nudge(low_t_index,:), & @@ -642,7 +642,7 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) call find_vertical_index_pressure(scm_input%input_pres_forcing(low_t_index,scm_input%input_k_thil_nudge(low_t_index)), scm_state%pres_l(i,:), scm_state%force_nudging_T_k(i)) end do end if - + if (scm_state%force_nudging_qv) then do i=1, scm_state%n_cols call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres_forcing(low_t_index,:), scm_input%input_qt_nudge(low_t_index,:), & @@ -657,7 +657,7 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) call find_vertical_index_pressure(scm_input%input_pres_forcing(low_t_index,scm_input%input_k_qt_nudge(low_t_index)), scm_state%pres_l(i,:), scm_state%force_nudging_qv_k(i)) end do end if - + if (scm_state%force_nudging_u) then do i=1, scm_state%n_cols call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres_forcing(low_t_index,:), scm_input%input_u_nudge(low_t_index,:), & @@ -672,7 +672,7 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) call find_vertical_index_pressure(scm_input%input_pres_forcing(low_t_index,scm_input%input_k_u_nudge(low_t_index)), scm_state%pres_l(i,:), scm_state%force_nudging_u_k(i)) end do end if - + if (scm_state%force_nudging_v) then do i=1, scm_state%n_cols call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres_forcing(low_t_index,:), scm_input%input_v_nudge(low_t_index,:), & @@ -687,7 +687,7 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) call find_vertical_index_pressure(scm_input%input_pres_forcing(low_t_index,scm_input%input_k_v_nudge(low_t_index)), scm_state%pres_l(i,:), scm_state%force_nudging_v_k(i)) end do end if - + if (scm_state%force_rad_T == 1 .or. scm_state%force_rad_T == 2 .or. scm_state%force_rad_T == 3) then do i=1, scm_state%n_cols call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres_forcing(low_t_index,:), scm_input%input_dT_dt_rad(low_t_index,:), & @@ -701,14 +701,14 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) scm_state%dT_dt_rad(i,:) = (1.0 - lifrac)*dT_dt_rad_bracket(1,:) + lifrac*dT_dt_rad_bracket(2,:) end do end if - + if (scm_state%surface_thermo_control == 0 .or. scm_state%surface_thermo_control == 1 .or. scm_state%surface_thermo_control == 2) then !skin temperature is needed if surface fluxes are specified (for calculating bulk Richardson number in the specified surface flux scheme) and for simple ocean scheme do i=1, scm_state%n_cols scm_state%T_surf(i) = (1.0 - lifrac)*scm_input%input_T_surf(low_t_index) + lifrac*scm_input%input_T_surf(low_t_index+1) end do end if - + if (scm_state%surface_thermo_control == 0) then do i=1, scm_state%n_cols scm_state%sh_flux(i) = (1.0 - lifrac)*scm_input%input_sh_flux_sfc_kin(low_t_index) + & @@ -726,7 +726,7 @@ subroutine interpolate_forcing(scm_input, scm_state, in_spinup) lifrac*scm_input%input_lh_flux_sfc(low_t_index+1)) end do end if - + do i=1, scm_state%n_cols !Interpolate the surface parameters in time. scm_state%pres_surf(i) = (1.0 - lifrac)*scm_input%input_pres_surf(low_t_index) + & @@ -792,7 +792,7 @@ subroutine apply_forcing_leapfrog(scm_state) select case(scm_state%mom_forcing_type) case (1) write(*,*) 'momentum forcing type = 1 is not implemented. Pick 2 or 3. Stopping...' - stop + error stop case (2) !> - Calculate change in state momentum variables due to vertical advection (subsidence). @@ -935,12 +935,12 @@ subroutine apply_forcing_forward_Euler(scm_state, in_spinup) integer :: i,k real(kind=dp) :: f_coriolis, grav_inv, g_over_cp, omega_plus, omega_minus, dth_dp_plus, dth_dp_minus, & dqv_dp_plus, dqv_dp_minus, spinup_relax_time - + !> \section apply_leapfrog_forcing_alg Algorithm !! @{ - + spinup_relax_time = scm_state%dt - + grav_inv = 1.0/con_g g_over_cp = con_g/con_cp @@ -971,7 +971,7 @@ subroutine apply_forcing_forward_Euler(scm_state, in_spinup) zi(i,scm_state%n_levels+1) = scm_state%geopotential_i(i,scm_state%n_levels+1)*grav_inv end do !end if - + if (in_spinup) then do i=1, scm_state%n_cols do k=1, scm_state%n_levels @@ -991,10 +991,10 @@ subroutine apply_forcing_forward_Euler(scm_state, in_spinup) select case(scm_state%mom_forcing_type) case (1) write(*,*) 'momentum forcing type = 1 is not implemented. Pick 2 or 3. Stopping...' - stop + error stop case (2) !> - Calculate change in state momentum variables due to vertical advection (subsidence). - + !> - Calculate tendencies due to vertical advection using same discretization as in previous GFS SCM implmentation (staggered central difference) !! \f[ !! \frac{\partial x}{\partial t}|_{vert. advection} = \frac{w_{k+1}\left(x_{k+1} - x_{k}\right) + w_k\left(x_k - x_{k-1}\right)}{-2\left(z_{k+1}-z_{k}\right)} @@ -1014,7 +1014,7 @@ subroutine apply_forcing_forward_Euler(scm_state, in_spinup) scm_state%v_force_tend(i,1) = -w_ls_i(i,2)*(old_v(i,2) - old_v(i,1))/(zi(i,2)-zi(i,1)) scm_state%v_force_tend(i,scm_state%n_levels) = -w_ls_i(i,scm_state%n_levels)*& (old_v(i,scm_state%n_levels) - old_v(i,scm_state%n_levels-1))/(zi(i,scm_state%n_levels+1)-zi(i,scm_state%n_levels)) - + !> - Add forcing due to geostrophic wind !> - Calculate Coriolis parameter. f_coriolis = 2.0*con_omega*sin(scm_state%lat(i)) @@ -1037,7 +1037,7 @@ subroutine apply_forcing_forward_Euler(scm_state, in_spinup) scm_state%u_force_tend = 0.0 scm_state%v_force_tend = 0.0 end select - + select case (scm_state%thermo_forcing_type) case (1) do i=1, scm_state%n_cols @@ -1061,7 +1061,7 @@ subroutine apply_forcing_forward_Euler(scm_state, in_spinup) scm_state%qv_force_tend(i,k) = -omega_plus*dqv_dp_minus - omega_minus*dqv_dp_plus scm_state%T_force_tend(i,k) = scm_state%exner_l(i,k)*(-omega_plus*dth_dp_minus - omega_minus*dth_dp_plus) end do - + !> - Add forcing due to prescribed radiation and horizontal advection do k=1, scm_state%n_levels scm_state%T_force_tend(i,k) = scm_state%T_force_tend(i,k) + scm_state%dT_dt_rad(i,k) + & @@ -1077,7 +1077,7 @@ subroutine apply_forcing_forward_Euler(scm_state, in_spinup) scm_state%T_force_tend(i,k) = (scm_state%T_nudge(i,k) - old_T(i,k))/scm_state%relax_time scm_state%qv_force_tend(i,k) = (scm_state%qt_nudge(i,k) - old_qv(i,k))/scm_state%relax_time end do - + do k=2, scm_state%n_levels-1 !upstream scheme (for boundaries, assume vertical derivatives are 0 => no vertical advection) omega_plus = MAX(scm_state%omega(i,k), 0.0) @@ -1120,28 +1120,28 @@ subroutine apply_forcing_DEPHY(scm_state, in_spinup) type(scm_state_type), intent(inout) :: scm_state logical, intent(in) :: in_spinup - + real(kind=dp) :: old_u(scm_state%n_cols, scm_state%n_levels), old_v(scm_state%n_cols, scm_state%n_levels), & old_T(scm_state%n_cols, scm_state%n_levels), old_qv(scm_state%n_cols, scm_state%n_levels) real(kind=dp) :: theta(scm_state%n_cols, scm_state%n_levels) - + real(kind=dp) :: spinup_relax_time, omega_asc, omega_des, w_asc, w_des, gradient_asc, gradient_des, rho, adiabatic_exp_comp_term, & f_coriolis - + integer :: i,k - - logical :: use_theta !formulations using potential temperature don't need adiabatic expansion/compression term (simpler), + + logical :: use_theta !formulations using potential temperature don't need adiabatic expansion/compression term (simpler), !but reqires conversion to/from since absolute temperature is state variable - + use_theta = .false. spinup_relax_time = scm_state%dt - + !Save old state variables old_u = scm_state%state_u(:,:,1) old_v = scm_state%state_v(:,:,1) old_T = scm_state%state_T(:,:,1) old_qv = scm_state%state_tracer(:,:,scm_state%water_vapor_index,1) - + if (use_theta) then theta = old_T/scm_state%exner_l(:,:) end if @@ -1151,7 +1151,7 @@ subroutine apply_forcing_DEPHY(scm_state, in_spinup) scm_state%v_force_tend = 0.0 scm_state%T_force_tend = 0.0 scm_state%qv_force_tend = 0.0 - + if (in_spinup) then do i=1, scm_state%n_cols do k=1, scm_state%n_levels @@ -1194,7 +1194,7 @@ subroutine apply_forcing_DEPHY(scm_state, in_spinup) end do end if !use_theta end if !force_sub_for_T - + if (scm_state%force_sub_for_qv) then do i=1, scm_state%n_cols do k=2, scm_state%n_levels-1 @@ -1206,7 +1206,7 @@ subroutine apply_forcing_DEPHY(scm_state, in_spinup) end do end do end if - + if (scm_state%force_sub_for_u) then do i=1, scm_state%n_cols do k=2, scm_state%n_levels-1 @@ -1218,7 +1218,7 @@ subroutine apply_forcing_DEPHY(scm_state, in_spinup) end do end do end if - + if (scm_state%force_sub_for_v) then do i=1, scm_state%n_cols do k=2, scm_state%n_levels-1 @@ -1230,7 +1230,7 @@ subroutine apply_forcing_DEPHY(scm_state, in_spinup) end do end do end if - + else if (scm_state%force_w) then if (scm_state%force_sub_for_T) then if (use_theta) then @@ -1258,7 +1258,7 @@ subroutine apply_forcing_DEPHY(scm_state, in_spinup) end do end if !use_theta end if !force_sub_for_T - + if (scm_state%force_sub_for_qv) then do i=1, scm_state%n_cols do k=2, scm_state%n_levels-1 @@ -1271,7 +1271,7 @@ subroutine apply_forcing_DEPHY(scm_state, in_spinup) end do end do end if - + if (scm_state%force_sub_for_u) then do i=1, scm_state%n_cols do k=2, scm_state%n_levels-1 @@ -1284,7 +1284,7 @@ subroutine apply_forcing_DEPHY(scm_state, in_spinup) end do end do end if - + if (scm_state%force_sub_for_v) then do i=1, scm_state%n_cols do k=2, scm_state%n_levels-1 @@ -1297,12 +1297,12 @@ subroutine apply_forcing_DEPHY(scm_state, in_spinup) end do end do end if - + end if !force_omega or force_w - + if (scm_state%force_geo) then !Add forcing due to geostrophic wind - + !Calculate Coriolis parameter. do i=1, scm_state%n_cols f_coriolis = 2.0*con_omega*sin(scm_state%lat(i)) @@ -1313,7 +1313,7 @@ subroutine apply_forcing_DEPHY(scm_state, in_spinup) end do end do end if !force_geo - + if (scm_state%force_adv_T == 1) then !advection term is in terms of absolute temperature do i=1, scm_state%n_cols @@ -1336,7 +1336,7 @@ subroutine apply_forcing_DEPHY(scm_state, in_spinup) end do end do end if - + if (scm_state%force_adv_qv) then do i=1, scm_state%n_cols do k=1, scm_state%n_levels @@ -1344,7 +1344,7 @@ subroutine apply_forcing_DEPHY(scm_state, in_spinup) end do end do end if - + if (scm_state%force_adv_u) then do i=1, scm_state%n_cols do k=1, scm_state%n_levels @@ -1352,7 +1352,7 @@ subroutine apply_forcing_DEPHY(scm_state, in_spinup) end do end do end if - + if (scm_state%force_adv_v) then do i=1, scm_state%n_cols do k=1, scm_state%n_levels @@ -1360,7 +1360,7 @@ subroutine apply_forcing_DEPHY(scm_state, in_spinup) end do end do end if - + if (scm_state%force_nudging_t == 1) then do i=1, scm_state%n_cols do k=scm_state%force_nudging_T_k(i), scm_state%n_levels @@ -1375,7 +1375,7 @@ subroutine apply_forcing_DEPHY(scm_state, in_spinup) end do end do end if - + if (scm_state%force_nudging_qv) then do i=1, scm_state%n_cols do k=scm_state%force_nudging_qv_k(i), scm_state%n_levels @@ -1383,7 +1383,7 @@ subroutine apply_forcing_DEPHY(scm_state, in_spinup) end do end do end if - + if (scm_state%force_nudging_u) then do i=1, scm_state%n_cols do k=scm_state%force_nudging_u_k(i), scm_state%n_levels @@ -1391,7 +1391,7 @@ subroutine apply_forcing_DEPHY(scm_state, in_spinup) end do end do end if - + if (scm_state%force_nudging_v) then do i=1, scm_state%n_cols do k=scm_state%force_nudging_v_k(i), scm_state%n_levels @@ -1399,7 +1399,7 @@ subroutine apply_forcing_DEPHY(scm_state, in_spinup) end do end do end if - + if (scm_state%force_rad_T == 1 .or. scm_state%force_rad_T == 2 .or. scm_state%force_rad_T == 3) then do i=1, scm_state%n_cols do k=1, scm_state%n_levels @@ -1407,9 +1407,9 @@ subroutine apply_forcing_DEPHY(scm_state, in_spinup) end do end do end if - + end if !in_spinup - + do i=1, scm_state%n_cols do k=1, scm_state%n_levels !> - Update the state variables using the forward Euler scheme: @@ -1424,23 +1424,23 @@ subroutine apply_forcing_DEPHY(scm_state, in_spinup) scm_state%dt*(scm_state%qv_force_tend(i,k)) end do end do - + end subroutine apply_forcing_DEPHY subroutine set_spinup_nudging(scm_state) use scm_type_defs, only: scm_state_type type(scm_state_type), intent(inout) :: scm_state - + integer :: i - + do i=1, scm_state%n_cols scm_state%u_nudge(i,:) = scm_state%state_u(i,:,1) scm_state%v_nudge(i,:) = scm_state%state_v(i,:,1) scm_state%T_nudge(i,:) = scm_state%state_T(i,:,1) scm_state%qt_nudge(i,:) = scm_state%state_tracer(i,:,scm_state%water_vapor_index,1) end do - + end subroutine set_spinup_nudging !> @} diff --git a/scm/src/scm_input.F90 b/scm/src/scm_input.F90 index cc3effcd5..abaeedefc 100644 --- a/scm/src/scm_input.F90 +++ b/scm/src/scm_input.F90 @@ -67,7 +67,7 @@ subroutine get_config_nml(scm_state) character(len=character_length) :: physics_suite !< name of the physics suite name (currently only GFS_operational supported) character(len=character_length) :: physics_nml - + character(len=character_length), allocatable, dimension(:) :: tracer_names integer, allocatable, dimension(:) :: tracer_types @@ -80,7 +80,7 @@ subroutine get_config_nml(scm_state) lsm_ics, do_spinup, C_RES, spinup_timesteps, mom_forcing_type, relax_time, sfc_type, sfc_flux_spec, & sfc_roughness_length_cm, reference_profile_choice, year, month, day, hour, min, & column_area, input_type - + NAMELIST /physics_config/ physics_suite, physics_nml !> \section get_config_alg Algorithm @@ -119,12 +119,12 @@ subroutine get_config_nml(scm_state) hour = 3 min = 0 input_type = 0 - + open(unit=10, file=experiment_namelist, status='old', action='read', iostat=ioerror) if(ioerror /= 0) then write(*,'(a,i0)') 'There was an error opening the file ' // experiment_namelist // & '; error code = ', ioerror - STOP + error stop "error opening namelist" else read(10, NML=case_config, iostat=ioerror) end if @@ -132,7 +132,7 @@ subroutine get_config_nml(scm_state) if(ioerror /= 0) then write(*,'(a,i0)') 'There was an error reading the namelist case_config in the file '& // experiment_namelist // '; error code = ',ioerror - STOP + error stop "error opening namelist" end if !The current implementation of GFS physics does not support more than one column, since radiation sub schemes use @@ -140,10 +140,9 @@ subroutine get_config_nml(scm_state) !the code crashes in GFS_initialize_scm_run and later in radiation_gases.f, because it tries to allocate module !variables that are already allocated. For now, throw an error and abort. if (n_columns>1) then - write(*,'(a)') 'The current implementation does not allow to run more than one column at a time.' - STOP + error stop "The current implementation does not allow to run more than one column at a time." end if - + !read in the physics suite and namelist read(10, NML=physics_config, iostat=ioerror) close(10) @@ -156,9 +155,9 @@ subroutine get_config_nml(scm_state) case default n_time_levels = 2 end select - + call get_tracers(tracer_names, tracer_types) - + call scm_state%create(n_columns, n_levels, n_soil, n_snow, n_time_levels, tracer_names, tracer_types) scm_state%experiment_name = experiment_name @@ -199,7 +198,7 @@ subroutine get_config_nml(scm_state) scm_state%reference_profile_choice = reference_profile_choice scm_state%relax_time = relax_time scm_state%input_type = input_type - + deallocate(tracer_names) !> @} end subroutine get_config_nml @@ -212,7 +211,7 @@ subroutine get_case_init(scm_state, scm_input) use NetCDF_read, only: NetCDF_read_var, check, missing_value type(scm_state_type), intent(in) :: scm_state type(scm_input_type), target, intent(inout) :: scm_input - + integer :: input_nlev !< number of levels in the input file integer :: input_nsoil !< number of soil levels in the input file integer :: input_nsnow !< number of snow levels in the input file @@ -222,9 +221,9 @@ subroutine get_case_init(scm_state, scm_input) real(kind=dp) :: input_lat !< column latitude (deg) real(kind=dp) :: input_lon !< column longitude (deg) real(kind=dp) :: input_area !< surface area [m^2] - + integer :: input_vegsrc !< vegetation source - + real(kind=dp) :: input_slmsk !< sea land ice mask [0,1,2] real(kind=dp) :: input_tsfco !< input sea surface temperature OR surface skin temperature over land OR surface skin temperature over ice (depending on slmsk) (K) real(kind=dp) :: input_weasd !< water equivalent accumulated snow depth (mm) @@ -275,14 +274,14 @@ subroutine get_case_init(scm_state, scm_input) real(kind=dp) :: input_albdifvis_ice !< real(kind=dp) :: input_albdifnir_ice !< real(kind=dp) :: input_zorlwav !< surface roughness length from wave model (cm) - + real(kind=dp), allocatable :: input_stc(:) !< soil temperature (K) - real(kind=dp), allocatable :: input_smc(:) !< total soil moisture content (fraction) + real(kind=dp), allocatable :: input_smc(:) !< total soil moisture content (fraction) real(kind=dp), allocatable :: input_slc(:) !< liquid soil moisture content (fraction) real(kind=dp), allocatable :: input_tiice(:) !< sea ice internal temperature (K) real(kind=dp) :: input_stddev !< standard deviation of subgrid orography (m) - real(kind=dp) :: input_convexity !< convexity of subgrid orography + real(kind=dp) :: input_convexity !< convexity of subgrid orography real(kind=dp) :: input_ol1 !< fraction of grid box with subgrid orography higher than critical height 1 real(kind=dp) :: input_ol2 !< fraction of grid box with subgrid orography higher than critical height 2 real(kind=dp) :: input_ol3 !< fraction of grid box with subgrid orography higher than critical height 3 @@ -330,13 +329,13 @@ subroutine get_case_init(scm_state, scm_input) real(kind=dp) :: input_deeprechxy !< recharge to or from the water table when deep (m) real(kind=dp) :: input_rechxy !< recharge to or from the water table when shallow (m) real(kind=dp) :: input_snowxy !< number of snow layers - + real(kind=dp), allocatable :: input_snicexy(:) !< snow layer ice (mm) real(kind=dp), allocatable :: input_snliqxy(:) !< snow layer liquid (mm) real(kind=dp), allocatable :: input_tsnoxy(:) !< snow temperature (K) real(kind=dp), allocatable :: input_smoiseq(:) !< equilibrium soil water content (m3 m-3) real(kind=dp), allocatable :: input_zsnsoxy(:) !< layer bottom depth from snow surface (m) - + real(kind=dp) :: input_tref !< sea surface reference temperature for NSST (K) real(kind=dp) :: input_z_c !< sub-layer cooling thickness for NSST (m) real(kind=dp) :: input_c_0 !< coefficient 1 to calculate d(Tz)/d(Ts) for NSST @@ -355,7 +354,7 @@ subroutine get_case_init(scm_state, scm_input) real(kind=dp) :: input_ifd !< index to start DTM run for NSST real(kind=dp) :: input_dt_cool !< sub-layer cooling amount for NSST (K) real(kind=dp) :: input_qrain !< sensible heat due to rainfall for NSST (W) - + real(kind=dp) :: input_wetness !< normalized soil wetness for RUC LSM real(kind=dp) :: input_clw_surf_land !< cloud condensed water mixing ratio at surface over land for RUC LSM (kg kg-1) real(kind=dp) :: input_clw_surf_ice !< cloud condensed water mixing ratio at surface over ice for RUC LSM (kg kg-1) @@ -371,13 +370,13 @@ subroutine get_case_init(scm_state, scm_input) real(kind=dp) :: input_sfalb_ice real(kind=dp) :: input_emis_ice real(kind=dp) :: input_lai !< leaf area index for RUC LSM - + real(kind=dp), allocatable :: input_tslb(:) !< soil temperature for RUC LSM (K) real(kind=dp), allocatable :: input_smois(:) !< volume fraction of soil moisture for RUC LSM (frac) real(kind=dp), allocatable :: input_sh2o(:) !< volume fraction of unfrozen soil moisture for RUC LSM (frac) real(kind=dp), allocatable :: input_smfr(:) !< volume fraction of frozen soil moisture for RUC LSM (frac) real(kind=dp), allocatable :: input_flfr(:) !< flag for frozen soil physics - + ! dimension variables !real(kind=dp), allocatable :: input_pres_i(:) !< interface pressures !real(kind=dp), allocatable :: input_pres_l(:) !< layer pressures @@ -394,7 +393,7 @@ subroutine get_case_init(scm_state, scm_input) real(kind=dp), allocatable :: input_v(:) !< north-south horizontal wind profile (m s^-1) real(kind=dp), allocatable :: input_tke(:) !< TKE profile (m^2 s^-2) real(kind=dp), allocatable :: input_ozone(:) !< ozone profile (kg kg^-1) - + real(kind=dp), allocatable :: input_pres_surf(:) !< time-series of surface pressure (Pa) real(kind=dp), allocatable :: input_T_surf(:) !< time-series of surface temperature (K) @@ -415,7 +414,7 @@ subroutine get_case_init(scm_state, scm_input) real(kind=dp), allocatable :: input_sh_flux_sfc(:) !< time-series of surface sensible heat flux (K m s^-1) real(kind=dp), allocatable :: input_lh_flux_sfc(:) !< time-series of surface latent heat flux (kg kg^-1 m s^-1) - + CHARACTER(LEN=nf90_max_name) :: tmpName integer :: ncid, varID, grp_ncid, allocate_status,ierr real(kind=dp) :: nc_missing_value @@ -425,21 +424,21 @@ subroutine get_case_init(scm_state, scm_input) !> - Open the case input file found in the processed_case_input dir corresponding to the experiment name. call check(NF90_OPEN(trim(adjustl(scm_state%case_name))//'.nc',nf90_nowrite,ncid),"nf90_open()") - + !> - Read in missing value from file (replace module variable if present) ierr = NF90_GET_ATT(ncid, NF90_GLOBAL, 'missing_value', nc_missing_value) if(ierr == NF90_NOERR) then missing_value = nc_missing_value end if - + !> - Get the dimensions (global group). - + !required dimensions call check(NF90_INQ_DIMID(ncid,"levels",varID),"nf90_inq_dimid(levels)") call check(NF90_INQUIRE_DIMENSION(ncid, varID, tmpName, input_nlev),"nf90_inq_dim(levels)") call check(NF90_INQ_DIMID(ncid,"time",varID),"inq_dimid(time)") call check(NF90_INQUIRE_DIMENSION(ncid, varID, tmpName, input_ntimes),"nf90_inq_dim(time)") - + !possible dimensions (if using model ICs) ierr = NF90_INQ_DIMID(ncid,"nsoil",varID) if(ierr /= NF90_NOERR) then @@ -458,8 +457,8 @@ subroutine get_case_init(scm_state, scm_input) input_nice = missing_ice_layers else call check(NF90_INQUIRE_DIMENSION(ncid, varID, tmpName, input_nice),"nf90_inq_dim(nice)") - end if - + end if + !> - Allocate the dimension variables. allocate(input_pres(input_nlev),input_time(input_ntimes), stat=allocate_status) @@ -475,15 +474,15 @@ subroutine get_case_init(scm_state, scm_input) !> - Allocate the initial profiles (required). One of thetail or temp is required. allocate(input_thetail(input_nlev), input_temp(input_nlev), input_qt(input_nlev), input_ql(input_nlev), input_qi(input_nlev), & input_u(input_nlev), input_v(input_nlev), input_tke(input_nlev), input_ozone(input_nlev), stat=allocate_status) - + !> - Read in the initial profiles. The variable names in all input files are expected to be identical. - + !Either thetail or T must be present call NetCDF_read_var(grp_ncid, "thetail", .False., input_thetail) call NetCDF_read_var(grp_ncid, "temp", .False., input_temp) if (maxval(input_thetail) < 0 .and. maxval(input_temp) < 0) then write(*,*) "One of thetail or temp variables must be present in ",trim(adjustl(scm_state%case_name))//'.nc',". Stopping..." - STOP + error stop "One of thetail or temp variables" end if call NetCDF_read_var(grp_ncid, "qt", .True., input_qt ) call NetCDF_read_var(grp_ncid, "ql", .True., input_ql ) @@ -492,7 +491,7 @@ subroutine get_case_init(scm_state, scm_input) call NetCDF_read_var(grp_ncid, "v", .True., input_v ) call NetCDF_read_var(grp_ncid, "tke", .True., input_tke ) call NetCDF_read_var(grp_ncid, "ozone", .True., input_ozone) - + !possible initial profiles !needed for Noah LSM and others (when running with model ICs) allocate(input_stc(input_nsoil), input_smc(input_nsoil), input_slc(input_nsoil), & @@ -500,7 +499,7 @@ subroutine get_case_init(scm_state, scm_input) call NetCDF_read_var(grp_ncid, "stc", .False., input_stc) call NetCDF_read_var(grp_ncid, "smc", .False., input_smc) call NetCDF_read_var(grp_ncid, "slc", .False., input_slc) - + !needed for NoahMP LSM (when running with model ICs) allocate(input_snicexy(input_nsnow), input_snliqxy(input_nsnow), input_tsnoxy(input_nsnow), & input_smoiseq(input_nsoil), input_zsnsoxy(input_nsnow + input_nsoil)) @@ -509,11 +508,11 @@ subroutine get_case_init(scm_state, scm_input) call NetCDF_read_var(grp_ncid, "tsnoxy", .False., input_tsnoxy ) call NetCDF_read_var(grp_ncid, "smoiseq", .False., input_smoiseq) call NetCDF_read_var(grp_ncid, "zsnsoxy", .False., input_zsnsoxy) - + !needed for fractional grid (when running with model ICs) allocate(input_tiice(input_nice)) call NetCDF_read_var(grp_ncid, "tiice", .False., input_tiice) - + !needed for RUC LSM (when running with model ICs) allocate(input_tslb(input_nsoil), input_smois(input_nsoil), input_sh2o(input_nsoil), & input_smfr(input_nsoil), input_flfr(input_nsoil)) @@ -522,16 +521,16 @@ subroutine get_case_init(scm_state, scm_input) call NetCDF_read_var(grp_ncid, "sh2o", .False., input_sh2o ) call NetCDF_read_var(grp_ncid, "smfr", .False., input_smfr ) call NetCDF_read_var(grp_ncid, "flfr", .False., input_flfr ) - + !> - Find group ncid for scalar group. call check(NF90_INQ_GRP_NCID(ncid,"scalars",grp_ncid),"nf90_inq_grp_ncid(scalars)") - + !required call NetCDF_read_var(grp_ncid, "lat", .True., input_lat) call NetCDF_read_var(grp_ncid, "lon", .True., input_lon) !time data in file ignored? call NetCDF_read_var(grp_ncid, "area", .False., input_area) - + !possible scalars !Noah LSM parameters (when running with model ICs) call NetCDF_read_var(grp_ncid, "vegsrc", .False., input_vegsrc ) @@ -585,7 +584,7 @@ subroutine get_case_init(scm_state, scm_input) call NetCDF_read_var(grp_ncid, "albdifvis_ice", .False., input_albdifvis_ice) call NetCDF_read_var(grp_ncid, "albdifnir_ice", .False., input_albdifnir_ice) call NetCDF_read_var(grp_ncid, "zorlwav", .False., input_zorlwav) - + !orographic parameters call NetCDF_read_var(grp_ncid, "stddev", .False., input_stddev) call NetCDF_read_var(grp_ncid, "convexity", .False., input_convexity) @@ -606,7 +605,7 @@ subroutine get_case_init(scm_state, scm_input) call NetCDF_read_var(grp_ncid, "landfrac", .False., input_landfrac) call NetCDF_read_var(grp_ncid, "lakefrac", .False., input_lakefrac) call NetCDF_read_var(grp_ncid, "lakedepth", .False., input_lakedepth) - + !NoahMP parameters call NetCDF_read_var(grp_ncid, "tvxy", .False., input_tvxy) call NetCDF_read_var(grp_ncid, "tgxy", .False., input_tgxy) @@ -637,7 +636,7 @@ subroutine get_case_init(scm_state, scm_input) call NetCDF_read_var(grp_ncid, "deeprechxy",.False., input_deeprechxy) call NetCDF_read_var(grp_ncid, "rechxy", .False., input_rechxy) call NetCDF_read_var(grp_ncid, "snowxy", .False., input_snowxy) - + !NSST variables call NetCDF_read_var(grp_ncid, "tref", .False., input_tref) call NetCDF_read_var(grp_ncid, "z_c", .False., input_z_c) @@ -657,7 +656,7 @@ subroutine get_case_init(scm_state, scm_input) call NetCDF_read_var(grp_ncid, "ifd", .False., input_ifd) call NetCDF_read_var(grp_ncid, "dt_cool", .False., input_dt_cool) call NetCDF_read_var(grp_ncid, "qrain", .False., input_qrain) - + !RUC LSM variables call NetCDF_read_var(grp_ncid, "wetness", .False., input_wetness) call NetCDF_read_var(grp_ncid, "clw_surf_land", .False., input_clw_surf_land) @@ -673,7 +672,7 @@ subroutine get_case_init(scm_state, scm_input) call NetCDF_read_var(grp_ncid, "sfalb_lnd_bck", .False., input_sfalb_lnd_bck) call NetCDF_read_var(grp_ncid, "emis_ice", .False., input_emis_ice) call NetCDF_read_var(grp_ncid, "lai", .False., input_lai) - + !> - Read in the forcing data. !> - Find group ncid for forcing group. @@ -696,7 +695,7 @@ subroutine get_case_init(scm_state, scm_input) call NetCDF_read_var(grp_ncid, "T_surf", .True., input_T_surf) call NetCDF_read_var(grp_ncid, "sh_flux_sfc", .False., input_sh_flux_sfc) call NetCDF_read_var(grp_ncid, "lh_flux_sfc", .False., input_lh_flux_sfc) - + call NetCDF_read_var(grp_ncid, "w_ls", .True., input_w_ls) call NetCDF_read_var(grp_ncid, "omega", .True., input_omega) call NetCDF_read_var(grp_ncid, "u_g", .True., input_u_g) @@ -715,7 +714,7 @@ subroutine get_case_init(scm_state, scm_input) call check(NF90_CLOSE(NCID=ncid),"nf90_close()") call scm_input%create(input_ntimes, input_nlev, input_nsoil, input_nsnow, input_nice) - + ! GJF already done in scm_input%create routine !scm_input%input_nlev = input_nlev !scm_input%input_ntimes = input_ntimes @@ -751,26 +750,26 @@ subroutine get_case_init(scm_state, scm_input) scm_input%input_T_nudge = input_T_nudge scm_input%input_thil_nudge = input_thil_nudge scm_input%input_qt_nudge = input_qt_nudge - - scm_input%input_stc = input_stc - scm_input%input_smc = input_smc - scm_input%input_slc = input_slc - + + scm_input%input_stc = input_stc + scm_input%input_smc = input_smc + scm_input%input_slc = input_slc + scm_input%input_snicexy = input_snicexy scm_input%input_snliqxy = input_snliqxy scm_input%input_tsnoxy = input_tsnoxy scm_input%input_smoiseq = input_smoiseq scm_input%input_zsnsoxy = input_zsnsoxy - + scm_input%input_tiice = input_tiice scm_input%input_tslb = input_tslb scm_input%input_smois = input_smois scm_input%input_sh2o = input_sh2o scm_input%input_smfr = input_smfr scm_input%input_flfr = input_flfr - + scm_input%input_vegsrc = input_vegsrc - + scm_input%input_slmsk = input_slmsk scm_input%input_canopy = input_canopy scm_input%input_hice = input_hice @@ -831,7 +830,7 @@ subroutine get_case_init(scm_state, scm_input) scm_input%input_albdifvis_ice = input_albdifvis_ice scm_input%input_albdifnir_ice = input_albdifnir_ice scm_input%input_zorlwav = input_zorlwav - + scm_input%input_stddev = input_stddev scm_input%input_convexity= input_convexity scm_input%input_oa1 = input_oa1 @@ -851,7 +850,7 @@ subroutine get_case_init(scm_state, scm_input) scm_input%input_landfrac = input_landfrac scm_input%input_lakefrac = input_lakefrac scm_input%input_lakedepth= input_lakedepth - + scm_input%input_tvxy = input_tvxy scm_input%input_tgxy = input_tgxy scm_input%input_tahxy = input_tahxy @@ -881,7 +880,7 @@ subroutine get_case_init(scm_state, scm_input) scm_input%input_deeprechxy = input_deeprechxy scm_input%input_rechxy = input_rechxy scm_input%input_snowxy = input_snowxy - + scm_input%input_tref = input_tref scm_input%input_z_c = input_z_c scm_input%input_c_0 = input_c_0 @@ -900,9 +899,9 @@ subroutine get_case_init(scm_state, scm_input) scm_input%input_ifd = input_ifd scm_input%input_dt_cool = input_dt_cool scm_input%input_qrain = input_qrain - + scm_input%input_area = input_area - + scm_input%input_wetness = input_wetness scm_input%input_clw_surf_land = input_clw_surf_land scm_input%input_clw_surf_ice = input_clw_surf_ice @@ -917,29 +916,29 @@ subroutine get_case_init(scm_state, scm_input) scm_input%input_sfalb_lnd_bck = input_sfalb_lnd_bck scm_input%input_emis_ice = input_emis_ice scm_input%input_lai = input_lai - + !> @} end subroutine get_case_init subroutine get_case_init_DEPHY(scm_state, scm_input) !corresponds to the DEPHY-SCM specs, version 1 - + use scm_type_defs, only : scm_state_type, scm_input_type use NetCDF_read, only: NetCDF_read_var, NetCDF_read_att, NetCDF_conditionally_read_var, check, missing_value, missing_value_int use scm_physical_constants, only: con_hvap, con_hfus, con_cp, con_rocp, con_rd use scm_utils, only: find_vertical_index_pressure, find_vertical_index_height - + type(scm_state_type), intent(inout) :: scm_state type(scm_input_type), target, intent(inout) :: scm_input - + ! dimension variables real(kind=dp), allocatable :: input_t0(:) !< input initialization times (seconds since global attribute "startdate") real(kind=dp), allocatable :: input_time(:) !< input forcing times (seconds since the beginning of the case) real(kind=dp), allocatable :: input_lev(:) !< corresponds to either pressure or height (depending on attribute) - why is this needed when both pressure and height also provided in ICs? - + !non-standard dimensions (may or may not exist in the file) real(kind=dp), allocatable :: input_soil(:) !< soil depth - + ! global attributes character(len=19) :: char_startDate, char_endDate !format YYYY-MM-DD HH:MM:SS integer :: init_year, init_month, init_day, init_hour, init_min, init_sec, end_year, end_month, end_day, end_hour, end_min, end_sec @@ -951,7 +950,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) real(kind=sp) :: p_nudging_temp, p_nudging_theta, p_nudging_thetal, p_nudging_qv, p_nudging_qt, p_nudging_rv, p_nudging_rt, p_nudging_u, p_nudging_v character(len=5) :: input_surfaceType character(len=12) :: input_surfaceForcingWind='',input_surfaceForcingMoist='',input_surfaceForcingLSM='',input_surfaceForcingTemp='' - + ! initial variables (IC = Initial Condition) real(kind=dp), allocatable :: input_lat(:) !< column latitude (deg) real(kind=dp), allocatable :: input_lon(:) !< column longitude (deg) @@ -974,11 +973,11 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) real(kind=sp), allocatable :: input_ri(:,:) !< IC ice water mixing ratio profile (kg kg^-1) real(kind=sp), allocatable :: input_rh(:,:) !< IC relative humidity profile (%) real(kind=sp), allocatable :: input_tke(:,:) !< IC TKE profile (m^2 s^-2) - + ! Model ICs (extension of DEPHY format) real(kind=dp), allocatable :: input_ozone(:,:) !< ozone profile (kg kg^-1) real(kind=dp), allocatable :: input_stc(:,:) !< soil temperature (K) - real(kind=dp), allocatable :: input_smc(:,:) !< total soil moisture content (fraction) + real(kind=dp), allocatable :: input_smc(:,:) !< total soil moisture content (fraction) real(kind=dp), allocatable :: input_slc(:,:) !< liquid soil moisture content (fraction) real(kind=dp), allocatable :: input_snicexy(:,:) !< snow layer ice (mm) real(kind=dp), allocatable :: input_snliqxy(:,:) !< snow layer liquid (mm) @@ -991,7 +990,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) real(kind=dp), allocatable :: input_sh2o(:,:) !< volume fraction of unfrozen soil moisture for RUC LSM (frac) real(kind=dp), allocatable :: input_smfr(:,:) !< volume fraction of frozen soil moisture for RUC LSM (frac) real(kind=dp), allocatable :: input_flfr(:,:) !< flag for frozen soil physics - + real(kind=dp), allocatable :: input_area(:) !< surface area [m^2] real(kind=dp), allocatable :: input_tsfco(:) !< input sea surface temperature OR surface skin temperature over land OR surface skin temperature over ice (depending on slmsk) (K) integer , allocatable :: input_vegsrc(:) !< vegetation source @@ -1030,9 +1029,9 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) real(kind=dp), allocatable :: input_zorll(:) !< surface roughness length over land (cm) real(kind=dp), allocatable :: input_zorli(:) !< surface roughness length over ice (cm) real(kind=dp), allocatable :: input_zorlw(:) !< surface roughness length from wave model (cm) - + real(kind=dp), allocatable :: input_stddev(:) !< standard deviation of subgrid orography (m) - real(kind=dp), allocatable :: input_convexity(:) !< convexity of subgrid orography + real(kind=dp), allocatable :: input_convexity(:) !< convexity of subgrid orography real(kind=dp), allocatable :: input_ol1(:) !< fraction of grid box with subgrid orography higher than critical height 1 real(kind=dp), allocatable :: input_ol2(:) !< fraction of grid box with subgrid orography higher than critical height 2 real(kind=dp), allocatable :: input_ol3(:) !< fraction of grid box with subgrid orography higher than critical height 3 @@ -1050,7 +1049,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) real(kind=dp), allocatable :: input_landfrac(:) !< fraction of horizontal grid area occupied by land real(kind=dp), allocatable :: input_lakefrac(:) !< fraction of horizontal grid area occupied by lake real(kind=dp), allocatable :: input_lakedepth(:) !< lake depth (m) - + real(kind=dp), allocatable :: input_tvxy(:) !< vegetation temperature (K) real(kind=dp), allocatable :: input_tgxy(:) !< ground temperature for Noahmp (K) real(kind=dp), allocatable :: input_tahxy(:) !< canopy air temperature (K) @@ -1080,7 +1079,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) real(kind=dp), allocatable :: input_deeprechxy(:) !< recharge to or from the water table when deep (m) real(kind=dp), allocatable :: input_rechxy(:) !< recharge to or from the water table when shallow (m) real(kind=dp), allocatable :: input_snowxy(:) !< number of snow layers - + real(kind=dp), allocatable :: input_tref(:) !< sea surface reference temperature for NSST (K) real(kind=dp), allocatable :: input_z_c(:) !< sub-layer cooling thickness for NSST (m) real(kind=dp), allocatable :: input_c_0(:) !< coefficient 1 to calculate d(Tz)/d(Ts) for NSST @@ -1099,23 +1098,23 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) real(kind=dp), allocatable :: input_ifd(:) !< index to start DTM run for NSST real(kind=dp), allocatable :: input_dt_cool(:) !< sub-layer cooling amount for NSST (K) real(kind=dp), allocatable :: input_qrain(:) !< sensible heat due to rainfall for NSST (W) - + real(kind=dp), allocatable :: input_wetness(:) !< normalized soil wetness for RUC LSM real(kind=dp), allocatable :: input_lai(:) !< leaf area index for RUC LSM - real(kind=dp), allocatable :: input_clw_surf_land(:) !< cloud condensed water mixing ratio at surface over land for RUC LSM + real(kind=dp), allocatable :: input_clw_surf_land(:) !< cloud condensed water mixing ratio at surface over land for RUC LSM real(kind=dp), allocatable :: input_clw_surf_ice(:) !< cloud condensed water mixing ratio at surface over ice for RUC LSM - real(kind=dp), allocatable :: input_qwv_surf_land(:) !< water vapor mixing ratio at surface over land for RUC LSM - real(kind=dp), allocatable :: input_qwv_surf_ice(:) !< water vapor mixing ratio at surface over ice for RUC LSM - real(kind=dp), allocatable :: input_tsnow_land(:) !< snow temperature at the bottom of the first snow layer over land for RUC LSM - real(kind=dp), allocatable :: input_tsnow_ice(:) !< snow temperature at the bottom of the first snow layer over ice for RUC LSM - real(kind=dp), allocatable :: input_snowfallac_land(:) !< run-total snow accumulation on the ground over land for RUC LSM - real(kind=dp), allocatable :: input_snowfallac_ice(:) !< run-total snow accumulation on the ground over ice for RUC LSM + real(kind=dp), allocatable :: input_qwv_surf_land(:) !< water vapor mixing ratio at surface over land for RUC LSM + real(kind=dp), allocatable :: input_qwv_surf_ice(:) !< water vapor mixing ratio at surface over ice for RUC LSM + real(kind=dp), allocatable :: input_tsnow_land(:) !< snow temperature at the bottom of the first snow layer over land for RUC LSM + real(kind=dp), allocatable :: input_tsnow_ice(:) !< snow temperature at the bottom of the first snow layer over ice for RUC LSM + real(kind=dp), allocatable :: input_snowfallac_land(:) !< run-total snow accumulation on the ground over land for RUC LSM + real(kind=dp), allocatable :: input_snowfallac_ice(:) !< run-total snow accumulation on the ground over ice for RUC LSM real(kind=dp), allocatable :: input_sncovr_ice(:) !< real(kind=dp), allocatable :: input_sfalb_lnd(:) !< real(kind=dp), allocatable :: input_sfalb_lnd_bck(:) !< real(kind=dp), allocatable :: input_sfalb_ice(:) !< real(kind=dp), allocatable :: input_emis_ice(:) !< - + ! forcing variables real(kind=sp), allocatable :: input_force_pres_surf(:) !< forcing surface pressure (Pa) real(kind=sp), allocatable :: input_force_height(:,:) !< forcing height levels (m) @@ -1154,7 +1153,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) real(kind=sp), allocatable :: input_force_rt_nudging(:,:) real(kind=sp), allocatable :: input_force_u_nudging(:,:) real(kind=sp), allocatable :: input_force_v_nudging(:,:) - + integer :: ncid, varID, allocate_status, ierr, i, k integer :: active_lon, active_lat, active_init_time CHARACTER(LEN=nf90_max_name) :: tmpName @@ -1164,14 +1163,14 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) integer :: jdat(1:8), idat(1:8) !(yr, mon, day, t-zone, hr, min, sec, mil-sec) integer :: input_n_init_times, input_n_forcing_times, input_n_lev, input_n_snow, input_n_ice, input_n_soil - + missing_value_eps = missing_value + 0.01 - + !> - Open the case input file found in the processed_case_input dir corresponding to the experiment name. call check(NF90_OPEN(trim(adjustl(scm_state%case_name))//'_SCM_driver.nc',nf90_nowrite,ncid),"nf90_open()") - + !> - Get the dimensions. - + !required dimensions call check(NF90_INQ_DIMID(ncid,"t0",varID),"nf90_inq_dimid(t0)") call check(NF90_INQUIRE_DIMENSION(ncid, varID, tmpName, input_n_init_times),"nf90_inq_dim(t0)") @@ -1201,8 +1200,8 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) input_n_ice = missing_ice_layers else call check(NF90_INQUIRE_DIMENSION(ncid, varID, tmpName, input_n_ice),"nf90_inq_dim(nice)") - end if - + end if + !> - Allocate the dimension variables. allocate(input_t0 (input_n_init_times), & input_time (input_n_forcing_times), & @@ -1217,23 +1216,23 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) !> - Read in global attributes call NetCDF_read_att(ncid, NF90_GLOBAL, 'start_date', .True., char_startDate) - + read(char_startDate(1:4),'(i4)') init_year read(char_startDate(6:7),'(i2)') init_month read(char_startDate(9:10),'(i2)') init_day read(char_startDate(12:13),'(i2)') init_hour read(char_startDate(15:16),'(i2)') init_min read(char_startDate(18:19),'(i2)') init_sec - + call NetCDF_read_att(ncid, NF90_GLOBAL, 'end_date', .True., char_endDate) - + read(char_endDate(1:4),'(i4)') end_year read(char_endDate(6:7),'(i2)') end_month read(char_endDate(9:10),'(i2)') end_day read(char_endDate(12:13),'(i2)') end_hour read(char_endDate(15:16),'(i2)') end_min read(char_endDate(18:19),'(i2)') end_sec - + !compare init time to what was in case config file? replace? call NetCDF_read_att(ncid, NF90_GLOBAL, 'adv_ua', .False., adv_u) call NetCDF_read_att(ncid, NF90_GLOBAL, 'adv_va', .False., adv_v) @@ -1325,8 +1324,8 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) input_smfr (input_n_soil, input_n_init_times), & input_flfr (input_n_soil, input_n_init_times), & stat=allocate_status) - - + + !variables without vertical extent allocate(input_area ( input_n_init_times), & input_tsfco ( input_n_init_times), & @@ -1388,7 +1387,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) input_lakedepth ( input_n_init_times), & stat=allocate_status) allocate(input_tvxy ( input_n_init_times), & - input_tgxy ( input_n_init_times), & + input_tgxy ( input_n_init_times), & input_tahxy ( input_n_init_times), & input_canicexy ( input_n_init_times), & input_canliqxy ( input_n_init_times), & @@ -1414,8 +1413,8 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) input_fastcpxy ( input_n_init_times), & input_smcwtdxy ( input_n_init_times), & input_deeprechxy( input_n_init_times), & - input_rechxy ( input_n_init_times), & - input_snowxy ( input_n_init_times), & + input_rechxy ( input_n_init_times), & + input_snowxy ( input_n_init_times), & stat=allocate_status) allocate(input_tref ( input_n_init_times), & input_z_c ( input_n_init_times), & @@ -1460,12 +1459,12 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) call NetCDF_read_var(ncid, "ps", .True., input_pres_surf) call NetCDF_read_var(ncid, "ua", .True., input_u) call NetCDF_read_var(ncid, "va", .True., input_v) - + !one of the following should be present, but not all, hence they are not requried call NetCDF_read_var(ncid, "ta", .False., input_temp) call NetCDF_read_var(ncid, "theta", .False., input_theta) call NetCDF_read_var(ncid, "thetal", .False., input_thetal) - + !one or more of the following should be present, but not all, hence they are not requried call NetCDF_read_var(ncid, "qv", .False., input_qv) call NetCDF_read_var(ncid, "qt", .False., input_qt) @@ -1476,13 +1475,13 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) call NetCDF_read_var(ncid, "rl", .False., input_rl) call NetCDF_read_var(ncid, "ri", .False., input_ri) call NetCDF_read_var(ncid, "hur", .False., input_rh) - + call NetCDF_read_var(ncid, "tke", .True., input_tke) - + if (trim(input_surfaceForcingLSM) == "lsm") then call NetCDF_read_var(ncid, "o3", .True., input_ozone) call NetCDF_read_var(ncid, "area", .True., input_area) - + !orographic parameters call NetCDF_read_var(ncid, "stddev", .True., input_stddev) call NetCDF_read_var(ncid, "convexity", .True., input_convexity) @@ -1503,7 +1502,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) call NetCDF_read_var(ncid, "landfrac", .True., input_landfrac) call NetCDF_read_var(ncid, "lakefrac", .True., input_lakefrac) call NetCDF_read_var(ncid, "lakedepth", .True., input_lakedepth) - + !NSST variables call NetCDF_read_var(ncid, "tref", .True., input_tref) call NetCDF_read_var(ncid, "z_c", .True., input_z_c) @@ -1524,9 +1523,9 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) call NetCDF_read_var(ncid, "dt_cool", .True., input_dt_cool) call NetCDF_read_var(ncid, "qrain", .True., input_qrain) end if - + !> - Allocate the forcing variables. - + !allocate all, but conditionally read forcing variables given global atts; set unused forcing variables to missing allocate(input_lat (input_n_forcing_times), & @@ -1572,11 +1571,11 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) stat=allocate_status) call NetCDF_read_var(ncid, "lat", .True., input_lat) - call NetCDF_read_var(ncid, "lon", .True., input_lon) + call NetCDF_read_var(ncid, "lon", .True., input_lon) call NetCDF_read_var(ncid, "ps_forc", .True., input_force_pres_surf) call NetCDF_read_var(ncid, "zh_forc", .True., input_force_height) call NetCDF_read_var(ncid, "pa_forc", .True., input_force_pres) - + !conditionally read forcing vars (or set to missing); if the global attribute is set to expect a variable and it doesn't exist, stop the model call NetCDF_conditionally_read_var(adv_u, "adv_ua", "tnua_adv", trim(adjustl(scm_state%case_name))//'.nc', ncid, input_force_u_adv) call NetCDF_conditionally_read_var(adv_v, "adv_va", "tnva_adv", trim(adjustl(scm_state%case_name))//'.nc', ncid, input_force_v_adv) @@ -1592,12 +1591,12 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) call NetCDF_conditionally_read_var(rad_thetal, "rad_thetal", "tnthetal_rad", trim(adjustl(scm_state%case_name))//'.nc', ncid, input_force_thetal_rad) !need to also handle the case when rad_[temp,theta,thetal]_char = 'adv' (make sure [temp,theta,thetal]_adv is not missing) !need to also turn off radiation when radiation is being forced (put in a warning that this is not supported for now?) - + call NetCDF_conditionally_read_var(forc_w, "forc_w", "wa", trim(adjustl(scm_state%case_name))//'.nc', ncid, input_force_w) call NetCDF_conditionally_read_var(forc_omega, "forc_wap", "wap", trim(adjustl(scm_state%case_name))//'.nc', ncid, input_force_omega) call NetCDF_conditionally_read_var(forc_geo, "forc_geo", "ug", trim(adjustl(scm_state%case_name))//'.nc', ncid, input_force_u_g) call NetCDF_conditionally_read_var(forc_geo, "forc_geo", "vg", trim(adjustl(scm_state%case_name))//'.nc', ncid, input_force_v_g) - + call NetCDF_conditionally_read_var(nudging_u, "nudging_u", "ua_nud", trim(adjustl(scm_state%case_name))//'.nc', ncid, input_force_u_nudging) call NetCDF_conditionally_read_var(nudging_v, "nudging_v", "va_nud", trim(adjustl(scm_state%case_name))//'.nc', ncid, input_force_v_nudging) call NetCDF_conditionally_read_var(nudging_temp, "nudging_temp", "ta_nud", trim(adjustl(scm_state%case_name))//'.nc', ncid, input_force_temp_nudging) @@ -1660,7 +1659,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) call NetCDF_read_var(ncid, "sh2o", .True., input_sh2o ) call NetCDF_read_var(ncid, "smfr", .True., input_smfr ) call NetCDF_read_var(ncid, "flfr", .True., input_flfr ) - + call NetCDF_read_var(ncid, "vegsrc", .True., input_vegsrc ) call NetCDF_read_var(ncid, "vegtyp", .True., input_vegtyp ) call NetCDF_read_var(ncid, "soiltyp", .True., input_soiltyp ) @@ -1698,7 +1697,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) call NetCDF_read_var(ncid, "zorll", .True., input_zorll) call NetCDF_read_var(ncid, "zorli", .True., input_zorli) call NetCDF_read_var(ncid, "zorlw", .True., input_zorlw) - + !NoahMP parameters call NetCDF_read_var(ncid, "tvxy", .False., input_tvxy) call NetCDF_read_var(ncid, "tgxy", .False., input_tgxy) @@ -1745,18 +1744,18 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) call NetCDF_read_var(ncid, "emis_ice", .False., input_emis_ice) call NetCDF_read_var(ncid, "lai", .False., input_lai) end if - + call check(NF90_CLOSE(NCID=ncid),"nf90_close()") - + call scm_input%create(input_n_forcing_times, input_n_lev, input_n_soil, input_n_snow, input_n_ice) - + !fill the scm_input DDT - + !There may need to be logic to control which of the lon, lat, and init_times to use in the future, but for now, just take the first active_lon = 1 active_lat = 1 active_init_time = 1 - + rinc(1:5) = 0 idat = 0 jdat = 0 @@ -1774,7 +1773,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) jdat(7) = end_sec call w3difdat(jdat,idat,4,rinc) elapsed_sec = rinc(4) - + !the following variables replace what is in the case configuration file scm_state%init_year = init_year scm_state%init_month = init_month @@ -1782,14 +1781,14 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) scm_state%init_hour = init_hour scm_state%init_min = init_min scm_state%runtime = elapsed_sec - + scm_input%input_time = input_time scm_input%input_pres_surf(1) = input_pres_surf(active_init_time) !perhaps input_pres_surf should only be equal to input_force_pres_surf? scm_input%input_pres = input_pres(:,active_init_time) scm_input%input_u = input_u(:,active_init_time) scm_input%input_v = input_v(:,active_init_time) scm_input%input_tke = input_tke(:,active_init_time) - + !if mixing ratios are present, and not specific humidities, convert from mixing ratio to specific humidities if ((maxval(input_qv(:,active_init_time)) < 0 .and. & maxval(input_qt(:,active_init_time)) < 0) .and. & @@ -1820,7 +1819,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) end do end if end if - + !make sure that one of qv or qt (and rv or rt due to above conversion) is present (add support for rh later) if (maxval(input_qv(:,active_init_time)) >= 0) then if (maxval(input_qt(:,active_init_time)) >= 0) then @@ -1840,7 +1839,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) scm_input%input_qi(k) = max(0.0, scm_input%input_qt(k) - scm_input%input_qv(k) - scm_input%input_ql(k)) end do end if !qi test - else + else if (maxval(input_qi(:,active_init_time)) >= 0) then !qv, qt, qi, but no ql scm_input%input_qv = input_qv(:,active_init_time) scm_input%input_qt = input_qt(:,active_init_time) @@ -1876,7 +1875,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) do k=1, input_n_lev scm_input%input_qt(k) = max(0.0, scm_input%input_qv(k) + scm_input%input_ql(k)) end do - scm_input%input_qi = 0.0 + scm_input%input_qi = 0.0 end if ! qi test else if (maxval(input_qi(:,active_init_time)) >= 0) then !qv, no qt, no ql, qi @@ -1933,9 +1932,9 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) else !no qv or qt write(*,*) 'When reading '//trim(adjustl(scm_state%case_name))//'.nc, all of the supported moisture variables (qv, qt, rv, rt) were missing. Stopping...' - stop + error stop "Aall of the supported moisture variables (qv, qt, rv, rt) were missing" end if - + !make sure that at least one of temp, theta, thetal is present; !the priority for use is temp, thetal, theta if (maxval(input_temp(:,active_init_time)) > 0) then @@ -1963,13 +1962,13 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) scm_input%input_temp = missing_value else write(*,*) 'When reading '//trim(adjustl(scm_state%case_name))//'.nc, all of the supported temperature variables (temp, theta, thetal) were missing. Stopping...' - stop + error stop "All of the supported temperature variables (temp, theta, thetal) were missing" end if if (trim(input_surfaceForcingLSM) == "lsm") then scm_input%input_ozone = input_ozone(:,active_init_time) scm_input%input_area = input_area(active_init_time) - + scm_input%input_stddev = input_stddev(active_init_time) scm_input%input_convexity= input_convexity(active_init_time) scm_input%input_oa1 = input_oa1(active_init_time) @@ -1989,7 +1988,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) scm_input%input_landfrac = input_landfrac(active_init_time) scm_input%input_lakefrac = input_lakefrac(active_init_time) scm_input%input_lakedepth= input_lakedepth(active_init_time) - + scm_input%input_tref = input_tref(active_init_time) scm_input%input_z_c = input_z_c(active_init_time) scm_input%input_c_0 = input_c_0(active_init_time) @@ -2014,24 +2013,24 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) end if scm_input%input_lat = input_lat(active_lat) scm_input%input_lon = input_lon(active_lon) - + scm_input%input_pres_surf = input_force_pres_surf(:) - + do i=1, input_n_forcing_times scm_input%input_pres_forcing(i,:) = input_force_pres(:,i) end do - + if (input_SurfaceType == 'ocean') then scm_state%sfc_type = 0.0 else if (input_SurfaceType == 'land') then scm_state%sfc_type = 1.0 end if !no sea ice type? - + if (input_surfaceForcingTemp == 'ts') then if (maxval(input_force_ts) < 0) then write(*,*) 'The global attribute surfaceForcing in '//trim(adjustl(scm_state%case_name))//'.nc indicates that the variable ts should be present, but it is missing. Stopping ...' - stop + error stop "The global attribute surfaceForcing indicates that the variable ts should be present, but it is missing" else !overwrite sfc_flux_spec scm_state%sfc_flux_spec = .false. @@ -2042,7 +2041,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) !overwrite sfc_flux_spec scm_state%sfc_flux_spec = .true. scm_state%surface_thermo_control = 0 - + if (maxval(input_force_ts) < 0) then !since no surface temperature is given, assume that the surface temperature is equivalent to the static, surface-adjacent temperature in the initial profile if (maxval(scm_input%input_temp) > 0) then @@ -2059,11 +2058,11 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) else scm_input%input_T_surf = input_force_ts(:) end if - + !kinematic surface fluxes are specified (but may need to be converted) if (maxval(input_force_wpthetap(:)) < missing_value_eps) then write(*,*) 'The global attribute surfaceForcing in '//trim(adjustl(scm_state%case_name))//'.nc indicates that the variable wpthetap should be present, but it is missing. Stopping ...' - stop + error stop "The global attribute surfaceForcing indicates that the variable wpthetap should be present, but it is missing." else !convert from theta to T do i=1, input_n_forcing_times @@ -2071,7 +2070,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) scm_input%input_sh_flux_sfc_kin(i) = exner*input_force_wpthetap(i) end do end if - + !if mixing ratios are present, and not specific humidities, convert from mixing ratio to specific humidities if ((maxval(input_force_wpqvp(:)) < missing_value_eps .and. & maxval(input_force_wpqtp(:)) < missing_value_eps) .and. & @@ -2090,10 +2089,10 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) end do end if end if - + if (maxval(input_force_wpqvp(:)) < missing_value_eps .and. maxval(input_force_wpqtp(:)) < missing_value_eps) then write(*,*) 'The global attribute surfaceForcing in '//trim(adjustl(scm_state%case_name))//'.nc indicates that the variable wpqvp, wpqtp, wprvp, or wprtp should be present, but all are missing. Stopping ...' - stop + error stop "The global attribute surfaceForcing indicates that the variable wpqvp, wpqtp, wprvp, or wprtp should be present, but all are missing." else if (maxval(input_force_wpqvp(:)) > missing_value_eps) then !use wpqvp if available scm_input%input_lh_flux_sfc_kin = input_force_wpqvp(:) @@ -2106,7 +2105,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) !overwrite sfc_flux_spec scm_state%sfc_flux_spec = .true. scm_state%surface_thermo_control = 1 - + if (maxval(input_force_ts) < 0) then !since no surface temperature is given, assume that the surface temperature is equivalent to the static, surface-adjacent temperature in the initial profile if (maxval(scm_input%input_temp) > 0) then @@ -2123,40 +2122,40 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) else scm_input%input_T_surf = input_force_ts(:) end if - - + + if (maxval(input_force_sfc_sens_flx(:)) < missing_value_eps) then write(*,*) 'The global attribute surfaceForcing in '//trim(adjustl(scm_state%case_name))//'.nc indicates that the variable sfc_sens_flx should be present, but it is missing. Stopping ...' - stop + error stop "The global attribute surfaceForcing in indicates that the variable sfc_sens_flx should be present, but it is missing." else scm_input%input_sh_flux_sfc = input_force_sfc_sens_flx(:) end if - + if (maxval(input_force_sfc_lat_flx(:)) < missing_value_eps) then write(*,*) 'The global attribute surfaceForcing in '//trim(adjustl(scm_state%case_name))//'.nc indicates that the variable sfc_lat_flx should be present, but it is missing. Stopping ...' - stop + error stop "The global attribute surfaceForcing indicates that the variable sfc_lat_flx should be present, but it is missing." else scm_input%input_lh_flux_sfc = input_force_sfc_lat_flx(:) end if else if (trim(input_surfaceForcingLSM) == 'lsm') then !these were considered required variables above, so they should not need to be checked for missing scm_input%input_stc = input_stc(:,active_init_time) - scm_input%input_smc = input_smc(:,active_init_time) - scm_input%input_slc = input_slc(:,active_init_time) - + scm_input%input_smc = input_smc(:,active_init_time) + scm_input%input_slc = input_slc(:,active_init_time) + scm_input%input_snicexy = input_snicexy(:,active_init_time) scm_input%input_snliqxy = input_snliqxy(:,active_init_time) scm_input%input_tsnoxy = input_tsnoxy(:,active_init_time) scm_input%input_smoiseq = input_smoiseq(:,active_init_time) scm_input%input_zsnsoxy = input_zsnsoxy(:,active_init_time) - + scm_input%input_tiice = input_tiice(:,active_init_time) scm_input%input_tslb = input_tslb(:,active_init_time) scm_input%input_smois = input_smois(:,active_init_time) scm_input%input_sh2o = input_sh2o(:,active_init_time) scm_input%input_smfr = input_smfr(:,active_init_time) scm_input%input_flfr = input_flfr(:,active_init_time) - + scm_input%input_vegsrc = input_vegsrc(active_init_time) scm_input%input_vegtyp = REAL(input_vegtyp(active_init_time), kind=dp) scm_input%input_soiltyp = REAL(input_soiltyp(active_init_time), kind=dp) @@ -2194,7 +2193,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) scm_input%input_zorll = input_zorll(active_init_time) scm_input%input_zorli = input_zorli(active_init_time) scm_input%input_zorlw = input_zorlw(active_init_time) - + scm_input%input_tvxy = input_tvxy(active_init_time) scm_input%input_tgxy = input_tgxy(active_init_time) scm_input%input_tahxy = input_tahxy(active_init_time) @@ -2239,7 +2238,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) scm_input%input_sfalb_lnd_bck = input_sfalb_lnd_bck(active_init_time) scm_input%input_emis_ice = input_emis_ice(active_init_time) end if - + if (input_surfaceForcingWind == 'z0') then scm_state%surface_momentum_control = 0 scm_state%sfc_roughness_length_cm = input_z0*100.0 !convert from m to cm @@ -2247,9 +2246,9 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) !not supported scm_state%surface_momentum_control = 1 write(*,*) 'The global attribute surfaceForcingWind in '//trim(adjustl(scm_state%case_name))//'.nc indicates that surface wind is controlled by a specified time-series of ustar. This is currently not supported. Stopping ...' - stop + error stop "The global attribute surfaceForcingWind indicates that surface wind is controlled by a specified time-series of ustar. This is currently not supported." end if - + if (forc_omega > 0) then do i=1, input_n_forcing_times scm_input%input_omega(i,:) = input_force_omega(:,i) @@ -2281,7 +2280,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) end do scm_state%force_geo = .true. end if - + if (adv_temp > 0) then do i=1, input_n_forcing_times scm_input%input_tot_advec_T(i,:) = input_force_temp_adv(:,i) @@ -2298,7 +2297,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) end do scm_state%force_adv_T = 3 end if - + if (adv_qv > 0) then do i=1, input_n_forcing_times scm_input%input_tot_advec_qv(i,:) = input_force_qv_adv(:,i) @@ -2330,26 +2329,26 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) end if scm_state%force_adv_qv = .true. end if - + if (adv_u > 0) then do i=1, input_n_forcing_times scm_input%input_tot_advec_u(i,:) = input_force_u_adv(:,i) end do scm_state%force_adv_u = .true. end if - + if (adv_v > 0) then do i=1, input_n_forcing_times scm_input%input_tot_advec_v(i,:) = input_force_v_adv(:,i) end do scm_state%force_adv_v = .true. end if - + if (char_rad_temp == 'adv' .or. char_rad_theta == 'adv' .or. char_rad_thetal == 'adv') then scm_state%force_rad_T = 4 if (scm_state%force_adv_T == 0) then write(*,*) 'The global attribute rad_temp, rad_theta, or rad_thetal in '//trim(adjustl(scm_state%case_name))//'.nc indicates that radiative forcing is included in the advection term, but there is no advection term. Stopping ...' - stop + error stop "The global attribute rad_temp, rad_theta, or rad_thetal indicates that radiative forcing is included in the advection term, but there is no advection term." end if else if (rad_temp > 0) then do i=1, input_n_forcing_times @@ -2375,7 +2374,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) else scm_state%force_rad_T = 0 end if - + if (nudging_temp > 0) then do i=1, input_n_forcing_times scm_input%input_T_nudge(i,:) = input_force_temp_nudging(:,i) @@ -2390,7 +2389,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) scm_input%input_k_T_nudge(i) = input_n_lev end if end do - else if (z_nudging_temp > 0) then + else if (z_nudging_temp > 0) then do i=1, input_n_forcing_times call find_vertical_index_height(z_nudging_temp, input_force_height(:,i), scm_input%input_k_T_nudge(i)) if (scm_input%input_k_T_nudge(i) < 0) then @@ -2416,7 +2415,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) scm_input%input_k_thil_nudge(i) = input_n_lev end if end do - else if (z_nudging_theta > 0) then + else if (z_nudging_theta > 0) then do i=1, input_n_forcing_times call find_vertical_index_height(z_nudging_theta, input_force_height(:,i), scm_input%input_k_thil_nudge(i)) if (scm_input%input_k_thil_nudge(i) < 0) then @@ -2442,7 +2441,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) scm_input%input_k_thil_nudge(i) = input_n_lev end if end do - else if (z_nudging_thetal > 0) then + else if (z_nudging_thetal > 0) then do i=1, input_n_forcing_times call find_vertical_index_height(z_nudging_thetal, input_force_height(:,i), scm_input%input_k_thil_nudge(i)) if (scm_input%input_k_thil_nudge(i) < 0) then @@ -2454,7 +2453,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) scm_input%input_k_thil_nudge = 1 end if end if - + if (nudging_qv > 0) then do i=1, input_n_forcing_times scm_input%input_qt_nudge(i,:) = input_force_qv_nudging(:,i) @@ -2469,7 +2468,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) scm_input%input_k_qt_nudge(i) = input_n_lev end if end do - else if (z_nudging_qv > 0) then + else if (z_nudging_qv > 0) then do i=1, input_n_forcing_times call find_vertical_index_height(z_nudging_qv, input_force_height(:,i), scm_input%input_k_qt_nudge(i)) if (scm_input%input_k_qt_nudge(i) < 0) then @@ -2494,7 +2493,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) scm_input%input_k_qt_nudge(i) = input_n_lev end if end do - else if (z_nudging_qt > 0) then + else if (z_nudging_qt > 0) then do i=1, input_n_forcing_times call find_vertical_index_height(z_nudging_qt, input_force_height(:,i), scm_input%input_k_qt_nudge(i)) if (scm_input%input_k_qt_nudge(i) < 0) then @@ -2522,7 +2521,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) scm_input%input_k_qt_nudge(i) = input_n_lev end if end do - else if (z_nudging_rv > 0) then + else if (z_nudging_rv > 0) then do i=1, input_n_forcing_times call find_vertical_index_height(z_nudging_rv, input_force_height(:,i), scm_input%input_k_qt_nudge(i)) if (scm_input%input_k_qt_nudge(i) < 0) then @@ -2550,7 +2549,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) scm_input%input_k_qt_nudge(i) = input_n_lev end if end do - else if (z_nudging_rt > 0) then + else if (z_nudging_rt > 0) then do i=1, input_n_forcing_times call find_vertical_index_height(z_nudging_rt, input_force_height(:,i), scm_input%input_k_qt_nudge(i)) if (scm_input%input_k_qt_nudge(i) < 0) then @@ -2562,7 +2561,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) scm_input%input_k_qt_nudge = 1 end if end if - + if (nudging_u > 0) then do i=1, input_n_forcing_times scm_input%input_u_nudge(i,:) = input_force_u_nudging(:,i) @@ -2577,8 +2576,8 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) scm_input%input_k_u_nudge(i) = input_n_lev end if end do - else if (z_nudging_u > 0) then - do i=1, input_n_forcing_times + else if (z_nudging_u > 0) then + do i=1, input_n_forcing_times call find_vertical_index_height(z_nudging_u, input_force_height(:,i), scm_input%input_k_u_nudge(i)) if (scm_input%input_k_u_nudge(i) < 0) then !if the vertical index is not found (when it is less than 0), set the nudging index to the top of the input profile so that nudging is turned off @@ -2589,7 +2588,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) scm_input%input_k_u_nudge = 1 end if end if - + if (nudging_v > 0) then do i=1, input_n_forcing_times scm_input%input_v_nudge(i,:) = input_force_v_nudging(:,i) @@ -2604,7 +2603,7 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) scm_input%input_k_v_nudge(i) = input_n_lev end if end do - else if (z_nudging_v > 0) then + else if (z_nudging_v > 0) then do i=1, input_n_forcing_times call find_vertical_index_height(z_nudging_v, input_force_height(:,i), scm_input%input_k_v_nudge(i)) if (scm_input%input_k_v_nudge(i) < 0) then @@ -2616,14 +2615,14 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) scm_input%input_k_v_nudge = 1 end if end if - + end subroutine get_case_init_DEPHY !> Subroutine to get reference profile to use above the case data (temporarily hard-coded profile) subroutine get_reference_profile(scm_state, scm_reference) use scm_type_defs, only : scm_state_type, scm_reference_type use NetCDF_read, only: check - + type(scm_state_type), target, intent(in) :: scm_state type(scm_reference_type), target, intent(inout) :: scm_reference @@ -2646,7 +2645,7 @@ subroutine get_reference_profile(scm_state, scm_reference) if(ioerror /= 0) then write(*,*) 'There was an error opening the file McCprofiles.dat in the processed_case_input directory. & Error code = ',ioerror - stop + error stop "There was an error opening the file McCprofiles.dat in the processed_case_input directory." endif ! find number of records @@ -2756,7 +2755,7 @@ subroutine get_tracers(tracer_names, tracer_types) else write(*,'(a,i0)') 'There was an error opening the file ' // FILE_NAME // & '; error code = ', rc - stop + error stop "Error opening tracers file" end if close (fu) diff --git a/scm/src/scm_setup.F90 b/scm/src/scm_setup.F90 index 5f4423e29..811844dc0 100644 --- a/scm/src/scm_setup.F90 +++ b/scm/src/scm_setup.F90 @@ -31,34 +31,34 @@ subroutine set_state(scm_input, scm_reference, scm_state) real(kind=dp), dimension(scm_input%input_nlev) :: input_qv, input_T real(kind=dp), parameter :: p0 = 1.0E5 real(kind=dp) :: deg_to_rad_const - + deg_to_rad_const = con_pi/180.0 !> \section set_state_alg Algorithm !! @{ - + !> - Set the longitude and latitude and convert from degrees to radians do i=1, scm_state%n_cols scm_state%lon(i) = scm_input%input_lon*deg_to_rad_const scm_state%lat(i) = scm_input%input_lat*deg_to_rad_const end do - - + + !> - \todo When patching in a reference sounding, need to handle the case when the reference sounding is too short; patch_in_ref !! checks for the case, but as of now, it just extrapolates where it needs to and returns an error code; error should be handled !! here or passed up to the main program. - + if (.NOT. scm_state%model_ics) then ! not a model - + if (scm_state%input_type == 0) then !> - Calculate water vapor from total water, suspended liquid water, and suspended ice. input_qv = scm_input%input_qt - scm_input%input_ql - scm_input%input_qi else input_qv = scm_input%input_qv end if - + !> - For each column, interpolate the water vapor to the model grid. do i=1, scm_state%n_cols call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres, input_qv, scm_state%pres_l(i,:), & @@ -70,7 +70,7 @@ subroutine set_state(scm_input, scm_reference, scm_state) scm_state%state_tracer(i,:,scm_state%water_vapor_index,1), grid_error) end if end do - + if (scm_state%input_type == 0) then !> - Calculate the input absolute temperature from input pressure, theta_il, ql, and qi. input_T = (scm_input%input_pres/p0)**con_rocp*(scm_input%input_thetail + (con_hvap/con_cp)*scm_input%input_ql + & @@ -83,7 +83,7 @@ subroutine set_state(scm_input, scm_reference, scm_state) (con_hfus/con_cp)*scm_input%input_qi) end if end if - + !> - For each column, interpolate the temperature to the model grid. do i=1, scm_state%n_cols call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres, input_T, scm_state%pres_l(i,:), & @@ -94,7 +94,7 @@ subroutine set_state(scm_input, scm_reference, scm_state) scm_reference%ref_T, scm_state%pres_l(i,:), scm_state%n_levels, scm_state%state_T(i,:,1), grid_error) end if end do - + !> - For each column, interpolate the u-wind to the model grid. do i=1, scm_state%n_cols call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres, scm_input%input_u, scm_state%pres_l(i,:), & @@ -106,7 +106,7 @@ subroutine set_state(scm_input, scm_reference, scm_state) end do end if end do - + !> - For each column, interpolate the v-wind to the model grid. do i=1, scm_state%n_cols call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres, scm_input%input_v, scm_state%pres_l(i,:), & @@ -118,7 +118,7 @@ subroutine set_state(scm_input, scm_reference, scm_state) end do end if end do - + !> - For each column, interpolate the ozone to the model grid. if(scm_state%ozone_index > 0) then do i=1, scm_state%n_cols @@ -132,7 +132,7 @@ subroutine set_state(scm_input, scm_reference, scm_state) end if end do end if - + !> - For each column, interpolate the cloud liquid water to the model grid. do i=1, scm_state%n_cols call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres, scm_input%input_ql, scm_state%pres_l(i,:), & @@ -142,7 +142,7 @@ subroutine set_state(scm_input, scm_reference, scm_state) scm_state%state_tracer(i,last_index_init+1:,scm_state%cloud_water_index,1) = 0.0 end if end do - + !> - For each column, interpolate the cloud ice water to the model grid. do i=1, scm_state%n_cols call interpolate_to_grid_centers(scm_input%input_nlev, scm_input%input_pres, scm_input%input_qi, scm_state%pres_l(i,:), & @@ -160,14 +160,14 @@ subroutine set_state(scm_input, scm_reference, scm_state) scm_state%state_T(i,:,1) = scm_input%input_temp(:) scm_state%state_tracer(i,:,scm_state%water_vapor_index,1)=scm_input%input_qt scm_state%state_tracer(i,:,scm_state%ozone_index,1)=scm_input%input_ozone - scm_state%area(i) = scm_input%input_area - + scm_state%area(i) = scm_input%input_area + if (scm_input%input_pres_i(1).GT. 0.0) then ! pressure are read in, overwrite values scm_state%pres_i(i,:)=scm_input%input_pres_i scm_state%pres_l(i,:)=scm_input%input_pres_l endif enddo - + endif !> @} end subroutine set_state @@ -291,8 +291,8 @@ subroutine GFS_suite_setup (Model, Statein, Stateout, Sfcprop, GFS_radtend_type, GFS_diag_type use CCPP_typedefs, only: GFS_interstitial_type use physcons, only: pi => con_pi - - + + !use cldwat2m_micro, only: ini_micro !use aer_cloud, only: aer_cloud_init !use module_ras, only: ras_init @@ -312,13 +312,13 @@ subroutine GFS_suite_setup (Model, Statein, Stateout, Sfcprop, type(GFS_init_type), intent(in) :: Init_parm integer, intent(in) :: ntasks, nthreads, n_cols - + real(kind=dp), dimension(n_cols), intent(in) :: lon, lat, area - + real(kind=dp), parameter :: rad2deg = 180.0_dp/pi - + integer :: i - + !--- set control properties (including namelist read) call Model%init (Init_parm%nlunit, Init_parm%fn_nml, & Init_parm%me, Init_parm%master, & @@ -336,7 +336,7 @@ subroutine GFS_suite_setup (Model, Statein, Stateout, Sfcprop, Init_parm%fcst_mpi_comm, ntasks, nthreads) !--- initialize DDTs - + call Statein%create(n_cols, Model) call Stateout%create(n_cols, Model) call Sfcprop%create(n_cols, Model) @@ -349,10 +349,10 @@ subroutine GFS_suite_setup (Model, Statein, Stateout, Sfcprop, call Diag%create(n_cols, Model) !--- internal representation of interstitials for CCPP physics call Interstitial%create(n_cols, Model) - + !--- populate the grid components !call GFS_grid_populate (Grid(i), Init_parm%xlon, Init_parm%xlat, Init_parm%area) - + do i=1, n_cols Grid%xlon(i) = lon(i) Grid%xlat(i) = lat(i) @@ -363,7 +363,7 @@ subroutine GFS_suite_setup (Model, Statein, Stateout, Sfcprop, Grid%area(i) = area(i) Grid%dx(i) = sqrt(area(i)) end do - + !--- initialize Morrison-Gettleman microphysics !if (Model%ncld == 2) then @@ -377,17 +377,17 @@ subroutine GFS_suite_setup (Model, Statein, Stateout, Sfcprop, !--- lsidea initialization if (Model%lsidea) then print *,' LSIDEA is active but needs to be reworked for FV3 - shutting down' - stop + error stop !--- NEED TO get the logic from the old phys/gloopb.f initialization area endif - + if(Model%do_ca)then print *,'Cellular automata cannot be used when CCPP is turned on until' print *,'the stochastic physics pattern generation code has been pulled' print *,'out of the FV3 repository and updated with the CCPP version.' - stop + error stop endif - + !--- sncovr may not exist in ICs from chgres. !--- FV3GFS handles this as part of the IC ingest !--- this not is placed here to alert users to the need to study diff --git a/scm/src/scm_time_integration.F90 b/scm/src/scm_time_integration.F90 index 4e5743c14..895d70435 100644 --- a/scm/src/scm_time_integration.F90 +++ b/scm/src/scm_time_integration.F90 @@ -11,7 +11,7 @@ module scm_time_integration only: ccpp_physics_timestep_init, & ccpp_physics_run, & ccpp_physics_timestep_finalize - + implicit none @@ -78,10 +78,9 @@ subroutine do_time_step(scm_state, physics, cdata, in_spinup) if (scm_state%input_type == 0) then call apply_forcing_leapfrog(scm_state) else - write(*,*) 'The application of forcing terms from the DEPHY file format has not been implemented for the leapfrog time scheme.' - stop + error stop 'The application of forcing terms from the DEPHY file format has not been implemented for the leapfrog time scheme.' end if - + case default if (scm_state%input_type == 0) then call apply_forcing_forward_Euler(scm_state, in_spinup) @@ -108,19 +107,19 @@ subroutine do_time_step(scm_state, physics, cdata, in_spinup) physics%Diag%dtend(i,:,idtend) = physics%Diag%dtend(i,:,idtend) & + (physics%Statein%ugrs(i,:) - physics%Stateout%gu0(i,:)) endif - + idtend = physics%Model%dtidx(physics%Model%index_of_y_wind,physics%Model%index_of_process_non_physics) if(idtend>=1) then physics%Diag%dtend(i,:,idtend) = physics%Diag%dtend(i,:,idtend) & + (physics%Statein%vgrs(i,:) - physics%Stateout%gv0(i,:)) endif - + idtend = physics%Model%dtidx(physics%Model%index_of_temperature,physics%Model%index_of_process_non_physics) if(idtend>=1) then physics%Diag%dtend(i,:,idtend) = physics%Diag%dtend(i,:,idtend) & + (physics%Statein%tgrs(i,:) - physics%Stateout%gt0(i,:)) endif - + if (physics%Model%qdiag3d) then do itrac=1,physics%Model%ntrac idtend = physics%Model%dtidx(itrac+100,physics%Model%index_of_process_non_physics) @@ -132,13 +131,13 @@ subroutine do_time_step(scm_state, physics, cdata, in_spinup) endif endif enddo - + call ccpp_physics_timestep_init(cdata, suite_name=trim(adjustl(scm_state%physics_suite_name)), ierr=ierr) if (ierr/=0) then write(*,'(a,i0,a)') 'An error occurred in ccpp_physics_timestep_init: ' // trim(cdata%errmsg) // '. Exiting...' - stop + error stop trim(cdata%errmsg) end if - + !--- determine if radiation diagnostics buckets need to be cleared if (nint(physics%Model%fhzero*3600) >= nint(max(physics%Model%fhswr,physics%Model%fhlwr))) then if (mod(physics%Model%kdt,physics%Model%nszero) == 1 .or. physics%Model%nszero == 1) then @@ -150,22 +149,22 @@ subroutine do_time_step(scm_state, physics, cdata, in_spinup) call physics%Diag%rad_zero (physics%Model) endif endif - + !--- determine if physics diagnostics buckets need to be cleared if (mod(physics%Model%kdt,physics%Model%nszero) == 1 .or. physics%Model%nszero == 1) then call physics%Diag%phys_zero (physics%Model) endif - + call ccpp_physics_run(cdata, suite_name=trim(adjustl(scm_state%physics_suite_name)), ierr=ierr) if (ierr/=0) then write(*,'(a,i0,a)') 'An error occurred in ccpp_physics_run: ' // trim(cdata%errmsg) // '. Exiting...' - stop + error stop trim(cdata%errmsg) end if call ccpp_physics_timestep_finalize(cdata, suite_name=trim(adjustl(scm_state%physics_suite_name)), ierr=ierr) if (ierr/=0) then write(*,'(a,i0,a)') 'An error occurred in ccpp_physics_timestep_finalize: ' // trim(cdata%errmsg) // '. Exiting...' - stop + error stop trim(cdata%errmsg) end if !if no physics call, need to transfer state_variables(:,:,1) to state_variables (:,:,2) diff --git a/scm/src/scm_utils.F90 b/scm/src/scm_utils.F90 index ce2183afd..dee65c4d8 100644 --- a/scm/src/scm_utils.F90 +++ b/scm/src/scm_utils.F90 @@ -543,7 +543,7 @@ subroutine check(status, var_name) if(status /= NF90_NOERR) then print *, trim(nf90_strerror(status)),' ',var_name - stop "stopped" + error stop "stopped" end if end subroutine check @@ -560,7 +560,7 @@ subroutine NetCDF_read_att_int(ncid, var_id, att_name, req, att_data) ierr = NF90_INQUIRE_ATTRIBUTE(ncid, var_id, att_name) if (ierr /= NF90_NOERR) then write(*,*) 'There was an error reading the required '//adjustl(trim(att_name))//' attribute. Stopping...' - stop + error stop "There was an error reading the required attribute" else call check(NF90_GET_ATT(ncid, var_id, att_name, att_data),att_name) end if @@ -588,7 +588,7 @@ subroutine NetCDF_read_att_sp(ncid, var_id, att_name, req, att_data) ierr = NF90_INQUIRE_ATTRIBUTE(ncid, var_id, att_name) if (ierr /= NF90_NOERR) then write(*,*) 'There was an error reading the required '//adjustl(trim(att_name))//' attribute. Stopping...' - stop + error stop "There was an error reading the required attribute" else call check(NF90_GET_ATT(ncid, var_id, att_name, att_data),att_name) end if @@ -616,7 +616,7 @@ subroutine NetCDF_read_att_char(ncid, var_id, att_name, req, att_data) ierr = NF90_INQUIRE_ATTRIBUTE(ncid, var_id, att_name) if (ierr /= NF90_NOERR) then write(*,*) 'There was an error reading the required '//adjustl(trim(att_name))//' attribute. Stopping...' - stop + error stop "There was an error reading the required attribute" else call check(NF90_GET_ATT(ncid, var_id, att_name, att_data),att_name) end if @@ -645,7 +645,7 @@ subroutine NetCDF_read_att_char_or_int(ncid, var_id, att_name, req, att_data, ch ierr = NF90_INQUIRE_ATTRIBUTE(ncid, var_id, att_name, xtype = type) if (ierr /= NF90_NOERR) then write(*,*) 'There was an error reading the required '//adjustl(trim(att_name))//' attribute. Stopping...' - stop + error stop "There was an error reading the required attribute" else if (type == NF90_CHAR) then call check(NF90_GET_ATT(ncid, var_id, att_name, char_att_data),att_name) @@ -691,7 +691,7 @@ subroutine NetCDF_conditionally_read_var_1d_sp(var_ctl, var_att, var_name, filen call NetCDF_read_var(ncid, var_name, .False., var_data) if (maxval(var_data) < missing_value_eps) then write(*,*) 'The global attribute '//var_att//' in '//filename//' indicates that the variable '//var_name//' should be present, but it is missing. Stopping ...' - stop + error stop "Missing variable" end if else var_data = missing_value @@ -710,7 +710,7 @@ subroutine NetCDF_conditionally_read_var_2d_sp(var_ctl, var_att, var_name, filen call NetCDF_read_var(ncid, var_name, .False., var_data) if (maxval(var_data) < missing_value_eps) then write(*,*) 'The global attribute '//var_att//' in '//filename//' indicates that the variable '//var_name//' should be present, but it is missing. Stopping ...' - stop + error stop "Missing variable" end if else var_data = missing_value @@ -729,7 +729,7 @@ subroutine NetCDF_conditionally_read_var_3d_sp(var_ctl, var_att, var_name, filen call NetCDF_read_var(ncid, var_name, .False., var_data) if (maxval(var_data) < missing_value_eps) then write(*,*) 'The global attribute '//var_att//' in '//filename//' indicates that the variable '//var_name//' should be present, but it is missing. Stopping ...' - stop + error stop "Missing variable" end if else var_data = missing_value @@ -748,7 +748,7 @@ subroutine NetCDF_conditionally_read_var_4d_sp(var_ctl, var_att, var_name, filen call NetCDF_read_var(ncid, var_name, .False., var_data) if (maxval(var_data) < missing_value_eps) then write(*,*) 'The global attribute '//var_att//' in '//filename//' indicates that the variable '//var_name//' should be present, but it is missing. Stopping ...' - stop + error stop "Missing variable" end if else var_data = missing_value @@ -789,7 +789,7 @@ subroutine NetCDF_def_var(ncid, var_name, var_type, desc, unit, varid, dims) call CHECK(NF90_PUT_ATT(NCID=ncid,VARID=varid,NAME="_FillValue",VALUES=missing_value_int),var_name) else write(0,'(a,i0,a)') "The variable '" // var_name // "' is defined as a type other than NF90_FLOAT or NF90_INT. Stopping..." - STOP + error stop "Variable defined as a type other than NF90_FLOAT or NF90_INT." end if end subroutine NetCDF_def_var @@ -933,7 +933,7 @@ subroutine conditionally_set_int_var_0d(input, set_var, input_name, req, missing else if (req) then write(0,'(a,i0,a)') "The variable '" // input_name // "' in the case data file had missing data, but it is required for the given physics configuration. Stopping..." - STOP + error stop "Variable in the case data file had missing data, but it is required for the given physics configuration." end if end if @@ -953,7 +953,7 @@ subroutine conditionally_set_int_var_1d(input, set_var, input_name, req, missing else if (req) then write(0,'(a,i0,a)') "The variable '" // input_name // "' in the case data file had missing data, but it is required for the given physics configuration. Stopping..." - STOP + error stop "The variable in the case data file had missing data, but it is required for the given physics configuration" end if end if @@ -973,7 +973,7 @@ subroutine conditionally_set_real_dp_var_0d(input, set_var, input_name, req, mis else if (req) then write(0,'(a,i0,a)') "The variable '" // input_name // "' in the case data file had missing data, but it is required for the given physics configuration. Stopping..." - STOP + error stop "The variable in the case data file had missing data, but it is required for the given physics configuration" end if end if @@ -993,7 +993,7 @@ subroutine conditionally_set_real_dp_var_1d(input, set_var, input_name, req, mis else if (req) then write(0,'(a,i0,a)') "The variable '" // input_name // "' in the case data file had missing data, but it is required for the given physics configuration. Stopping..." - STOP + error stop "The variable in the case data file had missing data, but it is required for the given physics configuration" end if end if diff --git a/scm/src/scm_vgrid.F90 b/scm/src/scm_vgrid.F90 index 12ac24fc0..e492824fe 100644 --- a/scm/src/scm_vgrid.F90 +++ b/scm/src/scm_vgrid.F90 @@ -36,16 +36,16 @@ subroutine get_FV3_vgrid(scm_input, scm_state) ! local real(kind=dp) :: pres_sfc_inv, p_ref, ak_tmp, bk_tmp - + real:: p0=1000.E2 real:: pc=200.E2 - + real :: pint = 100.E2 real :: stretch_fac = 1.03 integer :: auto_routine = 0 - + integer k, last_index, mid_index, ierr, dummy, n_levels_file - + character(len=80) :: line character(len=16) :: file_format integer :: nx, ny @@ -55,13 +55,13 @@ subroutine get_FV3_vgrid(scm_input, scm_state) ! single and double precision runs real(kind_scm_sp), parameter :: zero_sp = 0.0 real(kind_scm_sp), allocatable :: pres_l_row_sp(:) - + #include "fv_eta.h" - + km = scm_state%n_levels ptop = 1. ! Definition: press(i,j,k) = ak(k) + bk(k) * ps(i,j) - + if (trim(scm_state%npz_type) == 'superC' .or. trim(scm_state%npz_type) == 'superK') then auto_routine = 1 select case (km) @@ -99,33 +99,33 @@ subroutine get_FV3_vgrid(scm_input, scm_state) auto_routine = 2 end select else if (trim(scm_state%npz_type) == 'input') then - + !> - Open the appropriate file. open(unit=1, file=scm_state%vert_coord_file, status='old', action='read', iostat=ierr) if(ierr /= 0) then write(*,*) 'There was an error opening the file ', scm_state%vert_coord_file, ' in the run directory. & Error code = ',ierr - stop + error stop endif - + !> The file being read in must have the following format: !! include a single line description: number of coefficients, number of layers !! ak/bk pairs, with each pair occupying a single line !! the pairs must be ordered from surface to TOA !! the pairs define the interfaces of the grid to create levels-1 layer - - !> - The first line contains the number of coefficients and number of levels + + !> - The first line contains the number of coefficients and number of levels read(1,*) dummy, n_levels_file if (n_levels_file /= scm_state%n_levels) then write(*,*) 'There is a mismatch in the number of levels expected and the number of coefficients supplied in the file ',scm_state%vert_coord_file - stop + error stop end if - !> - Read in the coefficient data. + !> - Read in the coefficient data. do k=1, km+1 read(1,*) scm_state%a_k(k), scm_state%b_k(k) end do close(1) - + ! flip scm_state%a_k, scm_state%b_k in vertical (a_k and b_k are expected to be TOA-to-surface at this point) mid_index = (km+1)/2 last_index = km+1 @@ -138,7 +138,7 @@ subroutine get_FV3_vgrid(scm_input, scm_state) scm_state%b_k(last_index) = bk_tmp last_index = last_index - 1 end do - + else select case (km) case (5,10) ! does this work???? @@ -217,7 +217,7 @@ subroutine get_FV3_vgrid(scm_input, scm_state) pint = 100.E2 stretch_fac = 1.035 auto_routine = 1 - case (47) + case (47) if (trim(scm_state%npz_type) == 'lowtop') then ptop = 100. stretch_fac = 1.035 @@ -504,7 +504,7 @@ subroutine get_FV3_vgrid(scm_input, scm_state) endif end select endif ! superC/superK - + select case (auto_routine) case (1) call var_hi(km, scm_state%a_k, scm_state%b_k, ptop, ks, pint, stretch_fac) @@ -519,7 +519,7 @@ subroutine get_FV3_vgrid(scm_input, scm_state) case (6) call var_gfs(km, scm_state%a_k, scm_state%b_k, ptop, ks, pint, stretch_fac) end select - + call check_eta_levels (scm_state%a_k, scm_state%b_k) if (verbose) then @@ -528,7 +528,7 @@ subroutine get_FV3_vgrid(scm_input, scm_state) write(*,'(I4, F13.5, F13.5, F11.2)') k, scm_state%a_k(k), scm_state%b_k(k), 1000.E2*scm_state%b_k(k) + scm_state%a_k(k) enddo endif - + !> - Calculate interface pressures, sigma, and exner function. ! flip scm_state%a_k, scm_state%b_k in vertical @@ -905,7 +905,7 @@ subroutine var_hi2(km, ak, bk, ptop, ks, pint, s_rate) end subroutine var_hi2 - + subroutine var_les(km, ak, bk, ptop, ks, pint, s_rate) implicit none integer, intent(in):: km @@ -1065,7 +1065,7 @@ subroutine var_les(km, ak, bk, ptop, ks, pint, s_rate) 800 format(1x,5(1x,f9.4)) end subroutine var_les - + subroutine mount_waves(km, ak, bk, ptop, ks, pint) integer, intent(in):: km real, intent(out):: ak(km+1), bk(km+1) @@ -1586,7 +1586,7 @@ subroutine check_eta_levels(ak, bk) enddo endif write(*,*) 'FV3 check_eta_levels: ak/bk pairs do not provide a monotonic vertical coordinate' - stop + error stop endif end subroutine check_eta_levels From ae787929b148f255fe25e83935c19b96c5246020 Mon Sep 17 00:00:00 2001 From: Soren Rasmussen Date: Thu, 25 Jul 2024 11:48:26 -0600 Subject: [PATCH 21/40] Docker will checkout PR if being run during PR CI --- .github/workflows/ci_test_docker.yml | 4 +++- docker/Dockerfile | 23 +++++++++++++++++------ scm/src/run_scm.py | 12 ++++++------ 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci_test_docker.yml b/.github/workflows/ci_test_docker.yml index 51991a10d..730a5381c 100644 --- a/.github/workflows/ci_test_docker.yml +++ b/.github/workflows/ci_test_docker.yml @@ -4,6 +4,7 @@ on: [pull_request,workflow_dispatch] env: TEST_TAG: dtcenter/ccpp-scm:test + PR_NUMBER: ${{ github.event.number }} jobs: docker: @@ -22,8 +23,9 @@ jobs: file: docker/Dockerfile load: true tags: ${{ env.TEST_TAG }} + build-args: PR_NUMBER=${{ github.event.number }} - name: Test run: | mkdir $HOME/output chmod a+rw $HOME/output - docker run --rm -v $HOME/output:/home ${{ env.TEST_TAG }} ./run_scm.py -f ../../test/rt_test_cases.py --runtime_mult 0.1 -d -a + docker run --rm -v $HOME/output:/home ${{ env.TEST_TAG }} ./run_scm.py -f ../../test/rt_test_cases.py --runtime_mult 0.1 -d --stop_on_error diff --git a/docker/Dockerfile b/docker/Dockerfile index 85ad4d856..f269fff5f 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,8 +1,10 @@ FROM debian:12 LABEL maintainer="Michael Kavulich " -# Set up base OS environment +# arguments that can be passed in +ARG PR_NUMBER +# Set up base OS environment RUN apt-get -y update # Get "essential" tools and libraries @@ -70,11 +72,20 @@ ENV sp_ROOT=/comsoftware/nceplibs ENV w3emc_ROOT=/comsoftware/nceplibs # Obtain CCPP SCM source code, build code, and download static data -RUN cd /comsoftware \ - && git clone --recursive -b main https://github.com/NCAR/ccpp-scm \ - && mkdir /comsoftware/ccpp-scm/scm/bin - -RUN cd /comsoftware/ccpp-scm/scm/bin \ +RUN if [ -z "$PR_NUMBER" ]; then \ + cd /comsoftware \ + && git clone --recursive -b main https://github.com/NCAR/ccpp-scm; \ + else \ + cd /comsoftware \ + && git clone https://github.com/NCAR/ccpp-scm \ + && cd ccpp-scm \ + && git fetch origin pull/${PR_NUMBER}/head:test_pr \ + && git checkout test_pr \ + && git submodule update --init --recursive; \ + fi + +RUN mkdir /comsoftware/ccpp-scm/scm/bin \ + && cd /comsoftware/ccpp-scm/scm/bin \ && cmake ../src \ && make -j diff --git a/scm/src/run_scm.py b/scm/src/run_scm.py index 35222f168..40c658843 100755 --- a/scm/src/run_scm.py +++ b/scm/src/run_scm.py @@ -34,6 +34,7 @@ # Default command string to run MPI apps (number of processes should be 1 since SCM is not set up to use more than 1 yet) DEFAULT_MPI_COMMAND = 'mpirun -np 1' + # Copy executable to run directory if true (otherwise it will be linked) COPY_EXECUTABLE = False @@ -120,7 +121,7 @@ parser.add_argument('--n_itt_out', help='period of instantaneous output (number of timesteps)', required=False, type=int) parser.add_argument('--n_itt_diag', help='period of diagnostic output (number of timesteps)', required=False, type=int) parser.add_argument('-dt', '--timestep', help='timestep (s)', required=False, type=float) -parser.add_argument('-a', '--actions', help='if running from Github Actions this will select correct configuration', required=False, action='store_true') +parser.add_argument('--stop_on_error', help='when running multiple SCM runs, stop on first error', required=False, action='store_true') parser.add_argument('-v', '--verbose', help='set logging level to debug and write log to file', action='count', default=0) parser.add_argument('-f', '--file', help='name of file where SCM runs are defined') parser.add_argument('--mpi_command', help='command used to invoke the executable via MPI (including options)', required=False) @@ -191,14 +192,14 @@ def parse_arguments(): bin_dir = args.bin_dir timestep = args.timestep mpi_command = args.mpi_command - github_actions = args.actions + stop_on_error = args.stop_on_error if not sdf: sdf = DEFAULT_SUITE return (file, case, sdf, namelist, tracers, gdb, runtime, runtime_mult, docker, \ verbose, levels, npz_type, vert_coord_file, case_data_dir, n_itt_out, \ - n_itt_diag, run_dir, bin_dir, timestep, mpi_command, github_actions) + n_itt_diag, run_dir, bin_dir, timestep, mpi_command, stop_on_error) def find_gdb(): """Detect gdb, abort if not found""" @@ -767,7 +768,7 @@ def copy_outdir(exp_dir): def main(): (file, case, sdf, namelist, tracers, use_gdb, runtime, runtime_mult, docker, \ verbose, levels, npz_type, vert_coord_file, case_data_dir, n_itt_out, \ - n_itt_diag, run_dir, bin_dir, timestep, mpi_command, github_actions) = parse_arguments() + n_itt_diag, run_dir, bin_dir, timestep, mpi_command, stop_on_error) = parse_arguments() setup_logging(verbose) @@ -884,8 +885,7 @@ def main(): l_ignore_error = MULTIRUN_IGNORE_ERROR else: l_ignore_error = False - # need to correctly fail if running Github Actions - if github_actions: + if stop_on_error: l_ignore_error = False (status, time_elapsed) = launch_executable(use_gdb, gdb, mpi_command, ignore_error = l_ignore_error) From f935b13a09d19f784520232ee7a364c00ad9e72a Mon Sep 17 00:00:00 2001 From: Soren Rasmussen Date: Fri, 26 Jul 2024 12:55:26 -0600 Subject: [PATCH 22/40] Print summary of failed cases and exit it with an error if a failed cases exists Continue docker run so report of all failed tests gets produced. --- .github/workflows/ci_test_docker.yml | 2 +- scm/src/run_scm.py | 54 +++++++++++++++++++++++----- 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci_test_docker.yml b/.github/workflows/ci_test_docker.yml index 730a5381c..b1dd5e747 100644 --- a/.github/workflows/ci_test_docker.yml +++ b/.github/workflows/ci_test_docker.yml @@ -28,4 +28,4 @@ jobs: run: | mkdir $HOME/output chmod a+rw $HOME/output - docker run --rm -v $HOME/output:/home ${{ env.TEST_TAG }} ./run_scm.py -f ../../test/rt_test_cases.py --runtime_mult 0.1 -d --stop_on_error + docker run --rm -v $HOME/output:/home ${{ env.TEST_TAG }} ./run_scm.py -f ../../test/rt_test_cases.py --runtime_mult 0.1 -d diff --git a/scm/src/run_scm.py b/scm/src/run_scm.py index 40c658843..c0febaa48 100755 --- a/scm/src/run_scm.py +++ b/scm/src/run_scm.py @@ -3,6 +3,7 @@ import argparse import f90nml import logging +import numpy as np import os import re import shutil @@ -156,17 +157,18 @@ def execute(cmd, ignore_error = False): stderr = subprocess.PIPE, shell = True) (stdout, stderr) = p.communicate() status = p.returncode + message = 'Execution of "{0}" returned with exit code {1}\n'.format(cmd, status) + message += ' stdout: "{0}"\n'.format(stdout.decode(encoding='ascii', errors='ignore').rstrip('\n')) + message += ' stderr: "{0}"'.format(stderr.decode(encoding='ascii', errors='ignore').rstrip('\n')) + if status == 0: - message = 'Execution of "{0}" returned with exit code {1}\n'.format(cmd, status) - message += ' stdout: "{0}"\n'.format(stdout.decode(encoding='ascii', errors='ignore').rstrip('\n')) - message += ' stderr: "{0}"'.format(stderr.decode(encoding='ascii', errors='ignore').rstrip('\n')) logging.debug(message) elif not ignore_error: - message = 'Execution of command "{0}" failed, exit code {1}\n'.format(cmd, status) - message += ' stdout: "{0}"\n'.format(stdout.decode(encoding='ascii', errors='ignore').rstrip('\n')) - message += ' stderr: "{0}"'.format(stderr.decode(encoding='ascii', errors='ignore').rstrip('\n')) logging.critical(message) raise Exception('Execution of command "{0}" failed, exit code {1}\n'.format(cmd, status)) + else: + print("SHOULD PRINT ERROR MESSAGE: status and ignore error ==", status, ignore_error) + logging.error(message) return (status, stdout.decode(encoding='ascii', errors='ignore').rstrip('\n'), stderr.decode(encoding='ascii', errors='ignore').rstrip('\n')) def parse_arguments(): @@ -765,6 +767,30 @@ def copy_outdir(exp_dir): shutil.rmtree(home_output_dir) shutil.copytree(exp_dir, home_output_dir) +def print_error_report(error_logs, total_count): + case_l = len(max(error_logs[:,0], key=len)) + suite_l = len(max(error_logs[:,1], key=len)) + namelist_l = len(max(error_logs[:,2], key=len)) + status_l = len(max(error_logs[:,3], key=len)) + # error_log contains header, subtracting 1 from error + error_count = error_logs.shape[0] - 1 + passing_count = total_count - error_count + header_printed = False + column_width = (case_l + suite_l + namelist_l + status_l + 13) + + # print formatted asummary + print("Failure Summary:") + print("-" * column_width) + for error_log in error_logs: + case_s, suite, namelist, status = error_log + print(f"| {case_s:<{case_l}} | {suite:<{suite_l}} | {namelist:<{namelist_l}} | {status:<{status_l}} |") + if not header_printed: + print("-" * column_width) + header_printed = True + print("-" * column_width) + print(f"[{error_count}/{total_count}] failed cases, [{passing_count}/{total_count}] passing cases") + + def main(): (file, case, sdf, namelist, tracers, use_gdb, runtime, runtime_mult, docker, \ verbose, levels, npz_type, vert_coord_file, case_data_dir, n_itt_out, \ @@ -822,6 +848,8 @@ def main(): if (tracers != None): run_list[0]["tracers"] = tracers # Loop through all input "run dictionaires" + error_logs = [["Failed Case", "Suite", "Namelist", "Status"]] + failed_case = False irun = 0 for run in run_list: @@ -894,13 +922,23 @@ def main(): logging.info('Process "(case={0}, suite={1}, namelist={2}" completed successfully'. \ format(run["case"], run["suite"], active_suite.namelist)) else: - logging.warning('Process "(case={0}, suite={1}, namelist={2}" exited with code {3}'. \ - format( run["case"], run["suite"], active_suite.namelist, status)) + failed_case = True + error_str = 'Process "(case={0}, suite={1}, namelist={2}" exited with code {3}'. \ + format( run["case"], run["suite"], active_suite.namelist, status) + logging.warning(error_str) + error_logs = np.append(error_logs, + [[run["case"], run["suite"], active_suite.namelist, status]], + axis=0) # if time_elapsed: logging.info(' Elapsed time: {0}s'.format(time_elapsed)) if docker: copy_outdir(exp_dir) + if (failed_case): + print_error_report(error_logs, len(run_list)) + sys.exit(1) + + if __name__ == '__main__': main() From b394f933c222d9b26f798b4e06dbe1b816d46e6d Mon Sep 17 00:00:00 2001 From: Soren Rasmussen Date: Fri, 26 Jul 2024 15:36:44 -0600 Subject: [PATCH 23/40] Printing formatted string for each experiment to making searching CI output easy --- scm/src/run_scm.py | 56 ++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 47 insertions(+), 9 deletions(-) diff --git a/scm/src/run_scm.py b/scm/src/run_scm.py index c0febaa48..87d2020c5 100755 --- a/scm/src/run_scm.py +++ b/scm/src/run_scm.py @@ -167,7 +167,6 @@ def execute(cmd, ignore_error = False): logging.critical(message) raise Exception('Execution of command "{0}" failed, exit code {1}\n'.format(cmd, status)) else: - print("SHOULD PRINT ERROR MESSAGE: status and ignore error ==", status, ignore_error) logging.error(message) return (status, stdout.decode(encoding='ascii', errors='ignore').rstrip('\n'), stderr.decode(encoding='ascii', errors='ignore').rstrip('\n')) @@ -767,11 +766,19 @@ def copy_outdir(exp_dir): shutil.rmtree(home_output_dir) shutil.copytree(exp_dir, home_output_dir) -def print_error_report(error_logs, total_count): - case_l = len(max(error_logs[:,0], key=len)) - suite_l = len(max(error_logs[:,1], key=len)) - namelist_l = len(max(error_logs[:,2], key=len)) - status_l = len(max(error_logs[:,3], key=len)) + +def print_report_line(case_s, suite, namelist, max_str_lens): + case_l = max_str_lens.case + suite_l = max_str_lens.suite + namelist_l = max_str_lens.namelist + logging.info(f"| {case_s:<{case_l}} | {suite:<{suite_l}} | {namelist:<{namelist_l}} |") + + +def print_error_report(error_logs, total_count, max_str_lens): + case_l = max_str_lens.case + suite_l = max_str_lens.suite + namelist_l = max_str_lens.namelist + status_l = max_str_lens.status # error_log contains header, subtracting 1 from error error_count = error_logs.shape[0] - 1 passing_count = total_count - error_count @@ -791,6 +798,32 @@ def print_error_report(error_logs, total_count): print(f"[{error_count}/{total_count}] failed cases, [{passing_count}/{total_count}] passing cases") +class MaxStrLengths: + def __init__(self, max_case_len, max_suite_len, + max_namelist_len, max_status_len): + self.case = max_case_len + self.suite = max_suite_len + self.namelist = max_namelist_len + self.status = max_status_len + + +def find_max_str_lengths(run_list): + max_case_len = 0 + max_suite_len = 0 + max_status_len = len('status') + + # Loop through the list of dictionaries to find the longest lengths + for item in run_list: + max_case_len = max(max_case_len, len(item['case'])) + max_suite_len = max(max_suite_len, len(item['suite'])) + + # add 6, e.g. diff between len('SCM_HRRR_gf') and len('input_HRRR_gf.nml') + max_namelist_len = max_suite_len + 6 + max_str_lens = MaxStrLengths(max_case_len, max_suite_len, + max_namelist_len, max_status_len) + return max_str_lens + + def main(): (file, case, sdf, namelist, tracers, use_gdb, runtime, runtime_mult, docker, \ verbose, levels, npz_type, vert_coord_file, case_data_dir, n_itt_out, \ @@ -847,15 +880,19 @@ def main(): if (namelist != None): run_list[0]["namelist"] = namelist if (tracers != None): run_list[0]["tracers"] = tracers - # Loop through all input "run dictionaires" + + # setup variables error_logs = [["Failed Case", "Suite", "Namelist", "Status"]] + max_str_lens = find_max_str_lengths(run_list) failed_case = False irun = 0 + + # Loop through all input "run dictionaires" for run in run_list: # # Is this a "supported" SCM configuration? - # (e.g Do we have defualt namelist and tracer files for this suite?) + # (e.g Do we have default namelist and tracer files for this suite?) # If supported, copy default configuration, modify below if necessary. # active_suite = None @@ -902,6 +939,7 @@ def main(): # # Run the SCM case # + print_report_line(run["case"], run["suite"], active_suite.namelist, max_str_lens) logging.info('Executing process {0} of {1}: case={2}, suite={3}, namelist={4}'.format( irun, len(run_list), run["case"], run["suite"], active_suite.namelist)) # @@ -936,7 +974,7 @@ def main(): copy_outdir(exp_dir) if (failed_case): - print_error_report(error_logs, len(run_list)) + print_error_report(error_logs, len(run_list), max_str_lens) sys.exit(1) From 1a54e8de500a2616ba8e3955fafbd24cd70f2a3d Mon Sep 17 00:00:00 2001 From: Soren Rasmussen Date: Fri, 2 Aug 2024 11:36:06 -0600 Subject: [PATCH 24/40] CCPP Physics branch: bugfix/scm-rts --- ccpp/physics | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ccpp/physics b/ccpp/physics index 62f7656eb..e2f4a6368 160000 --- a/ccpp/physics +++ b/ccpp/physics @@ -1 +1 @@ -Subproject commit 62f7656ebdaa39d989413e5d285ed6d6723eb4de +Subproject commit e2f4a63682c679660f0fd334b34e7c5c8c4042d4 From 6fe54a5904699f17872435e45a07d6d717891078 Mon Sep 17 00:00:00 2001 From: "Michael J. Kavulich, Jr" Date: Thu, 8 Aug 2024 20:01:58 -0500 Subject: [PATCH 25/40] Convert enormous regular string to multi-line f-string. This is much shorter and will make list maintenance less of a hassle if changes are needed --- scm/etc/scripts/dephy_converter.py | 380 +++++++++++++---------------- 1 file changed, 175 insertions(+), 205 deletions(-) diff --git a/scm/etc/scripts/dephy_converter.py b/scm/etc/scripts/dephy_converter.py index 4dba44be8..6f9128fdc 100755 --- a/scm/etc/scripts/dephy_converter.py +++ b/scm/etc/scripts/dephy_converter.py @@ -251,211 +251,181 @@ def __init__(self, name, missing_value, time, levels, soil_depth, lat, lon, slms self._lh_flux_sfc = lh_flux_sfc def __repr__(self): - return "Case_Data \n Globals: \n" \ - " name:% s \n" \ - " missing_value:% s \n" \ - " Dimensions: \n" \ - " time:% s \n" \ - " levels: % s \n" \ - " soil_depth: % s \n" \ - " Scalars: \n" \ - " lat: % s \n" \ - " lon: % s \n" \ - " area: % s \n" \ - " slmsk: % s \n" \ - " vegsrc: % s \n" \ - " vegtyp: % s \n" \ - " soiltyp: % s \n" \ - " scolor: % s \n" \ - " slopetyp: % s \n" \ - " tsfco: % s \n" \ - " vegfrac: % s \n" \ - " shdmin: % s \n" \ - " shdmax: % s \n" \ - " canopy: % s \n" \ - " hice: % s \n" \ - " fice: % s \n" \ - " tisfc: % s \n" \ - " snowd: % s \n" \ - " snoalb: % s \n" \ - " tg3: % s \n" \ - " uustar: % s \n" \ - " alvsf: % s \n" \ - " alnsf: % s \n" \ - " alvwf: % s \n" \ - " alnwf: % s \n" \ - " facsf: % s \n" \ - " facwf: % s \n" \ - " weasd: % s \n" \ - " f10m: % s \n" \ - " t2m: % s \n" \ - " q2m: % s \n" \ - " ffmm: % s \n" \ - " ffhh: % s \n" \ - " tprcp: % s \n" \ - " srflag: % s \n" \ - " sncovr: % s \n" \ - " tsfcl: % s \n" \ - " zorl: % s \n" \ - " zorll: % s \n" \ - " zorli: % s \n" \ - " zorlw: % s \n" \ - " zorlwav: % s \n" \ - " tvxy: % s \n" \ - " tgxy: % s \n" \ - " tahxy: % s \n" \ - " canicexy: % s \n" \ - " canliqxy: % s \n" \ - " eahxy: % s \n" \ - " cmxy: % s \n" \ - " chxy: % s \n" \ - " fwetxy: % s \n" \ - " sneqvoxy: % s \n" \ - " alboldxy: % s \n" \ - " qsnowxy: % s \n" \ - " wslakexy: % s \n" \ - " taussxy: % s \n" \ - " waxy: % s \n" \ - " wtxy: % s \n" \ - " zwtxy: % s \n" \ - " xlaixy: % s \n" \ - " xsaixy: % s \n" \ - " lfmassxy: % s \n" \ - " stmassxy: % s \n" \ - " rtmassxy: % s \n" \ - " woodxy: % s \n" \ - " stblcpxy: % s \n" \ - " fastcpxy: % s \n" \ - " smcwtdxy: % s \n" \ - " deeprechxy: % s \n" \ - " rechxy: % s \n" \ - " snowxy: % s \n" \ - " wetness: % s \n" \ - " clw_surf_land: % s \n" \ - " clw_surf_ice: % s \n" \ - " qwv_surf_land: % s \n" \ - " qwv_surf_ice: % s \n" \ - " tsnow_land: % s \n" \ - " tsnow_ice: % s \n" \ - " snowfallac_land: % s \n" \ - " snowfallac_ice: % s \n" \ - " sncovr_ice: % s \n" \ - " sfalb_lnd: % s \n" \ - " sfalb_lnd_bck: % s \n" \ - " emis_ice: % s \n" \ - " lai: % s \n" \ - " stddev: % s \n" \ - " convexity: % s \n" \ - " oa1: % s \n" \ - " oa2: % s \n" \ - " oa3: % s \n" \ - " oa4: % s \n" \ - " ol1: % s \n" \ - " ol2: % s \n" \ - " ol3: % s \n" \ - " ol4: % s \n" \ - " theta_oro: % s \n" \ - " gamma: % s \n" \ - " sigma: % s \n" \ - " elvmax: % s \n" \ - " oro: % s \n" \ - " oro_uf: % s \n" \ - " landfrac: % s \n" \ - " lakefrac: % s \n" \ - " lakedepth: % s \n" \ - " tref: % s \n" \ - " z_c: % s \n" \ - " c_0: % s \n" \ - " c_d: % s \n" \ - " w_0: % s \n" \ - " w_d: % s \n" \ - " xt: % s \n" \ - " xs: % s \n" \ - " xu: % s \n" \ - " xv: % s \n" \ - " xz: % s \n" \ - " zm: % s \n" \ - " xtts: % s \n" \ - " xzts: % s \n" \ - " d_conv: % s \n" \ - " ifd: % s \n" \ - " dt_cool: % s \n" \ - " qrain: % s \n" \ - " Initial: \n" \ - " height: % s \n" \ - " theta_il: % s \n" \ - " t: % s \n" \ - " qt: % s \n" \ - " ql: % s \n" \ - " qi: % s \n" \ - " u: % s \n" \ - " v: % s \n" \ - " tke: %s \n" \ - " ozone: %s \n" \ - " stc: %s \n" \ - " smc: %s \n" \ - " slc: %s \n" \ - " snicexy: % s \n" \ - " snliqxy: % s \n" \ - " tsnoxy: % s \n" \ - " smoiseq: % s \n" \ - " zsnsoxy: % s \n" \ - " tiice: % s \n" \ - " tslb: % s \n" \ - " smois: % s \n" \ - " sh2o: % s \n" \ - " smfr: % s \n" \ - " flfr: % s \n" \ - " Forcing: \n" \ - " p_surf: %s \n" \ - " T_surf: %s \n" \ - " w_ls (time avg): %s \n" \ - " omega (time avg): %s \n" \ - " u_g (time avg): %s \n" \ - " v_g (time avg): %s \n" \ - " u_nudge (time avg): %s \n" \ - " v_nudge (time avg): %s \n" \ - " T_nudge (time avg): %s \n" \ - " thil_nudge (time avg): %s \n" \ - " qt_nudge (time avg): %s \n" \ - " dT_dt_rad (time avg): %s \n" \ - " h_advec_thil (time avg): %s \n" \ - " v_advec_thil (time avg): %s \n" \ - " h_advec_qt (time avg): %s \n" \ - " v_advec_qt (time avg): %s \n" \ - " sh_flux_sfc: %s \n" \ - " lh_flux_sfc: %s \n" \ - % (self._name, self._missing_value, self._time, self._levels, - self._soil_depth, self._lat, self._lon, self._area, self._slmsk, self._vegsrc, - self._vegtyp, self._soiltyp, self._scolor, - self._slopetyp, self._tsfco, self._vegfrac, self._shdmin, - self._shdmax, self._canopy, self._hice, self._fice, self._tisfc, self._snowd, self._snoalb, - self._tg3, self._uustar, self._alvsf, self._alnsf, self._alvwf, self._alnwf, self._facsf, self._facwf, - self._weasd, self._f10m, self._t2m, self._q2m, self._ffmm, self._ffhh, - self._tprcp, self._srflag, self._sncovr, self._tsfcl, self._zorl, self._zorll, self._zorli, self._zorlw, self._zorlwav, - self._tvxy, self._tgxy, self._tahxy, self._canicexy, self._canliqxy, self._eahxy, - self._cmxy, self._chxy, self._fwetxy, self._sneqvoxy, self._alboldxy, self._qsnowxy, self._wslakexy, self._taussxy, - self._waxy, self._wtxy, self._zwtxy, self._xlaixy, self._xsaixy, self._lfmassxy, self._stmassxy, self._rtmassxy, - self._woodxy, self._stblcpxy, self._fastcpxy, self._smcwtdxy, self._deeprechxy, self._rechxy, self._snowxy, - self._wetness, self._clw_surf_land, self._clw_surf_ice, self._qwv_surf_land, self._qwv_surf_ice, self._tsnow_land, self._tsnow_ice, - self._snowfallac_land, self._snowfallac_ice, self._sncovr_ice, self._sfalb_lnd, self._sfalb_lnd_bck, self._emis_ice, self._lai, - self._stddev, self._convexity, self._oa1, self._oa2, self._oa3, self._oa4, self._ol1, self._ol2, self._ol3, self._ol4, - self._theta_oro, self._gamma, self._sigma, self._elvmax, self._oro, self._oro_uf, self._landfrac, self._lakefrac, self._lakedepth, - self._tref, self._z_c, self._c_0, self._c_d, self._w_0, self._w_d, self._xt, self._xs, self._xu, self._xv, self._xz, self._zm, - self._xtts, self._xzts, self._d_conv, self._ifd, self._dt_cool, self._qrain, - self._height, self._theta_il, self._t, - self._qt, self._ql, self._qi, self._u, self._v, - self._tke, self._ozone, self._stc, self._smc, self._slc, self._snicexy, self._snliqxy, self._tsnoxy, - self._smoiseq, self._zsnsoxy, self._tiice, self._tslb, self._smois, self._sh2o, self._smfr, self._flfr, - self._p_surf, self._T_surf, np.mean(self._w_ls, axis=1), - np.mean(self._omega, axis=1), np.mean(self._u_g, axis=1), - np.mean(self._v_g, axis=1), np.mean(self._u_nudge, axis=1), - np.mean(self._v_nudge, axis=1), np.mean(self._T_nudge, axis=1), - np.mean(self._thil_nudge, axis=1),np.mean(self._qt_nudge, axis=1), - np.mean(self._dT_dt_rad, axis=1), - np.mean(self._h_advec_thil, axis=1),np.mean(self._v_advec_thil, axis=1), - np.mean(self._h_advec_qt, axis=1),np.mean(self._v_advec_qt, axis=1), - self._sh_flux_sfc, self._lh_flux_sfc) + return f"""Case_Data + Globals: + name: {self._name} + missing_value: {self._missing_value} + Dimensions: + time: {self._time} + levels: {self._levels} + soil_depth: {self._soil_depth} + Scalars: + lat: {self._lat} + lon: {self._lon} + area: {self._area} + slmsk: {self._slmsk} + vegsrc: {self._vegsrc} + vegtyp: {self._vegtyp} + soiltyp: {self._soiltyp} + scolor: {self._scolor} + slopetyp: {self._slopetyp} + tsfco: {self._tsfco} + vegfrac: {self._vegfrac} + shdmin: {self._shdmin} + shdmax: {self._shdmax} + canopy: {self._canopy} + hice: {self._hice} + fice: {self._fice} + tisfc: {self._tisfc} + snowd: {self._snowd} + snoalb: {self._snoalb} + tg3: {self._tg3} + uustar: {self._uustar} + alvsf: {self._alvsf} + alnsf: {self._alnsf} + alvwf: {self._alvwf} + alnwf: {self._alnwf} + facsf: {self._facsf} + facwf: {self._facwf} + weasd: {self._weasd} + f10m: {self._f10m} + t2m: {self._t2m} + q2m: {self._q2m} + ffmm: {self._ffmm} + ffhh: {self._ffhh} + tprcp: {self._tprcp} + srflag: {self._srflag} + sncovr: {self._sncovr} + tsfcl: {self._tsfcl} + zorl: {self._zorl} + zorll: {self._zorll} + zorli: {self._zorli} + zorlw: {self._zorlw} + zorlwav: {self._zorlwav} + tvxy: {self._tvxy} + tgxy: {self._tgxy} + tahxy: {self._tahxy} + canicexy: {self._canicexy} + canliqxy: {self._canliqxy} + eahxy: {self._eahxy} + cmxy: {self._cmxy} + chxy: {self._chxy} + fwetxy: {self._fwetxy} + sneqvoxy: {self._sneqvoxy} + alboldxy: {self._alboldxy} + qsnowxy: {self._qsnowxy} + wslakexy: {self._wslakexy} + taussxy: {self._taussxy} + waxy: {self._waxy} + wtxy: {self._wtxy} + zwtxy: {self._zwtxy} + xlaixy: {self._xlaixy} + xsaixy: {self._xsaixy} + lfmassxy: {self._lfmassxy} + stmassxy: {self._stmassxy} + rtmassxy: {self._rtmassxy} + woodxy: {self._woodxy} + stblcpxy: {self._stblcpxy} + fastcpxy: {self._fastcpxy} + smcwtdxy: {self._smcwtdxy} + deeprechxy: {self._deeprechxy} + rechxy: {self._rechxy} + snowxy: {self._snowxy} + wetness: {self._wetness} + clw_surf_land: {self._clw_surf_land} + clw_surf_ice: {self._clw_surf_ice} + qwv_surf_land: {self._qwv_surf_land} + qwv_surf_ice: {self._qwv_surf_ice} + tsnow_land: {self._tsnow_land} + tsnow_ice: {self._tsnow_ice} + snowfallac_land: {self._snowfallac_land} + snowfallac_ice: {self._snowfallac_ice} + sncovr_ice: {self._sncovr_ice} + sfalb_lnd: {self._sfalb_lnd} + sfalb_lnd_bck: {self._sfalb_lnd_bck} + emis_ice: {self._emis_ice} + lai: {self._lai} + stddev: {self._stddev} + convexity: {self._convexity} + oa1: {self._oa1} + oa2: {self._oa2} + oa3: {self._oa3} + oa4: {self._oa4} + ol1: {self._ol1} + ol2: {self._ol2} + ol3: {self._ol3} + ol4: {self._ol4} + theta_oro: {self._theta_oro} + gamma: {self._gamma} + sigma: {self._sigma} + elvmax: {self._elvmax} + oro: {self._oro} + oro_uf: {self._oro_uf} + landfrac: {self._landfrac} + lakefrac: {self._lakefrac} + lakedepth: {self._lakedepth} + tref: {self._tref} + z_c: {self._z_c} + c_0: {self._c_0} + c_d: {self._c_d} + w_0: {self._w_0} + w_d: {self._w_d} + xt: {self._xt} + xs: {self._xs} + xu: {self._xu} + xv: {self._xv} + xz: {self._xz} + zm: {self._zm} + xtts: {self._xtts} + xzts: {self._xzts} + d_conv: {self._d_conv} + ifd: {self._ifd} + dt_cool: {self._dt_cool} + qrain: {self._qrain} + Initial: + height: {self._height} + theta_il: {self._theta_il} + t: {self._t} + qt: {self._qt} + ql: {self._ql} + qi: {self._qi} + u: {self._u} + v: {self._v} + tke: {self._tke} + ozone: {self._ozone} + stc: {self._stc} + smc: {self._smc} + slc: {self._slc} + snicexy: {self._snicexy} + snliqxy: {self._snliqxy} + tsnoxy: {self._tsnoxy} + smoiseq: {self._smoiseq} + zsnsoxy: {self._zsnsoxy} + tiice: {self._tiice} + tslb: {self._tslb} + smois: {self._smois} + sh2o: {self._sh2o} + smfr: {self._smfr} + flfr: {self._flfr} + Forcing: + p_surf: {self._p_surf} + T_surf: {self._T_surf} + w_ls (time avg): {np.mean(self._w_ls, axis=1)} + omega (time avg): {np.mean(self._omega, axis=1)} + u_g (time avg): {np.mean(self._u_g, axis=1)} + v_g (time avg): {np.mean(self._v_g, axis=1)} + u_nudge (time avg): {np.mean(self._u_nudge, axis=1)} + v_nudge (time avg): {np.mean(self._v_nudge, axis=1)} + T_nudge (time avg): {np.mean(self._T_nudge, axis=1)} + thil_nudge (time avg): {np.mean(self._thil_nudge, axis=1)} + qt_nudge (time avg): {np.mean(self._qt_nudge, axis=1)} + dT_dt_rad (time avg): {np.mean(self._dT_dt_rad, axis=1)} + h_advec_thil (time avg): {np.mean(self._h_advec_thil, axis=1)} + v_advec_thil (time avg): {np.mean(self._v_advec_thil, axis=1)} + h_advec_qt (time avg): {np.mean(self._h_advec_qt, axis=1)} + v_advec_qt (time avg): {np.mean(self._v_advec_qt, axis=1)} + sh_flux_sfc: {self._sh_flux_sfc} + lh_flux_sfc: {self._lh_flux_sfc}""" def get_case_nml(case_name): """Returns case configuration Fortran namelist""" From 18883a7582bfe5866bb8fb4a2d67676eed07f705 Mon Sep 17 00:00:00 2001 From: "Michael J. Kavulich, Jr" Date: Fri, 9 Aug 2024 12:35:44 -0500 Subject: [PATCH 26/40] - Convert logging level to command-line argument - Fix calls to logging.critical() with no argument --- scm/etc/scripts/dephy_converter.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/scm/etc/scripts/dephy_converter.py b/scm/etc/scripts/dephy_converter.py index 6f9128fdc..bdc1ea31d 100755 --- a/scm/etc/scripts/dephy_converter.py +++ b/scm/etc/scripts/dephy_converter.py @@ -33,6 +33,7 @@ parser = argparse.ArgumentParser() parser.add_argument('-n', '--case_name', help='name of case', required=True) parser.add_argument('-a', '--use_area', help='use column_area namelist attribute as forcing_scale', action='store_true') +parser.add_argument('-d', '--debug', help='enable debugging output', action='store_true') ######################################################################################## @@ -41,18 +42,18 @@ def parse_arguments(): """Parse command line arguments""" args = parser.parse_args() - case_name = args.case_name - use_area = args.use_area - - return (case_name, use_area) + return (args.case_name, args.use_area, args.debug) ######################################################################################## # ######################################################################################## -def setup_logging(): +def setup_logging(debug): """Sets up the logging module.""" - logging.basicConfig(format='%(levelname)s: %(message)s', level=LOGLEVEL) + if debug: + logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO) + else: + logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.DEBUG) class Case_Data(object): def __init__(self, name, missing_value, time, levels, soil_depth, lat, lon, slmsk, vegsrc, vegtyp, soiltyp, \ @@ -2282,7 +2283,7 @@ def write_SCM_case_file(case_nml, case_data, use_area): if (nc_file.adv_ta == forcing_on): message = 'adv_ta is turned on, but is not implemented in the proprietery CCPP SCM case format and cannot be used.' - logging.critical() + logging.critical(message) raise Exception(message) # tnta_adv_var = nc_file.createVariable('tnta_adv', wp, ('time','lev')) # tnta_adv_var.units = 'K s-1' @@ -2291,7 +2292,7 @@ def write_SCM_case_file(case_nml, case_data, use_area): if (nc_file.adv_qv == forcing_on): message = 'adv_qv is turned on, but is not implemented in the proprietery CCPP SCM case format and cannot be used.' - logging.critical() + logging.critical(message) raise Exception(message) # tnqv_adv_var = nc_file.createVariable('tnqv_adv', wp, ('time','lev')) # tnqv_adv_var.units = 'kg kg-1 s-1' @@ -2300,7 +2301,7 @@ def write_SCM_case_file(case_nml, case_data, use_area): if (nc_file.adv_ua == forcing_on): message = 'adv_ua is turned on, but is not implemented in the proprietery CCPP SCM case format and cannot be used.' - logging.critical() + logging.critical(message) raise Exception(message) # tnua_adv_var = nc_file.createVariable('tnua_adv', wp, ('time','lev')) # tnua_adv_var.units = 'm s-2' @@ -2309,7 +2310,7 @@ def write_SCM_case_file(case_nml, case_data, use_area): if (nc_file.adv_va == forcing_on): message = 'adv_va is turned on, but is not implemented in the proprietery CCPP SCM case format and cannot be used.' - logging.critical() + logging.critical(message) raise Exception(message) # tnva_adv_var = nc_file.createVariable('tnva_adv', wp, ('time','lev')) # tnva_adv_var.units = 'm s-2' @@ -2318,7 +2319,7 @@ def write_SCM_case_file(case_nml, case_data, use_area): if (nc_file.adv_theta == forcing_on): message = 'adv_theta is turned on, but is not implemented in the proprietery CCPP SCM case format and cannot be used.' - logging.critical() + logging.critical(message) raise Exception(message) # tntheta_adv_var = nc_file.createVariable('tntheta_adv', wp, ('time','lev')) # tntheta_adv_var.units = 'K s-1' @@ -2345,7 +2346,7 @@ def write_SCM_case_file(case_nml, case_data, use_area): if (nc_file.adv_rv == forcing_on): message = 'adv_rv is turned on, but is not implemented in the proprietery CCPP SCM case format and cannot be used.' - logging.critical() + logging.critical(message) raise Exception(message) # tnrv_adv_var = nc_file.createVariable('tnrv_adv', wp, ('time','lev')) # tnrv_adv_var.units = 'kg kg-1 s-1' @@ -2354,7 +2355,7 @@ def write_SCM_case_file(case_nml, case_data, use_area): if (nc_file.adv_rt == forcing_on): message = 'adv_rt is turned on, but is not implemented in the proprietery CCPP SCM case format and cannot be used.' - logging.critical() + logging.critical(message) raise Exception(message) # tnrt_adv_var = nc_file.createVariable('tnrt_adv', wp, ('time','lev')) # tnrt_adv_var.units = 'kg kg-1 s-1' From 4288c2a0f657a60e86c99390124da615b6ebe683 Mon Sep 17 00:00:00 2001 From: Soren Rasmussen Date: Fri, 9 Aug 2024 13:02:57 -0600 Subject: [PATCH 27/40] Print passing summary as well as the failing summary --- scm/src/run_scm.py | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/scm/src/run_scm.py b/scm/src/run_scm.py index 87d2020c5..520e1fb93 100755 --- a/scm/src/run_scm.py +++ b/scm/src/run_scm.py @@ -774,28 +774,36 @@ def print_report_line(case_s, suite, namelist, max_str_lens): logging.info(f"| {case_s:<{case_l}} | {suite:<{suite_l}} | {namelist:<{namelist_l}} |") -def print_error_report(error_logs, total_count, max_str_lens): +def print_report(logs, total_count, max_str_lens, + passing=False, failing=False): case_l = max_str_lens.case suite_l = max_str_lens.suite namelist_l = max_str_lens.namelist status_l = max_str_lens.status # error_log contains header, subtracting 1 from error - error_count = error_logs.shape[0] - 1 + error_count = logs.shape[0] - 1 passing_count = total_count - error_count header_printed = False column_width = (case_l + suite_l + namelist_l + status_l + 13) - # print formatted asummary - print("Failure Summary:") + # print formatted summary + print("") + if (passing): + print("Passing Summary:") + if (failing): + print("Failure Summary:") print("-" * column_width) - for error_log in error_logs: - case_s, suite, namelist, status = error_log + for log in logs: + case_s, suite, namelist, status = log print(f"| {case_s:<{case_l}} | {suite:<{suite_l}} | {namelist:<{namelist_l}} | {status:<{status_l}} |") if not header_printed: print("-" * column_width) header_printed = True print("-" * column_width) - print(f"[{error_count}/{total_count}] failed cases, [{passing_count}/{total_count}] passing cases") + if (passing): + print(f"[{passing_count}/{total_count}] passing cases") + if (failing): + print(f"[{error_count}/{total_count}] failed cases") class MaxStrLengths: @@ -827,7 +835,8 @@ def find_max_str_lengths(run_list): def main(): (file, case, sdf, namelist, tracers, use_gdb, runtime, runtime_mult, docker, \ verbose, levels, npz_type, vert_coord_file, case_data_dir, n_itt_out, \ - n_itt_diag, run_dir, bin_dir, timestep, mpi_command, stop_on_error) = parse_arguments() + n_itt_diag, run_dir, bin_dir, timestep, mpi_command, stop_on_error \ + ) = parse_arguments() setup_logging(verbose) @@ -883,6 +892,7 @@ def main(): # setup variables error_logs = [["Failed Case", "Suite", "Namelist", "Status"]] + pass_logs = [["Passing Case", "Suite", "Namelist", "Status"]] max_str_lens = find_max_str_lengths(run_list) failed_case = False irun = 0 @@ -959,6 +969,9 @@ def main(): if status == 0: logging.info('Process "(case={0}, suite={1}, namelist={2}" completed successfully'. \ format(run["case"], run["suite"], active_suite.namelist)) + pass_logs = np.append(pass_logs, + [[run["case"], run["suite"], active_suite.namelist, status]], + axis=0) else: failed_case = True error_str = 'Process "(case={0}, suite={1}, namelist={2}" exited with code {3}'. \ @@ -973,8 +986,9 @@ def main(): if docker: copy_outdir(exp_dir) + print_report(pass_logs, len(run_list), max_str_lens, passing=True) if (failed_case): - print_error_report(error_logs, len(run_list), max_str_lens) + print_report(error_logs, len(run_list), max_str_lens, failing=True) sys.exit(1) From c2447bb6403bd7d49ec9322e7314addcac2a4ad9 Mon Sep 17 00:00:00 2001 From: Soren Rasmussen Date: Fri, 9 Aug 2024 13:06:33 -0600 Subject: [PATCH 28/40] Adding merge pull request #1081 --- ccpp/physics | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ccpp/physics b/ccpp/physics index e2f4a6368..7506fd110 160000 --- a/ccpp/physics +++ b/ccpp/physics @@ -1 +1 @@ -Subproject commit e2f4a63682c679660f0fd334b34e7c5c8c4042d4 +Subproject commit 7506fd110dbeefca83ecc6ecd7f50c0b4989694a From 06ebb1761a5dbab4ccb6ae2658bc44c3cd0d80a2 Mon Sep 17 00:00:00 2001 From: Soren Rasmussen Date: Fri, 9 Aug 2024 13:50:50 -0600 Subject: [PATCH 29/40] fixing passing/failing counts in CI summary --- scm/src/run_scm.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scm/src/run_scm.py b/scm/src/run_scm.py index 520e1fb93..93f09435f 100755 --- a/scm/src/run_scm.py +++ b/scm/src/run_scm.py @@ -780,9 +780,6 @@ def print_report(logs, total_count, max_str_lens, suite_l = max_str_lens.suite namelist_l = max_str_lens.namelist status_l = max_str_lens.status - # error_log contains header, subtracting 1 from error - error_count = logs.shape[0] - 1 - passing_count = total_count - error_count header_printed = False column_width = (case_l + suite_l + namelist_l + status_l + 13) @@ -799,10 +796,14 @@ def print_report(logs, total_count, max_str_lens, if not header_printed: print("-" * column_width) header_printed = True + print("-" * column_width) if (passing): + # error_log contains header, subtracting 1 from error + passing_count = logs.shape[0] - 1 print(f"[{passing_count}/{total_count}] passing cases") if (failing): + error_count = logs.shape[0] - 1 print(f"[{error_count}/{total_count}] failed cases") From c6801d2b51a3420e255f0f06f32fda4de7c7ac41 Mon Sep 17 00:00:00 2001 From: Grant Firl Date: Fri, 9 Aug 2024 19:49:19 -0400 Subject: [PATCH 30/40] fix w_0/w_d bug caught by @mkavulich --- scm/etc/scripts/dephy_converter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm/etc/scripts/dephy_converter.py b/scm/etc/scripts/dephy_converter.py index bdc1ea31d..f04d859d8 100755 --- a/scm/etc/scripts/dephy_converter.py +++ b/scm/etc/scripts/dephy_converter.py @@ -907,7 +907,7 @@ def get_case_data(case_name): except KeyError: w_0 = missing_value try: - w_d = scalars_grp.variables['w_0'][:] + w_d = scalars_grp.variables['w_d'][:] except KeyError: w_d = missing_value try: From 1d5c77fc9ddc1a64de7da7d6a6e7bcca3465e7c5 Mon Sep 17 00:00:00 2001 From: Grant Firl Date: Fri, 9 Aug 2024 19:54:20 -0400 Subject: [PATCH 31/40] Update scm/etc/scripts/dephy_converter.py Co-authored-by: Michael Kavulich --- scm/etc/scripts/dephy_converter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm/etc/scripts/dephy_converter.py b/scm/etc/scripts/dephy_converter.py index f04d859d8..326a570c5 100755 --- a/scm/etc/scripts/dephy_converter.py +++ b/scm/etc/scripts/dephy_converter.py @@ -433,7 +433,7 @@ def get_case_nml(case_name): filename = os.path.join(CASE_NML_DIR, case_name + '.nml') - print(filename) + logging.debug(filename) error = False nml = '' From f40427b23f779b032f934251fde744706dfbe600 Mon Sep 17 00:00:00 2001 From: Grant Firl Date: Fri, 9 Aug 2024 19:54:39 -0400 Subject: [PATCH 32/40] Update scm/etc/scripts/dephy_converter.py Co-authored-by: Michael Kavulich --- scm/etc/scripts/dephy_converter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm/etc/scripts/dephy_converter.py b/scm/etc/scripts/dephy_converter.py index 326a570c5..f533691c1 100755 --- a/scm/etc/scripts/dephy_converter.py +++ b/scm/etc/scripts/dephy_converter.py @@ -445,7 +445,7 @@ def get_case_nml(case_name): return (nml, error) def get_case_data(case_name): - """Returns proprietery CCPP SCM case data in NetCDF Dataset format""" + """Returns proprietary CCPP SCM case data in NetCDF Dataset format""" #TODO: need to handle LSM ICs From 9a4c5264e15ca732fc9d557cbeaeb3bd216fdca7 Mon Sep 17 00:00:00 2001 From: Grant Firl Date: Fri, 9 Aug 2024 20:00:32 -0400 Subject: [PATCH 33/40] set default logging level to info --- scm/etc/scripts/dephy_converter.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scm/etc/scripts/dephy_converter.py b/scm/etc/scripts/dephy_converter.py index f533691c1..dd843d503 100755 --- a/scm/etc/scripts/dephy_converter.py +++ b/scm/etc/scripts/dephy_converter.py @@ -20,8 +20,8 @@ PROCESSED_CASE_DIR = '../../data/processed_case_input' # For developers: set logging level to DEBUG for additional output -LOGLEVEL = logging.DEBUG -#LOGLEVEL = logging.INFO +#LOGLEVEL = logging.DEBUG +LOGLEVEL = logging.INFO DEFAULT_MISSING_VALUE = -9999.0 DEFAULT_NUDGING_TIMESCALE = 7200.0 #s From c5dc7b0e97f69119979158e6cf5de86b9503797b Mon Sep 17 00:00:00 2001 From: Grant Firl Date: Fri, 9 Aug 2024 20:32:39 -0400 Subject: [PATCH 34/40] fix debug logging logic --- scm/etc/scripts/dephy_converter.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/scm/etc/scripts/dephy_converter.py b/scm/etc/scripts/dephy_converter.py index dd843d503..3a803ec21 100755 --- a/scm/etc/scripts/dephy_converter.py +++ b/scm/etc/scripts/dephy_converter.py @@ -51,9 +51,9 @@ def parse_arguments(): def setup_logging(debug): """Sets up the logging module.""" if debug: - logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO) - else: logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.DEBUG) + else: + logging.basicConfig(format='%(levelname)s: %(message)s', level=logging.INFO) class Case_Data(object): def __init__(self, name, missing_value, time, levels, soil_depth, lat, lon, slmsk, vegsrc, vegtyp, soiltyp, \ @@ -2521,10 +2521,9 @@ def write_SCM_nml_file(case_nml): # ######################################################################################## def main(): - setup_logging() + (case_name, use_area, debug) = parse_arguments() - #read in arguments - (case_name, use_area) = parse_arguments() + setup_logging(debug) (case_nml, error) = get_case_nml(case_name) if (error): @@ -2546,7 +2545,6 @@ def main(): logging.debug("Created {}".format(fileOUT)) write_SCM_nml_file(case_nml) - #logging.debug("Created {}".format(nmlOUT)) if __name__ == '__main__': main() From 4b4cfd3586fc4ef6672adb40eaca199c5c77eeef Mon Sep 17 00:00:00 2001 From: Grant Firl Date: Tue, 13 Aug 2024 11:52:21 -0400 Subject: [PATCH 35/40] Update scm/etc/scripts/scm_analysis.py Co-authored-by: Michael Kavulich --- scm/etc/scripts/scm_analysis.py | 1 - 1 file changed, 1 deletion(-) diff --git a/scm/etc/scripts/scm_analysis.py b/scm/etc/scripts/scm_analysis.py index d6516dc7a..2b1ff7664 100755 --- a/scm/etc/scripts/scm_analysis.py +++ b/scm/etc/scripts/scm_analysis.py @@ -1380,7 +1380,6 @@ def replace_fill_with_nan(nc_ds, var_name, var, group, time_diag, pres_l, datase else: y_max_val = profiles_mean['y_max'] y_lim_val = [y_min_val, y_max_val] - #plot mean profiles for k in range(len(profiles_mean['vars'])): #get the python variable associated with the vars listed in the config file From 15bea3113206a0f166d5ef7e7d2c1a010e682d6f Mon Sep 17 00:00:00 2001 From: Grant Firl Date: Tue, 13 Aug 2024 11:52:35 -0400 Subject: [PATCH 36/40] Update scm/src/scm_input.F90 Co-authored-by: Michael Kavulich --- scm/src/scm_input.F90 | 1 - 1 file changed, 1 deletion(-) diff --git a/scm/src/scm_input.F90 b/scm/src/scm_input.F90 index af946e763..0770c9503 100644 --- a/scm/src/scm_input.F90 +++ b/scm/src/scm_input.F90 @@ -1515,7 +1515,6 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) call NetCDF_read_var(ncid, "rl", .False., input_rl) call NetCDF_read_var(ncid, "ri", .False., input_ri) call NetCDF_read_var(ncid, "hur", .False., input_rh) - call NetCDF_read_var(ncid, "tke", .False., input_tke) From 9a842b919a4294c1bd200f8ce6193dd822399524 Mon Sep 17 00:00:00 2001 From: Grant Firl Date: Tue, 13 Aug 2024 11:52:43 -0400 Subject: [PATCH 37/40] Update scm/src/scm_input.F90 Co-authored-by: Michael Kavulich --- scm/src/scm_input.F90 | 1 - 1 file changed, 1 deletion(-) diff --git a/scm/src/scm_input.F90 b/scm/src/scm_input.F90 index 0770c9503..24881e064 100644 --- a/scm/src/scm_input.F90 +++ b/scm/src/scm_input.F90 @@ -1517,7 +1517,6 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) call NetCDF_read_var(ncid, "hur", .False., input_rh) call NetCDF_read_var(ncid, "tke", .False., input_tke) - call NetCDF_read_var(ncid, "o3", .False., input_ozone) call NetCDF_read_var(ncid, "area", .False., input_area) From dbce3ff5e711ea87666d0d8c5d25a4084a68738d Mon Sep 17 00:00:00 2001 From: Grant Firl Date: Tue, 13 Aug 2024 11:53:01 -0400 Subject: [PATCH 38/40] Update scm/src/scm_input.F90 Co-authored-by: Michael Kavulich --- scm/src/scm_input.F90 | 1 - 1 file changed, 1 deletion(-) diff --git a/scm/src/scm_input.F90 b/scm/src/scm_input.F90 index 24881e064..59229cf68 100644 --- a/scm/src/scm_input.F90 +++ b/scm/src/scm_input.F90 @@ -1519,7 +1519,6 @@ subroutine get_case_init_DEPHY(scm_state, scm_input) call NetCDF_read_var(ncid, "o3", .False., input_ozone) call NetCDF_read_var(ncid, "area", .False., input_area) - !orographic parameters call NetCDF_read_var(ncid, "stddev", needed_for_model_ics, input_stddev) call NetCDF_read_var(ncid, "convexity", needed_for_model_ics, input_convexity) From 4e12394247d1e7167e08d46c8f5c1eae5b0a0e61 Mon Sep 17 00:00:00 2001 From: Grant Firl Date: Tue, 13 Aug 2024 11:59:36 -0400 Subject: [PATCH 39/40] fix indenting in scm_read_obs.py" --- scm/etc/scripts/scm_read_obs.py | 425 ++++++++++++++++---------------- 1 file changed, 208 insertions(+), 217 deletions(-) diff --git a/scm/etc/scripts/scm_read_obs.py b/scm/etc/scripts/scm_read_obs.py index ac6b80100..ba9dc712d 100644 --- a/scm/etc/scripts/scm_read_obs.py +++ b/scm/etc/scripts/scm_read_obs.py @@ -7,249 +7,240 @@ import forcing_file_common as ffc def read_MOSAiC_obs(obs_file, time_slices, date): - obs_time_slice_indices = [] + obs_time_slice_indices = [] - obs_fid = Dataset(obs_file, 'r') + obs_fid = Dataset(obs_file, 'r') - obs_year = obs_fid.variables['year'][:] - obs_month = obs_fid.variables['month'][:] - obs_day = obs_fid.variables['day'][:] - obs_hour = obs_fid.variables['hour'][:] - obs_time = obs_fid.variables['time_offset'][:] + obs_year = obs_fid.variables['year'][:] + obs_month = obs_fid.variables['month'][:] + obs_day = obs_fid.variables['day'][:] + obs_hour = obs_fid.variables['hour'][:] + obs_time = obs_fid.variables['time_offset'][:] - obs_date = [] - for i in range(obs_hour.size): - obs_date.append(datetime.datetime(obs_year[i], obs_month[i], obs_day[i], obs_hour[i], 0, 0, 0)) - obs_date = np.array(obs_date) + obs_date = [] + for i in range(obs_hour.size): + obs_date.append(datetime.datetime(obs_year[i], obs_month[i], obs_day[i], obs_hour[i], 0, 0, 0)) + obs_date = np.array(obs_date) - for time_slice in time_slices: - start_date = datetime.datetime(time_slices[time_slice]['start'][0], time_slices[time_slice]['start'][1],time_slices[time_slice]['start'][2], time_slices[time_slice]['start'][3], time_slices[time_slice]['start'][4]) - end_date = datetime.datetime(time_slices[time_slice]['end'][0], time_slices[time_slice]['end'][1],time_slices[time_slice]['end'][2], time_slices[time_slice]['end'][3], time_slices[time_slice]['end'][4]) - start_date_index = np.where(obs_date == start_date)[0][0] - end_date_index = np.where(obs_date == end_date)[0][0] - obs_time_slice_indices.append([start_date_index, end_date_index]) + for time_slice in time_slices: + start_date = datetime.datetime(time_slices[time_slice]['start'][0], time_slices[time_slice]['start'][1],time_slices[time_slice]['start'][2], time_slices[time_slice]['start'][3], time_slices[time_slice]['start'][4]) + end_date = datetime.datetime(time_slices[time_slice]['end'][0], time_slices[time_slice]['end'][1],time_slices[time_slice]['end'][2], time_slices[time_slice]['end'][3], time_slices[time_slice]['end'][4]) + start_date_index = np.where(obs_date == start_date)[0][0] + end_date_index = np.where(obs_date == end_date)[0][0] + obs_time_slice_indices.append([start_date_index, end_date_index]) -#print(start_date, end_date, start_date_index, end_date_index, obs_date[start_date_index], obs_date[end_date_index]) + #print(start_date, end_date, start_date_index, end_date_index, obs_date[start_date_index], obs_date[end_date_index]) - #find the index corresponding to the start of the simulations - obs_start_index = np.where(obs_date == date[0][0])[0] - obs_time = obs_time - obs_time[obs_start_index] + #find the index corresponding to the start of the simulations + obs_start_index = np.where(obs_date == date[0][0])[0] + obs_time = obs_time - obs_time[obs_start_index] - obs_pres_l = obs_fid.variables['levels'][:]*100.0 #pressure levels in mb + obs_pres_l = obs_fid.variables['levels'][:]*100.0 #pressure levels in mb + + obs_T = obs_fid.variables['T'][:] + obs_q = obs_fid.variables['q'][:] + obs_qi= obs_fid.variables['qi'][:] + obs_ql= obs_fid.variables['ql'][:] + obs_u = obs_fid.variables['u'][:] + obs_v = obs_fid.variables['v'][:] + obs_rad_net_srf = obs_fid.variables['rad_net_srf'][:] + obs_lw_dn_srf = obs_fid.variables['lw_dn_srf'][:] + obs_tsk = obs_fid.variables['T_skin'][:] + obs_shf = obs_fid.variables['SH'][:] + obs_lhf = obs_fid.variables['LH'][:] + obs_t2m = obs_fid.variables['T_srf'][:] + obs_q2m = obs_fid.variables['q_srf'][:] + + obs_time_h = obs_time/3600.0 + + Rd = 287.0 + Rv = 461.0 + + e_s = 6.1078*np.exp(17.2693882*(obs_T - 273.16)/(obs_T - 35.86))*100.0 #Tetens formula produces e_s in mb (convert to Pa) + e = obs_q*obs_pres_l/(obs_q + (Rd/Rv)*(1.0 - obs_q)) #compute vapor pressure from specific humidity + obs_rh = np.clip(e/e_s, 0.0, 1.0) + + return_dict = {'year': obs_year, 'month': obs_month, 'day': obs_day, 'hour': obs_hour, + 'time': obs_time, 'date': obs_date, 'time_slice_indices': obs_time_slice_indices, + 'pres_l': obs_pres_l, 'T': obs_T, 'q': obs_q, 'rh': obs_rh, 'u': obs_u, 'v': obs_v, 'shf': obs_shf, + 'lhf': obs_lhf, 't2m': obs_t2m, 'q2m': obs_q2m, 'time_h': obs_time_h, 'tsfc': obs_tsk, + 'qv': obs_q, 'qi': obs_qi, 'ql': obs_ql, 'rad_net_srf': obs_rad_net_srf, 'sfc_dwn_lw': obs_lw_dn_srf} +# 'lwp': obs_lwp, 'T_force_tend': obs_T_forcing, 'qv_force_tend': obs_q_forcing} - obs_T = obs_fid.variables['T'][:] - obs_q = obs_fid.variables['q'][:] - obs_qi= obs_fid.variables['qi'][:] - obs_ql= obs_fid.variables['ql'][:] - obs_u = obs_fid.variables['u'][:] - obs_v = obs_fid.variables['v'][:] - obs_rad_net_srf = obs_fid.variables['rad_net_srf'][:] - obs_lw_dn_srf = obs_fid.variables['lw_dn_srf'][:] - obs_tsk = obs_fid.variables['T_skin'][:] - obs_shf = obs_fid.variables['SH'][:] - obs_lhf = obs_fid.variables['LH'][:] - obs_t2m = obs_fid.variables['T_srf'][:] - obs_q2m = obs_fid.variables['q_srf'][:] + obs_fid.close() - obs_time_h = obs_time/3600.0 + return return_dict - Rd = 287.0 - Rv = 461.0 +def read_twpice_obs(obs_file, time_slices, date): + obs_time_slice_indices = [] - e_s = 6.1078*np.exp(17.2693882*(obs_T - 273.16)/(obs_T - 35.86))*100.0 #Tetens formula produces e_s in mb (convert to Pa) - e = obs_q*obs_pres_l/(obs_q + (Rd/Rv)*(1.0 - obs_q)) #compute vapor pressure from specific humidity - obs_rh = np.clip(e/e_s, 0.0, 1.0) + obs_fid = Dataset(obs_file, 'r') - return_dict = {'year': obs_year, 'month': obs_month, 'day': obs_day, 'hour': obs_hour, - 'time': obs_time, 'date': obs_date, 'time_slice_indices': obs_time_slice_indices, - 'pres_l': obs_pres_l, 'T': obs_T, 'q': obs_q, 'rh': obs_rh, 'u': obs_u, 'v': obs_v, 'shf': obs_shf, - 'lhf': obs_lhf, 't2m': obs_t2m, 'q2m': obs_q2m, 'time_h': obs_time_h, 'tsfc': obs_tsk, - 'qv': obs_q, 'qi': obs_qi, 'ql': obs_ql, 'rad_net_srf': obs_rad_net_srf, 'sfc_dwn_lw': obs_lw_dn_srf} -# 'lwp': obs_lwp, 'T_force_tend': obs_T_forcing, 'qv_force_tend': obs_q_forcing} + obs_year = obs_fid.variables['year'][:] + obs_month = obs_fid.variables['month'][:] + obs_day = obs_fid.variables['day'][:] + obs_hour = obs_fid.variables['hour'][:] + obs_time = obs_fid.variables['time_offset'][:] - obs_fid.close() + obs_date = [] + for i in range(obs_hour.size): + obs_date.append(datetime.datetime(obs_year[i], obs_month[i], obs_day[i], obs_hour[i], 0, 0, 0)) + obs_date = np.array(obs_date) - return return_dict + for time_slice in time_slices: + start_date = datetime.datetime(time_slices[time_slice]['start'][0], time_slices[time_slice]['start'][1],time_slices[time_slice]['start'][2], time_slices[time_slice]['start'][3], time_slices[time_slice]['start'][4]) + end_date = datetime.datetime(time_slices[time_slice]['end'][0], time_slices[time_slice]['end'][1],time_slices[time_slice]['end'][2], time_slices[time_slice]['end'][3], time_slices[time_slice]['end'][4]) + start_date_index = np.where(obs_date == start_date)[0][0] + end_date_index = np.where(obs_date == end_date)[0][0] + obs_time_slice_indices.append([start_date_index, end_date_index]) -def read_twpice_obs(obs_file, time_slices, date): - obs_time_slice_indices = [] + #find the index corresponding to the start of the simulations + obs_start_index = np.where(obs_date == date[0][0])[0] + obs_time = obs_time - obs_time[obs_start_index] - obs_fid = Dataset(obs_file, 'r') + obs_pres_l = obs_fid.variables['lev'][:]*100.0 #pressure levels in mb + + obs_cld = obs_fid.variables['cld'][:]/100.0 + obs_T = obs_fid.variables['T'][:] + obs_q = obs_fid.variables['q'][:]/1000.0 + obs_u = obs_fid.variables['u'][:] + obs_v = obs_fid.variables['v'][:] + obs_precip = obs_fid.variables['prec_srf'][:]/3.6E7 #convert from mm/hr to m/s + obs_shf = obs_fid.variables['SH'][:] + obs_lhf = obs_fid.variables['LH'][:] + obs_pwat = obs_fid.variables['PW'][:]*10.0 #convert from cm to kg/m2 + obs_lw_net_toa = obs_fid.variables['lw_net_toa'][:] + obs_rad_net_srf = obs_fid.variables['rad_net_srf'][:] + obs_sw_dn_toa = obs_fid.variables['sw_dn_toa'][:] + obs_sw_dn_srf = obs_fid.variables['sw_dn_srf'][:] + obs_lw_dn_srf = obs_fid.variables['lw_dn_srf'][:] + obs_lwp = obs_fid.variables['LWP'][:]*10.0 #convert from cm to kg/m2 + #obs_T_forcing = obs_fid.variables['dTdt'][:]*24.0 #convert from K/hour to K/day + #obs_q_forcing = obs_fid.variables['dqdt'][:]*24.0 #convert from g/kg/hour to g/kg/day + obs_h_advec_T = obs_fid.variables['T_adv_h'][:]*24.0 + obs_h_advec_q = obs_fid.variables['q_adv_h'][:]*24.0 + obs_v_advec_T = obs_fid.variables['T_adv_v'][:]*24.0 + obs_v_advec_q = obs_fid.variables['q_adv_v'][:]*24.0 + + obs_T_forcing = obs_h_advec_T + obs_v_advec_T + obs_q_forcing = obs_h_advec_q + obs_v_advec_q + + obs_time_h = obs_time/3600.0 + + Rd = 287.0 + Rv = 461.0 + + e_s = 6.1078*np.exp(17.2693882*(obs_T - 273.16)/(obs_T - 35.86))*100.0 #Tetens formula produces e_s in mb (convert to Pa) + e = obs_q*obs_pres_l/(obs_q + (Rd/Rv)*(1.0 - obs_q)) #compute vapor pressure from specific humidity + obs_rh = np.clip(e/e_s, 0.0, 1.0) + + obs_rh_500 = np.zeros(obs_rh.shape[0]) + index_500 = np.where(obs_pres_l[:]*0.01 < 500.0)[0][0] + lifrac = (obs_pres_l[index_500-1] - 50000.0)/(obs_pres_l[index_500-1] - obs_pres_l[index_500]) + for j in range(obs_rh.shape[0]): #loop over times + obs_rh_500[j] = obs_rh[j,index_500-1] + lifrac*(obs_rh[j,index_500] - obs_rh[j,index_500-1]) + #print index_500, pres_l[-1][j,index_500,k], pres_l[-1][j,index_500-1,k], rh_500_kj, rh[-1][j,index_500,k], rh[-1][j,index_500-1,k] + + return_dict = {'year': obs_year, 'month': obs_month, 'day': obs_day, 'hour': obs_hour, + 'time': obs_time, 'date': obs_date, 'time_slice_indices': obs_time_slice_indices, + 'pres_l': obs_pres_l, 'cld': obs_cld, 'T': obs_T, 'q': obs_q, 'u': obs_u, 'v': obs_v, + 'shf': obs_shf, 'lhf': obs_lhf, 'pwat': obs_pwat, 'time_h': obs_time_h, + 'tprcp_rate_accum': obs_precip, 'qv': obs_q, 'rh': obs_rh, 'rh_500': obs_rh_500, + 'lw_up_TOA_tot': obs_lw_net_toa, 'rad_net_srf': obs_rad_net_srf, 'sw_dn_TOA_tot': obs_sw_dn_toa, + 'lw_dn_sfc_tot': obs_lw_dn_srf, 'sw_dn_sfc_tot': obs_sw_dn_srf, 'lwp': obs_lwp, + 'T_force_tend': obs_T_forcing, 'qv_force_tend': obs_q_forcing} - obs_year = obs_fid.variables['year'][:] - obs_month = obs_fid.variables['month'][:] - obs_day = obs_fid.variables['day'][:] - obs_hour = obs_fid.variables['hour'][:] - obs_time = obs_fid.variables['time_offset'][:] + obs_fid.close() - obs_date = [] - for i in range(obs_hour.size): - obs_date.append(datetime.datetime(obs_year[i], obs_month[i], obs_day[i], obs_hour[i], 0, 0, 0)) - obs_date = np.array(obs_date) + return return_dict - for time_slice in time_slices: +def read_arm_sgp_summer_1997_obs(obs_file, time_slices, date): + obs_time_slice_indices = [] + + obs_fid = Dataset(obs_file, 'r') + + obs_year = obs_fid.variables['Year'][:] + obs_month = obs_fid.variables['Month'][:] + obs_day = obs_fid.variables['Day'][:] + #obs_hour = obs_fid.variables['hour'][:] + obs_time = obs_fid.variables['time_offset'][:] + + #this file doesn't have the hour variable - calculate from the time offset (seconds from 00Z on 6/18/1997) + obs_hour = (((obs_time - 3)/3600.0)%24).astype(int) + + obs_date = [] + for i in range(obs_hour.size): + obs_date.append(datetime.datetime(obs_year[i], obs_month[i], obs_day[i], obs_hour[i], 0, 0, 0)) + obs_date = np.array(obs_date) + + for time_slice in time_slices: start_date = datetime.datetime(time_slices[time_slice]['start'][0], time_slices[time_slice]['start'][1],time_slices[time_slice]['start'][2], time_slices[time_slice]['start'][3], time_slices[time_slice]['start'][4]) end_date = datetime.datetime(time_slices[time_slice]['end'][0], time_slices[time_slice]['end'][1],time_slices[time_slice]['end'][2], time_slices[time_slice]['end'][3], time_slices[time_slice]['end'][4]) start_date_index = np.where(obs_date == start_date)[0][0] end_date_index = np.where(obs_date == end_date)[0][0] obs_time_slice_indices.append([start_date_index, end_date_index]) + #print start_date, end_date, start_date_index, end_date_index, obs_date[start_date_index], obs_date[end_date_index] + + #find the index corresponding to the start of the simulations + obs_start_index = np.where(obs_date == date[0][0])[0] + obs_time = obs_time - obs_time[obs_start_index] - #find the index corresponding to the start of the simulations - obs_start_index = np.where(obs_date == date[0][0])[0] - obs_time = obs_time - obs_time[obs_start_index] - - obs_pres_l = obs_fid.variables['lev'][:]*100.0 #pressure levels in mb - - obs_cld = obs_fid.variables['cld'][:]/100.0 - obs_T = obs_fid.variables['T'][:] - obs_q = obs_fid.variables['q'][:]/1000.0 - obs_u = obs_fid.variables['u'][:] - obs_v = obs_fid.variables['v'][:] - obs_precip = obs_fid.variables['prec_srf'][:]/3.6E7 #convert from mm/hr to m/s - obs_shf = obs_fid.variables['SH'][:] - obs_lhf = obs_fid.variables['LH'][:] - obs_pwat = obs_fid.variables['PW'][:]*10.0 #convert from cm to kg/m2 - obs_lw_net_toa = obs_fid.variables['lw_net_toa'][:] - obs_rad_net_srf = obs_fid.variables['rad_net_srf'][:] - obs_sw_dn_toa = obs_fid.variables['sw_dn_toa'][:] - obs_sw_dn_srf = obs_fid.variables['sw_dn_srf'][:] - obs_lw_dn_srf = obs_fid.variables['lw_dn_srf'][:] - obs_lwp = obs_fid.variables['LWP'][:]*10.0 #convert from cm to kg/m2 - #obs_T_forcing = obs_fid.variables['dTdt'][:]*24.0 #convert from K/hour to K/day - #obs_q_forcing = obs_fid.variables['dqdt'][:]*24.0 #convert from g/kg/hour to g/kg/day - obs_h_advec_T = obs_fid.variables['T_adv_h'][:]*24.0 - obs_h_advec_q = obs_fid.variables['q_adv_h'][:]*24.0 - obs_v_advec_T = obs_fid.variables['T_adv_v'][:]*24.0 - obs_v_advec_q = obs_fid.variables['q_adv_v'][:]*24.0 - - obs_T_forcing = obs_h_advec_T + obs_v_advec_T - obs_q_forcing = obs_h_advec_q + obs_v_advec_q - - obs_time_h = obs_time/3600.0 - - Rd = 287.0 - Rv = 461.0 - - e_s = 6.1078*np.exp(17.2693882*(obs_T - 273.16)/(obs_T - 35.86))*100.0 #Tetens formula produces e_s in mb (convert to Pa) - e = obs_q*obs_pres_l/(obs_q + (Rd/Rv)*(1.0 - obs_q)) #compute vapor pressure from specific humidity - obs_rh = np.clip(e/e_s, 0.0, 1.0) - - obs_rh_500 = np.zeros(obs_rh.shape[0]) - index_500 = np.where(obs_pres_l[:]*0.01 < 500.0)[0][0] - lifrac = (obs_pres_l[index_500-1] - 50000.0)/(obs_pres_l[index_500-1] - obs_pres_l[index_500]) - for j in range(obs_rh.shape[0]): #loop over times - obs_rh_500[j] = obs_rh[j,index_500-1] + lifrac*(obs_rh[j,index_500] - obs_rh[j,index_500-1]) - #print index_500, pres_l[-1][j,index_500,k], pres_l[-1][j,index_500-1,k], rh_500_kj, rh[-1][j,index_500,k], rh[-1][j,index_500-1,k] - - return_dict = {'year': obs_year, 'month': obs_month, 'day': obs_day, 'hour': obs_hour, - 'time': obs_time, 'date': obs_date, 'time_slice_indices': obs_time_slice_indices, - 'pres_l': obs_pres_l, 'cld': obs_cld, 'T': obs_T, 'q': obs_q, 'u': obs_u, 'v': obs_v, - 'shf': obs_shf, 'lhf': obs_lhf, 'pwat': obs_pwat, 'time_h': obs_time_h, - 'tprcp_rate_accum': obs_precip, 'qv': obs_q, 'rh': obs_rh, 'rh_500': obs_rh_500, - 'lw_up_TOA_tot': obs_lw_net_toa, 'rad_net_srf': obs_rad_net_srf, 'sw_dn_TOA_tot': obs_sw_dn_toa, - 'lw_dn_sfc_tot': obs_lw_dn_srf, 'sw_dn_sfc_tot': obs_sw_dn_srf, 'lwp': obs_lwp, - 'T_force_tend': obs_T_forcing, 'qv_force_tend': obs_q_forcing} - - obs_fid.close() - - return return_dict -def read_arm_sgp_summer_1997_obs(obs_file, time_slices, date): - obs_time_slice_indices = [] - - obs_fid = Dataset(obs_file, 'r') - - obs_year = obs_fid.variables['Year'][:] - obs_month = obs_fid.variables['Month'][:] - obs_day = obs_fid.variables['Day'][:] - #obs_hour = obs_fid.variables['hour'][:] - obs_time = obs_fid.variables['time_offset'][:] - - #this file doesn't have the hour variable - calculate from the time offset (seconds from 00Z on 6/18/1997) - obs_hour = (((obs_time - 3)/3600.0)%24).astype(int) - - obs_date = [] - for i in range(obs_hour.size): - obs_date.append(datetime.datetime(obs_year[i], obs_month[i], obs_day[i], obs_hour[i], 0, 0, 0)) - obs_date = np.array(obs_date) - - for time_slice in time_slices: - start_date = datetime.datetime(time_slices[time_slice]['start'][0], time_slices[time_slice]['start'][1],time_slices[time_slice]['start'][2], time_slices[time_slice]['start'][3], time_slices[time_slice]['start'][4]) - end_date = datetime.datetime(time_slices[time_slice]['end'][0], time_slices[time_slice]['end'][1],time_slices[time_slice]['end'][2], time_slices[time_slice]['end'][3], time_slices[time_slice]['end'][4]) - start_date_index = np.where(obs_date == start_date)[0][0] - end_date_index = np.where(obs_date == end_date)[0][0] - obs_time_slice_indices.append([start_date_index, end_date_index]) - #print start_date, end_date, start_date_index, end_date_index, obs_date[start_date_index], obs_date[end_date_index] - - #find the index corresponding to the start of the simulations - obs_start_index = np.where(obs_date == date[0][0])[0] - obs_time = obs_time - obs_time[obs_start_index] - - - obs_pres_l = np.flipud(obs_fid.variables['lev'][:])*100.0 #pressure levels in mb - - obs_cld = np.fliplr(obs_fid.variables['ARSCL_Cld'][:,:,0,0])/100.0 - obs_T = np.fliplr(obs_fid.variables['Temp'][:,:,0,0]) - obs_q = np.fliplr(obs_fid.variables['H2O_Mixing_Ratio'][:,:,0,0]/1000.0) - obs_u = np.fliplr(obs_fid.variables['u_wind'][:,:,0,0]) - obs_v = np.fliplr(obs_fid.variables['v_wind'][:,:,0,0]) - obs_precip = obs_fid.variables['Prec'][:,0,0] - # obs_shf = obs_fid.variables['SH'][:] - # obs_lhf = obs_fid.variables['LH'][:] - # obs_pwat = obs_fid.variables['PW'][:] - # obs_lw_net_toa = obs_fid.variables['lw_net_toa'][:] - # obs_rad_net_srf = obs_fid.variables['rad_net_srf'][:] - # obs_sw_dn_toa = obs_fid.variables['sw_dn_toa'][:] - # obs_sw_dn_srf = obs_fid.variables['sw_dn_srf'][:] - # obs_lw_dn_srf = obs_fid.variables['lw_dn_srf'][:] - # obs_lwp = obs_fid.variables['LWP'][:]*10.0 #convert from cm to kg/m2 - # #obs_T_forcing = obs_fid.variables['dTdt'][:]*24.0 #convert from K/hour to K/day - # #obs_q_forcing = obs_fid.variables['dqdt'][:]*24.0 #convert from g/kg/hour to g/kg/day - # obs_h_advec_T = obs_fid.variables['T_adv_h'][:]*24.0 - # obs_h_advec_q = obs_fid.variables['q_adv_h'][:]*24.0 - # obs_v_advec_T = obs_fid.variables['T_adv_v'][:]*24.0 - # obs_v_advec_q = obs_fid.variables['q_adv_v'][:]*24.0 - # - # obs_T_forcing = obs_h_advec_T + obs_v_advec_T - # obs_q_forcing = obs_h_advec_q + obs_v_advec_q - # - # obs_time_h = obs_time/3600.0 - # - # Rd = 287.0 - # Rv = 461.0 - # - # e_s = 6.1078*np.exp(17.2693882*(obs_T - 273.16)/(obs_T - 35.86))*100.0 #Tetens formula produces e_s in mb (convert to Pa) - # e = obs_q*obs_pres_l/(obs_q + (Rd/Rv)*(1.0 - obs_q)) #compute vapor pressure from specific humidity - # obs_rh = np.clip(e/e_s, 0.0, 1.0) - # - # obs_rh_500 = np.zeros(obs_rh.shape[0]) - # index_500 = np.where(obs_pres_l[:]*0.01 < 500.0)[0][0] - # lifrac = (obs_pres_l[index_500-1] - 50000.0)/(obs_pres_l[index_500-1] - obs_pres_l[index_500]) - # for j in range(obs_rh.shape[0]): #loop over times - # obs_rh_500[j] = obs_rh[j,index_500-1] + lifrac*(obs_rh[j,index_500] - obs_rh[j,index_500-1]) - # #print index_500, pres_l[-1][j,index_500,k], pres_l[-1][j,index_500-1,k], rh_500_kj, rh[-1][j,index_500,k], rh[-1][j,index_500-1,k] - - return_dict = {'year': obs_year, 'month': obs_month, 'day': obs_day, 'hour': obs_hour, - 'time': obs_time, 'date': obs_date, 'time_slice_indices': obs_time_slice_indices, - 'pres_l': obs_pres_l, 'cld': obs_cld, 'T': obs_T, 'qv': obs_q, 'u': obs_u, 'v': obs_v, - 'precip': obs_precip}#, 'shf': obs_shf, 'lhf': obs_lhf, 'pwat': obs_pwat, 'time_h': obs_time_h, - # 'rain': obs_precip, 'rainc': obs_precip, 'qv': obs_q, 'rh': obs_rh, 'rh_500': obs_rh_500, - # 'lw_up_TOA_tot': obs_lw_net_toa, 'rad_net_srf': obs_rad_net_srf, 'sw_dn_TOA_tot': obs_sw_dn_toa, - # 'lw_dn_sfc_tot': obs_lw_dn_srf, 'sw_dn_sfc_tot': obs_sw_dn_srf, 'lwp': obs_lwp, - # 'T_force_tend': obs_T_forcing, 'qv_force_tend': obs_q_forcing} - - # return_dict = {'year': obs_year, 'month': obs_month, 'day': obs_day, 'hour': obs_hour, - # 'time': obs_time, 'date': obs_date, 'time_slice_indices': obs_time_slice_indices, - # 'pres_l': obs_pres_l, 'cld': obs_cld, 'T': obs_T, 'q': obs_q, 'u': obs_u, 'v': obs_v, - # 'precip': obs_precip, 'shf': obs_shf, 'lhf': obs_lhf, 'pwat': obs_pwat, 'time_h': obs_time_h, - # 'rain': obs_precip, 'rainc': obs_precip, 'qv': obs_q, 'rh': obs_rh, 'rh_500': obs_rh_500, - # 'lw_up_TOA_tot': obs_lw_net_toa, 'rad_net_srf': obs_rad_net_srf, 'sw_dn_TOA_tot': obs_sw_dn_toa, - # 'lw_dn_sfc_tot': obs_lw_dn_srf, 'sw_dn_sfc_tot': obs_sw_dn_srf, 'lwp': obs_lwp, - # 'T_force_tend': obs_T_forcing, 'qv_force_tend': obs_q_forcing} - - obs_fid.close() - - return return_dict + obs_pres_l = np.flipud(obs_fid.variables['lev'][:])*100.0 #pressure levels in mb + + obs_cld = np.fliplr(obs_fid.variables['ARSCL_Cld'][:,:,0,0])/100.0 + obs_T = np.fliplr(obs_fid.variables['Temp'][:,:,0,0]) + obs_q = np.fliplr(obs_fid.variables['H2O_Mixing_Ratio'][:,:,0,0]/1000.0) + obs_u = np.fliplr(obs_fid.variables['u_wind'][:,:,0,0]) + obs_v = np.fliplr(obs_fid.variables['v_wind'][:,:,0,0]) + obs_precip = obs_fid.variables['Prec'][:,0,0] + # obs_shf = obs_fid.variables['SH'][:] + # obs_lhf = obs_fid.variables['LH'][:] + # obs_pwat = obs_fid.variables['PW'][:] + # obs_lw_net_toa = obs_fid.variables['lw_net_toa'][:] + # obs_rad_net_srf = obs_fid.variables['rad_net_srf'][:] + # obs_sw_dn_toa = obs_fid.variables['sw_dn_toa'][:] + # obs_sw_dn_srf = obs_fid.variables['sw_dn_srf'][:] + # obs_lw_dn_srf = obs_fid.variables['lw_dn_srf'][:] + # obs_lwp = obs_fid.variables['LWP'][:]*10.0 #convert from cm to kg/m2 + # #obs_T_forcing = obs_fid.variables['dTdt'][:]*24.0 #convert from K/hour to K/day + # #obs_q_forcing = obs_fid.variables['dqdt'][:]*24.0 #convert from g/kg/hour to g/kg/day + # obs_h_advec_T = obs_fid.variables['T_adv_h'][:]*24.0 + # obs_h_advec_q = obs_fid.variables['q_adv_h'][:]*24.0 + # obs_v_advec_T = obs_fid.variables['T_adv_v'][:]*24.0 + # obs_v_advec_q = obs_fid.variables['q_adv_v'][:]*24.0 + # + # obs_T_forcing = obs_h_advec_T + obs_v_advec_T + # obs_q_forcing = obs_h_advec_q + obs_v_advec_q + # + # obs_time_h = obs_time/3600.0 + # + # Rd = 287.0 + # Rv = 461.0 + # + # e_s = 6.1078*np.exp(17.2693882*(obs_T - 273.16)/(obs_T - 35.86))*100.0 #Tetens formula produces e_s in mb (convert to Pa) + # e = obs_q*obs_pres_l/(obs_q + (Rd/Rv)*(1.0 - obs_q)) #compute vapor pressure from specific humidity + # obs_rh = np.clip(e/e_s, 0.0, 1.0) + # + # obs_rh_500 = np.zeros(obs_rh.shape[0]) + # index_500 = np.where(obs_pres_l[:]*0.01 < 500.0)[0][0] + # lifrac = (obs_pres_l[index_500-1] - 50000.0)/(obs_pres_l[index_500-1] - obs_pres_l[index_500]) + # for j in range(obs_rh.shape[0]): #loop over times + # obs_rh_500[j] = obs_rh[j,index_500-1] + lifrac*(obs_rh[j,index_500] - obs_rh[j,index_500-1]) + # #print index_500, pres_l[-1][j,index_500,k], pres_l[-1][j,index_500-1,k], rh_500_kj, rh[-1][j,index_500,k], rh[-1][j,index_500-1,k] + + return_dict = {'year': obs_year, 'month': obs_month, 'day': obs_day, 'hour': obs_hour, + 'time': obs_time, 'date': obs_date, 'time_slice_indices': obs_time_slice_indices, + 'pres_l': obs_pres_l, 'cld': obs_cld, 'T': obs_T, 'qv': obs_q, 'u': obs_u, 'v': obs_v, + 'precip': obs_precip}#, 'shf': obs_shf, 'lhf': obs_lhf, 'pwat': obs_pwat, 'time_h': obs_time_h, + # 'rain': obs_precip, 'rainc': obs_precip, 'qv': obs_q, 'rh': obs_rh, 'rh_500': obs_rh_500, + # 'lw_up_TOA_tot': obs_lw_net_toa, 'rad_net_srf': obs_rad_net_srf, 'sw_dn_TOA_tot': obs_sw_dn_toa, + # 'lw_dn_sfc_tot': obs_lw_dn_srf, 'sw_dn_sfc_tot': obs_sw_dn_srf, 'lwp': obs_lwp, + # 'T_force_tend': obs_T_forcing, 'qv_force_tend': obs_q_forcing} + + obs_fid.close() + + return return_dict def read_LASSO_obs(obs_file, time_slices, date): obs_time_slice_indices = [] From 4c9559c85c4047165e542bf9bc9aa7e9d98c196f Mon Sep 17 00:00:00 2001 From: Grant Firl Date: Tue, 13 Aug 2024 12:05:44 -0400 Subject: [PATCH 40/40] fix COMBLE case namelist format --- scm/etc/case_config/COMBLE.nml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm/etc/case_config/COMBLE.nml b/scm/etc/case_config/COMBLE.nml index c408cd88a..fc332532b 100644 --- a/scm/etc/case_config/COMBLE.nml +++ b/scm/etc/case_config/COMBLE.nml @@ -6,4 +6,4 @@ do_spinup = .false., spinup_timesteps = 0, reference_profile_choice = 2, column_area = 1.45E8, -$end +/ \ No newline at end of file