From d5f30b4ad08cfb800a46e034b05c424dd74a12d2 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Thu, 15 Aug 2024 17:04:10 +0000 Subject: [PATCH 01/61] change hash to prod for smoke/dust --- Externals.cfg | 8 ++-- devbuild.sh | 2 +- modulefiles/build_hera_intel_prod.lua | 60 +++++++++++++++++++++++++++ 3 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 modulefiles/build_hera_intel_prod.lua diff --git a/Externals.cfg b/Externals.cfg index 4545cd8ca5..c07002de9d 100644 --- a/Externals.cfg +++ b/Externals.cfg @@ -3,7 +3,7 @@ protocol = git repo_url = https://github.com/ufs-community/UFS_UTILS # Specify either a branch name or a hash but not both. #branch = develop -hash = 57bd832 +hash = 33cc663 local_path = sorc/UFS_UTILS required = True @@ -11,8 +11,8 @@ required = True protocol = git repo_url = https://github.com/ufs-community/ufs-weather-model # Specify either a branch name or a hash but not both. -#branch = develop -hash = b5a1976 +branch = production/RRFS.v1 +#hash = b5a1976 local_path = sorc/ufs-weather-model required = True @@ -21,7 +21,7 @@ protocol = git repo_url = https://github.com/NOAA-EMC/UPP # Specify either a branch name or a hash but not both. #branch = develop -hash = be0410e +hash = fc85241 local_path = sorc/UPP required = True diff --git a/devbuild.sh b/devbuild.sh index 014fbdb3b7..61b20fecaf 100755 --- a/devbuild.sh +++ b/devbuild.sh @@ -314,7 +314,7 @@ if [ -f ${RUN_VERSION_FILE} ]; then fi # set MODULE_FILE for this platform/compiler combination -MODULE_FILE="build_${PLATFORM}_${COMPILER}" +MODULE_FILE="build_${PLATFORM}_${COMPILER}_prod" if [ ! -f "${SRW_DIR}/modulefiles/${MODULE_FILE}.lua" ]; then printf "ERROR: module file does not exist for platform/compiler\n" >&2 printf " MODULE_FILE=${MODULE_FILE}\n" >&2 diff --git a/modulefiles/build_hera_intel_prod.lua b/modulefiles/build_hera_intel_prod.lua new file mode 100644 index 0000000000..b44ca2467b --- /dev/null +++ b/modulefiles/build_hera_intel_prod.lua @@ -0,0 +1,60 @@ +help([[ +This module loads libraries for building the production branch on +the NOAA RDHPC machine Hera using Intel-2022.1.2 +]]) + +whatis([===[Loads libraries needed for building the RRFS workflow on Hera ]===]) + +prepend_path("MODULEPATH", "/scratch1/NCEPDEV/nems/role.epic/spack-stack/spack-stack-1.5.1/envs/gsi-addon-env-rocky8/install/modulefiles/Core") +load(pathJoin("stack-intel", os.getenv("stack_intel_ver") or "2021.5.0")) +load(pathJoin("stack-intel-oneapi-mpi", os.getenv("stack_impi_ver") or "2021.5.1")) +load(pathJoin("cmake", os.getenv("cmake_ver") or "3.23.1")) + +load(pathJoin("jasper", os.getenv("jasper_ver") or "2.0.32")) +load(pathJoin("zlib", os.getenv("zlib_ver") or "1.2.13")) +load(pathJoin("libpng", os.getenv("libpng_ver") or "1.6.37")) +load(pathJoin("parallelio", os.getenv("pio_ver") or "2.5.10")) +--loading parallelio will load netcdf_c, netcdf_fortran, hdf5, zlib, etc +load(pathJoin("esmf", os.getenv("esmf_ver") or "8.5.0")) +load(pathJoin("fms", os.getenv("fms_ver") or "2023.02.01")) + +load(pathJoin("bacio", os.getenv("bacio_ver") or "2.4.1")) +load(pathJoin("crtm", os.getenv("crtm_ver") or "2.4.0")) +load(pathJoin("g2", os.getenv("g2_ver") or "3.4.5")) +load(pathJoin("g2tmpl", os.getenv("g2tmpl_ver") or "1.10.2")) +load(pathJoin("ip", os.getenv("ip_ver") or "4.3.0")) +load(pathJoin("sp", os.getenv("sp_ver") or "2.3.3")) + +load(pathJoin("gftl-shared", os.getenv("gftl-shared_ver") or "1.6.1")) +load(pathJoin("mapl", os.getenv("mapl_ver") or "2.40.3-esmf-8.5.0")) +load(pathJoin("scotch", os.getenv("scotch_ver") or "7.0.4")) + +load(pathJoin("bufr", os.getenv("bufr_ver") or "11.7.0")) +load(pathJoin("sigio", os.getenv("sigio_ver") or "2.3.2")) +load(pathJoin("sfcio", os.getenv("sfcio_ver") or "1.4.1")) +load(pathJoin("nemsio", os.getenv("nemsio_ver") or "2.5.4")) +load(pathJoin("wrf-io", os.getenv("wrf_io_ver") or "1.2.0")) +load(pathJoin("ncio", os.getenv("ncio_ver") or "1.1.2")) +load(pathJoin("gsi-ncdiag", os.getenv("gsi-ncdiag_ver") or "1.1.2")) +load(pathJoin("w3emc", os.getenv("w3emc_ver") or "2.10.0")) +load(pathJoin("w3nco", os.getenv("w3nco_ver") or "2.4.1")) + +load(pathJoin("nco", os.getenv("nco_ver") or "5.0.6")) +--load(pathJoin("prod_util", os.getenv("prod_util_ver") or "1.2.2")) +--load(pathJoin("wgrib2", os.getenv("wgrib2_ver") or "2.0.8")) + +load(pathJoin("wgrib2", os.getenv("wgrib2_ver") or "2.0.8")) + +prepend_path("MODULEPATH", "/scratch2/BMC/rtrr/gge/lua") +load("prod_util/2.0.15") + +unload("fms/2023.02.01") +unload("g2tmpl/1.10.2") +setenv("g2tmpl_ROOT","/scratch1/BMC/wrfruc/mhu/rrfs/lib/g2tmpl/install") +setenv("FMS_ROOT","/scratch1/BMC/wrfruc/mhu/rrfs/lib/fms.2024.01/build") + +setenv("CMAKE_C_COMPILER","mpiicc") +setenv("CMAKE_CXX_COMPILER","mpiicpc") +setenv("CMAKE_Fortran_COMPILER","mpiifort") +setenv("CMAKE_Platform","hera.intel") +setenv("BLENDINGPYTHON","/contrib/miniconda3/4.5.12/envs/pygraf/bin/python") From 8bac93121b1450ebf255f51677400bf4560c40e9 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Thu, 15 Aug 2024 17:34:35 +0000 Subject: [PATCH 02/61] add scripts for smoke/dust --- jobs/JSRW_SMOKE_DUST | 163 +++++++++++++++++++++ scripts/exsrw_smoke_dust.sh | 259 +++++++++++++++++++++++++++++++++ ush/HWP_tools.py | 157 ++++++++++++++++++++ ush/fire_emiss_tools.py | 192 ++++++++++++++++++++++++ ush/generate_fire_emissions.py | 108 ++++++++++++++ ush/interp_tools.py | 230 +++++++++++++++++++++++++++++ 6 files changed, 1109 insertions(+) create mode 100755 jobs/JSRW_SMOKE_DUST create mode 100755 scripts/exsrw_smoke_dust.sh create mode 100755 ush/HWP_tools.py create mode 100755 ush/fire_emiss_tools.py create mode 100755 ush/generate_fire_emissions.py create mode 100755 ush/interp_tools.py diff --git a/jobs/JSRW_SMOKE_DUST b/jobs/JSRW_SMOKE_DUST new file mode 100755 index 0000000000..d448dce43b --- /dev/null +++ b/jobs/JSRW_SMOKE_DUST @@ -0,0 +1,163 @@ +#!/usr/bin/env bash + +# +#----------------------------------------------------------------------- +# +# This script processes smoke and dust +# +#----------------------------------------------------------------------- +# +date +export PS4='+ $SECONDS + ' +set -xue +# +#----------------------------------------------------------------------- +# +# Set the NCO standard environment variables (Table 1, pp.4) +# +#----------------------------------------------------------------------- +# +export USHsrw="${HOMEdir}/ush" +export EXECsrw="${HOMEdir}/exec" +export PARMsrw="${HOMEdir}/parm" +export SCRIPTSsrw="${HOMEdir}/scripts" +# +#----------------------------------------------------------------------- +# +# Source the variable definitions file and the bash utility functions. +# +#----------------------------------------------------------------------- +# +export USHdir="${USHsrw}" # should be removed later +. ${USHsrw}/source_util_funcs.sh +for sect in user nco platform workflow nco global cpl_aqm_parm cpl_aqm_parm ; do + source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} +done +# +#----------------------------------------------------------------------- +# +# Get the full path to the file in which this script/function is located +# (scrfunc_fp), the name of that file (scrfunc_fn), and the directory in +# which the file is located (scrfunc_dir). +# +#----------------------------------------------------------------------- +# +scrfunc_fp=$( $READLINK -f "${BASH_SOURCE[0]}" ) +scrfunc_fn=$( basename "${scrfunc_fp}" ) +scrfunc_dir=$( dirname "${scrfunc_fp}" ) +# +#----------------------------------------------------------------------- +# +# Print message indicating entry into script. +# +#----------------------------------------------------------------------- +# +print_info_msg " +======================================================================== +Entering script: \"${scrfunc_fn}\" +In directory: \"${scrfunc_dir}\" + +This is the J-job script for the task that copies or fetches RAVE fire +emission data files from disk, or HPSS. +========================================================================" +# +#----------------------------------------------------------------------- +# +# Define job and jobid by default for rocoto +# +#----------------------------------------------------------------------- +# +WORKFLOW_MANAGER="${WORKFLOW_MANAGER:-rocoto}" +if [ "${WORKFLOW_MANAGER}" = "rocoto" ]; then + if [ "${SCHED}" = "slurm" ]; then + job=${SLURM_JOB_NAME} + pid=${SLURM_JOB_ID} + elif [ "${SCHED}" = "pbspro" ]; then + job=${PBS_JOBNAME} + pid=${PBS_JOBID} + else + job="task" + pid=$$ + fi + jobid="${job}.${PDY}${cyc}.${pid}" +fi +# +#----------------------------------------------------------------------- +# +# Create a temp working directory (DATA) and cd into it. +# +#----------------------------------------------------------------------- +# +export DATA="${DATA:-${DATAROOT}/${jobid}}" +mkdir -p $DATA +cd $DATA +# +#----------------------------------------------------------------------- +# +# Define NCO environment variables and set COM type definitions. +# +#----------------------------------------------------------------------- +# +export NET="${NET:-${NET_default}}" +export RUN="${RUN:-${RUN_default}}" + +[[ "$WORKFLOW_MANAGER" = "rocoto" ]] && export COMROOT=$COMROOT +if [ "${MACHINE}" = "WCOSS2" ]; then + export COMIN="${COMIN:-$(compath.py -o ${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR})}" + export COMOUT="${COMOUT:-$(compath.py -o ${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR})}" +else + export COMIN="${COMIN:-${COMROOT}/${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR}}" + export COMOUT="${COMOUT:-${COMROOT}/${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR}}" +fi + +mkdir -p ${COMOUT} + +export COMINfire="${COMINfire:-${COMINfire_default}}" + +# Run setpdy to initialize PDYm and PDYp variables +export cycle="${cycle:-t${cyc}z}" +setpdy.sh +. ./PDY +# +#----------------------------------------------------------------------- +# +# Set sub-cycle and ensemble member names in file/diectory names +# +#----------------------------------------------------------------------- +# +if [ ${subcyc} -ne 0 ]; then + export cycle="t${cyc}${subcyc}z" +fi +if [ $(boolify "${DO_ENSEMBLE}") = "TRUE" ] && [ ! -z ${ENSMEM_INDX} ]; then + export dot_ensmem=".mem${ENSMEM_INDX}" +else + export dot_ensmem= +fi +# +#----------------------------------------------------------------------- +# +# Call the ex-script for this J-job. +# +#----------------------------------------------------------------------- +# +export pgmout="${DATA}/OUTPUT.$$" +env + +${SCRIPTSsrw}/exsrw_smoke_dust.sh +export err=$?; err_chk + +if [ -e "$pgmout" ]; then + cat $pgmout +fi +# +#----------------------------------------------------------------------- +# +# Whether or not working directory DATA should be kept. +# +#----------------------------------------------------------------------- +# +if [ "${KEEPDATA}" = "NO" ]; then + rm -rf ${DATA} +fi +date + diff --git a/scripts/exsrw_smoke_dust.sh b/scripts/exsrw_smoke_dust.sh new file mode 100755 index 0000000000..55140ae11e --- /dev/null +++ b/scripts/exsrw_smoke_dust.sh @@ -0,0 +1,259 @@ +#!/bin/bash + +# +# +#----------------------------------------------------------------------- +# +# Source the variable definitions file and the bash utility functions. +# +#----------------------------------------------------------------------- +# +. ${GLOBAL_VAR_DEFNS_FP} +. $USHdir/source_util_funcs.sh +# +#----------------------------------------------------------------------- +# +# Save current shell options (in a global array). Then set new options +# for this script/function. +# +#----------------------------------------------------------------------- +# +{ save_shell_opts; set -u -x; } > /dev/null 2>&1 +# +#----------------------------------------------------------------------- +# +# Get the full path to the file in which this script/function is located +# (scrfunc_fp), the name of that file (scrfunc_fn), and the directory in +# which the file is located (scrfunc_dir). +# +#----------------------------------------------------------------------- +# +scrfunc_fp=$( readlink -f "${BASH_SOURCE[0]}" ) +scrfunc_fn=$( basename "${scrfunc_fp}" ) +scrfunc_dir=$( dirname "${scrfunc_fp}" ) +# +#----------------------------------------------------------------------- +# +# Print message indicating entry into script. +# +#----------------------------------------------------------------------- +# +print_info_msg " +======================================================================== +Entering script: \"${scrfunc_fn}\" +In directory: \"${scrfunc_dir}\" + +This is the script for the task that runs smoke emissions preprocessing. +========================================================================" +# +#----------------------------------------------------------------------- +# +# Set the name of and create the directory in which the output from this +# script will be saved for long time (if that directory doesn't already exist). +# +#----------------------------------------------------------------------- +# +export rave_nwges_dir=${NWGES_DIR}/RAVE_INTP +mkdir -p "${rave_nwges_dir}" +export hourly_hwpdir=${NWGES_BASEDIR}/HOURLY_HWP +mkdir -p "${hourly_hwpdir}" +# +#----------------------------------------------------------------------- +# +# Link the the hourly, interpolated RAVE data from $rave_nwges_dir so it +# is reused +# +#----------------------------------------------------------------------- +ECHO=/bin/echo +SED=/bin/sed +DATE=/bin/date +LN=/bin/ln +ebb_dc=${EBB_DCYCLE} + +# Start date manipulation +START_DATE=$(${ECHO} "${CDATE}" | ${SED} 's/\([[:digit:]]\{2\}\)$/ \1/') +YYYYMMDDHH=$(${DATE} +%Y%m%d%H -d "${START_DATE}") +YYYYMMDD=${YYYYMMDDHH:0:8} +HH=${YYYYMMDDHH:8:2} +${ECHO} ${YYYYMMDD} +${ECHO} ${HH} + +# Current and previous day calculation +current_day=`${DATE} -d "${YYYYMMDD}"` +current_hh=`${DATE} -d ${HH} +"%H"` + +prev_hh=`${DATE} -d "$current_hh -24 hour" +"%H"` +previous_day=`${DATE} '+%C%y%m%d' -d "$current_day-1 days"` +previous_day="${previous_day} ${prev_hh}" + +# Number of files to process +nfiles=24 +smokeFile=SMOKE_RRFS_data_${YYYYMMDDHH}00.nc + +for i in $(seq 0 $(($nfiles - 1)) ) +do + if [ "$ebb_dc" -eq 2 ]; then + + # For ebb_dc == 2 + timestr=`date +%Y%m%d%H -d "$previous_day + $i hours"` + intp_fname=${PREDEF_GRID_NAME}_intp_${timestr}00_${timestr}59.nc + else + # For ebb_dc == 1 + timestr=`date +%Y%m%d%H -d "$current_day $current_hh + $i hours"` + intp_fname=${PREDEF_GRID_NAME}_intp_${timestr}00_${timestr}59.nc + fi + + if [ -f ${rave_nwges_dir}/${intp_fname} ]; then + ${LN} -sf ${rave_nwges_dir}/${intp_fname} ${workdir}/${intp_fname} + echo "${rave_nwges_dir}/${intp_fname} interoplated file available to reuse" + else + echo "${rave_nwges_dir}/${intp_fname} interoplated file non available to reuse" + fi +done + +#----------------------------------------------------------------------- +# +# link RAVE data to work directory $workdir +# +#----------------------------------------------------------------------- + +previous_2day=`${DATE} '+%C%y%m%d' -d "$current_day-2 days"` +YYYYMMDDm1=${previous_day:0:8} +YYYYMMDDm2=${previous_2day:0:8} +if [ -d ${FIRE_RAVE_DIR}/${YYYYMMDDm1}/rave ]; then + fire_rave_dir_work=${workdir} + ln -snf ${FIRE_RAVE_DIR}/${YYYYMMDD}/rave/RAVE-HrlyEmiss-3km_* ${fire_rave_dir_work}/. + ln -snf ${FIRE_RAVE_DIR}/${YYYYMMDDm1}/rave/RAVE-HrlyEmiss-3km_* ${fire_rave_dir_work}/. + ln -snf ${FIRE_RAVE_DIR}/${YYYYMMDDm2}/rave/RAVE-HrlyEmiss-3km_* ${fire_rave_dir_work}/. +else + fire_rave_dir_work=${FIRE_RAVE_DIR} +fi + +# Check whether the RAVE files need to be split into hourly files +# Format the current day and hour properly for UTC +if [ "$ebb_dc" -eq 1 ]; then + ddhh_to_use="${current_day}${current_hh}" + dd_to_use="${current_day}" +else + ddhh_to_use="${previous_day}${prev_hh}" + dd_to_use="${previous_day}" +fi + +# Construct file names and check their existence +intp_fname="${fire_rave_dir_work}/RAVE-HrlyEmiss-3km_v2r0_blend_s${ddhh_to_use}00000_e${dd_to_use}23*" +intp_fname_beta="${fire_rave_dir_work}/Hourly_Emissions_3km_${ddhh_to_use}00_${dd_to_use}23*" + +echo "Checking for files in directory: $fire_rave_dir_work" + +# Find files matching the specified patterns +files_found=$(find "$fire_rave_dir_work" -type f \( -name "${intp_fname##*/}" -o -name "${intp_fname_beta##*/}" \)) + +if [ -z "$files_found" ]; then + echo "No files found matching patterns." +else + echo "Files found, proceeding with processing..." + for file_to_use in $files_found; do + echo "Using file: $file_to_use" + for hour in {00..23}; do + output_file="${fire_rave_dir_work}/Hourly_Emissions_3km_${dd_to_use}${hour}00_${dd_to_use}${hour}00.nc" + if [ -f "$output_file" ]; then + echo "Output file for hour $hour already exists: $output_file. Skipping..." + continue + fi + echo "Splitting data for hour $hour..." + ncks -d time,$hour,$hour "$file_to_use" "$output_file" + done + echo "Hourly files processing completed for: $file_to_use" + done +fi + +# +#----------------------------------------------------------------------- +# +# Call the ex-script for this J-job. +# +#----------------------------------------------------------------------- +# +python -u ${USHdir}/generate_fire_emissions.py \ + "${FIX_SMOKE_DUST}/${PREDEF_GRID_NAME}" \ + "${fire_rave_dir_work}" \ + "${workdir}" \ + "${PREDEF_GRID_NAME}" \ + "${EBB_DCYCLE}" \ + "${RESTART_INTERVAL}" \ + +# Capture the return code from the previous command +err=$? +echo "Return code from generate_fire_emissions.py: $err" +export err + +# Check the return code before calling err_chk +if [ $err -ne 0 ]; then + echo "Error: generate_fire_emissions.py failed with return code $err" + err_chk +fi + +#Copy the the hourly, interpolated RAVE data to $rave_nwges_dir so it +# is maintained there for future cycles. +# Function to check if all files in the directory are older than 15 days + +are_all_files_older_than_15_days() { + find "$1" -type f -mtime -15 | read + return $? +} + +# Check if all files in the rave_nwges_dir are older than 5 days +if are_all_files_older_than_15_days "${rave_nwges_dir}"; then + echo "All files are older than 5 days. Replacing all files." + + # Loop through all files in the work directory and replace them in rave_nwges_dir + for file in ${workdir}/*; do + filename=$(basename "$file") + target_file="${rave_nwges_dir}/${filename}" + + cp "${file}" "${target_file}" + echo "Copied file: $filename" + done +else + echo "Not all files are older than 5 days. Checking individual files." + + # Loop through all files in the work directory + for file in ${workdir}/*; do + filename=$(basename "$file") + target_file="${rave_nwges_dir}/${filename}" + + # Check if the file matches the pattern or is missing in the target directory + if [[ "$filename" =~ SMOKE_RRFS_data_.*\.nc ]]; then + cp "${file}" "${target_file}" + echo "Copied file: $filename" + elif [ ! -f "${target_file}" ]; then + cp "${file}" "${target_file}" + echo "Copied missing file: $filename" + fi + done +fi + +echo "Copy RAVE interpolated files completed" + +# +#----------------------------------------------------------------------- +# +# Print exit message. +# +#----------------------------------------------------------------------- +# +print_info_msg " +======================================================================== +Exiting script: \"${scrfunc_fn}\" +In directory: \"${scrfunc_dir}\" +========================================================================" +# +#----------------------------------------------------------------------- +# +# Restore the shell options saved at the beginning of this script/function. +# +#----------------------------------------------------------------------- +# +{ restore_shell_opts; } > /dev/null 2>&1 + + diff --git a/ush/HWP_tools.py b/ush/HWP_tools.py new file mode 100755 index 0000000000..5a8faf18d2 --- /dev/null +++ b/ush/HWP_tools.py @@ -0,0 +1,157 @@ +import numpy as np +import os +import datetime as dt +import shutil +from datetime import timedelta +import xarray as xr +import fnmatch + +def check_restart_files(hourly_hwpdir, fcst_dates): + hwp_avail_hours = [] + hwp_non_avail_hours = [] + + for cycle in fcst_dates: + restart_file = f"{cycle[:8]}.{cycle[8:10]}0000.phy_data.nc" + file_path = os.path.join(hourly_hwpdir, restart_file) + + if os.path.exists(file_path): + print(f'Restart file available for: {restart_file}') + hwp_avail_hours.append(cycle) + else: + print(f'Copy restart file for: {restart_file}') + hwp_non_avail_hours.append(cycle) + + print(f'Available restart at: {hwp_avail_hours}, Non-available restart files at: {hwp_non_avail_hours}') + return(hwp_avail_hours, hwp_non_avail_hours) + +def copy_missing_restart(nwges_dir, hwp_non_avail_hours, hourly_hwpdir, len_restart_interval): + restart_avail_hours = [] + restart_nonavail_hours_test = [] + + for cycle in hwp_non_avail_hours: + try: + YYYYMMDDHH = dt.datetime.strptime(cycle, "%Y%m%d%H") + HH = cycle[8:10] + prev_hr = YYYYMMDDHH - timedelta(hours=1) + prev_hr_str = prev_hr.strftime("%Y%m%d%H") + + source_restart_dir = os.path.join(nwges_dir, prev_hr_str, 'fcst_fv3lam', 'RESTART') + wildcard_name = '*.phy_data.nc' + + if len_restart_interval > 1: + print('ENTERING LOOP for len_restart_interval > 1') + if os.path.exists(source_restart_dir): + matching_files_found = False + print('PATH EXISTS') + for file in sorted(os.listdir(source_restart_dir)): + if fnmatch.fnmatch(file, wildcard_name): + matching_files_found = True + print('MATCHING FILES FOUND') + source_file_path = os.path.join(source_restart_dir, file) + target_file_path = os.path.join(hourly_hwpdir, file) + var1, var2 = 'rrfs_hwp_ave', 'totprcp_ave' + if os.path.exists(source_file_path): + with xr.open_dataset(source_file_path) as ds: + try: + if var1 in ds.variables and var2 in ds.variables: + ds = ds[[var1, var2]] + ds.to_netcdf(target_file_path) + restart_avail_hours.append(cycle) + print(f'Restart file copied: {file}') + else: + print(f'Missing variables {var1} or {var2} in {file}. Skipping file.') + except AttributeError as e: + print(f"AttributeError processing NetCDF file {source_file_path}: {e}") + else: + print(f"Source file not found: {source_file_path}") + if not matching_files_found: + print('No matching files found') + restart_nonavail_hours_test.append(cycle) + else: + print(f"Source directory not found: {source_restart_dir}") + restart_nonavail_hours_test.append(cycle) + else: + if os.path.exists(source_restart_dir): + try: + matching_files = [f for f in os.listdir(source_restart_dir) if fnmatch.fnmatch(f, wildcard_name)] + if not matching_files: + print(f"No matching files for cycle {cycle} in {source_restart_dir}") + restart_nonavail_hours_test.append(cycle) + continue + + for matching_file in matching_files: + source_file_path = os.path.join(source_restart_dir, matching_file) + target_file_path = os.path.join(hourly_hwpdir, matching_file) + var1, var2 = 'rrfs_hwp_ave', 'totprcp_ave' + + if os.path.exists(source_file_path): + try: + with xr.open_dataset(source_file_path) as ds: + if var1 in ds.variables and var2 in ds.variables: + ds = ds[[var1, var2]] + ds.to_netcdf(target_file_path) + restart_avail_hours.append(cycle) + print(f'Restart file copied: {matching_file}') + else: + print(f'Missing variables {var1} or {var2} in {matching_file}. Skipping file.') + except (FileNotFoundError, IOError, OSError, RuntimeError, ValueError, TypeError, KeyError, IndexError, MemoryError) as e: + print(f"Error processing NetCDF file {source_file_path}: {e}") + restart_nonavail_hours_test.append(cycle) + else: + print(f"Source file not found: {source_file_path}") + restart_nonavail_hours_test.append(cycle) + except (FileNotFoundError, IOError, OSError, RuntimeError) as e: + print(f"Error accessing directory {source_restart_dir}: {e}") + restart_nonavail_hours_test.append(cycle) + else: + print(f"Source directory not found: {source_restart_dir}") + restart_nonavail_hours_test.append(cycle) + + except (ValueError, TypeError) as e: + print(f"Error processing cycle {cycle}: {e}") + restart_nonavail_hours_test.append(cycle) + + return(restart_avail_hours, restart_nonavail_hours_test) + +def process_hwp(fcst_dates, hourly_hwpdir, cols, rows, intp_dir, rave_to_intp): + hwp_ave = [] + totprcp = np.zeros((cols*rows)) + var1, var2 = 'rrfs_hwp_ave', 'totprcp_ave' + + for cycle in fcst_dates: + try: + print(f'Processing restart file for date: {cycle}') + file_path = os.path.join(hourly_hwpdir, f"{cycle[:8]}.{cycle[8:10]}0000.phy_data.nc") + rave_path = os.path.join(intp_dir, f"{rave_to_intp}{cycle}00_{cycle}59.nc") + + if os.path.exists(file_path) and os.path.exists(rave_path): + try: + with xr.open_dataset(file_path) as nc: + if var1 in nc.variables and var2 in nc.variables: + hwp_values = nc.rrfs_hwp_ave.values.ravel() + tprcp_values = nc.totprcp_ave.values.ravel() + totprcp += np.where(tprcp_values > 0, tprcp_values, 0) + hwp_ave.append(hwp_values) + print(f'Restart file processed for: {cycle}') + else: + print(f'Missing variables {var1} or {var2} in file: {file_path}') + except (FileNotFoundError, IOError, OSError, RuntimeError, ValueError, TypeError, KeyError, IndexError, MemoryError) as e: + print(f"Error processing NetCDF file {file_path}: {e}") + else: + print(f'One or more files non-available for this cycle: {file_path}, {rave_path}') + except (ValueError, TypeError) as e: + print(f"Error processing cycle {cycle}: {e}") + + # Calculate the mean HWP values if available + if hwp_ave: + hwp_ave_arr = np.nanmean(hwp_ave, axis=0).reshape(cols, rows) + totprcp_ave_arr = totprcp.reshape(cols, rows) + else: + hwp_ave_arr = np.zeros((cols, rows)) + totprcp_ave_arr = np.zeros((cols, rows)) + + xarr_hwp = xr.DataArray(hwp_ave_arr) + xarr_totprcp = xr.DataArray(totprcp_ave_arr) + + return(hwp_ave_arr, xarr_hwp, totprcp_ave_arr, xarr_totprcp) + diff --git a/ush/fire_emiss_tools.py b/ush/fire_emiss_tools.py new file mode 100755 index 0000000000..7f90e1f82a --- /dev/null +++ b/ush/fire_emiss_tools.py @@ -0,0 +1,192 @@ +import os +import numpy as np +import xarray as xr +from datetime import datetime +from netCDF4 import Dataset +import interp_tools as i_tools + +#Compute average FRP from raw RAVE for the previous 24 hours +def averaging_FRP(ebb_dcycle, fcst_dates, cols, rows, intp_dir, rave_to_intp, veg_map, tgt_area, beta, fg_to_ug, to_s): + base_array = np.zeros((cols*rows)) + frp_daily = base_array + ebb_smoke_total = [] + ebb_smoke_hr = [] + frp_avg_hr = [] + + try: + ef_map = xr.open_dataset(veg_map) + emiss_factor = ef_map.emiss_factor.values + target_area = tgt_area.values + except (FileNotFoundError, IOError, OSError, RuntimeError, ValueError, TypeError, KeyError, IndexError, MemoryError) as e: + print(f"Error loading vegetation map: {e}") + return np.zeros((cols, rows)), np.zeros((cols, rows)) + + num_files = 0 + for cycle in fcst_dates: + try: + file_path = os.path.join(intp_dir, f'{rave_to_intp}{cycle}00_{cycle}59.nc') + if os.path.exists(file_path): + try: + with xr.open_dataset(file_path) as nc: + open_fre = nc.FRE[0, :, :].values + open_frp = nc.frp_avg_hr[0, :, :].values + num_files += 1 + if ebb_dcycle == 1: + print('Processing emissions for ebb_dcyc 1') + print(file_path) + frp_avg_hr.append(open_frp) + ebb_hourly = (open_fre * emiss_factor * beta * fg_to_ug) / (target_area * to_s) + ebb_smoke_total.append(np.where(open_frp > 0, ebb_hourly, 0)) + else: + print('Processing emissions for ebb_dcyc 2') + ebb_hourly = open_fre * emiss_factor * beta * fg_to_ug / target_area + ebb_smoke_total.append(np.where(open_frp > 0, ebb_hourly, 0).ravel()) + frp_daily += np.where(open_frp > 0, open_frp, 0).ravel() + except (FileNotFoundError, IOError, OSError, RuntimeError, ValueError, TypeError, KeyError, IndexError, MemoryError) as e: + print(f"Error processing NetCDF file {file_path}: {e}") + if ebb_dcycle == 1: + frp_avg_hr.append(np.zeros((cols, rows))) + ebb_smoke_total.append(np.zeros((cols, rows))) + else: + if ebb_dcycle == 1: + frp_avg_hr.append(np.zeros((cols, rows))) + ebb_smoke_total.append(np.zeros((cols, rows))) + except Exception as e: + print(f"Error processing cycle {cycle}: {e}") + if ebb_dcycle == 1: + frp_avg_hr.append(np.zeros((cols, rows))) + ebb_smoke_total.append(np.zeros((cols, rows))) + + if num_files > 0: + if ebb_dcycle == 1: + frp_avg_reshaped = np.stack(frp_avg_hr, axis=0) + ebb_total_reshaped = np.stack(ebb_smoke_total, axis=0) + else: + summed_array = np.sum(np.array(ebb_smoke_total), axis=0) + num_zeros = len(ebb_smoke_total) - np.sum([arr == 0 for arr in ebb_smoke_total], axis=0) + safe_zero_count = np.where(num_zeros == 0, 1, num_zeros) + result_array = [summed_array[i] / 2 if safe_zero_count[i] == 1 else summed_array[i] / safe_zero_count[i] for i in range(len(safe_zero_count))] + result_array = np.array(result_array) + result_array[num_zeros == 0] = summed_array[num_zeros == 0] + ebb_total = result_array.reshape(cols, rows) + ebb_total_reshaped = ebb_total / 3600 + temp_frp = [frp_daily[i] / 2 if safe_zero_count[i] == 1 else frp_daily[i] / safe_zero_count[i] for i in range(len(safe_zero_count))] + temp_frp = np.array(temp_frp) + temp_frp[num_zeros == 0] = frp_daily[num_zeros == 0] + frp_avg_reshaped = temp_frp.reshape(cols, rows) + else: + if ebb_dcycle == 1: + frp_avg_reshaped = np.zeros((24, cols, rows)) + ebb_total_reshaped = np.zeros((24, cols, rows)) + else: + frp_avg_reshaped = np.zeros((cols, rows)) + ebb_total_reshaped = np.zeros((cols, rows)) + + return(frp_avg_reshaped, ebb_total_reshaped) + +def estimate_fire_duration(intp_avail_hours, intp_dir, fcst_dates, current_day, cols, rows, rave_to_intp): + # There are two steps here. + # 1) First day simulation no RAVE from previous 24 hours available (fire age is set to zero) + # 2) previus files are present (estimate fire age as the difference between the date of the current cycle and the date whe the fire was last observed whiting 24 hours) + t_fire = np.zeros((cols, rows)) + + for date_str in fcst_dates: + try: + date_file = int(date_str[:10]) + print('Date processing for fire duration', date_file) + file_path = os.path.join(intp_dir, f'{rave_to_intp}{date_str}00_{date_str}59.nc') + + if os.path.exists(file_path): + try: + with xr.open_dataset(file_path) as open_intp: + FRP = open_intp.frp_avg_hr[0, :, :].values + dates_filtered = np.where(FRP > 0, date_file, 0) + t_fire = np.maximum(t_fire, dates_filtered) + except (FileNotFoundError, IOError, OSError,RuntimeError,ValueError, TypeError, KeyError, IndexError, MemoryError) as e: + print(f"Error processing NetCDF file {file_path}: {e}") + except Exception as e: + print(f"Error processing date {date_str}: {e}") + + t_fire_flattened = t_fire.flatten() + t_fire_flattened = [int(i) if i != 0 else 0 for i in t_fire_flattened] + + try: + fcst_t = datetime.strptime(current_day, '%Y%m%d%H') + hr_ends = [datetime.strptime(str(hr), '%Y%m%d%H') if hr != 0 else 0 for hr in t_fire_flattened] + te = [(fcst_t - i).total_seconds() / 3600 if i != 0 else 0 for i in hr_ends] + except ValueError as e: + print(f"Error processing forecast time {current_day}: {e}") + te = np.zeros((rows, cols)) + + return(te) + +def save_fire_dur(cols, rows, te): + fire_dur = np.array(te).reshape(cols, rows) + return(fire_dur) + +def produce_emiss_24hr_file(ebb_dcycle, frp_reshaped, intp_dir, current_day, tgt_latt, tgt_lont, ebb_smoke_reshaped, cols, rows): + file_path = os.path.join(intp_dir, f'SMOKE_RRFS_data_{current_day}00.nc') + with Dataset(file_path, 'w') as fout: + i_tools.create_emiss_file(fout, cols, rows) + i_tools.Store_latlon_by_Level(fout, 'geolat', tgt_latt, 'cell center latitude', 'degrees_north', '2D', '-9999.f', '1.f') + i_tools.Store_latlon_by_Level(fout, 'geolon', tgt_lont, 'cell center longitude', 'degrees_east', '2D', '-9999.f', '1.f') + + i_tools.Store_by_Level(fout,'frp_avg_hr','mean Fire Radiative Power','MW','3D','0.f','1.f') + fout.variables['frp_avg_hr'][:, :, :] = frp_reshaped + i_tools.Store_by_Level(fout,'ebb_smoke_hr','EBB emissions','ug m-2 s-1','3D','0.f','1.f') + fout.variables['ebb_smoke_hr'][:, :, :] = ebb_smoke_reshaped + +def produce_emiss_file(xarr_hwp, frp_avg_reshaped, totprcp_ave_arr, xarr_totprcp, intp_dir, current_day, tgt_latt, tgt_lont, ebb_tot_reshaped, fire_age, cols, rows): + # Ensure arrays are not negative or NaN + frp_avg_reshaped = np.clip(frp_avg_reshaped, 0, None) + frp_avg_reshaped = np.nan_to_num(frp_avg_reshaped) + + ebb_tot_reshaped = np.clip(ebb_tot_reshaped, 0, None) + ebb_tot_reshaped = np.nan_to_num(ebb_tot_reshaped) + + fire_age = np.clip(fire_age, 0, None) + fire_age = np.nan_to_num(fire_age) + + # Filter HWP Prcp arrays to be non-negative and replace NaNs + filtered_hwp = xarr_hwp.where(frp_avg_reshaped > 0, 0).fillna(0) + filtered_prcp = xarr_totprcp.where(frp_avg_reshaped > 0, 0).fillna(0) + + # Filter based on ebb_rate + ebb_rate_threshold = 0 # Define an appropriate threshold if needed + mask = (ebb_tot_reshaped > ebb_rate_threshold) + + filtered_hwp = filtered_hwp.where(mask, 0).fillna(0) + filtered_prcp = filtered_prcp.where(mask, 0).fillna(0) + frp_avg_reshaped = frp_avg_reshaped * mask + ebb_tot_reshaped = ebb_tot_reshaped * mask + fire_age = fire_age * mask + + # Produce emiss file + file_path = os.path.join(intp_dir, f'SMOKE_RRFS_data_{current_day}00.nc') + + try: + with Dataset(file_path, 'w') as fout: + i_tools.create_emiss_file(fout, cols, rows) + i_tools.Store_latlon_by_Level(fout, 'geolat', tgt_latt, 'cell center latitude', 'degrees_north', '2D', '-9999.f', '1.f') + i_tools.Store_latlon_by_Level(fout, 'geolon', tgt_lont, 'cell center longitude', 'degrees_east', '2D', '-9999.f', '1.f') + + print('Storing different variables') + i_tools.Store_by_Level(fout, 'frp_davg', 'Daily mean Fire Radiative Power', 'MW', '3D', '0.f', '1.f') + fout.variables['frp_davg'][0, :, :] = frp_avg_reshaped + i_tools.Store_by_Level(fout, 'ebb_rate', 'Total EBB emission', 'ug m-2 s-1', '3D', '0.f', '1.f') + fout.variables['ebb_rate'][0, :, :] = ebb_tot_reshaped + i_tools.Store_by_Level(fout, 'fire_end_hr', 'Hours since fire was last detected', 'hrs', '3D', '0.f', '1.f') + fout.variables['fire_end_hr'][0, :, :] = fire_age + i_tools.Store_by_Level(fout, 'hwp_davg', 'Daily mean Hourly Wildfire Potential', 'none', '3D', '0.f', '1.f') + fout.variables['hwp_davg'][0, :, :] = filtered_hwp + i_tools.Store_by_Level(fout, 'totprcp_24hrs', 'Sum of precipitation', 'm', '3D', '0.f', '1.f') + fout.variables['totprcp_24hrs'][0, :, :] = filtered_prcp + + print("Emissions file created successfully") + return "Emissions file created successfully" + + except (OSError, IOError) as e: + print(f"Error creating or writing to NetCDF file {file_path}: {e}") + return f"Error creating or writing to NetCDF file {file_path}: {e}" + + return "Emissions file created successfully" diff --git a/ush/generate_fire_emissions.py b/ush/generate_fire_emissions.py new file mode 100755 index 0000000000..3cc84ed4dc --- /dev/null +++ b/ush/generate_fire_emissions.py @@ -0,0 +1,108 @@ +######################################################################### +# # +# Python script for fire emissions preprocessing from RAVE FRP and FRE # +# (Li et al.,2022). # +# johana.romero-alvarez@noaa.gov # +# # +######################################################################### +import sys +import os +import time +import numpy as np +import fire_emiss_tools as femmi_tools +import HWP_tools +import interp_tools as i_tools + +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Workflow +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def generate_emiss_workflow(staticdir, ravedir, newges_dir, predef_grid, ebb_dcycle, restart_interval): + + # ---------------------------------------------------------------------- + # Import envs from workflow and get the predifying grid + # Set variable names, constants and unit conversions + # Set predefined grid + # Set directories + # ---------------------------------------------------------------------- + beta = 0.3 + fg_to_ug = 1e6 + to_s = 3600 + current_day = os.environ.get("CDATE") + nwges_dir = os.environ.get("NWGES_DIR") + vars_emis = ["FRP_MEAN","FRE"] + cols, rows = (2700, 3950) if predef_grid == 'RRFS_NA_3km' else (1092, 1820) + print('PREDEF GRID',predef_grid,'cols,rows',cols,rows) + print('WARNING, EBB_DCYCLE set to', ebb_dcycle, 'emissions are comes from same day satellite obs') + #used later when working with ebb_dcyle 1 or 2 + ebb_dcycle = float(ebb_dcycle) + + #This is used later when copying the rrfs restart file + restart_interval = restart_interval.split() + restart_interval_list = [float(num) for num in restart_interval] + len_restart_interval = len(restart_interval_list) + + #Setting the directories + veg_map = staticdir+'/veg_map.nc' + RAVE= ravedir + rave_to_intp = predef_grid+"_intp_" + intp_dir = newges_dir + grid_in = staticdir+'/grid_in.nc' + weightfile = staticdir+'/weight_file.nc' + grid_out = staticdir+'/ds_out_base.nc' + hourly_hwpdir = os.path.join(nwges_dir,'HOURLY_HWP') + + # ---------------------------------------------------------------------- + # Workflow + # ---------------------------------------------------------------------- + + # ---------------------------------------------------------------------- + # Sort raw RAVE, create source and target filelds, and compute emissions + # ---------------------------------------------------------------------- + fcst_dates = i_tools.date_range(current_day, ebb_dcycle) + intp_avail_hours, intp_non_avail_hours, inp_files_2use = i_tools.check_for_intp_rave(intp_dir, fcst_dates, rave_to_intp) + rave_avail, rave_avail_hours, rave_nonavail_hours_test, first_day = i_tools.check_for_raw_rave(RAVE, intp_non_avail_hours, intp_avail_hours) + srcfield, tgtfield, tgt_latt, tgt_lont, srcgrid, tgtgrid, src_latt, tgt_area = i_tools.creates_st_fields(grid_in, grid_out, intp_dir, rave_avail_hours) + + if not first_day: + regridder, use_dummy_emiss = i_tools.generate_regrider(rave_avail_hours, srcfield, tgtfield, weightfile, inp_files_2use, intp_avail_hours) + if use_dummy_emiss: + print('RAVE files corrupted, no data to process') + i_tools.create_dummy(intp_dir, current_day, tgt_latt, tgt_lont, cols, rows) + else: + i_tools.interpolate_rave(RAVE, rave_avail, rave_avail_hours, + use_dummy_emiss, vars_emis, regridder, srcgrid, tgtgrid, rave_to_intp, + intp_dir, src_latt, tgt_latt, tgt_lont, cols, rows) + + if ebb_dcycle == 1: + print('Processing emissions for ebb_dcyc 1') + frp_avg_reshaped, ebb_total_reshaped = femmi_tools.averaging_FRP(ebb_dcycle, fcst_dates, cols, rows, intp_dir, rave_to_intp, veg_map, tgt_area, beta, fg_to_ug, to_s) + femmi_tools.produce_emiss_24hr_file(ebb_dcycle, frp_avg_reshaped, intp_dir, current_day, tgt_latt, tgt_lont, ebb_total_reshaped, cols, rows) + elif ebb_dcycle == 2: + print('Restart dates to process',fcst_dates) + hwp_avail_hours, hwp_non_avail_hours = HWP_tools.check_restart_files(hourly_hwpdir, fcst_dates) + restart_avail, restart_nonavail_hours_test = HWP_tools.copy_missing_restart(nwges_dir, hwp_non_avail_hours, hourly_hwpdir, len_restart_interval) + hwp_ave_arr, xarr_hwp, totprcp_ave_arr, xarr_totprcp = HWP_tools.process_hwp(fcst_dates, hourly_hwpdir, cols, rows, intp_dir, rave_to_intp) + frp_avg_reshaped, ebb_total_reshaped = femmi_tools.averaging_FRP(ebb_dcycle, fcst_dates, cols, rows, intp_dir, rave_to_intp, veg_map, tgt_area, beta, fg_to_ug, to_s) + #Fire end hours processing + te = femmi_tools.estimate_fire_duration(intp_avail_hours, intp_dir, fcst_dates, current_day, cols, rows, rave_to_intp) + fire_age = femmi_tools.save_fire_dur(cols, rows, te) + #produce emiss file + femmi_tools.produce_emiss_file(xarr_hwp, frp_avg_reshaped, totprcp_ave_arr, xarr_totprcp, intp_dir, current_day, tgt_latt, tgt_lont, ebb_total_reshaped, fire_age, cols, rows) + else: + print('First day true, no RAVE files available. Use dummy emissions file') + i_tools.create_dummy(intp_dir, current_day, tgt_latt, tgt_lont, cols, rows) + +if __name__ == '__main__': + + print('') + print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~') + print('Welcome to interpolating RAVE and processing fire emissions!') + print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~') + print('') + generate_emiss_workflow(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5], sys.argv[6]) + print('') + print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~') + print('Successful Completion. Bye!') + print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~') + print('') + diff --git a/ush/interp_tools.py b/ush/interp_tools.py new file mode 100755 index 0000000000..3f6fed8618 --- /dev/null +++ b/ush/interp_tools.py @@ -0,0 +1,230 @@ +import datetime as dt +import pandas as pd +import os +import fnmatch +import ESMF +import xarray as xr +import numpy as np +from netCDF4 import Dataset + +#Create date range, this is later used to search for RAVE and HWP from previous 24 hours +def date_range(current_day, ebb_dcycle): + print(f'Searching for interpolated RAVE for {current_day}') + print('EBB CYCLE:',ebb_dcycle) + + fcst_datetime = dt.datetime.strptime(current_day, "%Y%m%d%H") + + if ebb_dcycle == 1: + print('Find RAVE for ebb_dcyc 1') + fcst_dates = pd.date_range(start=fcst_datetime, periods=24, freq='H').strftime("%Y%m%d%H") + else: + start_datetime = fcst_datetime - dt.timedelta(days=1, hours=1) + + fcst_dates = pd.date_range(start=start_datetime, periods=24, freq='H').strftime("%Y%m%d%H") + + print(f'Current cycle: {fcst_datetime}') + return(fcst_dates) + +# Check if interoplated RAVE is available for the previous 24 hours +def check_for_intp_rave(intp_dir, fcst_dates, rave_to_intp): + intp_avail_hours = [] + intp_non_avail_hours = [] + # There are four situations here. + # 1) the file is missing (interpolate a new file) + # 2) the file is present (use it) + # 3) there is a link, but it's broken (interpolate a new file) + # 4) there is a valid link (use it) + for date in fcst_dates: + file_name = f'{rave_to_intp}{date}00_{date}59.nc' + file_path = os.path.join(intp_dir, file_name) + file_exists = os.path.isfile(file_path) + is_link = os.path.islink(file_path) + is_valid_link = is_link and os.path.exists(file_path) + + if file_exists or is_valid_link: + print(f'RAVE interpolated file available for {file_name}') + intp_avail_hours.append(date) + else: + print(f'Interpolated file non available, interpolate RAVE for {file_name}') + intp_non_avail_hours.append(date) + + print(f'Available interpolated files for hours: {intp_avail_hours}, Non available interpolated files for hours: {intp_non_avail_hours}') + + inp_files_2use = len(intp_avail_hours) > 0 + + return(intp_avail_hours, intp_non_avail_hours, inp_files_2use) + +#Check if raw RAVE in intp_non_avail_hours list is available for interpolatation +def check_for_raw_rave(RAVE, intp_non_avail_hours, intp_avail_hours): + rave_avail = [] + rave_avail_hours = [] + rave_nonavail_hours_test = [] + for date in intp_non_avail_hours: + wildcard_name = f'*-3km*{date}*{date}59590*.nc' + name_retro = f'*3km*{date}*{date}*.nc' + matching_files = [f for f in os.listdir(RAVE) if fnmatch.fnmatch(f, wildcard_name) or fnmatch.fnmatch(f, name_retro)] + print(f'Find raw RAVE: {matching_files}') + if not matching_files: + print(f'Raw RAVE non_available for interpolation {date}') + rave_nonavail_hours_test.append(date) + else: + print(f'Raw RAVE available for interpolation {matching_files}') + rave_avail.append(matching_files) + rave_avail_hours.append(date) + + print(f"Raw RAVE available: {rave_avail_hours}, rave_nonavail_hours: {rave_nonavail_hours_test}") + first_day = not rave_avail_hours and not intp_avail_hours + + print(f'FIRST DAY?: {first_day}') + return(rave_avail, rave_avail_hours, rave_nonavail_hours_test, first_day) + +#Create source and target fields +def creates_st_fields(grid_in, grid_out, intp_dir, rave_avail_hours): + + # Open datasets with context managers + with xr.open_dataset(grid_in) as ds_in, xr.open_dataset(grid_out) as ds_out: + tgt_area = ds_out['area'] + tgt_latt = ds_out['grid_latt'] + tgt_lont = ds_out['grid_lont'] + src_latt = ds_in['grid_latt'] + + srcgrid = ESMF.Grid(np.array(src_latt.shape), staggerloc=[ESMF.StaggerLoc.CENTER, ESMF.StaggerLoc.CORNER], coord_sys=ESMF.CoordSys.SPH_DEG) + tgtgrid = ESMF.Grid(np.array(tgt_latt.shape), staggerloc=[ESMF.StaggerLoc.CENTER, ESMF.StaggerLoc.CORNER], coord_sys=ESMF.CoordSys.SPH_DEG) + + srcfield = ESMF.Field(srcgrid, name='test', staggerloc=ESMF.StaggerLoc.CENTER) + tgtfield = ESMF.Field(tgtgrid, name='test', staggerloc=ESMF.StaggerLoc.CENTER) + + print('Grid in and out files available. Generating target and source fields') + return(srcfield, tgtfield, tgt_latt, tgt_lont, srcgrid, tgtgrid, src_latt, tgt_area) + +#Define output and variable meta data +def create_emiss_file(fout, cols, rows): + """Create necessary dimensions for the emission file.""" + fout.createDimension('t', None) + fout.createDimension('lat', cols) + fout.createDimension('lon', rows) + setattr(fout, 'PRODUCT_ALGORITHM_VERSION', 'Beta') + setattr(fout, 'TIME_RANGE', '1 hour') + +def Store_latlon_by_Level(fout, varname, var, long_name, units, dim, fval, sfactor): + """Store a 2D variable (latitude/longitude) in the file.""" + var_out = fout.createVariable(varname, 'f4', ('lat','lon')) + var_out.units=units + var_out.long_name=long_name + var_out.standard_name=varname + fout.variables[varname][:]=var + var_out.FillValue=fval + var_out.coordinates='geolat geolon' + +def Store_by_Level(fout, varname, long_name, units, dim, fval, sfactor): + """Store a 3D variable (time, latitude/longitude) in the file.""" + var_out = fout.createVariable(varname, 'f4', ('t','lat','lon')) + var_out.units=units + var_out.long_name = long_name + var_out.standard_name=long_name + var_out.FillValue=fval + var_out.coordinates='t geolat geolon' + +#create a dummy rave interpolated file if first day or regrider fails +def create_dummy(intp_dir, current_day, tgt_latt, tgt_lont, cols, rows): + file_path = os.path.join(intp_dir, f'SMOKE_RRFS_data_{current_day}00.nc') + dummy_file = np.zeros((cols, rows)) # Changed to 3D to match the '3D' dimensions + with Dataset(file_path, 'w') as fout: + create_emiss_file(fout, cols, rows) + # Store latitude and longitude + Store_latlon_by_Level(fout, 'geolat', tgt_latt, 'cell center latitude', 'degrees_north', '2D','-9999.f','1.f') + Store_latlon_by_Level(fout, 'geolon', tgt_lont, 'cell center longitude', 'degrees_east', '2D','-9999.f','1.f') + + # Initialize and store each variable + Store_by_Level(fout,'frp_davg','Daily mean Fire Radiative Power','MW','3D','0.f','1.f') + fout.variables['frp_davg'][0, :, :] = dummy_file + Store_by_Level(fout,'ebb_rate','Total EBB emission','ug m-2 s-1','3D','0.f','1.f') + fout.variables['ebb_rate'][0, :, :] = dummy_file + Store_by_Level(fout,'fire_end_hr','Hours since fire was last detected','hrs','3D','0.f','1.f') + fout.variables['fire_end_hr'][0, :, :] = dummy_file + Store_by_Level(fout,'hwp_davg','Daily mean Hourly Wildfire Potential', 'none','3D','0.f','1.f') + fout.variables['hwp_davg'][0, :, :] = dummy_file + Store_by_Level(fout,'totprcp_24hrs','Sum of precipitation', 'm', '3D', '0.f','1.f') + fout.variables['totprcp_24hrs'][0, :, :] = dummy_file + + return "Emissions dummy file created successfully" + +#generate regridder +def generate_regrider(rave_avail_hours, srcfield, tgtfield, weightfile, inp_files_2use, intp_avail_hours): + print('Checking conditions for generating regridder.') + use_dummy_emiss = len(rave_avail_hours) == 0 and len(intp_avail_hours) == 0 + regridder = None + + if not use_dummy_emiss: + try: + print('Generating regridder.') + regridder = ESMF.RegridFromFile(srcfield, tgtfield, weightfile) + print('Regridder generated successfully.') + except ValueError as e: + print(f'Regridder failed due to a ValueError: {e}.') + except OSError as e: + print(f'Regridder failed due to an OSError: {e}. Check if the weight file exists and is accessible.') + except (FileNotFoundError, IOError, RuntimeError, TypeError, KeyError, IndexError, MemoryError) as e: + print(f'Regridder failed due to corrupted file: {e}. Check if RAVE file has a different grid or format. ') + except Exception as e: + print(f'An unexpected error occurred while generating regridder: {e}.') + else: + use_dummy_emiss = True + + return(regridder, use_dummy_emiss) + +#process RAVE available for interpolation +def interpolate_rave(RAVE, rave_avail, rave_avail_hours, use_dummy_emiss, vars_emis, regridder, + srcgrid, tgtgrid, rave_to_intp, intp_dir, src_latt, tgt_latt, tgt_lont, cols, rows): + for index, current_hour in enumerate(rave_avail_hours): + file_name = rave_avail[index] + rave_file_path = os.path.join(RAVE, file_name[0]) + + print(f"Processing file: {rave_file_path} for hour: {current_hour}") + + if not use_dummy_emiss and os.path.exists(rave_file_path): + try: + with xr.open_dataset(rave_file_path, decode_times=False) as ds_togrid: + try: + ds_togrid = ds_togrid[['FRP_MEAN', 'FRE']] + except KeyError as e: + print(f"Missing required variables in {rave_file_path}: {e}") + continue + + output_file_path = os.path.join(intp_dir, f'{rave_to_intp}{current_hour}00_{current_hour}59.nc') + print('=============before regridding===========', 'FRP_MEAN') + print(np.sum(ds_togrid['FRP_MEAN'], axis=(1, 2))) + + try: + with Dataset(output_file_path, 'w') as fout: + create_emiss_file(fout, cols, rows) + Store_latlon_by_Level(fout, 'geolat', tgt_latt, 'cell center latitude', 'degrees_north', '2D', '-9999.f', '1.f') + Store_latlon_by_Level(fout, 'geolon', tgt_lont, 'cell center longitude', 'degrees_east', '2D', '-9999.f', '1.f') + + for svar in vars_emis: + try: + srcfield = ESMF.Field(srcgrid, name=svar, staggerloc=ESMF.StaggerLoc.CENTER) + tgtfield = ESMF.Field(tgtgrid, name=svar, staggerloc=ESMF.StaggerLoc.CENTER) + src_rate = ds_togrid[svar].fillna(0) + src_QA = xr.where(ds_togrid['FRE'] > 1000, src_rate, 0.0) + srcfield.data[...] = src_QA[0, :, :] + tgtfield = regridder(srcfield, tgtfield) + + if svar == 'FRP_MEAN': + Store_by_Level(fout, 'frp_avg_hr', 'Mean Fire Radiative Power', 'MW', '3D', '0.f', '1.f') + tgt_rate = tgtfield.data + fout.variables['frp_avg_hr'][0, :, :] = tgt_rate + print('=============after regridding===========' + svar) + print(np.sum(tgt_rate)) + elif svar == 'FRE': + Store_by_Level(fout, 'FRE', 'FRE', 'MJ', '3D', '0.f', '1.f') + tgt_rate = tgtfield.data + fout.variables['FRE'][0, :, :] = tgt_rate + except (ValueError, KeyError) as e: + print(f"Error processing variable {svar} in {rave_file_path}: {e}") + except (OSError, IOError, RuntimeError, FileNotFoundError, TypeError, IndexError, MemoryError) as e: + print(f"Error creating or writing to NetCDF file {output_file_path}: {e}") + except (OSError, IOError, RuntimeError, FileNotFoundError, TypeError, IndexError, MemoryError) as e: + print(f"Error reading NetCDF file {rave_file_path}: {e}") + else: + print(f"File not found or dummy emissions required: {rave_file_path}") \ No newline at end of file From c5f546edc3d9a586ff27afe666d7b842a704d300 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Thu, 15 Aug 2024 20:06:59 +0000 Subject: [PATCH 03/61] add hrrr_gf suite --- sorc/CMakeLists.txt | 2 +- ush/config.smoke.yaml | 85 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 ush/config.smoke.yaml diff --git a/sorc/CMakeLists.txt b/sorc/CMakeLists.txt index e84319ad6e..2e69635d59 100644 --- a/sorc/CMakeLists.txt +++ b/sorc/CMakeLists.txt @@ -30,7 +30,7 @@ if (BUILD_UFS) if(CPL_AQM) set(CCPP_SUITES "FV3_GFS_v15p2,FV3_GFS_v16,FV3_GFS_v17_p8") else() - set(CCPP_SUITES "FV3_GFS_v15p2,FV3_GFS_v16,FV3_GFS_v17_p8,FV3_RRFS_v1beta,FV3_HRRR,FV3_RAP,FV3_GFS_v15_thompson_mynn_lam3km,FV3_WoFS_v0") + set(CCPP_SUITES "FV3_GFS_v15p2,FV3_GFS_v16,FV3_GFS_v17_p8,FV3_RRFS_v1beta,FV3_HRRR,FV3_HRRR_gf,FV3_RAP,FV3_GFS_v15_thompson_mynn_lam3km,FV3_WoFS_v0") endif() endif() diff --git a/ush/config.smoke.yaml b/ush/config.smoke.yaml new file mode 100644 index 0000000000..58dcf76c51 --- /dev/null +++ b/ush/config.smoke.yaml @@ -0,0 +1,85 @@ +metadata: + description: config for Smoke and Dust, RRFS_CONUS_3km +user: + RUN_ENVIR: community + MACHINE: hera + ACCOUNT: [account name] +workflow: + USE_CRON_TO_RELAUNCH: true + CRON_RELAUNCH_INTVL_MNTS: 3 + EXPT_SUBDIR: smoke_dust_conus3km + PREDEF_GRID_NAME: RRFS_CONUS_3km + CCPP_PHYS_SUITE: FV3_HRRR_gf + DATE_FIRST_CYCL: '2019072200' + DATE_LAST_CYCL: '2019072206' + INCR_CYCL_FREQ: 6 + FCST_LEN_HRS: 6 + PREEXISTING_DIR_METHOD: rename + VERBOSE: true + DEBUG: false + COMPILER: intel + DIAG_TABLE_TMPL_FN: diag_table_aqm.FV3_GFS_v16 + FIELD_TABLE_TMPL_FN: field_table_aqm.FV3_GFS_v16 + DO_REAL_TIME: false + COLDSTART: false # set to true for cold start + WARMSTART_CYCLE_DIR: '/scratch2/NAGAPE/epic/SRW-AQM_DATA/aqm_data/restart/2023111000' # for hera +# WARMSTART_CYCLE_DIR: '/work/noaa/epic/SRW-AQM_DATA/aqm_data/restart/2023111000' # for orion/hercules +# WARMSTART_CYCLE_DIR: '/glade/work/chanhooj/SRW-AQM_DATA/aqm_data/restart/2023111000' # for derecho +nco: + envir_default: test_aqm_warmstart + NET_default: aqm + RUN_default: aqm +rocoto: + tasks: + taskgroups: '{{ ["parm/wflow/prep.yaml", "parm/wflow/aqm_prep.yaml", "parm/wflow/coldstart.yaml", "parm/wflow/post.yaml"]|include }}' +# task_aqm_ics_ext: # uncomment this in case of COLDSTART: true + metatask_run_ensemble: + task_run_fcst_mem#mem#: + walltime: 01:20:00 +task_get_extrn_ics: + EXTRN_MDL_NAME_ICS: FV3GFS + FV3GFS_FILE_FMT_ICS: netcdf + EXTRN_MDL_ICS_OFFSET_HRS: 0 +task_get_extrn_lbcs: + EXTRN_MDL_NAME_LBCS: FV3GFS + LBC_SPEC_INTVL_HRS: 6 + FV3GFS_FILE_FMT_LBCS: netcdf + EXTRN_MDL_LBCS_OFFSET_HRS: 0 +task_run_fcst: + DT_ATMOS: 180 + LAYOUT_X: 50 + LAYOUT_Y: 34 + BLOCKSIZE: 16 + RESTART_INTERVAL: 12 24 + QUILTING: true + PRINT_ESMF: false + DO_FCST_RESTART: false +task_run_post: + POST_OUTPUT_DOMAIN_NAME: 793 + USE_CUSTOM_POST_CONFIG_FILE: false +global: + DO_ENSEMBLE: false + NUM_ENS_MEMBERS: 2 + HALO_BLEND: 0 +cpl_aqm_parm: + CPL_AQM: true + DO_AQM_CHEM_LBCS: true + DO_AQM_GEFS_LBCS: true + DO_AQM_DUST: true + DO_AQM_CANOPY: false + DO_AQM_PRODUCT: true + DO_AQM_SAVE_AIRNOW_HIST: false + DO_AQM_SAVE_FIRE: false + AQM_BIO_FILE: BEIS_RRFScmaq_C775.ncf + AQM_DUST_FILE_PREFIX: FENGSHA_p8_10km_inputs + AQM_DUST_FILE_SUFFIX: .nc + AQM_CANOPY_FILE_PREFIX: gfs.t12z.geo + AQM_CANOPY_FILE_SUFFIX: .canopy_regrid.nc + AQM_FIRE_FILE_PREFIX: Hourly_Emissions_regrid_NA_13km + AQM_FIRE_FILE_SUFFIX: _h72.nc + AQM_RC_FIRE_FREQUENCY: hourly + AQM_LBCS_FILES: am4_bndy.c793.2019.v1.nc + AQM_GEFS_FILE_PREFIX: geaer + NEXUS_GRID_FN: grid_spec_793.nc + NUM_SPLIT_NEXUS: 3 + From 97521848eb72e79659c73e1a7b3bb1c0895f6b03 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Fri, 16 Aug 2024 12:05:51 +0000 Subject: [PATCH 04/61] add config for smoke/dust --- ush/config.smoke.yaml | 40 +++++++++------------------------------- ush/config_defaults.yaml | 14 ++++++++++++++ 2 files changed, 23 insertions(+), 31 deletions(-) diff --git a/ush/config.smoke.yaml b/ush/config.smoke.yaml index 58dcf76c51..890168e87b 100644 --- a/ush/config.smoke.yaml +++ b/ush/config.smoke.yaml @@ -18,24 +18,21 @@ workflow: VERBOSE: true DEBUG: false COMPILER: intel - DIAG_TABLE_TMPL_FN: diag_table_aqm.FV3_GFS_v16 - FIELD_TABLE_TMPL_FN: field_table_aqm.FV3_GFS_v16 + DIAG_TABLE_TMPL_FN: diag_table_smoke.FV3_HRRR_gf + FIELD_TABLE_TMPL_FN: field_table_smoke.FV3_HRRR_gf DO_REAL_TIME: false - COLDSTART: false # set to true for cold start + COLDSTART: true # set to true for cold start WARMSTART_CYCLE_DIR: '/scratch2/NAGAPE/epic/SRW-AQM_DATA/aqm_data/restart/2023111000' # for hera -# WARMSTART_CYCLE_DIR: '/work/noaa/epic/SRW-AQM_DATA/aqm_data/restart/2023111000' # for orion/hercules -# WARMSTART_CYCLE_DIR: '/glade/work/chanhooj/SRW-AQM_DATA/aqm_data/restart/2023111000' # for derecho nco: - envir_default: test_aqm_warmstart - NET_default: aqm - RUN_default: aqm + envir_default: test_smoke_dust + NET_default: smoke_dust + RUN_default: smoke_dust rocoto: tasks: taskgroups: '{{ ["parm/wflow/prep.yaml", "parm/wflow/aqm_prep.yaml", "parm/wflow/coldstart.yaml", "parm/wflow/post.yaml"]|include }}' -# task_aqm_ics_ext: # uncomment this in case of COLDSTART: true metatask_run_ensemble: task_run_fcst_mem#mem#: - walltime: 01:20:00 + walltime: 03:00:00 task_get_extrn_ics: EXTRN_MDL_NAME_ICS: FV3GFS FV3GFS_FILE_FMT_ICS: netcdf @@ -61,25 +58,6 @@ global: DO_ENSEMBLE: false NUM_ENS_MEMBERS: 2 HALO_BLEND: 0 -cpl_aqm_parm: - CPL_AQM: true - DO_AQM_CHEM_LBCS: true - DO_AQM_GEFS_LBCS: true - DO_AQM_DUST: true - DO_AQM_CANOPY: false - DO_AQM_PRODUCT: true - DO_AQM_SAVE_AIRNOW_HIST: false - DO_AQM_SAVE_FIRE: false - AQM_BIO_FILE: BEIS_RRFScmaq_C775.ncf - AQM_DUST_FILE_PREFIX: FENGSHA_p8_10km_inputs - AQM_DUST_FILE_SUFFIX: .nc - AQM_CANOPY_FILE_PREFIX: gfs.t12z.geo - AQM_CANOPY_FILE_SUFFIX: .canopy_regrid.nc - AQM_FIRE_FILE_PREFIX: Hourly_Emissions_regrid_NA_13km - AQM_FIRE_FILE_SUFFIX: _h72.nc - AQM_RC_FIRE_FREQUENCY: hourly - AQM_LBCS_FILES: am4_bndy.c793.2019.v1.nc - AQM_GEFS_FILE_PREFIX: geaer - NEXUS_GRID_FN: grid_spec_793.nc - NUM_SPLIT_NEXUS: 3 +smoke_dust_parm: + DO_SMOKE_DUST: true diff --git a/ush/config_defaults.yaml b/ush/config_defaults.yaml index 90651c1b7f..3474cef744 100644 --- a/ush/config_defaults.yaml +++ b/ush/config_defaults.yaml @@ -2677,6 +2677,20 @@ cpl_aqm_parm: NEXUS_GFS_SFC_DIR: "" NEXUS_GFS_SFC_ARCHV_DIR: "/NCEPPROD/hpssprod/runhistory" +#------------------------------ +# Smoke/Dust config parameters +#------------------------------ +smoke_dust_parm: + # + #----------------------------------------------------------------------- + # + # DO_SMOKE_DUST: + # Flag turning on/off Smoke and Dust + # + #----------------------------------------------------------------------- + # + DO_SMOKE_DUST: false + rocoto: attrs: "" cycledefs: "" From 56c3c12c9d82ba0d3dd9abe59027c227ef39b350 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Fri, 16 Aug 2024 12:56:58 +0000 Subject: [PATCH 05/61] add config for smoke/dust --- parm/wflow/coldstart.yaml | 9 ++++++++ parm/wflow/smoke_dust_prep.yaml | 39 +++++++++++++++++++++++++++++++++ ush/config.smoke.yaml | 4 ++-- 3 files changed, 50 insertions(+), 2 deletions(-) create mode 100644 parm/wflow/smoke_dust_prep.yaml diff --git a/parm/wflow/coldstart.yaml b/parm/wflow/coldstart.yaml index 6fad0b8d83..29e0c26229 100644 --- a/parm/wflow/coldstart.yaml +++ b/parm/wflow/coldstart.yaml @@ -209,3 +209,12 @@ metatask_run_ensemble: taskdep: attrs: task: aqm_lbcs + or_smoke_dust: + not: + taskvalid: + attrs: + task: smoke_dust + taskdep: + attrs: + task: smoke_dust + diff --git a/parm/wflow/smoke_dust_prep.yaml b/parm/wflow/smoke_dust_prep.yaml new file mode 100644 index 0000000000..33edff8ace --- /dev/null +++ b/parm/wflow/smoke_dust_prep.yaml @@ -0,0 +1,39 @@ +default_smoke_dust_task: &default_smoke_dust + account: '&ACCOUNT;' + attrs: + cycledefs: forecast + maxtries: '2' + envars: &default_vars + GLOBAL_VAR_DEFNS_FP: '&GLOBAL_VAR_DEFNS_FP;' + HOMEdir: '&HOMEdir;' + envir: '&envir;' + model_ver: '&model_ver;' + KEEPDATA: '&KEEPDATA;' + SENDCOM: '&SENDCOM;' + COMROOT: '&COMROOT;' + DATAROOT: '&DATAROOT;' + DCOMROOT: '&DCOMROOT;' + LOGDIR: !cycstr "&LOGDIR;" + PDY: !cycstr "@Y@m@d" + cyc: !cycstr "@H" + nprocs: '{{ parent.nnodes * parent.ppn // 1 }}' + subcyc: !cycstr "@M" + SLASH_ENSMEM_SUBDIR: '&SLASH_ENSMEM_SUBDIR;' + native: '{{ platform.SCHED_NATIVE_CMD }}' + nnodes: 1 + nodes: '{{ nnodes }}:ppn={{ ppn }}' + partition: '{% if platform.get("PARTITION_DEFAULT") %}&PARTITION_DEFAULT;{% else %}None{% endif %}' + ppn: 1 + queue: '&QUEUE_DEFAULT;' + walltime: 00:30:00 + +task_smoke_dust: + <<: *default_smoke_dust + command: '&LOAD_MODULES_RUN_TASK; "smoke_dust" "&HOMEdir;/jobs/JSRW_SMOKE_DUST"' + join: !cycstr '&LOGDIR;/{{ jobname }}_@Y@m@d@H&LOGEXT;' + memory: 2G + ppn: 24 + dependency: + taskdep: + attrs: + task: make_lbcs_mem000 diff --git a/ush/config.smoke.yaml b/ush/config.smoke.yaml index 890168e87b..7f88670118 100644 --- a/ush/config.smoke.yaml +++ b/ush/config.smoke.yaml @@ -18,8 +18,8 @@ workflow: VERBOSE: true DEBUG: false COMPILER: intel - DIAG_TABLE_TMPL_FN: diag_table_smoke.FV3_HRRR_gf - FIELD_TABLE_TMPL_FN: field_table_smoke.FV3_HRRR_gf + DIAG_TABLE_TMPL_FN: diag_table_smoke_dust.FV3_HRRR_gf + FIELD_TABLE_TMPL_FN: field_table_smoke_dust.FV3_HRRR_gf DO_REAL_TIME: false COLDSTART: true # set to true for cold start WARMSTART_CYCLE_DIR: '/scratch2/NAGAPE/epic/SRW-AQM_DATA/aqm_data/restart/2023111000' # for hera From 49b3050cb62eb53080c269c3a3a804ce46ad60a8 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Fri, 16 Aug 2024 13:44:22 +0000 Subject: [PATCH 06/61] add input files for smoke/dust --- parm/diag_table_smoke_dust.FV3_HRRR_gf | 430 ++++++++++++++++++++++++ parm/field_table_smoke_dust.FV3_HRRR_gf | 80 +++++ scripts/exregional_run_fcst.sh | 24 ++ ush/config.smoke.yaml | 2 +- 4 files changed, 535 insertions(+), 1 deletion(-) create mode 100644 parm/diag_table_smoke_dust.FV3_HRRR_gf create mode 100644 parm/field_table_smoke_dust.FV3_HRRR_gf diff --git a/parm/diag_table_smoke_dust.FV3_HRRR_gf b/parm/diag_table_smoke_dust.FV3_HRRR_gf new file mode 100644 index 0000000000..547ac3aab0 --- /dev/null +++ b/parm/diag_table_smoke_dust.FV3_HRRR_gf @@ -0,0 +1,430 @@ +{{ starttime.strftime("%Y%m%d.%H") }}Z.{{ cres }}.32bit.non-hydro.regional +{{ starttime.strftime("%Y %m %d %H %M %S") }} + +"grid_spec", -1, "months", 1, "days", "time" +"atmos_static", -1, "hours", 1, "hours", "time" +#"atmos_4xdaily", 1, "hours", 1, "days", "time" +"fv3_history", 1, "years", 1, "hours", "time" +"fv3_history2d", 1, "years", 1, "hours", "time" + +# +#======================= +# ATMOSPHERE DIAGNOSTICS +#======================= +### +# grid_spec +### + "dynamics", "grid_lon", "grid_lon", "grid_spec", "all", .false., "none", 2, + "dynamics", "grid_lat", "grid_lat", "grid_spec", "all", .false., "none", 2, + "dynamics", "grid_lont", "grid_lont", "grid_spec", "all", .false., "none", 2, + "dynamics", "grid_latt", "grid_latt", "grid_spec", "all", .false., "none", 2, + "dynamics", "area", "area", "grid_spec", "all", .false., "none", 2, +### +# 4x daily output +### +# "dynamics", "slp", "slp", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "vort850", "vort850", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "vort200", "vort200", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "us", "us", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "u1000", "u1000", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "u850", "u850", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "u700", "u700", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "u500", "u500", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "u200", "u200", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "u100", "u100", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "u50", "u50", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "u10", "u10", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "vs", "vs", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "v1000", "v1000", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "v850", "v850", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "v700", "v700", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "v500", "v500", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "v200", "v200", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "v100", "v100", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "v50", "v50", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "v10", "v10", "atmos_4xdaily", "all", .false., "none", 2 +#### +# "dynamics", "tm", "tm", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "t1000", "t1000", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "t850", "t850", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "t700", "t700", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "t500", "t500", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "t200", "t200", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "t100", "t100", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "t50", "t50", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "t10", "t10", "atmos_4xdaily", "all", .false., "none", 2 +#### +# "dynamics", "z1000", "z1000", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "z850", "z850", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "z700", "z700", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "z500", "z500", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "z200", "z200", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "z100", "z100", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "z50", "z50", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "z10", "z10", "atmos_4xdaily", "all", .false., "none", 2 +#### +# "dynamics", "w1000", "w1000", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "w850", "w850", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "w700", "w700", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "w500", "w500", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "w200", "w200", "atmos_4xdaily", "all", .false., "none", 2 +#### +# "dynamics", "q1000", "q1000", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "q850", "q850", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "q700", "q700", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "q500", "q500", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "q200", "q200", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "q100", "q100", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "q50", "q50", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "q10", "q10", "atmos_4xdaily", "all", .false., "none", 2 +#### +# "dynamics", "rh1000", "rh1000", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "rh850", "rh850", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "rh700", "rh700", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "rh500", "rh500", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "rh200", "rh200", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "omg1000", "omg1000", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "omg850", "omg850", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "omg700", "omg700", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "omg500", "omg500", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "omg200", "omg200", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "omg100", "omg100", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "omg50", "omg50", "atmos_4xdaily", "all", .false., "none", 2 +# "dynamics", "omg10", "omg10", "atmos_4xdaily", "all", .false., "none", 2 +### +# gfs static data +### + "dynamics", "pk", "pk", "atmos_static", "all", .false., "none", 2 + "dynamics", "bk", "bk", "atmos_static", "all", .false., "none", 2 + "dynamics", "hyam", "hyam", "atmos_static", "all", .false., "none", 2 + "dynamics", "hybm", "hybm", "atmos_static", "all", .false., "none", 2 + "dynamics", "zsurf", "zsurf", "atmos_static", "all", .false., "none", 2 +### +# FV3 variabls needed for NGGPS evaluation +### +"gfs_dyn", "ucomp", "ugrd", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "vcomp", "vgrd", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "sphum", "spfh", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "temp", "tmp", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "liq_wat", "clwmr", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "o3mr", "o3mr", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "delp", "dpres", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "delz", "delz", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "w", "dzdt", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "ice_wat", "icmr", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "rainwat", "rwmr", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "snowwat", "snmr", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "graupel", "grle", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "ps", "pressfc", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "hs", "hgtsfc", "fv3_history", "all", .false., "none", 2 +"gfs_phys", "refl_10cm" "refl_10cm" "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "ice_nc", "nicp", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "rain_nc", "rain_nc", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "water_nc", "water_nc", "fv3_history", "all", .false., "none", 2 + +"gfs_dyn", "wmaxup", "upvvelmax", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "wmaxdn", "dnvvelmax", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "uhmax03", "uhmax03", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "uhmax25", "uhmax25", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "uhmin03", "uhmin03", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "uhmin25", "uhmin25", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "maxvort01", "maxvort01", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "maxvort02", "maxvort02", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "maxvorthy1", "maxvorthy1", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "hailcast_dhail_max", "hailcast_dhail", "fv3_history2d", "all", .false., "none", 2 + +"gfs_phys", "ALBDO_ave", "albdo_ave", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "cnvprcp_ave", "cprat_ave", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "cnvprcpb_ave", "cpratb_ave", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "totprcp_ave", "prate_ave", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "totprcpb_ave", "prateb_ave", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "DLWRF", "dlwrf_ave", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "DLWRFI", "dlwrf", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "ULWRF", "ulwrf_ave", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "ULWRFI", "ulwrf", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "DSWRF", "dswrf_ave", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "DSWRFI", "dswrf", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "DSWRFCI", "dswrf_clr", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "USWRF", "uswrf_ave", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "USWRFI", "uswrf", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "DSWRFtoa", "dswrf_avetoa","fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "USWRFtoa", "uswrf_avetoa","fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "ULWRFtoa", "ulwrf_avetoa","fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "gflux_ave", "gflux_ave", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "hpbl", "hpbl", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "lhtfl_ave", "lhtfl_ave", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "shtfl_ave", "shtfl_ave", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "pwat", "pwatclm", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "soilm", "soilm", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "TCDC_aveclm", "tcdc_aveclm", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "TCDC_avebndcl", "tcdc_avebndcl", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "TCDC_avehcl", "tcdc_avehcl", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "TCDC_avelcl", "tcdc_avelcl", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "TCDC_avemcl", "tcdc_avemcl", "fv3_history2d", "all", .false., "none", 2 +#"gfs_phys", "TCDCcnvcl", "tcdccnvcl", "fv3_history2d", "all", .false., "none", 2 +#"gfs_phys", "PREScnvclt", "prescnvclt", "fv3_history2d", "all", .false., "none", 2 +#"gfs_phys", "PREScnvclb", "prescnvclb", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "PRES_avehct", "pres_avehct", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "PRES_avehcb", "pres_avehcb", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "TEMP_avehct", "tmp_avehct", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "PRES_avemct", "pres_avemct", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "PRES_avemcb", "pres_avemcb", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "TEMP_avemct", "tmp_avemct", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "PRES_avelct", "pres_avelct", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "PRES_avelcb", "pres_avelcb", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "TEMP_avelct", "tmp_avelct", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "u-gwd_ave", "u-gwd_ave", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "v-gwd_ave", "v-gwd_ave", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "dusfc", "uflx_ave", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "dvsfc", "vflx_ave", "fv3_history2d", "all", .false., "none", 2 +#"gfs_phys", "cnvw", "cnvcldwat", "fv3_history2d", "all", .false., "none", 2 + +"gfs_phys", "u10max", "u10max", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "v10max", "v10max", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "spd10max", "spd10max", "fv3_history2d", "all", .false., "none", 2 +"gfs_dyn", "ustm", "ustm", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "vstm", "vstm", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "srh01", "srh01", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "srh03", "srh03", "fv3_history", "all", .false., "none", 2 +"gfs_phys", "pratemax", "pratemax", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "refdmax", "refdmax", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "refdmax263k","refdmax263k","fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "t02max", "t02max", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "t02min", "t02min", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "rh02max", "rh02max", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "rh02min", "rh02min", "fv3_history2d", "all", .false., "none", 2 + +"gfs_phys", "psurf", "pressfc", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "u10m", "ugrd10m", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "v10m", "vgrd10m", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "crain", "crain", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "tprcp", "tprcp", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "hgtsfc", "orog", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "weasd", "weasd", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "f10m", "f10m", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "q2m", "spfh2m", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "t2m", "tmp2m", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "dpt2m", "dpt2m", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "tsfc", "tmpsfc", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "vtype", "vtype", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "stype", "sotyp", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "slmsksfc", "land", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "vfracsfc", "veg", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "wetness", "wetness", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "zorlsfc", "sfcr", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "uustar", "fricv", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "soilt1", "soilt1" "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "soilt2", "soilt2" "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "soilt3", "soilt3" "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "soilt4", "soilt4" "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "soilt5", "soilt5" "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "soilt6", "soilt6" "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "soilt7", "soilt7" "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "soilt8", "soilt8" "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "soilt9", "soilt9" "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "soilw1", "soilw1" "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "soilw2", "soilw2" "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "soilw3", "soilw3" "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "soilw4", "soilw4" "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "soilw5", "soilw5" "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "soilw6", "soilw6" "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "soilw7", "soilw7" "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "soilw8", "soilw8" "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "soilw9", "soilw9" "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "slc_1", "soill1", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "slc_2", "soill2", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "slc_3", "soill3", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "slc_4", "soill4", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "slc_5", "soill5", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "slc_6", "soill6", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "slc_7", "soill7", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "slc_8", "soill8", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "slc_9", "soill9", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "slope", "sltyp", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "alnsf", "alnsf", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "alnwf", "alnwf", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "alvsf", "alvsf", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "alvwf", "alvwf", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "canopy", "cnwat", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "facsf", "facsf", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "facwf", "facwf", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "ffhh", "ffhh", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "ffmm", "ffmm", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "fice", "icec", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "hice", "icetk", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "snoalb", "snoalb", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "shdmax", "shdmax", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "shdmin", "shdmin", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "snowd", "snod", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "tg3", "tg3", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "tisfc", "tisfc", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "tref", "tref", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "z_c", "zc", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "c_0", "c0", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "c_d", "cd", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "w_0", "w0", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "w_d", "wd", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "xt", "xt", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "xz", "xz", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "dt_cool", "dtcool", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "xs", "xs", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "xu", "xu", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "xv", "xv", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "xtts", "xtts", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "xzts", "xzts", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "d_conv", "dconv", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "qrain", "qrain", "fv3_history2d", "all", .false., "none", 2 + +"gfs_phys", "acond", "acond", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "cduvb_ave", "cduvb_ave", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "cpofp", "cpofp", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "duvb_ave", "duvb_ave", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "csdlf_ave", "csdlf", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "csusf_ave", "csusf", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "csusf_avetoa", "csusftoa", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "csdsf_ave", "csdsf", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "csulf_ave", "csulf", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "csulf_avetoa", "csulftoa", "fv3_history2d", "all", .false., "none", 2 +#"gfs_phys", "cwork_ave", "cwork_aveclm", "fv3_history2d", "all", .false., "none", 2 +#"gfs_phys", "fldcp", "fldcp", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "hgt_hyblev1", "hgt_hyblev1", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "spfh_hyblev1", "spfh_hyblev1", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "ugrd_hyblev1", "ugrd_hyblev1", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "vgrd_hyblev1", "vgrd_hyblev1", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "tmp_hyblev1", "tmp_hyblev1", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "gfluxi", "gflux", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "lhtfl", "lhtfl", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "shtfl", "shtfl", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "pevpr", "pevpr", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "pevpr_ave", "pevpr_ave", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "sbsno_ave", "sbsno_ave", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "sfexc", "sfexc", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "snohf", "snohf", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "snowc", "snowc", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "spfhmax2m", "spfhmax_max2m", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "spfhmin2m", "spfhmin_min2m", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "tmpmax2m", "tmax_max2m", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "tmpmin2m", "tmin_min2m", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "ssrun_acc", "ssrun_acc", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "sunsd_acc", "sunsd_acc", "fv3_history2d", "all", .false., "none", 2 +# "gfs_phys", "watr_acc", "watr_acc", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "wilt", "wilt", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "nirbmdi", "nirbmdi", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "nirdfdi", "nirdfdi", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "visbmdi", "visbmdi", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "visdfdi", "visdfdi", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "vbdsf_ave", "vbdsf_ave", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "vddsf_ave", "vddsf_ave", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "nbdsf_ave", "nbdsf_ave", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "nddsf_ave", "nddsf_ave", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "trans_ave", "transp_ave", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "evbs_ave", "direvap_ave", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "evcw_ave", "canevap_ave", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "sbsno", "sublim", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "evbs", "direvap", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "evcw", "canevap", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "trans", "transp", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "snowmt_land", "snom_land", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "snowmt_ice", "snom_ice", "fv3_history2d", "all", .false., "none", 2 +# Aerosols (CCN, IN) from Thompson microphysics +"gfs_phys", "nwfa", "nwfa", "fv3_history", "all", .false., "none", 2 +"gfs_phys", "nifa", "nifa", "fv3_history", "all", .false., "none", 2 +"gfs_sfc", "nwfa2d", "nwfa2d", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "nifa2d", "nifa2d", "fv3_history2d", "all", .false., "none", 2 +# Cloud effective radii from Thompson and WSM6 microphysics +"gfs_phys", "cleffr", "cleffr", "fv3_history", "all", .false., "none", 2 +"gfs_phys", "cieffr", "cieffr", "fv3_history", "all", .false., "none", 2 +"gfs_phys", "cseffr", "cseffr", "fv3_history", "all", .false., "none", 2 +# Prognostic/diagnostic variables from MYNN +"gfs_phys", "QC_BL", "qc_bl", "fv3_history", "all", .false., "none", 2 +"gfs_phys", "CLDFRA", "cldfra", "fv3_history", "all", .false., "none", 2 +"gfs_phys", "EL_PBL", "el_pbl", "fv3_history", "all", .false., "none", 2 +"gfs_phys", "QKE", "qke", "fv3_history", "all", .false., "none", 2 +"gfs_sfc", "maxmf", "maxmf", "fv3_history2d", "all", .false., "none", 2 +#"gfs_sfc", "nupdraft", "nupdrafts", "fv3_history2d", "all", .false., "none", 2 +#"gfs_sfc", "ktop_shallow", "ktop_shallow", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "zol", "zol", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "flhc", "flhc", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "flqc", "flqc", "fv3_history2d", "all", .false., "none", 2 +# Prognostic/diagnostic variables from RUC LSM +"gfs_sfc", "rhofr", "rhofr", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "snowfall_acc_land", "snacc_land", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "acsnow_land", "accswe_land", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "snowfall_acc_ice", "snacc_ice", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "acsnow_ice", "accswe_ice", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "xlaixy", "xlaixy", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "sfalb", "sfalb", "fv3_history2d", "all", .false., "none", 2 +# Stochastic physics +#"gfs_phys", "sppt_wts", "sppt_wts", "fv3_history", "all", .false., "none", 2 +#"gfs_phys", "skebu_wts", "skebu_wts", "fv3_history", "all", .false., "none", 2 +#"gfs_phys", "skebv_wts", "skebv_wts", "fv3_history", "all", .false., "none", 2 +#"dynamics", "diss_est", "diss_est", "fv3_history", "all", .false., "none", 2 +#"gfs_phys", "shum_wts", "shum_wts", "fv3_history", "all", .false., "none", 2 +# +"gfs_phys", "frzr", "frzr", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "frzrb", "frzrb", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "frozr", "frozr", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "frozrb", "frozrb", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "tsnowp", "tsnowp", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "tsnowpb", "tsnowpb", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "rhonewsn", "rhonewsn", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "snow", "snow", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "graupel", "graupel", "fv3_history2d", "all", .false., "none", 2 +# lightning threat indices +"gfs_sfc", "ltg1_max", "ltg1_max", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "ltg2_max", "ltg2_max", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "ltg3_max", "ltg3_max", "fv3_history2d", "all", .false., "none", 2 +#============================================================================================= +# +#====> This file can be used with diag_manager/v2.0a (or higher) <==== +# +# +# FORMATS FOR FILE ENTRIES (not all input values are used) +# ------------------------ +# +#"file_name", output_freq, "output_units", format, "time_units", "long_name", +# +# +#output_freq: > 0 output frequency in "output_units" +# = 0 output frequency every time step +# =-1 output frequency at end of run +# +#output_units = units used for output frequency +# (years, months, days, minutes, hours, seconds) +# +#time_units = units used to label the time axis +# (days, minutes, hours, seconds) +# +# +# FORMAT FOR FIELD ENTRIES (not all input values are used) +# ------------------------ +# +#"module_name", "field_name", "output_name", "file_name" "time_sampling", time_avg, "other_opts", packing +# +#time_avg = .true. or .false. +# +#packing = 1 double precision +# = 2 float +# = 4 packed 16-bit integers +# = 8 packed 1-byte (not tested?) +# This file contains diag_table entries for the RRFS-SD. +# It should be appended to the end of the diag_table before execution of the test. + +# Tracers +"gfs_dyn", "smoke", "smoke", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "dust", "dust", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "coarsepm", "coarsepm", "fv3_history", "all", .false., "none", 2 +"gfs_dyn", "smoke_ave", "smoke_ave", "fv3_history2d", "all", .false., "none", 2 +"gfs_dyn", "dust_ave", "dust_ave", "fv3_history2d", "all", .false., "none", 2 +"gfs_dyn", "coarsepm_ave", "coarsepm_ave", "fv3_history2d", "all", .false., "none", 2 + +# Aerosols emission for smoke +"gfs_sfc", "emdust", "emdust", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "coef_bb_dc", "coef_bb_dc", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "min_fplume", "min_fplume", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "max_fplume", "max_fplume", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "hwp", "hwp", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "hwp_ave", "hwp_ave", "fv3_history2d", "all", .false., "none", 2 +"gfs_sfc", "frp_output", "frp_output", "fv3_history2d", "all", .false., "none", 2 +"gfs_phys", "ebu_smoke", "ebu_smoke", "fv3_history", "all", .false., "none", 2 +"gfs_phys", "ext550", "ext550", "fv3_history", "all", .false., "none", 2 diff --git a/parm/field_table_smoke_dust.FV3_HRRR_gf b/parm/field_table_smoke_dust.FV3_HRRR_gf new file mode 100644 index 0000000000..3d4e0afcd4 --- /dev/null +++ b/parm/field_table_smoke_dust.FV3_HRRR_gf @@ -0,0 +1,80 @@ +# added by FRE: sphum must be present in atmos +# specific humidity for moist runs + "TRACER", "atmos_mod", "sphum" + "longname", "specific humidity" + "units", "kg/kg" + "profile_type", "fixed", "surface_value=1.e-6" / +# prognostic cloud water mixing ratio + "TRACER", "atmos_mod", "liq_wat" + "longname", "cloud water mixing ratio" + "units", "kg/kg" + "profile_type", "fixed", "surface_value=1.e30" / +# prognostic ice water mixing ratio + "TRACER", "atmos_mod", "ice_wat" + "longname", "cloud ice mixing ratio" + "units", "kg/kg" + "profile_type", "fixed", "surface_value=1.e30" / +# prognostic rain water mixing ratio + "TRACER", "atmos_mod", "rainwat" + "longname", "rain water mixing ratio" + "units", "kg/kg" + "profile_type", "fixed", "surface_value=1.e30" / +# prognostic snow water mixing ratio + "TRACER", "atmos_mod", "snowwat" + "longname", "snow water mixing ratio" + "units", "kg/kg" + "profile_type", "fixed", "surface_value=1.e30" / +# prognostic graupel mixing ratio + "TRACER", "atmos_mod", "graupel" + "longname", "graupel mixing ratio" + "units", "kg/kg" + "profile_type", "fixed", "surface_value=1.e30" / +# prognostic cloud water number concentration + "TRACER", "atmos_mod", "water_nc" + "longname", "cloud liquid water number concentration" + "units", "/kg" + "profile_type", "fixed", "surface_value=0.0" / +# prognostic cloud ice number concentration + "TRACER", "atmos_mod", "ice_nc" + "longname", "cloud ice water number concentration" + "units", "/kg" + "profile_type", "fixed", "surface_value=0.0" / +# prognostic rain number concentration + "TRACER", "atmos_mod", "rain_nc" + "longname", "rain number concentration" + "units", "/kg" + "profile_type", "fixed", "surface_value=0.0" / +# prognostic ozone mixing ratio tracer + "TRACER", "atmos_mod", "o3mr" + "longname", "ozone mixing ratio" + "units", "kg/kg" + "profile_type", "fixed", "surface_value=1.e30" / +# water- and ice-friendly aerosols (Thompson) + "TRACER", "atmos_mod", "liq_aero" + "longname", "water-friendly aerosol number concentration" + "units", "/kg" + "profile_type", "fixed", "surface_value=0.0" / + "TRACER", "atmos_mod", "ice_aero" + "longname", "ice-friendly aerosol number concentration" + "units", "/kg" + "profile_type", "fixed", "surface_value=0.0" / +# prognostic subgrid scale turbulent kinetic energy + "TRACER", "atmos_mod", "sgs_tke" + "longname", "subgrid scale turbulent kinetic energy" + "units", "m2/s2" + "profile_type", "fixed", "surface_value=0.0" / +# prognostic smoke mixing ratio tracer + "TRACER", "atmos_mod", "smoke" + "longname", "smoke mixing ratio" + "units", "ug/kg" + "profile_type", "fixed", "surface_value=1.e-12" / +# prognostic dust mixing ratio tracer + "TRACER", "atmos_mod", "dust" + "longname", "dust mixing ratio" + "units", "ug/kg" + "profile_type", "fixed", "surface_value=1.e-12" / +# prognostic coarsepm mixing ratio tracer + "TRACER", "atmos_mod", "coarsepm" + "longname", "coarsepm mixing ratio" + "units", "ug/kg" + "profile_type", "fixed", "surface_value=1.e-12" / diff --git a/scripts/exregional_run_fcst.sh b/scripts/exregional_run_fcst.sh index 0241dbd728..5dae29ef8d 100755 --- a/scripts/exregional_run_fcst.sh +++ b/scripts/exregional_run_fcst.sh @@ -389,6 +389,30 @@ else create_symlink_to_file $target $symlink ${relative_link_flag} done fi +# Smoke and Dust +if [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then + ln -snf ${FIX_SMOKE_DUST}/${PREDEF_GRID_NAME}/dust12m_data.nc ${run_dir}/INPUT/dust12m_data.nc + ln -snf ${FIX_SMOKE_DUST}/${PREDEF_GRID_NAME}/emi_data.nc ${run_dir}/INPUT/emi_data.nc + yyyymmddhh=${cdate:0:10} + echo ${yyyymmddhh} + if [ ${cycle_type} = "spinup" ]; then + smokefile=${NWGES_BASEDIR}/RAVE_INTP/SMOKE_RRFS_data_${yyyymmddhh}00_spinup.nc + else + smokefile=${NWGES_BASEDIR}/RAVE_INTP/SMOKE_RRFS_data_${yyyymmddhh}00.nc + fi + echo "try to use smoke file=",${smokefile} + if [ -f ${smokefile} ]; then + ln -snf ${smokefile} ${run_dir}/INPUT/SMOKE_RRFS_data.nc + else + if [ ${EBB_DCYCLE} = "1" ]; then + ln -snf ${FIX_SMOKE_DUST}/${PREDEF_GRID_NAME}/dummy_24hr_smoke_ebbdc1.nc ${run_dir}/INPUT/SMOKE_RRFS_data.nc + echo "WARNING: Smoke file is not available, use dummy_24hr_smoke_ebbdc1.nc instead" + else + ln -snf ${FIX_SMOKE_DUST}/${PREDEF_GRID_NAME}/dummy_24hr_smoke.nc ${run_dir}/INPUT/SMOKE_RRFS_data.nc + echo "WARNING: Smoke file is not available, use dummy_24hr_smoke.nc instead" + fi + fi +fi # #----------------------------------------------------------------------- # diff --git a/ush/config.smoke.yaml b/ush/config.smoke.yaml index 7f88670118..4b1c7b6e48 100644 --- a/ush/config.smoke.yaml +++ b/ush/config.smoke.yaml @@ -29,7 +29,7 @@ nco: RUN_default: smoke_dust rocoto: tasks: - taskgroups: '{{ ["parm/wflow/prep.yaml", "parm/wflow/aqm_prep.yaml", "parm/wflow/coldstart.yaml", "parm/wflow/post.yaml"]|include }}' + taskgroups: '{{ ["parm/wflow/prep.yaml", "parm/wflow/smoke_dust_prep.yaml", "parm/wflow/coldstart.yaml", "parm/wflow/post.yaml"]|include }}' metatask_run_ensemble: task_run_fcst_mem#mem#: walltime: 03:00:00 From 58824aaba4838878917bea9aeca077f044540f88 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Fri, 16 Aug 2024 14:08:39 +0000 Subject: [PATCH 07/61] add separate external.cfg for smoke/dust --- Externals.cfg | 8 ++--- Externals_smoke_dust.cfg | 29 +++++++++++++++++++ ...nfig.smoke.yaml => config.smoke_dust.yaml} | 0 3 files changed, 33 insertions(+), 4 deletions(-) create mode 100644 Externals_smoke_dust.cfg rename ush/{config.smoke.yaml => config.smoke_dust.yaml} (100%) diff --git a/Externals.cfg b/Externals.cfg index c07002de9d..4545cd8ca5 100644 --- a/Externals.cfg +++ b/Externals.cfg @@ -3,7 +3,7 @@ protocol = git repo_url = https://github.com/ufs-community/UFS_UTILS # Specify either a branch name or a hash but not both. #branch = develop -hash = 33cc663 +hash = 57bd832 local_path = sorc/UFS_UTILS required = True @@ -11,8 +11,8 @@ required = True protocol = git repo_url = https://github.com/ufs-community/ufs-weather-model # Specify either a branch name or a hash but not both. -branch = production/RRFS.v1 -#hash = b5a1976 +#branch = develop +hash = b5a1976 local_path = sorc/ufs-weather-model required = True @@ -21,7 +21,7 @@ protocol = git repo_url = https://github.com/NOAA-EMC/UPP # Specify either a branch name or a hash but not both. #branch = develop -hash = fc85241 +hash = be0410e local_path = sorc/UPP required = True diff --git a/Externals_smoke_dust.cfg b/Externals_smoke_dust.cfg new file mode 100644 index 0000000000..475390ca35 --- /dev/null +++ b/Externals_smoke_dust.cfg @@ -0,0 +1,29 @@ +[ufs_utils] +protocol = git +repo_url = https://github.com/ufs-community/UFS_UTILS +# Specify either a branch name or a hash but not both. +#branch = develop +hash = 33cc663 +local_path = sorc/UFS_UTILS +required = True + +[ufs-weather-model] +protocol = git +repo_url = https://github.com/ufs-community/ufs-weather-model +# Specify either a branch name or a hash but not both. +branch = production/RRFS.v1 +#hash = b5a1976 +local_path = sorc/ufs-weather-model +required = True + +[UPP] +protocol = git +repo_url = https://github.com/NOAA-EMC/UPP +# Specify either a branch name or a hash but not both. +#branch = develop +hash = fc85241 +local_path = sorc/UPP +required = True + +[externals_description] +schema_version = 1.0.0 diff --git a/ush/config.smoke.yaml b/ush/config.smoke_dust.yaml similarity index 100% rename from ush/config.smoke.yaml rename to ush/config.smoke_dust.yaml From fa2fcac0d022d43134614a24d7953d8f60fe6bad Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Fri, 16 Aug 2024 15:35:20 +0000 Subject: [PATCH 08/61] update config yaml --- ush/config.smoke_dust.yaml | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/ush/config.smoke_dust.yaml b/ush/config.smoke_dust.yaml index 4b1c7b6e48..b9ba2de496 100644 --- a/ush/config.smoke_dust.yaml +++ b/ush/config.smoke_dust.yaml @@ -34,25 +34,23 @@ rocoto: task_run_fcst_mem#mem#: walltime: 03:00:00 task_get_extrn_ics: - EXTRN_MDL_NAME_ICS: FV3GFS - FV3GFS_FILE_FMT_ICS: netcdf + EXTRN_MDL_NAME_ICS: RAP EXTRN_MDL_ICS_OFFSET_HRS: 0 task_get_extrn_lbcs: - EXTRN_MDL_NAME_LBCS: FV3GFS + EXTRN_MDL_NAME_LBCS: RAP LBC_SPEC_INTVL_HRS: 6 - FV3GFS_FILE_FMT_LBCS: netcdf EXTRN_MDL_LBCS_OFFSET_HRS: 0 task_run_fcst: - DT_ATMOS: 180 - LAYOUT_X: 50 - LAYOUT_Y: 34 - BLOCKSIZE: 16 - RESTART_INTERVAL: 12 24 + DT_ATMOS: 36 + LAYOUT_X: 15 + LAYOUT_Y: 20 + BLOCKSIZE: 32 + RESTART_INTERVAL: 6 12 18 24 QUILTING: true PRINT_ESMF: false DO_FCST_RESTART: false task_run_post: - POST_OUTPUT_DOMAIN_NAME: 793 + POST_OUTPUT_DOMAIN_NAME: conus3km USE_CUSTOM_POST_CONFIG_FILE: false global: DO_ENSEMBLE: false From 236a1ba80e3f138176cb5abf79fb4d8f54a86270 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Fri, 16 Aug 2024 16:16:07 +0000 Subject: [PATCH 09/61] update config yaml --- parm/wflow/smoke_dust_prep.yaml | 3 +-- ush/config.smoke_dust.yaml | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/parm/wflow/smoke_dust_prep.yaml b/parm/wflow/smoke_dust_prep.yaml index 33edff8ace..b40f763057 100644 --- a/parm/wflow/smoke_dust_prep.yaml +++ b/parm/wflow/smoke_dust_prep.yaml @@ -1,7 +1,7 @@ default_smoke_dust_task: &default_smoke_dust account: '&ACCOUNT;' attrs: - cycledefs: forecast + cycledefs: cycled_from_second maxtries: '2' envars: &default_vars GLOBAL_VAR_DEFNS_FP: '&GLOBAL_VAR_DEFNS_FP;' @@ -32,7 +32,6 @@ task_smoke_dust: command: '&LOAD_MODULES_RUN_TASK; "smoke_dust" "&HOMEdir;/jobs/JSRW_SMOKE_DUST"' join: !cycstr '&LOGDIR;/{{ jobname }}_@Y@m@d@H&LOGEXT;' memory: 2G - ppn: 24 dependency: taskdep: attrs: diff --git a/ush/config.smoke_dust.yaml b/ush/config.smoke_dust.yaml index b9ba2de496..91abc8170d 100644 --- a/ush/config.smoke_dust.yaml +++ b/ush/config.smoke_dust.yaml @@ -45,6 +45,7 @@ task_run_fcst: LAYOUT_X: 15 LAYOUT_Y: 20 BLOCKSIZE: 32 + WRTCMP_write_tasks_per_group: 40 RESTART_INTERVAL: 6 12 18 24 QUILTING: true PRINT_ESMF: false From c6bf03f26ed9514ee715d32f829853eb6117081a Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Fri, 16 Aug 2024 17:52:15 +0000 Subject: [PATCH 10/61] modify ex-script for smoke/dust --- scripts/exsrw_smoke_dust.sh | 198 ++++++++++++++++-------------------- 1 file changed, 86 insertions(+), 112 deletions(-) diff --git a/scripts/exsrw_smoke_dust.sh b/scripts/exsrw_smoke_dust.sh index 55140ae11e..3765e25762 100755 --- a/scripts/exsrw_smoke_dust.sh +++ b/scripts/exsrw_smoke_dust.sh @@ -1,6 +1,5 @@ -#!/bin/bash +#!/usr/bin/env bash -# # #----------------------------------------------------------------------- # @@ -8,8 +7,12 @@ # #----------------------------------------------------------------------- # -. ${GLOBAL_VAR_DEFNS_FP} -. $USHdir/source_util_funcs.sh +. ${USHsrw}/source_util_funcs.sh +for sect in user nco platform workflow nco global verification cpl_aqm_parm \ + constants fixed_files grid_params \ + task_point_source task_run_fcst ; do + source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} +done # #----------------------------------------------------------------------- # @@ -18,7 +21,7 @@ # #----------------------------------------------------------------------- # -{ save_shell_opts; set -u -x; } > /dev/null 2>&1 +{ save_shell_opts; set -xue; } > /dev/null 2>&1 # #----------------------------------------------------------------------- # @@ -28,7 +31,7 @@ # #----------------------------------------------------------------------- # -scrfunc_fp=$( readlink -f "${BASH_SOURCE[0]}" ) +scrfunc_fp=$( $READLINK -f "${BASH_SOURCE[0]}" ) scrfunc_fn=$( basename "${scrfunc_fp}" ) scrfunc_dir=$( dirname "${scrfunc_fp}" ) # @@ -43,7 +46,7 @@ print_info_msg " Entering script: \"${scrfunc_fn}\" In directory: \"${scrfunc_dir}\" -This is the script for the task that runs smoke emissions preprocessing. +This is the ex-script for the task that runs Smoke and Dust. ========================================================================" # #----------------------------------------------------------------------- @@ -64,79 +67,58 @@ mkdir -p "${hourly_hwpdir}" # is reused # #----------------------------------------------------------------------- -ECHO=/bin/echo -SED=/bin/sed -DATE=/bin/date -LN=/bin/ln -ebb_dc=${EBB_DCYCLE} - -# Start date manipulation -START_DATE=$(${ECHO} "${CDATE}" | ${SED} 's/\([[:digit:]]\{2\}\)$/ \1/') -YYYYMMDDHH=$(${DATE} +%Y%m%d%H -d "${START_DATE}") -YYYYMMDD=${YYYYMMDDHH:0:8} -HH=${YYYYMMDDHH:8:2} -${ECHO} ${YYYYMMDD} -${ECHO} ${HH} - +# # Current and previous day calculation -current_day=`${DATE} -d "${YYYYMMDD}"` -current_hh=`${DATE} -d ${HH} +"%H"` - -prev_hh=`${DATE} -d "$current_hh -24 hour" +"%H"` -previous_day=`${DATE} '+%C%y%m%d' -d "$current_day-1 days"` -previous_day="${previous_day} ${prev_hh}" +CDATE=${PDY}${cyc} +CDATEm1="${PDYm1}${cyc}" # Number of files to process nfiles=24 -smokeFile=SMOKE_RRFS_data_${YYYYMMDDHH}00.nc +smokeFile="SMOKE_RRFS_data_${CDATE}00.nc" for i in $(seq 0 $(($nfiles - 1)) ) do - if [ "$ebb_dc" -eq 2 ]; then - - # For ebb_dc == 2 - timestr=`date +%Y%m%d%H -d "$previous_day + $i hours"` - intp_fname=${PREDEF_GRID_NAME}_intp_${timestr}00_${timestr}59.nc - else - # For ebb_dc == 1 - timestr=`date +%Y%m%d%H -d "$current_day $current_hh + $i hours"` - intp_fname=${PREDEF_GRID_NAME}_intp_${timestr}00_${timestr}59.nc - fi - - if [ -f ${rave_nwges_dir}/${intp_fname} ]; then - ${LN} -sf ${rave_nwges_dir}/${intp_fname} ${workdir}/${intp_fname} - echo "${rave_nwges_dir}/${intp_fname} interoplated file available to reuse" - else - echo "${rave_nwges_dir}/${intp_fname} interoplated file non available to reuse" - fi + if [ "${EBB_DCYCLE}" -eq 2 ]; then + # For ebb_dc == 2 + timestr=$($NDATE +$i ${CDATEm1}) + intp_fname=${PREDEF_GRID_NAME}_intp_${timestr}00_${timestr}59.nc + else + # For ebb_dc == 1 + timestr=$($NDATE +$i ${CDATE}) + intp_fname=${PREDEF_GRID_NAME}_intp_${timestr}00_${timestr}59.nc + fi + + if [ -f ${rave_nwges_dir}/${intp_fname} ]; then + ln -nsf ${rave_nwges_dir}/${intp_fname} ${workdir}/${intp_fname} + echo "${rave_nwges_dir}/${intp_fname} interoplated file available to reuse" + else + echo "${rave_nwges_dir}/${intp_fname} interoplated file non available to reuse" + fi done - +# #----------------------------------------------------------------------- # # link RAVE data to work directory $workdir # #----------------------------------------------------------------------- - -previous_2day=`${DATE} '+%C%y%m%d' -d "$current_day-2 days"` -YYYYMMDDm1=${previous_day:0:8} -YYYYMMDDm2=${previous_2day:0:8} -if [ -d ${FIRE_RAVE_DIR}/${YYYYMMDDm1}/rave ]; then - fire_rave_dir_work=${workdir} - ln -snf ${FIRE_RAVE_DIR}/${YYYYMMDD}/rave/RAVE-HrlyEmiss-3km_* ${fire_rave_dir_work}/. - ln -snf ${FIRE_RAVE_DIR}/${YYYYMMDDm1}/rave/RAVE-HrlyEmiss-3km_* ${fire_rave_dir_work}/. - ln -snf ${FIRE_RAVE_DIR}/${YYYYMMDDm2}/rave/RAVE-HrlyEmiss-3km_* ${fire_rave_dir_work}/. +# +if [ -d ${FIRE_RAVE_DIR}/${PDYm1}/rave ]; then + fire_rave_dir_work=${workdir} + ln -snf ${FIRE_RAVE_DIR}/${PDY}/rave/RAVE-HrlyEmiss-3km_* ${fire_rave_dir_work}/. + ln -snf ${FIRE_RAVE_DIR}/${PDYm1}/rave/RAVE-HrlyEmiss-3km_* ${fire_rave_dir_work}/. + ln -snf ${FIRE_RAVE_DIR}/${PDYm2}/rave/RAVE-HrlyEmiss-3km_* ${fire_rave_dir_work}/. else - fire_rave_dir_work=${FIRE_RAVE_DIR} + fire_rave_dir_work=${FIRE_RAVE_DIR} fi # Check whether the RAVE files need to be split into hourly files # Format the current day and hour properly for UTC -if [ "$ebb_dc" -eq 1 ]; then - ddhh_to_use="${current_day}${current_hh}" - dd_to_use="${current_day}" +if [ "${EBB_DCYCLE}" -eq 1 ]; then + ddhh_to_use="${PDY}${cyc}" + dd_to_use="${PDY}" else - ddhh_to_use="${previous_day}${prev_hh}" - dd_to_use="${previous_day}" + ddhh_to_use="${PDYm1}${cyc}" + dd_to_use="${PDYm1}" fi # Construct file names and check their existence @@ -149,24 +131,23 @@ echo "Checking for files in directory: $fire_rave_dir_work" files_found=$(find "$fire_rave_dir_work" -type f \( -name "${intp_fname##*/}" -o -name "${intp_fname_beta##*/}" \)) if [ -z "$files_found" ]; then - echo "No files found matching patterns." + echo "No files found matching patterns." else - echo "Files found, proceeding with processing..." - for file_to_use in $files_found; do - echo "Using file: $file_to_use" - for hour in {00..23}; do - output_file="${fire_rave_dir_work}/Hourly_Emissions_3km_${dd_to_use}${hour}00_${dd_to_use}${hour}00.nc" - if [ -f "$output_file" ]; then - echo "Output file for hour $hour already exists: $output_file. Skipping..." - continue - fi - echo "Splitting data for hour $hour..." - ncks -d time,$hour,$hour "$file_to_use" "$output_file" - done - echo "Hourly files processing completed for: $file_to_use" + echo "Files found, proceeding with processing..." + for file_to_use in $files_found; do + echo "Using file: $file_to_use" + for hour in {00..23}; do + output_file="${fire_rave_dir_work}/Hourly_Emissions_3km_${dd_to_use}${hour}00_${dd_to_use}${hour}00.nc" + if [ -f "$output_file" ]; then + echo "Output file for hour $hour already exists: $output_file. Skipping..." + continue + fi + echo "Splitting data for hour $hour..." + ncks -d time,$hour,$hour "$file_to_use" "$output_file" done + echo "Hourly files processing completed for: $file_to_use" + done fi - # #----------------------------------------------------------------------- # @@ -174,7 +155,7 @@ fi # #----------------------------------------------------------------------- # -python -u ${USHdir}/generate_fire_emissions.py \ +python -u ${USHdir}/generate_fire_emissions.py \ "${FIX_SMOKE_DUST}/${PREDEF_GRID_NAME}" \ "${fire_rave_dir_work}" \ "${workdir}" \ @@ -189,8 +170,8 @@ export err # Check the return code before calling err_chk if [ $err -ne 0 ]; then - echo "Error: generate_fire_emissions.py failed with return code $err" - err_chk + echo "Error: generate_fire_emissions.py failed with return code $err" + err_chk fi #Copy the the hourly, interpolated RAVE data to $rave_nwges_dir so it @@ -204,56 +185,49 @@ are_all_files_older_than_15_days() { # Check if all files in the rave_nwges_dir are older than 5 days if are_all_files_older_than_15_days "${rave_nwges_dir}"; then - echo "All files are older than 5 days. Replacing all files." - - # Loop through all files in the work directory and replace them in rave_nwges_dir - for file in ${workdir}/*; do - filename=$(basename "$file") - target_file="${rave_nwges_dir}/${filename}" + echo "All files are older than 5 days. Replacing all files." + # Loop through all files in the work directory and replace them in rave_nwges_dir + for file in ${workdir}/*; do + filename=$(basename "$file") + target_file="${rave_nwges_dir}/${filename}" - cp "${file}" "${target_file}" - echo "Copied file: $filename" - done + cp "${file}" "${target_file}" + echo "Copied file: $filename" + done else - echo "Not all files are older than 5 days. Checking individual files." - - # Loop through all files in the work directory - for file in ${workdir}/*; do - filename=$(basename "$file") - target_file="${rave_nwges_dir}/${filename}" - - # Check if the file matches the pattern or is missing in the target directory - if [[ "$filename" =~ SMOKE_RRFS_data_.*\.nc ]]; then - cp "${file}" "${target_file}" - echo "Copied file: $filename" - elif [ ! -f "${target_file}" ]; then - cp "${file}" "${target_file}" - echo "Copied missing file: $filename" - fi - done + echo "Not all files are older than 5 days. Checking individual files." + # Loop through all files in the work directory + for file in ${workdir}/*; do + filename=$(basename "$file") + target_file="${rave_nwges_dir}/${filename}" + + # Check if the file matches the pattern or is missing in the target directory + if [[ "$filename" =~ SMOKE_RRFS_data_.*\.nc ]]; then + cp "${file}" "${target_file}" + echo "Copied file: $filename" + elif [ ! -f "${target_file}" ]; then + cp "${file}" "${target_file}" + echo "Copied missing file: $filename" + fi + done fi echo "Copy RAVE interpolated files completed" - # #----------------------------------------------------------------------- # -# Print exit message. +# Print message indicating successful completion of script. # #----------------------------------------------------------------------- # print_info_msg " ======================================================================== +Smoke and Dust has successfully generated output files !!!! + Exiting script: \"${scrfunc_fn}\" In directory: \"${scrfunc_dir}\" ========================================================================" # #----------------------------------------------------------------------- # -# Restore the shell options saved at the beginning of this script/function. -# -#----------------------------------------------------------------------- -# { restore_shell_opts; } > /dev/null 2>&1 - - From a0281b65345c2e9ea069f485e4ec835cfe4b8977 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Mon, 19 Aug 2024 11:34:55 +0000 Subject: [PATCH 11/61] add hrrr_gf to fv3.input.yml --- modulefiles/tasks/hera/smoke_dust.local.lua | 2 + parm/FV3.input.yml | 108 ++++++++++++++++++ .../{smoke_dust_prep.yaml => smoke_dust.yaml} | 5 +- ush/config.smoke_dust.yaml | 6 +- ush/valid_param_vals.yaml | 1 + 5 files changed, 116 insertions(+), 6 deletions(-) create mode 100644 modulefiles/tasks/hera/smoke_dust.local.lua rename parm/wflow/{smoke_dust_prep.yaml => smoke_dust.yaml} (93%) diff --git a/modulefiles/tasks/hera/smoke_dust.local.lua b/modulefiles/tasks/hera/smoke_dust.local.lua new file mode 100644 index 0000000000..2eb2ea2ee0 --- /dev/null +++ b/modulefiles/tasks/hera/smoke_dust.local.lua @@ -0,0 +1,2 @@ +load("python_srw_aqm") +load(pathJoin("nco", os.getenv("nco_ver") or "5.1.6")) diff --git a/parm/FV3.input.yml b/parm/FV3.input.yml index efb6c85f5b..cfc0b3e23e 100644 --- a/parm/FV3.input.yml +++ b/parm/FV3.input.yml @@ -100,6 +100,114 @@ FV3_HRRR: nst_anl: null nstf_name: null +FV3_HRRR_gf: + atmos_model_nml: + avg_max_length: 3600. + ignore_rst_cksum: true + fv_core_nml: + agrid_vel_rst: true + d_con: 0.5 + d2_bg_k2: 0.04 + dz_min: 2.0 + hord_dp: 6 + hord_mt: 6 + hord_tm: 6 + hord_tr: 8 + hord_vt: 6 + k_split: 2 + kord_mt: 9 + kord_tm: -9 + kord_tr: 9 + kord_wz: 9 + n_split: 5 + psm_bc: 1 + nord_tr: 0 + nrows_blend: 10 + range_warn: False + regional_bcs_from_gsi: false + rf_cutoff: 2000.0 + vtdm4: 0.02 + write_restart_with_bcs: false + gfs_physics_nml: + cdmbgwd: [3.5, 1.0] + diag_log: true + do_deep: true + do_gsl_drag_ls_bl: true + do_gsl_drag_ss: true + do_gsl_drag_tofd: true + do_mynnsfclay: true + do_sfcperts: null + do_tofd : false + do_ugwp : false + do_ugwp_v0 : false + do_ugwp_v0_nst_only : false + do_ugwp_v0_orog_only : false + dt_inner : 36 + ebb_dcycle : 1 + effr_in: true + gwd_opt: 3 + fhlwr: 900.0 + fhswr: 900.0 + iaer: 1011 + ialb: 2 + iccn: 2 + icliq_sw: 2 + iems: 2 + imfdeepcnv: 3 + imfshalcnv: -1 + iopt_alb: 2 + iopt_btr: 1 + iopt_crs: 1 + iopt_dveg: 2 + iopt_frz: 1 + iopt_inf: 1 + iopt_rad: 1 + iopt_run: 1 + iopt_sfc: 1 + iopt_snf: 4 + iopt_stc: 1 + iopt_tbot: 2 + iovr: 3 + ldiag_ugwp: false + lgfdlmprad: false + lightning_threat: true + mosaic_lu: 1 + mosaic_soil: 1 + isncond_opt: 2 + isncovr_opt: 3 + sfclay_compute_flux: true + thsfc_loc: false + # Smoke/dust options + rrfs_sd : false + rrfs_smoke_debug : false + seas_opt : 0 + mix_chem : true + dust_opt : 1 + coarsepm_settling : 1 + smoke_conv_wet_coef : [0.5, 0.5, 0.5] + hwp_method : 1 + aero_ind_fdb : false + aero_dir_fdb : true + addsmoke_flag : 1 + wetdep_ls_opt : 1 + do_plumerise : true + do_smoke_transport : true + plumerisefire_frq : 30 + plume_wind_eff : 1 + dust_moist_correction : 2.0 + dust_drylimit_factor : 0.5 + dust_alpha : 10.0 + dust_gamma : 1.3 + drydep_opt : 1 + enh_mix : false + wetdep_ls_alpha : 0.5 + smoke_conv_wet_coef : [ 0.50, 0.50, 0.50 ] + do_smoke_transport : true + ebb_dcycle : 2 + sc_factor : 1.0 + fv_diagnostics_nml: + do_hailcast: true + FV3_RAP: fv_core_nml: <<: *HRRR_fv_core diff --git a/parm/wflow/smoke_dust_prep.yaml b/parm/wflow/smoke_dust.yaml similarity index 93% rename from parm/wflow/smoke_dust_prep.yaml rename to parm/wflow/smoke_dust.yaml index b40f763057..6516cd35fd 100644 --- a/parm/wflow/smoke_dust_prep.yaml +++ b/parm/wflow/smoke_dust.yaml @@ -32,7 +32,4 @@ task_smoke_dust: command: '&LOAD_MODULES_RUN_TASK; "smoke_dust" "&HOMEdir;/jobs/JSRW_SMOKE_DUST"' join: !cycstr '&LOGDIR;/{{ jobname }}_@Y@m@d@H&LOGEXT;' memory: 2G - dependency: - taskdep: - attrs: - task: make_lbcs_mem000 + diff --git a/ush/config.smoke_dust.yaml b/ush/config.smoke_dust.yaml index 91abc8170d..c41749c3d4 100644 --- a/ush/config.smoke_dust.yaml +++ b/ush/config.smoke_dust.yaml @@ -4,6 +4,8 @@ user: RUN_ENVIR: community MACHINE: hera ACCOUNT: [account name] +platform: + BUILD_MOD_FN: 'build_{{ user.MACHINE|lower() }}_intel_prod' workflow: USE_CRON_TO_RELAUNCH: true CRON_RELAUNCH_INTVL_MNTS: 3 @@ -22,14 +24,14 @@ workflow: FIELD_TABLE_TMPL_FN: field_table_smoke_dust.FV3_HRRR_gf DO_REAL_TIME: false COLDSTART: true # set to true for cold start - WARMSTART_CYCLE_DIR: '/scratch2/NAGAPE/epic/SRW-AQM_DATA/aqm_data/restart/2023111000' # for hera +# WARMSTART_CYCLE_DIR: '/path/to/warm/start/files' # for hera nco: envir_default: test_smoke_dust NET_default: smoke_dust RUN_default: smoke_dust rocoto: tasks: - taskgroups: '{{ ["parm/wflow/prep.yaml", "parm/wflow/smoke_dust_prep.yaml", "parm/wflow/coldstart.yaml", "parm/wflow/post.yaml"]|include }}' + taskgroups: '{{ ["parm/wflow/prep.yaml", "parm/wflow/smoke_dust.yaml", "parm/wflow/coldstart.yaml", "parm/wflow/post.yaml"]|include }}' metatask_run_ensemble: task_run_fcst_mem#mem#: walltime: 03:00:00 diff --git a/ush/valid_param_vals.yaml b/ush/valid_param_vals.yaml index 3530b51ae9..6004b56eb0 100644 --- a/ush/valid_param_vals.yaml +++ b/ush/valid_param_vals.yaml @@ -34,6 +34,7 @@ valid_vals_CCPP_PHYS_SUITE: [ "FV3_RRFS_v1beta", "FV3_WoFS_v0", "FV3_HRRR", +"FV3_HRRR_gf", "FV3_RAP" ] valid_vals_GFDLgrid_NUM_CELLS: [48, 96, 192, 384, 768, 1152, 3072] From c6f776643b802387fd18f293c26da1d6538d3383 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Mon, 19 Aug 2024 16:32:02 +0000 Subject: [PATCH 12/61] add fix dir to config --- modulefiles/tasks/hera/smoke_dust.local.lua | 2 +- parm/wflow/smoke_dust.yaml | 26 ++++++++++ scripts/exregional_make_ics.sh | 1 + scripts/exregional_make_lbcs.sh | 1 + scripts/exsrw_smoke_dust.sh | 53 ++++++++++----------- ush/config_defaults.yaml | 12 +++++ ush/machine/hera.yaml | 5 ++ 7 files changed, 70 insertions(+), 30 deletions(-) diff --git a/modulefiles/tasks/hera/smoke_dust.local.lua b/modulefiles/tasks/hera/smoke_dust.local.lua index 2eb2ea2ee0..63063d4fab 100644 --- a/modulefiles/tasks/hera/smoke_dust.local.lua +++ b/modulefiles/tasks/hera/smoke_dust.local.lua @@ -1,2 +1,2 @@ -load("python_srw_aqm") +load("python_srw") load(pathJoin("nco", os.getenv("nco_ver") or "5.1.6")) diff --git a/parm/wflow/smoke_dust.yaml b/parm/wflow/smoke_dust.yaml index 6516cd35fd..26f692f526 100644 --- a/parm/wflow/smoke_dust.yaml +++ b/parm/wflow/smoke_dust.yaml @@ -32,4 +32,30 @@ task_smoke_dust: command: '&LOAD_MODULES_RUN_TASK; "smoke_dust" "&HOMEdir;/jobs/JSRW_SMOKE_DUST"' join: !cycstr '&LOGDIR;/{{ jobname }}_@Y@m@d@H&LOGEXT;' memory: 2G + dependency: + and: + or_grid: + datadep_grid: + attrs: + age: 00:00:00:05 + text: '{{ task_make_grid.GRID_DIR }}/make_grid_task_complete.txt' + streq: + left: staged_grid + right: '{% if not rocoto.get("tasks", {}).get("task_make_grid") %}staged_grid{% endif %}' + or_orog: + datadep_orog: + attrs: + age: 00:00:00:05 + text: '{{ task_make_orog.OROG_DIR }}/make_orog_task_complete.txt' + streq: + left: staged_orog + right: '{% if not rocoto.get("tasks", {}).get("task_make_orog") %}staged_orog{% endif %}' + or_sfc_climo: + datadep_sfc_climo: + attrs: + age: 00:00:00:05 + text: '{{ task_make_sfc_climo.SFC_CLIMO_DIR }}/make_sfc_climo_task_complete.txt' + streq: + left: staged_sfc_climo + right: '{% if not rocoto.get("tasks", {}).get("task_make_sfc_climo") %}staged_sfc_climo{% endif %}' diff --git a/scripts/exregional_make_ics.sh b/scripts/exregional_make_ics.sh index 8cd49076b0..8a8aade972 100755 --- a/scripts/exregional_make_ics.sh +++ b/scripts/exregional_make_ics.sh @@ -195,6 +195,7 @@ case "${CCPP_PHYS_SUITE}" in "FV3_GFS_v17_p8" | \ "FV3_WoFS_v0" | \ "FV3_HRRR" | \ + "FV3_HRRR_gf" | \ "FV3_RAP" ) if [ "${EXTRN_MDL_NAME_ICS}" = "RAP" ] || \ [ "${EXTRN_MDL_NAME_ICS}" = "HRRR" ]; then diff --git a/scripts/exregional_make_lbcs.sh b/scripts/exregional_make_lbcs.sh index 35b4da388a..d174ba2933 100755 --- a/scripts/exregional_make_lbcs.sh +++ b/scripts/exregional_make_lbcs.sh @@ -194,6 +194,7 @@ case "${CCPP_PHYS_SUITE}" in "FV3_GFS_v17_p8" | \ "FV3_WoFS_v0" | \ "FV3_HRRR" | \ + "FV3_HRRR_gf" | \ "FV3_RAP") if [ "${EXTRN_MDL_NAME_LBCS}" = "RAP" ] || \ [ "${EXTRN_MDL_NAME_LBCS}" = "HRRR" ]; then diff --git a/scripts/exsrw_smoke_dust.sh b/scripts/exsrw_smoke_dust.sh index 3765e25762..3e034b2a10 100755 --- a/scripts/exsrw_smoke_dust.sh +++ b/scripts/exsrw_smoke_dust.sh @@ -8,9 +8,8 @@ #----------------------------------------------------------------------- # . ${USHsrw}/source_util_funcs.sh -for sect in user nco platform workflow nco global verification cpl_aqm_parm \ - constants fixed_files grid_params \ - task_point_source task_run_fcst ; do +for sect in user nco platform workflow nco global smoke_dust_parm \ + constants fixed_files grid_params task_run_fcst ; do source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} done # @@ -51,20 +50,16 @@ This is the ex-script for the task that runs Smoke and Dust. # #----------------------------------------------------------------------- # -# Set the name of and create the directory in which the output from this -# script will be saved for long time (if that directory doesn't already exist). +# Path to Smoke and Dust input files # #----------------------------------------------------------------------- # -export rave_nwges_dir=${NWGES_DIR}/RAVE_INTP -mkdir -p "${rave_nwges_dir}" -export hourly_hwpdir=${NWGES_BASEDIR}/HOURLY_HWP -mkdir -p "${hourly_hwpdir}" +rave_intp_dir=${COMINsmoke}/RAVE_INTP +hourly_hwpdir=${COMINsmoke}/HOURLY_HWP # #----------------------------------------------------------------------- # -# Link the the hourly, interpolated RAVE data from $rave_nwges_dir so it -# is reused +# Link the the hourly, interpolated RAVE data # #----------------------------------------------------------------------- # @@ -88,27 +83,27 @@ do intp_fname=${PREDEF_GRID_NAME}_intp_${timestr}00_${timestr}59.nc fi - if [ -f ${rave_nwges_dir}/${intp_fname} ]; then - ln -nsf ${rave_nwges_dir}/${intp_fname} ${workdir}/${intp_fname} - echo "${rave_nwges_dir}/${intp_fname} interoplated file available to reuse" + if [ -f ${rave_intp_dir}/${intp_fname} ]; then + ln -nsf ${rave_intp_dir}/${intp_fname} ${DATA}/${intp_fname} + echo "${rave_intp_dir}/${intp_fname} interoplated file available to reuse" else - echo "${rave_nwges_dir}/${intp_fname} interoplated file non available to reuse" + echo "${rave_intp_dir}/${intp_fname} interoplated file non available to reuse" fi done # #----------------------------------------------------------------------- # -# link RAVE data to work directory $workdir +# link RAVE data to work directory $DATA # #----------------------------------------------------------------------- # -if [ -d ${FIRE_RAVE_DIR}/${PDYm1}/rave ]; then - fire_rave_dir_work=${workdir} - ln -snf ${FIRE_RAVE_DIR}/${PDY}/rave/RAVE-HrlyEmiss-3km_* ${fire_rave_dir_work}/. - ln -snf ${FIRE_RAVE_DIR}/${PDYm1}/rave/RAVE-HrlyEmiss-3km_* ${fire_rave_dir_work}/. - ln -snf ${FIRE_RAVE_DIR}/${PDYm2}/rave/RAVE-HrlyEmiss-3km_* ${fire_rave_dir_work}/. +if [ -d ${COMINfire}/${PDYm1}/rave ]; then + fire_rave_dir_work=${DATA} + ln -snf ${COMINfire}/${PDY}/rave/RAVE-HrlyEmiss-3km_* ${fire_rave_dir_work}/. + ln -snf ${COMINfire}/${PDYm1}/rave/RAVE-HrlyEmiss-3km_* ${fire_rave_dir_work}/. + ln -snf ${COMINfire}/${PDYm2}/rave/RAVE-HrlyEmiss-3km_* ${fire_rave_dir_work}/. else - fire_rave_dir_work=${FIRE_RAVE_DIR} + fire_rave_dir_work=${COMINfire} fi # Check whether the RAVE files need to be split into hourly files @@ -155,10 +150,10 @@ fi # #----------------------------------------------------------------------- # -python -u ${USHdir}/generate_fire_emissions.py \ - "${FIX_SMOKE_DUST}/${PREDEF_GRID_NAME}" \ +${USHdir}/generate_fire_emissions.py \ + "${FIXlam}" \ "${fire_rave_dir_work}" \ - "${workdir}" \ + "${DATA}" \ "${PREDEF_GRID_NAME}" \ "${EBB_DCYCLE}" \ "${RESTART_INTERVAL}" \ @@ -187,9 +182,9 @@ are_all_files_older_than_15_days() { if are_all_files_older_than_15_days "${rave_nwges_dir}"; then echo "All files are older than 5 days. Replacing all files." # Loop through all files in the work directory and replace them in rave_nwges_dir - for file in ${workdir}/*; do + for file in ${DATA}/*; do filename=$(basename "$file") - target_file="${rave_nwges_dir}/${filename}" + target_file="${COMINsmoke}/${filename}" cp "${file}" "${target_file}" echo "Copied file: $filename" @@ -197,9 +192,9 @@ if are_all_files_older_than_15_days "${rave_nwges_dir}"; then else echo "Not all files are older than 5 days. Checking individual files." # Loop through all files in the work directory - for file in ${workdir}/*; do + for file in ${DATA}/*; do filename=$(basename "$file") - target_file="${rave_nwges_dir}/${filename}" + target_file="${COMINsmoke}/${filename}" # Check if the file matches the pattern or is missing in the target directory if [[ "$filename" =~ SMOKE_RRFS_data_.*\.nc ]]; then diff --git a/ush/config_defaults.yaml b/ush/config_defaults.yaml index 3474cef744..00f5fc8bd1 100644 --- a/ush/config_defaults.yaml +++ b/ush/config_defaults.yaml @@ -426,6 +426,9 @@ platform: # FIXemis: # System directory where AQM emission data files are located. # + # FIXsmoke: + # System directory where Smoke and Dust data files are located. + # # FIXcrtm: # System directory where CRTM fixed files are located # @@ -442,6 +445,7 @@ platform: FIXshp: "" FIXaqm: "" FIXemis: "" + FIXsmoke: "" FIXcrtm: "" FIXcrtmupp: "" # @@ -2687,9 +2691,17 @@ smoke_dust_parm: # DO_SMOKE_DUST: # Flag turning on/off Smoke and Dust # + # COMINsmoke_default: + # Path to the directory containing smoke and dust files + # + # COMINfire_default: + # Path to the directory containing RAVE fire files + # #----------------------------------------------------------------------- # DO_SMOKE_DUST: false + COMINsmoke_default: "" + COMINfire_default: "" rocoto: attrs: "" diff --git a/ush/machine/hera.yaml b/ush/machine/hera.yaml index 80fbb8fc98..e9dfc818b5 100644 --- a/ush/machine/hera.yaml +++ b/ush/machine/hera.yaml @@ -37,6 +37,7 @@ platform: FIXshp: /scratch1/NCEPDEV/nems/role.epic/UFS_SRW_data/develop/NaturalEarth FIXaqm: /scratch2/NAGAPE/epic/SRW-AQM_DATA/fix_aqm FIXemis: /scratch1/RDARCH/rda-arl-gpu/Barry.Baker/emissions/nexus + FIXsmoke: /scratch2/NAGAPE/epic/SRW-AQM_DATA/fix_smoke EXTRN_MDL_DATA_STORES: hpss aws nomads cpl_aqm_parm: @@ -44,6 +45,10 @@ cpl_aqm_parm: COMINgefs_default: /scratch2/NAGAPE/epic/SRW-AQM_DATA/aqm_data/GEFS_DATA NEXUS_GFS_SFC_DIR: /scratch2/NAGAPE/epic/SRW-AQM_DATA/aqm_data/GFS_SFC_DATA +smoke_dust_parm: + COMINsmoke_default: /scratch2/NAGAPE/epic/SRW-AQM_DATA/smoke_dust/RAVE_smoke_dust + COMINfire_default: /scratch2/NAGAPE/epic/SRW-AQM_DATA/smoke_dust/RAVE_fire + rocoto: tasks: metatask_run_ensemble: From 1a741000ac1dde5330625f261e271ba16738ea83 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Mon, 19 Aug 2024 17:22:54 +0000 Subject: [PATCH 13/61] fix smoke/dust script --- scripts/exsrw_smoke_dust.sh | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/scripts/exsrw_smoke_dust.sh b/scripts/exsrw_smoke_dust.sh index 3e034b2a10..455ab3d3a6 100755 --- a/scripts/exsrw_smoke_dust.sh +++ b/scripts/exsrw_smoke_dust.sh @@ -151,7 +151,7 @@ fi #----------------------------------------------------------------------- # ${USHdir}/generate_fire_emissions.py \ - "${FIXlam}" \ + "${FIXsmoke}/${PREDEF_GRID_NAME}" \ "${fire_rave_dir_work}" \ "${DATA}" \ "${PREDEF_GRID_NAME}" \ @@ -159,14 +159,11 @@ ${USHdir}/generate_fire_emissions.py \ "${RESTART_INTERVAL}" \ # Capture the return code from the previous command -err=$? -echo "Return code from generate_fire_emissions.py: $err" -export err - -# Check the return code before calling err_chk +export err=$? if [ $err -ne 0 ]; then - echo "Error: generate_fire_emissions.py failed with return code $err" - err_chk + message_txt="Generate_fire_emissions.py failed with return code $err" + err_exit "${message_txt}" + print_err_msg_exit "${message_txt}" fi #Copy the the hourly, interpolated RAVE data to $rave_nwges_dir so it @@ -179,7 +176,7 @@ are_all_files_older_than_15_days() { } # Check if all files in the rave_nwges_dir are older than 5 days -if are_all_files_older_than_15_days "${rave_nwges_dir}"; then +if are_all_files_older_than_15_days "${rave_intp_dir}"; then echo "All files are older than 5 days. Replacing all files." # Loop through all files in the work directory and replace them in rave_nwges_dir for file in ${DATA}/*; do From 9bbd61b81f3fdc11bf0c3a48989b3298edc13e06 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Mon, 19 Aug 2024 17:33:59 +0000 Subject: [PATCH 14/61] change branch to hash --- Externals_smoke_dust.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Externals_smoke_dust.cfg b/Externals_smoke_dust.cfg index 475390ca35..7245ce8967 100644 --- a/Externals_smoke_dust.cfg +++ b/Externals_smoke_dust.cfg @@ -11,8 +11,8 @@ required = True protocol = git repo_url = https://github.com/ufs-community/ufs-weather-model # Specify either a branch name or a hash but not both. -branch = production/RRFS.v1 -#hash = b5a1976 +#branch = production/RRFS.v1 +hash = ce43a6f local_path = sorc/ufs-weather-model required = True From 9ac98e033591ee026210f9da8d9e2a2cc4b3e349 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Tue, 20 Aug 2024 11:15:09 +0000 Subject: [PATCH 15/61] add prepstart --- jobs/JSRW_PREPSTART | 161 +++++++++++++++++++++++++++ jobs/JSRW_SMOKE_DUST | 3 +- scripts/exsrw_prepstart.sh | 216 ++++++++++++++++++++++++++++++++++++ scripts/exsrw_smoke_dust.sh | 27 +++-- ush/add_smoke.py | 84 ++++++++++++++ ush/config.smoke_dust.yaml | 2 + ush/config_defaults.yaml | 10 ++ ush/machine/hera.yaml | 4 +- 8 files changed, 490 insertions(+), 17 deletions(-) create mode 100755 jobs/JSRW_PREPSTART create mode 100755 scripts/exsrw_prepstart.sh create mode 100755 ush/add_smoke.py diff --git a/jobs/JSRW_PREPSTART b/jobs/JSRW_PREPSTART new file mode 100755 index 0000000000..f70bb60ae9 --- /dev/null +++ b/jobs/JSRW_PREPSTART @@ -0,0 +1,161 @@ +#!/usr/bin/env bash + +# +#----------------------------------------------------------------------- +# +# This script runs prepstart +# +#----------------------------------------------------------------------- +# +date +export PS4='+ $SECONDS + ' +set -xue +# +#----------------------------------------------------------------------- +# +# Set the NCO standard environment variables (Table 1, pp.4) +# +#----------------------------------------------------------------------- +# +export USHsrw="${HOMEdir}/ush" +export EXECsrw="${HOMEdir}/exec" +export PARMsrw="${HOMEdir}/parm" +export SCRIPTSsrw="${HOMEdir}/scripts" +# +#----------------------------------------------------------------------- +# +# Source the variable definitions file and the bash utility functions. +# +#----------------------------------------------------------------------- +# +export USHdir="${USHsrw}" # should be removed later +. ${USHsrw}/source_util_funcs.sh +for sect in user nco platform workflow nco global smoke_dust_parm ; do + source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} +done +# +#----------------------------------------------------------------------- +# +# Get the full path to the file in which this script/function is located +# (scrfunc_fp), the name of that file (scrfunc_fn), and the directory in +# which the file is located (scrfunc_dir). +# +#----------------------------------------------------------------------- +# +scrfunc_fp=$( $READLINK -f "${BASH_SOURCE[0]}" ) +scrfunc_fn=$( basename "${scrfunc_fp}" ) +scrfunc_dir=$( dirname "${scrfunc_fp}" ) +# +#----------------------------------------------------------------------- +# +# Print message indicating entry into script. +# +#----------------------------------------------------------------------- +# +print_info_msg " +======================================================================== +Entering script: \"${scrfunc_fn}\" +In directory: \"${scrfunc_dir}\" + +This is the J-job script for the task that copies or fetches RAVE fire +emission data files from disk, or HPSS. +========================================================================" +# +#----------------------------------------------------------------------- +# +# Define job and jobid by default for rocoto +# +#----------------------------------------------------------------------- +# +WORKFLOW_MANAGER="${WORKFLOW_MANAGER:-rocoto}" +if [ "${WORKFLOW_MANAGER}" = "rocoto" ]; then + if [ "${SCHED}" = "slurm" ]; then + job=${SLURM_JOB_NAME} + pid=${SLURM_JOB_ID} + elif [ "${SCHED}" = "pbspro" ]; then + job=${PBS_JOBNAME} + pid=${PBS_JOBID} + else + job="task" + pid=$$ + fi + jobid="${job}.${PDY}${cyc}.${pid}" +fi +# +#----------------------------------------------------------------------- +# +# Create a temp working directory (DATA) and cd into it. +# +#----------------------------------------------------------------------- +# +export DATA="${DATA:-${DATAROOT}/${jobid}}" +mkdir -p $DATA +cd $DATA +# +#----------------------------------------------------------------------- +# +# Define NCO environment variables and set COM type definitions. +# +#----------------------------------------------------------------------- +# +export NET="${NET:-${NET_default}}" +export RUN="${RUN:-${RUN_default}}" + +[[ "$WORKFLOW_MANAGER" = "rocoto" ]] && export COMROOT=$COMROOT +if [ "${MACHINE}" = "WCOSS2" ]; then + export COMIN="${COMIN:-$(compath.py -o ${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR})}" + export COMOUT="${COMOUT:-$(compath.py -o ${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR})}" +else + export COMIN="${COMIN:-${COMROOT}/${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR}}" + export COMOUT="${COMOUT:-${COMROOT}/${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR}}" +fi + +mkdir -p ${COMOUT} + +# Run setpdy to initialize PDYm and PDYp variables +export cycle="${cycle:-t${cyc}z}" +setpdy.sh +. ./PDY +# +#----------------------------------------------------------------------- +# +# Set sub-cycle and ensemble member names in file/diectory names +# +#----------------------------------------------------------------------- +# +if [ ${subcyc} -ne 0 ]; then + export cycle="t${cyc}${subcyc}z" +fi +if [ $(boolify "${DO_ENSEMBLE}") = "TRUE" ] && [ ! -z ${ENSMEM_INDX} ]; then + export dot_ensmem=".mem${ENSMEM_INDX}" +else + export dot_ensmem= +fi +# +#----------------------------------------------------------------------- +# +# Call the ex-script for this J-job. +# +#----------------------------------------------------------------------- +# +export pgmout="${DATA}/OUTPUT.$$" +env + +${SCRIPTSsrw}/exsrw_prepstart.sh +export err=$?; err_chk + +if [ -e "$pgmout" ]; then + cat $pgmout +fi +# +#----------------------------------------------------------------------- +# +# Whether or not working directory DATA should be kept. +# +#----------------------------------------------------------------------- +# +if [ "${KEEPDATA}" = "NO" ]; then + rm -rf ${DATA} +fi +date + diff --git a/jobs/JSRW_SMOKE_DUST b/jobs/JSRW_SMOKE_DUST index d448dce43b..6dd7cd6882 100755 --- a/jobs/JSRW_SMOKE_DUST +++ b/jobs/JSRW_SMOKE_DUST @@ -30,7 +30,7 @@ export SCRIPTSsrw="${HOMEdir}/scripts" # export USHdir="${USHsrw}" # should be removed later . ${USHsrw}/source_util_funcs.sh -for sect in user nco platform workflow nco global cpl_aqm_parm cpl_aqm_parm ; do +for sect in user nco platform workflow nco global smoke_dust_parm ; do source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} done # @@ -112,6 +112,7 @@ fi mkdir -p ${COMOUT} +export COMINsmoke="${COMINsmoke:-${COMINsmoke_default}}" export COMINfire="${COMINfire:-${COMINfire_default}}" # Run setpdy to initialize PDYm and PDYp variables diff --git a/scripts/exsrw_prepstart.sh b/scripts/exsrw_prepstart.sh new file mode 100755 index 0000000000..9ebbf0fa28 --- /dev/null +++ b/scripts/exsrw_prepstart.sh @@ -0,0 +1,216 @@ +#!/usr/bin/env bash + +# +#----------------------------------------------------------------------- +# +# Source the variable definitions file and the bash utility functions. +# +#----------------------------------------------------------------------- +# +. ${USHsrw}/source_util_funcs.sh +for sect in user nco platform workflow nco global smoke_dust_parm \ + constants fixed_files grid_params task_run_fcst ; do + source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} +done +# +#----------------------------------------------------------------------- +# +# Save current shell options (in a global array). Then set new options +# for this script/function. +# +#----------------------------------------------------------------------- +# +{ save_shell_opts; set -xue; } > /dev/null 2>&1 +# +#----------------------------------------------------------------------- +# +# Get the full path to the file in which this script/function is located +# (scrfunc_fp), the name of that file (scrfunc_fn), and the directory in +# which the file is located (scrfunc_dir). +# +#----------------------------------------------------------------------- +# +scrfunc_fp=$( $READLINK -f "${BASH_SOURCE[0]}" ) +scrfunc_fn=$( basename "${scrfunc_fp}" ) +scrfunc_dir=$( dirname "${scrfunc_fp}" ) +# +#----------------------------------------------------------------------- +# +# Print message indicating entry into script. +# +#----------------------------------------------------------------------- +# +print_info_msg " +======================================================================== +Entering script: \"${scrfunc_fn}\" +In directory: \"${scrfunc_dir}\" + +This is the ex-script for the task that runs prepstart. +========================================================================" + +#----------------------------------------------------------------------- +# +# smoke/dust cycling +# +#----------------------------------------------------------------------- +if [ "${DO_SMOKE_DUST}" = "TRUE" ] && [ "${CYCLE_TYPE}" = "spinup" ]; then # cycle smoke/dust fields + if_cycle_smoke_dust="FALSE" + if [ ${HH} -eq 4 ] || [ ${HH} -eq 16 ] ; then + if_cycle_smoke_dust="TRUE" + elif [ ${HH} -eq 6 ] && [ -f ${COMOUT}/../04_spinup/cycle_smoke_dust_skipped.txt ]; then + if_cycle_smoke_dust="TRUE" + elif [ ${HH} -eq 18 ] && [ -f ${COMOUT}/../16_spinup/cycle_smoke_dust_skipped.txt ]; then + if_cycle_smoke_dust="TRUE" + fi + if [ "${if_cycle_smoke_dust}" = "TRUE" ] ; then + # figure out which surface is available + surface_file_dir_name=fcst_fv3lam + bkpath_find="missing" + restart_prefix_find="missing" + restart_prefix=$( date +%Y%m%d.%H0000. -d "${START_DATE}" ) + if [ "${bkpath_find}" = "missing" ]; then + + offset_hours=${DA_CYCLE_INTERV} + YYYYMMDDHHmInterv=$( date +%Y%m%d%H -d "${START_DATE} ${offset_hours} hours ago" ) + bkpath=${fg_root}/${YYYYMMDDHHmInterv}${SLASH_ENSMEM_SUBDIR}/${surface_file_dir_name}/RESTART + + n=${DA_CYCLE_INTERV} + while [[ $n -le 25 ]] ; do + if [ "${IO_LAYOUT_Y}" = "1" ]; then + checkfile=${bkpath}/${restart_prefix}fv_tracer.res.tile1.nc + else + checkfile=${bkpath}/${restart_prefix}fv_tracer.res.tile1.nc.0000 + fi + if [ -r "${checkfile}" ] && [ "${bkpath_find}" = "missing" ]; then + bkpath_find=${bkpath} + restart_prefix_find=${restart_prefix} + print_info_msg "$VERBOSE" "Found ${checkfile}; Use it for smoke/dust cycle " + break + fi + + n=$((n + ${DA_CYCLE_INTERV})) + offset_hours=${n} + YYYYMMDDHHmInterv=$( date +%Y%m%d%H -d "${START_DATE} ${offset_hours} hours ago" ) + bkpath=${fg_root}/${YYYYMMDDHHmInterv}${SLASH_ENSMEM_SUBDIR}/${surface_file_dir_name}/RESTART # cycling, use background from RESTART + print_info_msg "$VERBOSE" "Trying this path: ${bkpath}" + done + fi + + # check if there are tracer file in continue cycle data space: + if [ "${bkpath_find}" = "missing" ]; then + checkfile=${CONT_CYCLE_DATA_ROOT}/tracer/${restart_prefix}fv_tracer.res.tile1.nc + if [ -r "${checkfile}" ]; then + bkpath_find=${CONT_CYCLE_DATA_ROOT}/tracer + restart_prefix_find=${restart_prefix} + print_info_msg "$VERBOSE" "Found ${checkfile}; Use it for smoke/dust cycle " + fi + fi + + # cycle smoke/dust + rm -f cycle_smoke_dust.done + if [ "${bkpath_find}" = "missing" ]; then + print_info_msg "Warning: cannot find smoke/dust files from previous cycle" + touch ${COMOUT}/cycle_smoke_dust_skipped.txt + else + if [ "${IO_LAYOUT_Y}" = "1" ]; then + checkfile=${bkpath_find}/${restart_prefix_find}fv_tracer.res.tile1.nc + if [ -r "${checkfile}" ]; then + ncks -A -v smoke,dust,coarsepm ${checkfile} fv_tracer.res.tile1.nc + fi + else + for ii in ${list_iolayout} + do + iii=$(printf %4.4i $ii) + checkfile=${bkpath_find}/${restart_prefix_find}fv_tracer.res.tile1.nc.${iii} + if [ -r "${checkfile}" ]; then + ncks -A -v smoke,dust,coarsepm ${checkfile} fv_tracer.res.tile1.nc.${iii} + fi + done + fi + echo "${YYYYMMDDHH}(${CYCLE_TYPE}): cycle smoke/dust from ${checkfile} " >> ${EXPTDIR}/log.cycles + fi + fi +fi + +#----------------------------------------------------------------------- +# +# smoke/dust cycling for Retros +# +#----------------------------------------------------------------------- + +if [ "${DO_SMOKE_DUST}" = "TRUE" ]; then + surface_file_dir_name=fcst_fv3lam + bkpath_find="missing" + restart_prefix_find="missing" + if [ "${bkpath_find}" = "missing" ]; then + restart_prefix=$( date +%Y%m%d.%H0000. -d "${START_DATE}" ) + + offset_hours=${DA_CYCLE_INTERV} + YYYYMMDDHHmInterv=$( date +%Y%m%d%H -d "${START_DATE} ${offset_hours} hours ago" ) + bkpath=${fg_root}/${YYYYMMDDHHmInterv}${SLASH_ENSMEM_SUBDIR}/${surface_file_dir_name}/RESTART + + n=${DA_CYCLE_INTERV} + while [[ $n -le 25 ]] ; do + if [ "${IO_LAYOUT_Y}" = "1" ]; then + checkfile=${bkpath}/${restart_prefix}fv_tracer.res.tile1.nc + else + checkfile=${bkpath}/${restart_prefix}fv_tracer.res.tile1.nc.0000 + fi + if [ -r "${checkfile}" ] && [ "${bkpath_find}" = "missing" ]; then + bkpath_find=${bkpath} + restart_prefix_find=${restart_prefix} + print_info_msg "$VERBOSE" "Found ${checkfile}; Use it for smoke/dust cycle " + break + fi + n=$((n + ${DA_CYCLE_INTERV})) + offset_hours=${n} + YYYYMMDDHHmInterv=$( date +%Y%m%d%H -d "${START_DATE} ${offset_hours} hours ago" ) + bkpath=${fg_root}/${YYYYMMDDHHmInterv}${SLASH_ENSMEM_SUBDIR}/${surface_file_dir_name}/RESTART # cycling, use background from RESTART + print_info_msg "$VERBOSE" "Trying this path: ${bkpath}" + done + fi + + # cycle smoke/dust + rm -f cycle_smoke_dust.done + if [ "${bkpath_find}" = "missing" ]; then + print_info_msg "Warning: cannot find smoke/dust files from previous cycle" + else + if [ "${IO_LAYOUT_Y}" = "1" ]; then + checkfile=${bkpath_find}/${restart_prefix_find}fv_tracer.res.tile1.nc + if [ -r "${checkfile}" ]; then + ncks -A -v smoke,dust,coarsepm ${checkfile} fv_tracer.res.tile1.nc + fi + else + for ii in ${list_iolayout} + do + iii=$(printf %4.4i $ii) + checkfile=${bkpath_find}/${restart_prefix_find}fv_tracer.res.tile1.nc.${iii} + if [ -r "${checkfile}" ]; then + ncks -A -v smoke,dust,coarsepm ${checkfile} fv_tracer.res.tile1.nc.${iii} + fi + done + fi + echo "${YYYYMMDDHH}(${CYCLE_TYPE}): cycle smoke/dust from ${checkfile} " >> ${EXPTDIR}/log.cycles + fi + + ${USHsrw}/add_smoke.py +fi + +# +#----------------------------------------------------------------------- +# +# Print message indicating successful completion of script. +# +#----------------------------------------------------------------------- +# +print_info_msg " +======================================================================== +PREPSTART has successfully been complete !!!! + +Exiting script: \"${scrfunc_fn}\" +In directory: \"${scrfunc_dir}\" +========================================================================" +# +#----------------------------------------------------------------------- +# +{ restore_shell_opts; } > /dev/null 2>&1 diff --git a/scripts/exsrw_smoke_dust.sh b/scripts/exsrw_smoke_dust.sh index 455ab3d3a6..c0e10d0696 100755 --- a/scripts/exsrw_smoke_dust.sh +++ b/scripts/exsrw_smoke_dust.sh @@ -64,12 +64,12 @@ hourly_hwpdir=${COMINsmoke}/HOURLY_HWP #----------------------------------------------------------------------- # # Current and previous day calculation -CDATE=${PDY}${cyc} -CDATEm1="${PDYm1}${cyc}" +export CDATE=${PDY}${cyc} +export CDATEm1="${PDYm1}${cyc}" # Number of files to process nfiles=24 -smokeFile="SMOKE_RRFS_data_${CDATE}00.nc" +smokeFile="${SMOKE_DUST_FILE_PREFIX}_${CDATE}00.nc" for i in $(seq 0 $(($nfiles - 1)) ) do @@ -85,23 +85,23 @@ do if [ -f ${rave_intp_dir}/${intp_fname} ]; then ln -nsf ${rave_intp_dir}/${intp_fname} ${DATA}/${intp_fname} - echo "${rave_intp_dir}/${intp_fname} interoplated file available to reuse" + echo "${rave_intp_dir}/${intp_fname} interoplated file available." else - echo "${rave_intp_dir}/${intp_fname} interoplated file non available to reuse" + echo "WARNING: ${rave_intp_dir}/${intp_fname} interoplated file non available." fi done # #----------------------------------------------------------------------- # -# link RAVE data to work directory $DATA +# link RAVE fire data to working directory $DATA # #----------------------------------------------------------------------- # if [ -d ${COMINfire}/${PDYm1}/rave ]; then fire_rave_dir_work=${DATA} - ln -snf ${COMINfire}/${PDY}/rave/RAVE-HrlyEmiss-3km_* ${fire_rave_dir_work}/. - ln -snf ${COMINfire}/${PDYm1}/rave/RAVE-HrlyEmiss-3km_* ${fire_rave_dir_work}/. - ln -snf ${COMINfire}/${PDYm2}/rave/RAVE-HrlyEmiss-3km_* ${fire_rave_dir_work}/. + ln -snf ${COMINfire}/${PDY}/rave/${RAVE_FIRE_FILE_PREFIX}_* ${fire_rave_dir_work}/. + ln -snf ${COMINfire}/${PDYm1}/rave/${RAVE_FIRE_FILE_PREFIX}_* ${fire_rave_dir_work}/. + ln -snf ${COMINfire}/${PDYm2}/rave/${RAVE_FIRE_FILE_PREFIX}_* ${fire_rave_dir_work}/. else fire_rave_dir_work=${COMINfire} fi @@ -126,7 +126,7 @@ echo "Checking for files in directory: $fire_rave_dir_work" files_found=$(find "$fire_rave_dir_work" -type f \( -name "${intp_fname##*/}" -o -name "${intp_fname_beta##*/}" \)) if [ -z "$files_found" ]; then - echo "No files found matching patterns." + echo "WARNING: No files found matching patterns." else echo "Files found, proceeding with processing..." for file_to_use in $files_found; do @@ -146,18 +146,17 @@ fi # #----------------------------------------------------------------------- # -# Call the ex-script for this J-job. +# Call python script to generate fire emission files. # #----------------------------------------------------------------------- # -${USHdir}/generate_fire_emissions.py \ +${USHsrw}/generate_fire_emissions.py \ "${FIXsmoke}/${PREDEF_GRID_NAME}" \ "${fire_rave_dir_work}" \ "${DATA}" \ "${PREDEF_GRID_NAME}" \ "${EBB_DCYCLE}" \ - "${RESTART_INTERVAL}" \ - + "${RESTART_INTERVAL}" # Capture the return code from the previous command export err=$? if [ $err -ne 0 ]; then diff --git a/ush/add_smoke.py b/ush/add_smoke.py new file mode 100755 index 0000000000..39795ce234 --- /dev/null +++ b/ush/add_smoke.py @@ -0,0 +1,84 @@ +import xarray as xr +import numpy as np +import os + +def populate_data(data, target_shape): + """ + Extracted variables need to match the target shape so we first populating it into a zero array. + + Parameters: + data (np.ndarray): The extracted data to be adjusted. + target_shape (tuple): The shape of the target data array. + + Returns: + np.ndarray: The adjusted data array. + """ + target_lev, target_lat, target_lon = target_shape + populated_data = np.zeros(target_shape) + populated_data[:data.shape[0], :, :] = data + return populated_data + +def main(): + # File paths + source_file = "fv_tracer.res.tile1.nc" + target_file = 'gfs_data.tile7.halo0.nc' + + # Check if the source file exists + if not os.path.exists(source_file): + print(f"Source file '{source_file}' does not exist. Exiting...") + return + + # Open the source file and extract data + data_to_extract = xr.open_dataset(source_file) + smoke_2_add = data_to_extract['smoke'][0,:,:, :] + dust_2_add = data_to_extract['dust'][0,:,:, :] + coarsepm_2_add = data_to_extract['coarsepm'][0,:, :, :] + + print('Max values in source file:', smoke_2_add.max()) + + # Open the target file and load it into memory + file_input = xr.open_dataset(target_file).load() + + # Drop the 'smoke' variable if it exists in both the source and target files + if 'smoke' in file_input.variables and 'smoke' in data_to_extract.variables: + file_input = file_input.drop('smoke') + + # Determine the shape of the new variables based on the target file dimensions + lev_dim = file_input.dims['lev'] + lat_dim = file_input.dims['lat'] + lon_dim = file_input.dims['lon'] + + # Populate the extracted data to match the target shape + #smoke_2_add_populated = populate_data(smoke_2_add, (lev_dim, lat_dim, lon_dim)) + #dust_2_add_populated = populate_data(dust_2_add, (lev_dim, lat_dim, lon_dim)) + #coarsepm_2_add_populated = populate_data(coarsepm_2_add, (lev_dim, lat_dim, lon_dim)) + + #print('Max values in populated data:', smoke_2_add_populated.max(), dust_2_add_populated.max(), coarsepm_2_add_populated.max()) + + # Create new data arrays filled with zeros + smoke_zero = xr.DataArray(np.zeros((lev_dim, lat_dim, lon_dim)), dims=['lev', 'lat', 'lon'], attrs={'units': 'ug/kg'}) + dust_zero = xr.DataArray(np.zeros((lev_dim, lat_dim, lon_dim)), dims=['lev', 'lat', 'lon'], attrs={'units': 'ug/kg'}) + coarsepm_zero = xr.DataArray(np.zeros((lev_dim, lat_dim, lon_dim)), dims=['lev', 'lat', 'lon'], attrs={'units': 'ug/kg'}) + + # Assign the data arrays to the dataset, initially with zeros + file_input['smoke'] = smoke_zero + file_input['dust'] = dust_zero + file_input['coarsepm']= coarsepm_zero + + # Populate the variables with the adjusted data + file_input['smoke'][1:66,:,:] = smoke_2_add + file_input['dust'][1:66,:,:] = dust_2_add + file_input['coarsepm'][1:66,:,:] = coarsepm_2_add + + # Save the modified dataset back to the file + file_input.to_netcdf(target_file, mode='w') + + # Reopen the target file to check the variables + with xr.open_dataset(target_file) as file_input: + print('Max values in target file after update:') + print('smoke:', file_input['smoke'].max().item()) + print('dust:', file_input['dust'].max().item()) + print('coarsepm:', file_input['coarsepm'].max().item()) + +if __name__ == "__main__": + main() diff --git a/ush/config.smoke_dust.yaml b/ush/config.smoke_dust.yaml index c41749c3d4..a9bd8a4afa 100644 --- a/ush/config.smoke_dust.yaml +++ b/ush/config.smoke_dust.yaml @@ -61,4 +61,6 @@ global: HALO_BLEND: 0 smoke_dust_parm: DO_SMOKE_DUST: true + SMOKE_DUST_FILE_PREFIX: "SMOKE_RRFS_data" + RAVE_FIRE_FILE_PREFIX: "RAVE-HrlyEmiss-3km" diff --git a/ush/config_defaults.yaml b/ush/config_defaults.yaml index 00f5fc8bd1..c663111aca 100644 --- a/ush/config_defaults.yaml +++ b/ush/config_defaults.yaml @@ -2697,11 +2697,21 @@ smoke_dust_parm: # COMINfire_default: # Path to the directory containing RAVE fire files # + # SMOKE_DUST_FILE_PREFIX: + # Prefix of Smoke and Dust file name + # + # RAVE_FIRE_FILE_PREFIX: + # Prefix of RAVE fire file name + # #----------------------------------------------------------------------- # DO_SMOKE_DUST: false COMINsmoke_default: "" COMINfire_default: "" + SMOKE_DUST_FILE_PREFIX: "SMOKE_RRFS_data" + RAVE_FIRE_FILE_PREFIX: "RAVE-HrlyEmiss-3km" + RAVE_FIRE_INTP_FILE_PREFIX: "RAVE-HrlyEmiss-3km_v2r0_blend" + RAVE_FIRE_HOURLY_FILE_PREFIX: "Hourly_Emissions_3km" rocoto: attrs: "" diff --git a/ush/machine/hera.yaml b/ush/machine/hera.yaml index e9dfc818b5..e6f8ce6e8d 100644 --- a/ush/machine/hera.yaml +++ b/ush/machine/hera.yaml @@ -46,8 +46,8 @@ cpl_aqm_parm: NEXUS_GFS_SFC_DIR: /scratch2/NAGAPE/epic/SRW-AQM_DATA/aqm_data/GFS_SFC_DATA smoke_dust_parm: - COMINsmoke_default: /scratch2/NAGAPE/epic/SRW-AQM_DATA/smoke_dust/RAVE_smoke_dust - COMINfire_default: /scratch2/NAGAPE/epic/SRW-AQM_DATA/smoke_dust/RAVE_fire + COMINsmoke_default: /scratch2/NAGAPE/epic/SRW-AQM_DATA/data_smoke_dust/RAVE_smoke_dust + COMINfire_default: /scratch2/NAGAPE/epic/SRW-AQM_DATA/data_smoke_dust/RAVE_fire rocoto: tasks: From 467489da09c605a68e5b3814e8e57820532de0f2 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Tue, 20 Aug 2024 12:12:18 +0000 Subject: [PATCH 16/61] add prepstart to xml yaml --- parm/wflow/smoke_dust.yaml | 10 ++++++++++ scripts/exregional_run_post.sh | 2 +- scripts/exsrw_prepstart.sh | 27 +++++++++++++++++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/parm/wflow/smoke_dust.yaml b/parm/wflow/smoke_dust.yaml index 26f692f526..bb054a6be2 100644 --- a/parm/wflow/smoke_dust.yaml +++ b/parm/wflow/smoke_dust.yaml @@ -59,3 +59,13 @@ task_smoke_dust: left: staged_sfc_climo right: '{% if not rocoto.get("tasks", {}).get("task_make_sfc_climo") %}staged_sfc_climo{% endif %}' +task_prepstart: + <<: *default_smoke_dust + command: '&LOAD_MODULES_RUN_TASK; "prepstart" "&HOMEdir;/jobs/JSRW_PREPSTART"' + join: !cycstr '&LOGDIR;/{{ jobname }}_@Y@m@d@H&LOGEXT;' + memory: 2G + dependency: + taskdep: + attrs: + task: smoke_dust + diff --git a/scripts/exregional_run_post.sh b/scripts/exregional_run_post.sh index 3f0ca93df9..f7db102788 100755 --- a/scripts/exregional_run_post.sh +++ b/scripts/exregional_run_post.sh @@ -65,7 +65,7 @@ #----------------------------------------------------------------------- # . $USHdir/source_util_funcs.sh -for sect in user nco platform workflow global cpl_aqm_parm \ +for sect in user nco platform workflow global cpl_aqm_parm smoke_dust_parm \ task_run_fcst task_run_post ; do source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} done diff --git a/scripts/exsrw_prepstart.sh b/scripts/exsrw_prepstart.sh index 9ebbf0fa28..a24ae4e1e3 100755 --- a/scripts/exsrw_prepstart.sh +++ b/scripts/exsrw_prepstart.sh @@ -48,6 +48,33 @@ In directory: \"${scrfunc_dir}\" This is the ex-script for the task that runs prepstart. ========================================================================" +# +#----------------------------------------------------------------------- +# +# Extract from CDATE the starting year, month, day, and hour of the +# forecast. These are needed below for various operations. +# +#----------------------------------------------------------------------- +# +START_DATE=$(echo "${CDATE}" | sed 's/\([[:digit:]]\{2\}\)$/ \1/') + +YYYYMMDDHH=$(date +%Y%m%d%H -d "${START_DATE}") +JJJ=$(date +%j -d "${START_DATE}") + +YYYY=${YYYYMMDDHH:0:4} +MM=${YYYYMMDDHH:4:2} +DD=${YYYYMMDDHH:6:2} +HH=${YYYYMMDDHH:8:2} +YYYYMMDD=${YYYYMMDDHH:0:8} +YYYYJJJHH=${YYYY}${JJJ}${HH} + +current_time=$(date "+%T") +cdate_crnt_fhr=$( date --utc --date "${YYYYMMDD} ${HH} UTC" "+%Y%m%d%H" ) + +YYYYMMDDm1=$(date +%Y%m%d -d "${START_DATE} 1 days ago") +YYYYMMDDm2=$(date +%Y%m%d -d "${START_DATE} 2 days ago") +YYYYMMDDm3=$(date +%Y%m%d -d "${START_DATE} 3 days ago") + #----------------------------------------------------------------------- # # smoke/dust cycling From 50100c4637f759ed1ae78882857718f482c3f255 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Tue, 20 Aug 2024 13:34:07 +0000 Subject: [PATCH 17/61] fix missing orog --- scripts/exregional_make_orog.sh | 2 +- scripts/exregional_run_fcst.sh | 30 ++++++++++++------------------ ush/config.smoke_dust.yaml | 1 + ush/config_defaults.yaml | 4 ++++ 4 files changed, 18 insertions(+), 19 deletions(-) diff --git a/scripts/exregional_make_orog.sh b/scripts/exregional_make_orog.sh index 34b1675d8c..f3d2e8508b 100755 --- a/scripts/exregional_make_orog.sh +++ b/scripts/exregional_make_orog.sh @@ -290,7 +290,7 @@ mv "${raw_orog_fp_orig}" "${raw_orog_fp}" # #----------------------------------------------------------------------- # -suites=( "FV3_RAP" "FV3_HRRR" "FV3_GFS_v15_thompson_mynn_lam3km" "FV3_GFS_v17_p8" ) +suites=( "FV3_RAP" "FV3_HRRR" "FV3_HRRR_gf" "FV3_GFS_v15_thompson_mynn_lam3km" "FV3_GFS_v17_p8" ) if [[ ${suites[@]} =~ "${CCPP_PHYS_SUITE}" ]] ; then DATA="${DATA:-${OROG_DIR}/temp_orog_data}" mkdir -p ${DATA} diff --git a/scripts/exregional_run_fcst.sh b/scripts/exregional_run_fcst.sh index 5dae29ef8d..49e5360eac 100755 --- a/scripts/exregional_run_fcst.sh +++ b/scripts/exregional_run_fcst.sh @@ -116,7 +116,7 @@ #----------------------------------------------------------------------- # . $USHdir/source_util_funcs.sh -for sect in user nco platform workflow global cpl_aqm_parm constants fixed_files \ +for sect in user nco platform workflow global cpl_aqm_parm smoke_dust_parm constants fixed_files \ task_get_extrn_lbcs task_run_fcst task_run_post ; do source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} done @@ -130,6 +130,7 @@ done #----------------------------------------------------------------------- # { save_shell_opts; . $USHdir/preamble.sh; } > /dev/null 2>&1 +set -xue # #----------------------------------------------------------------------- # @@ -299,7 +300,7 @@ create_symlink_to_file $target $symlink ${relative_link_flag} # that the FV3 model is hardcoded to recognize, and those are the names # we use below. # -suites=( "FV3_RAP" "FV3_HRRR" "FV3_GFS_v15_thompson_mynn_lam3km" "FV3_GFS_v17_p8" ) +suites=( "FV3_RAP" "FV3_HRRR" "FV3_HRRR_gf" "FV3_GFS_v15_thompson_mynn_lam3km" "FV3_GFS_v17_p8" ) if [[ ${suites[@]} =~ "${CCPP_PHYS_SUITE}" ]] ; then file_ids=( "ss" "ls" ) for file_id in "${file_ids[@]}"; do @@ -391,25 +392,18 @@ else fi # Smoke and Dust if [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then - ln -snf ${FIX_SMOKE_DUST}/${PREDEF_GRID_NAME}/dust12m_data.nc ${run_dir}/INPUT/dust12m_data.nc - ln -snf ${FIX_SMOKE_DUST}/${PREDEF_GRID_NAME}/emi_data.nc ${run_dir}/INPUT/emi_data.nc - yyyymmddhh=${cdate:0:10} - echo ${yyyymmddhh} - if [ ${cycle_type} = "spinup" ]; then - smokefile=${NWGES_BASEDIR}/RAVE_INTP/SMOKE_RRFS_data_${yyyymmddhh}00_spinup.nc - else - smokefile=${NWGES_BASEDIR}/RAVE_INTP/SMOKE_RRFS_data_${yyyymmddhh}00.nc - fi - echo "try to use smoke file=",${smokefile} + ln -snf ${FIX_SMOKE_DUST}/${PREDEF_GRID_NAME}/dust12m_data.nc . + ln -snf ${FIX_SMOKE_DUST}/${PREDEF_GRID_NAME}/emi_data.nc . + smokefile="${COMIN}/SMOKE_RRFS_data_${PDY}${cyc}00.nc" if [ -f ${smokefile} ]; then - ln -snf ${smokefile} ${run_dir}/INPUT/SMOKE_RRFS_data.nc + ln -snf ${smokefile} SMOKE_RRFS_data.nc else - if [ ${EBB_DCYCLE} = "1" ]; then - ln -snf ${FIX_SMOKE_DUST}/${PREDEF_GRID_NAME}/dummy_24hr_smoke_ebbdc1.nc ${run_dir}/INPUT/SMOKE_RRFS_data.nc - echo "WARNING: Smoke file is not available, use dummy_24hr_smoke_ebbdc1.nc instead" + if [ "${EBB_DCYCLE}" = "1" ]; then + ln -snf ${FIX_SMOKE_DUST}/${PREDEF_GRID_NAME}/dummy_24hr_smoke_ebbdc1.nc SMOKE_RRFS_data.nc + echo "WARNING: Smoke file is not available, use dummy_24hr_smoke_ebbdc1.nc instead" else - ln -snf ${FIX_SMOKE_DUST}/${PREDEF_GRID_NAME}/dummy_24hr_smoke.nc ${run_dir}/INPUT/SMOKE_RRFS_data.nc - echo "WARNING: Smoke file is not available, use dummy_24hr_smoke.nc instead" + ln -snf ${FIX_SMOKE_DUST}/${PREDEF_GRID_NAME}/dummy_24hr_smoke.nc SMOKE_RRFS_data.nc + echo "WARNING: Smoke file is not available, use dummy_24hr_smoke.nc instead" fi fi fi diff --git a/ush/config.smoke_dust.yaml b/ush/config.smoke_dust.yaml index a9bd8a4afa..b33c94c95c 100644 --- a/ush/config.smoke_dust.yaml +++ b/ush/config.smoke_dust.yaml @@ -61,6 +61,7 @@ global: HALO_BLEND: 0 smoke_dust_parm: DO_SMOKE_DUST: true + EBB_DCYCLE: 1 SMOKE_DUST_FILE_PREFIX: "SMOKE_RRFS_data" RAVE_FIRE_FILE_PREFIX: "RAVE-HrlyEmiss-3km" diff --git a/ush/config_defaults.yaml b/ush/config_defaults.yaml index c663111aca..ccc219e35d 100644 --- a/ush/config_defaults.yaml +++ b/ush/config_defaults.yaml @@ -2691,6 +2691,9 @@ smoke_dust_parm: # DO_SMOKE_DUST: # Flag turning on/off Smoke and Dust # + # EBB_DCYCLE: + # 1: for retro, 2: for forecast + # # COMINsmoke_default: # Path to the directory containing smoke and dust files # @@ -2706,6 +2709,7 @@ smoke_dust_parm: #----------------------------------------------------------------------- # DO_SMOKE_DUST: false + EBB_DCYCLE: 1 COMINsmoke_default: "" COMINfire_default: "" SMOKE_DUST_FILE_PREFIX: "SMOKE_RRFS_data" From 459ae249a2cbc40605a0815aeb599beb279f6fbe Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Tue, 20 Aug 2024 14:28:07 +0000 Subject: [PATCH 18/61] add ccpp suite for orog --- ush/link_fix.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ush/link_fix.py b/ush/link_fix.py index f0d103d8ea..b106499424 100755 --- a/ush/link_fix.py +++ b/ush/link_fix.py @@ -207,7 +207,7 @@ def link_fix( f"C*{dot_or_uscore}oro_data.tile{tile_rgnl}.halo{nh0}.nc", f"C*{dot_or_uscore}oro_data.tile{tile_rgnl}.halo{nh4}.nc", ] - if ccpp_phys_suite == "FV3_RAP" or ccpp_phys_suite == "FV3_HRRR" or ccpp_phys_suite == "FV3_GFS_v15_thompson_mynn_lam3km" or ccpp_phys_suite == "FV3_GFS_v17_p8": + if ccpp_phys_suite == "FV3_RAP" or ccpp_phys_suite == "FV3_HRRR" or ccpp_phys_suite == "FV3_HRRR_gf" or ccpp_phys_suite == "FV3_GFS_v15_thompson_mynn_lam3km" or ccpp_phys_suite == "FV3_GFS_v17_p8": fns += [ f"C*{dot_or_uscore}oro_data_ss.tile{tile_rgnl}.halo{nh0}.nc", f"C*{dot_or_uscore}oro_data_ls.tile{tile_rgnl}.halo{nh0}.nc", From bcff5cfd3e28ebae15834fb23229dd45dd09cd28 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Tue, 20 Aug 2024 18:18:29 +0000 Subject: [PATCH 19/61] update smoke_dust scripts --- scripts/exregional_run_fcst.sh | 8 +- scripts/exsrw_smoke_dust.sh | 211 ++++++++++++++++----------------- ush/config_defaults.yaml | 4 +- 3 files changed, 106 insertions(+), 117 deletions(-) diff --git a/scripts/exregional_run_fcst.sh b/scripts/exregional_run_fcst.sh index 49e5360eac..3826666e46 100755 --- a/scripts/exregional_run_fcst.sh +++ b/scripts/exregional_run_fcst.sh @@ -394,15 +394,15 @@ fi if [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then ln -snf ${FIX_SMOKE_DUST}/${PREDEF_GRID_NAME}/dust12m_data.nc . ln -snf ${FIX_SMOKE_DUST}/${PREDEF_GRID_NAME}/emi_data.nc . - smokefile="${COMIN}/SMOKE_RRFS_data_${PDY}${cyc}00.nc" + smokefile="${COMIN}/${SMOKE_DUST_FILE_PREFIX}_${PDY}${cyc}00.nc" if [ -f ${smokefile} ]; then - ln -snf ${smokefile} SMOKE_RRFS_data.nc + ln -snf ${smokefile} ${SMOKE_DUST_FILE_PREFIX}.nc else if [ "${EBB_DCYCLE}" = "1" ]; then - ln -snf ${FIX_SMOKE_DUST}/${PREDEF_GRID_NAME}/dummy_24hr_smoke_ebbdc1.nc SMOKE_RRFS_data.nc + ln -snf ${FIX_SMOKE_DUST}/${PREDEF_GRID_NAME}/dummy_24hr_smoke_ebbdc1.nc ${SMOKE_DUST_FILE_PREFIX}.nc echo "WARNING: Smoke file is not available, use dummy_24hr_smoke_ebbdc1.nc instead" else - ln -snf ${FIX_SMOKE_DUST}/${PREDEF_GRID_NAME}/dummy_24hr_smoke.nc SMOKE_RRFS_data.nc + ln -snf ${FIX_SMOKE_DUST}/${PREDEF_GRID_NAME}/dummy_24hr_smoke.nc ${SMOKE_DUST_FILE_PREFIX}.nc echo "WARNING: Smoke file is not available, use dummy_24hr_smoke.nc instead" fi fi diff --git a/scripts/exsrw_smoke_dust.sh b/scripts/exsrw_smoke_dust.sh index c0e10d0696..f298dd4825 100755 --- a/scripts/exsrw_smoke_dust.sh +++ b/scripts/exsrw_smoke_dust.sh @@ -67,72 +67,65 @@ hourly_hwpdir=${COMINsmoke}/HOURLY_HWP export CDATE=${PDY}${cyc} export CDATEm1="${PDYm1}${cyc}" -# Number of files to process -nfiles=24 +# Check if the fire file exists in the designated directory smokeFile="${SMOKE_DUST_FILE_PREFIX}_${CDATE}00.nc" +if [ -e "${COMINsmoke}/${smokeFile}" ]; then + cp -p "${COMINsmoke}/${smokeFile}" ${COMOUT} +else + # Number of files to process + nfiles=24 + + for i in $(seq 0 $(($nfiles - 1)) ) + do + if [ "${EBB_DCYCLE}" -eq 2 ]; then + # For ebb_dc == 2 + timestr=$($NDATE +$i ${CDATEm1}) + intp_fname=${PREDEF_GRID_NAME}_intp_${timestr}00_${timestr}59.nc + else + # For ebb_dc == 1 + timestr=$($NDATE +$i ${CDATE}) + intp_fname=${PREDEF_GRID_NAME}_intp_${timestr}00_${timestr}59.nc + fi -for i in $(seq 0 $(($nfiles - 1)) ) -do - if [ "${EBB_DCYCLE}" -eq 2 ]; then - # For ebb_dc == 2 - timestr=$($NDATE +$i ${CDATEm1}) - intp_fname=${PREDEF_GRID_NAME}_intp_${timestr}00_${timestr}59.nc - else - # For ebb_dc == 1 - timestr=$($NDATE +$i ${CDATE}) - intp_fname=${PREDEF_GRID_NAME}_intp_${timestr}00_${timestr}59.nc + if [ -f ${rave_intp_dir}/${intp_fname} ]; then + ln -nsf ${rave_intp_dir}/${intp_fname} ${DATA}/${intp_fname} + echo "${rave_intp_dir}/${intp_fname} interoplated file available." + else + echo "WARNING: ${rave_intp_dir}/${intp_fname} interoplated file non available." + fi + done + # + #----------------------------------------------------------------------- + # + # link RAVE fire data to working directory $DATA + # + #----------------------------------------------------------------------- + # + if [ -d ${COMINfire}/${PDYm1}/rave ]; then + ln -snf ${COMINfire}/${PDY}/rave/${RAVE_FIRE_FILE_PREFIX}_* ${DATA}/. + ln -snf ${COMINfire}/${PDYm1}/rave/${RAVE_FIRE_FILE_PREFIX}_* ${DATA}/. + ln -snf ${COMINfire}/${PDYm2}/rave/${RAVE_FIRE_FILE_PREFIX}_* ${DATA}/. fi - if [ -f ${rave_intp_dir}/${intp_fname} ]; then - ln -nsf ${rave_intp_dir}/${intp_fname} ${DATA}/${intp_fname} - echo "${rave_intp_dir}/${intp_fname} interoplated file available." + # Check whether the RAVE files need to be split into hourly files + # Format the current day and hour properly for UTC + if [ "${EBB_DCYCLE}" -eq 1 ]; then + ddhh_to_use="${PDY}${cyc}" + dd_to_use="${PDY}" else - echo "WARNING: ${rave_intp_dir}/${intp_fname} interoplated file non available." + ddhh_to_use="${PDYm1}${cyc}" + dd_to_use="${PDYm1}" fi -done -# -#----------------------------------------------------------------------- -# -# link RAVE fire data to working directory $DATA -# -#----------------------------------------------------------------------- -# -if [ -d ${COMINfire}/${PDYm1}/rave ]; then - fire_rave_dir_work=${DATA} - ln -snf ${COMINfire}/${PDY}/rave/${RAVE_FIRE_FILE_PREFIX}_* ${fire_rave_dir_work}/. - ln -snf ${COMINfire}/${PDYm1}/rave/${RAVE_FIRE_FILE_PREFIX}_* ${fire_rave_dir_work}/. - ln -snf ${COMINfire}/${PDYm2}/rave/${RAVE_FIRE_FILE_PREFIX}_* ${fire_rave_dir_work}/. -else - fire_rave_dir_work=${COMINfire} -fi - -# Check whether the RAVE files need to be split into hourly files -# Format the current day and hour properly for UTC -if [ "${EBB_DCYCLE}" -eq 1 ]; then - ddhh_to_use="${PDY}${cyc}" - dd_to_use="${PDY}" -else - ddhh_to_use="${PDYm1}${cyc}" - dd_to_use="${PDYm1}" -fi - -# Construct file names and check their existence -intp_fname="${fire_rave_dir_work}/RAVE-HrlyEmiss-3km_v2r0_blend_s${ddhh_to_use}00000_e${dd_to_use}23*" -intp_fname_beta="${fire_rave_dir_work}/Hourly_Emissions_3km_${ddhh_to_use}00_${dd_to_use}23*" - -echo "Checking for files in directory: $fire_rave_dir_work" - -# Find files matching the specified patterns -files_found=$(find "$fire_rave_dir_work" -type f \( -name "${intp_fname##*/}" -o -name "${intp_fname_beta##*/}" \)) - -if [ -z "$files_found" ]; then - echo "WARNING: No files found matching patterns." -else - echo "Files found, proceeding with processing..." + # Check various version of RAVE raw data files (new and old) + rave_raw_fn1="RAVE-HrlyEmiss-3km_v2r0_blend_s${ddhh_to_use}00000_e${dd_to_use}23*" + rave_raw_fn2="Hourly_Emissions_3km_${ddhh_to_use}00_${dd_to_use}23*" + # Find files matching the specified patterns + files_found=$(find "$DATA" -type f \( -name "${rave_raw_fn1##*/}" -o -name "${rave_raw_fn2##*/}" \)) + # Splitting 24-hour RAVE raw data into houly data for file_to_use in $files_found; do echo "Using file: $file_to_use" for hour in {00..23}; do - output_file="${fire_rave_dir_work}/Hourly_Emissions_3km_${dd_to_use}${hour}00_${dd_to_use}${hour}00.nc" + output_file="Hourly_Emissions_3km_${dd_to_use}${hour}00_${dd_to_use}${hour}00.nc" if [ -f "$output_file" ]; then echo "Output file for hour $hour already exists: $output_file. Skipping..." continue @@ -142,67 +135,65 @@ else done echo "Hourly files processing completed for: $file_to_use" done -fi -# -#----------------------------------------------------------------------- -# -# Call python script to generate fire emission files. -# -#----------------------------------------------------------------------- -# -${USHsrw}/generate_fire_emissions.py \ - "${FIXsmoke}/${PREDEF_GRID_NAME}" \ - "${fire_rave_dir_work}" \ - "${DATA}" \ - "${PREDEF_GRID_NAME}" \ - "${EBB_DCYCLE}" \ - "${RESTART_INTERVAL}" -# Capture the return code from the previous command -export err=$? -if [ $err -ne 0 ]; then - message_txt="Generate_fire_emissions.py failed with return code $err" - err_exit "${message_txt}" - print_err_msg_exit "${message_txt}" -fi -#Copy the the hourly, interpolated RAVE data to $rave_nwges_dir so it -# is maintained there for future cycles. -# Function to check if all files in the directory are older than 15 days + # + #----------------------------------------------------------------------- + # + # Call python script to generate fire emission files. + # + #----------------------------------------------------------------------- + # + ${USHsrw}/generate_fire_emissions.py \ + "${FIXsmoke}/${PREDEF_GRID_NAME}" \ + "${COMINfire}" \ + "${DATA}" \ + "${PREDEF_GRID_NAME}" \ + "${EBB_DCYCLE}" \ + "${RESTART_INTERVAL}" + export err=$? + if [ $err -ne 0 ]; then + message_txt="Generate_fire_emissions.py failed with return code $err" + err_exit "${message_txt}" + print_err_msg_exit "${message_txt}" + fi + + #Copy the the hourly, interpolated RAVE data to $rave_nwges_dir so it + # is maintained there for future cycles. + # Function to check if all files in the directory are older than 15 days -are_all_files_older_than_15_days() { + are_all_files_older_than_15_days() { find "$1" -type f -mtime -15 | read return $? -} - -# Check if all files in the rave_nwges_dir are older than 5 days -if are_all_files_older_than_15_days "${rave_intp_dir}"; then - echo "All files are older than 5 days. Replacing all files." - # Loop through all files in the work directory and replace them in rave_nwges_dir - for file in ${DATA}/*; do - filename=$(basename "$file") - target_file="${COMINsmoke}/${filename}" + } + + # Check if all files in the rave_nwges_dir are older than 5 days + if are_all_files_older_than_15_days "${rave_intp_dir}"; then + echo "All files are older than 5 days. Replacing all files." + # Loop through all files in the work directory and replace them in rave_nwges_dir + for file in ${DATA}/*; do + filename=$(basename "$file") + target_file="${COMINsmoke}/${filename}" - cp "${file}" "${target_file}" - echo "Copied file: $filename" - done -else - echo "Not all files are older than 5 days. Checking individual files." - # Loop through all files in the work directory - for file in ${DATA}/*; do - filename=$(basename "$file") - target_file="${COMINsmoke}/${filename}" - - # Check if the file matches the pattern or is missing in the target directory - if [[ "$filename" =~ SMOKE_RRFS_data_.*\.nc ]]; then cp "${file}" "${target_file}" echo "Copied file: $filename" - elif [ ! -f "${target_file}" ]; then - cp "${file}" "${target_file}" - echo "Copied missing file: $filename" - fi - done + done + else + echo "Not all files are older than 5 days. Checking individual files." + # Loop through all files in the work directory + for file in ${DATA}/*; do + filename=$(basename "$file") + target_file="${COMINsmoke}/${filename}" + # Check if the file matches the pattern or is missing in the target directory + if [[ "$filename" =~ SMOKE_RRFS_data_.*\.nc ]]; then + cp "${file}" "${target_file}" + echo "Copied file: $filename" + elif [ ! -f "${target_file}" ]; then + cp "${file}" "${target_file}" + echo "Copied missing file: $filename" + fi + done + fi fi - echo "Copy RAVE interpolated files completed" # #----------------------------------------------------------------------- diff --git a/ush/config_defaults.yaml b/ush/config_defaults.yaml index ccc219e35d..3e7ad01819 100644 --- a/ush/config_defaults.yaml +++ b/ush/config_defaults.yaml @@ -2713,9 +2713,7 @@ smoke_dust_parm: COMINsmoke_default: "" COMINfire_default: "" SMOKE_DUST_FILE_PREFIX: "SMOKE_RRFS_data" - RAVE_FIRE_FILE_PREFIX: "RAVE-HrlyEmiss-3km" - RAVE_FIRE_INTP_FILE_PREFIX: "RAVE-HrlyEmiss-3km_v2r0_blend" - RAVE_FIRE_HOURLY_FILE_PREFIX: "Hourly_Emissions_3km" + RAVE_FIRE_FILE_PREFIX: "Hourly_Emission_3km" rocoto: attrs: "" From 63512911b3ffdde1c974223d1f46b86e863b39fb Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Tue, 20 Aug 2024 21:14:15 +0000 Subject: [PATCH 20/61] add python shebang --- scripts/exsrw_smoke_dust.sh | 92 +++++++--------------------------- ush/HWP_tools.py | 2 + ush/add_smoke.py | 2 + ush/fire_emiss_tools.py | 2 + ush/generate_fire_emissions.py | 2 + ush/interp_tools.py | 4 +- 6 files changed, 30 insertions(+), 74 deletions(-) diff --git a/scripts/exsrw_smoke_dust.sh b/scripts/exsrw_smoke_dust.sh index f298dd4825..e5d5bf22b3 100755 --- a/scripts/exsrw_smoke_dust.sh +++ b/scripts/exsrw_smoke_dust.sh @@ -48,65 +48,11 @@ In directory: \"${scrfunc_dir}\" This is the ex-script for the task that runs Smoke and Dust. ========================================================================" # -#----------------------------------------------------------------------- -# -# Path to Smoke and Dust input files -# -#----------------------------------------------------------------------- -# -rave_intp_dir=${COMINsmoke}/RAVE_INTP -hourly_hwpdir=${COMINsmoke}/HOURLY_HWP -# -#----------------------------------------------------------------------- -# -# Link the the hourly, interpolated RAVE data -# -#----------------------------------------------------------------------- -# -# Current and previous day calculation -export CDATE=${PDY}${cyc} -export CDATEm1="${PDYm1}${cyc}" - # Check if the fire file exists in the designated directory -smokeFile="${SMOKE_DUST_FILE_PREFIX}_${CDATE}00.nc" +smokeFile="${SMOKE_DUST_FILE_PREFIX}_${PDY}${cyc}00.nc" if [ -e "${COMINsmoke}/${smokeFile}" ]; then cp -p "${COMINsmoke}/${smokeFile}" ${COMOUT} else - # Number of files to process - nfiles=24 - - for i in $(seq 0 $(($nfiles - 1)) ) - do - if [ "${EBB_DCYCLE}" -eq 2 ]; then - # For ebb_dc == 2 - timestr=$($NDATE +$i ${CDATEm1}) - intp_fname=${PREDEF_GRID_NAME}_intp_${timestr}00_${timestr}59.nc - else - # For ebb_dc == 1 - timestr=$($NDATE +$i ${CDATE}) - intp_fname=${PREDEF_GRID_NAME}_intp_${timestr}00_${timestr}59.nc - fi - - if [ -f ${rave_intp_dir}/${intp_fname} ]; then - ln -nsf ${rave_intp_dir}/${intp_fname} ${DATA}/${intp_fname} - echo "${rave_intp_dir}/${intp_fname} interoplated file available." - else - echo "WARNING: ${rave_intp_dir}/${intp_fname} interoplated file non available." - fi - done - # - #----------------------------------------------------------------------- - # - # link RAVE fire data to working directory $DATA - # - #----------------------------------------------------------------------- - # - if [ -d ${COMINfire}/${PDYm1}/rave ]; then - ln -snf ${COMINfire}/${PDY}/rave/${RAVE_FIRE_FILE_PREFIX}_* ${DATA}/. - ln -snf ${COMINfire}/${PDYm1}/rave/${RAVE_FIRE_FILE_PREFIX}_* ${DATA}/. - ln -snf ${COMINfire}/${PDYm2}/rave/${RAVE_FIRE_FILE_PREFIX}_* ${DATA}/. - fi - # Check whether the RAVE files need to be split into hourly files # Format the current day and hour properly for UTC if [ "${EBB_DCYCLE}" -eq 1 ]; then @@ -116,26 +62,26 @@ else ddhh_to_use="${PDYm1}${cyc}" dd_to_use="${PDYm1}" fi - # Check various version of RAVE raw data files (new and old) - rave_raw_fn1="RAVE-HrlyEmiss-3km_v2r0_blend_s${ddhh_to_use}00000_e${dd_to_use}23*" - rave_raw_fn2="Hourly_Emissions_3km_${ddhh_to_use}00_${dd_to_use}23*" - # Find files matching the specified patterns - files_found=$(find "$DATA" -type f \( -name "${rave_raw_fn1##*/}" -o -name "${rave_raw_fn2##*/}" \)) - # Splitting 24-hour RAVE raw data into houly data - for file_to_use in $files_found; do - echo "Using file: $file_to_use" - for hour in {00..23}; do - output_file="Hourly_Emissions_3km_${dd_to_use}${hour}00_${dd_to_use}${hour}00.nc" - if [ -f "$output_file" ]; then - echo "Output file for hour $hour already exists: $output_file. Skipping..." + for hour in {00..23}; do + fire_hr_fn="Hourly_Emissions_3km_${dd_to_use}${hour}00_${dd_to_use}${hour}00.nc" + if [ -f "${COMINfire}/${fire_hr_fn}" ]; then + echo "Hourly emission file for $hr found." + ln -nsf ${COMINfire}/${output_file} . + else + # Check various version of RAVE raw data files (new and old) + rave_raw_fn1="RAVE-HrlyEmiss-3km_v2r0_blend_s${ddhh_to_use}00000_e${dd_to_use}23*" + rave_raw_fn2="Hourly_Emissions_3km_${ddhh_to_use}00_${dd_to_use}23*" + # Find files matching the specified patterns + files_found=$(find "${COMINfire}" -type f \( -name "${rave_raw_fn1##*/}" -o -name "${rave_raw_fn2##*/}" \)) + # Splitting 24-hour RAVE raw data into houly data + for file_to_use in $files_found; do + echo "Using file: $file_to_use" + echo "Splitting data for hour $hour..." + ncks -d time,$hour,$hour "${COMINfire}/$file_to_use" "$output_file" continue - fi - echo "Splitting data for hour $hour..." - ncks -d time,$hour,$hour "$file_to_use" "$output_file" - done - echo "Hourly files processing completed for: $file_to_use" + done + fi done - # #----------------------------------------------------------------------- # diff --git a/ush/HWP_tools.py b/ush/HWP_tools.py index 5a8faf18d2..7ab7803287 100755 --- a/ush/HWP_tools.py +++ b/ush/HWP_tools.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + import numpy as np import os import datetime as dt diff --git a/ush/add_smoke.py b/ush/add_smoke.py index 39795ce234..036871dc4e 100755 --- a/ush/add_smoke.py +++ b/ush/add_smoke.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + import xarray as xr import numpy as np import os diff --git a/ush/fire_emiss_tools.py b/ush/fire_emiss_tools.py index 7f90e1f82a..2e5d87739b 100755 --- a/ush/fire_emiss_tools.py +++ b/ush/fire_emiss_tools.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + import os import numpy as np import xarray as xr diff --git a/ush/generate_fire_emissions.py b/ush/generate_fire_emissions.py index 3cc84ed4dc..5f9885fd09 100755 --- a/ush/generate_fire_emissions.py +++ b/ush/generate_fire_emissions.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + ######################################################################### # # # Python script for fire emissions preprocessing from RAVE FRP and FRE # diff --git a/ush/interp_tools.py b/ush/interp_tools.py index 3f6fed8618..855f7026f1 100755 --- a/ush/interp_tools.py +++ b/ush/interp_tools.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python3 + import datetime as dt import pandas as pd import os @@ -227,4 +229,4 @@ def interpolate_rave(RAVE, rave_avail, rave_avail_hours, use_dummy_emiss, vars_e except (OSError, IOError, RuntimeError, FileNotFoundError, TypeError, IndexError, MemoryError) as e: print(f"Error reading NetCDF file {rave_file_path}: {e}") else: - print(f"File not found or dummy emissions required: {rave_file_path}") \ No newline at end of file + print(f"File not found or dummy emissions required: {rave_file_path}") From 653057d47bf65794045d0bc63e6ed1881af1e939 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Tue, 20 Aug 2024 21:24:52 +0000 Subject: [PATCH 21/61] fix error in smoke dust ex-script --- scripts/exsrw_smoke_dust.sh | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/scripts/exsrw_smoke_dust.sh b/scripts/exsrw_smoke_dust.sh index e5d5bf22b3..7c3748c761 100755 --- a/scripts/exsrw_smoke_dust.sh +++ b/scripts/exsrw_smoke_dust.sh @@ -65,8 +65,8 @@ else for hour in {00..23}; do fire_hr_fn="Hourly_Emissions_3km_${dd_to_use}${hour}00_${dd_to_use}${hour}00.nc" if [ -f "${COMINfire}/${fire_hr_fn}" ]; then - echo "Hourly emission file for $hr found." - ln -nsf ${COMINfire}/${output_file} . + echo "Hourly emission file for $hour found." + ln -nsf ${COMINfire}/${fire_hr_fn} . else # Check various version of RAVE raw data files (new and old) rave_raw_fn1="RAVE-HrlyEmiss-3km_v2r0_blend_s${ddhh_to_use}00000_e${dd_to_use}23*" @@ -77,8 +77,12 @@ else for file_to_use in $files_found; do echo "Using file: $file_to_use" echo "Splitting data for hour $hour..." - ncks -d time,$hour,$hour "${COMINfire}/$file_to_use" "$output_file" - continue + ncks -d time,$hour,$hour "${COMINfire}/${file_to_use}" "${DATA}/${fire_hr_fn}" + if [ -f "${DATA}/${fire_hr_fn}" ]; then + break + else + echo "WARNING: Hourly emission file for $hour was NOT created from ${file_to_use}." + fi done fi done From 5f18707322b6faddb5dc0290074c8adf25533f01 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Tue, 20 Aug 2024 22:32:22 +0000 Subject: [PATCH 22/61] add set ff=unix --- scripts/exsrw_smoke_dust.sh | 2 +- ush/HWP_tools.py | 318 +++++++++++----------- ush/fire_emiss_tools.py | 388 +++++++++++++-------------- ush/generate_fire_emissions.py | 221 ++++++++-------- ush/interp_tools.py | 464 ++++++++++++++++----------------- 5 files changed, 697 insertions(+), 696 deletions(-) diff --git a/scripts/exsrw_smoke_dust.sh b/scripts/exsrw_smoke_dust.sh index 7c3748c761..70555b5696 100755 --- a/scripts/exsrw_smoke_dust.sh +++ b/scripts/exsrw_smoke_dust.sh @@ -65,7 +65,7 @@ else for hour in {00..23}; do fire_hr_fn="Hourly_Emissions_3km_${dd_to_use}${hour}00_${dd_to_use}${hour}00.nc" if [ -f "${COMINfire}/${fire_hr_fn}" ]; then - echo "Hourly emission file for $hour found." + echo "Hourly emission file for $hour was found." ln -nsf ${COMINfire}/${fire_hr_fn} . else # Check various version of RAVE raw data files (new and old) diff --git a/ush/HWP_tools.py b/ush/HWP_tools.py index 7ab7803287..7b175241e1 100755 --- a/ush/HWP_tools.py +++ b/ush/HWP_tools.py @@ -1,159 +1,159 @@ -#!/usr/bin/env python3 - -import numpy as np -import os -import datetime as dt -import shutil -from datetime import timedelta -import xarray as xr -import fnmatch - -def check_restart_files(hourly_hwpdir, fcst_dates): - hwp_avail_hours = [] - hwp_non_avail_hours = [] - - for cycle in fcst_dates: - restart_file = f"{cycle[:8]}.{cycle[8:10]}0000.phy_data.nc" - file_path = os.path.join(hourly_hwpdir, restart_file) - - if os.path.exists(file_path): - print(f'Restart file available for: {restart_file}') - hwp_avail_hours.append(cycle) - else: - print(f'Copy restart file for: {restart_file}') - hwp_non_avail_hours.append(cycle) - - print(f'Available restart at: {hwp_avail_hours}, Non-available restart files at: {hwp_non_avail_hours}') - return(hwp_avail_hours, hwp_non_avail_hours) - -def copy_missing_restart(nwges_dir, hwp_non_avail_hours, hourly_hwpdir, len_restart_interval): - restart_avail_hours = [] - restart_nonavail_hours_test = [] - - for cycle in hwp_non_avail_hours: - try: - YYYYMMDDHH = dt.datetime.strptime(cycle, "%Y%m%d%H") - HH = cycle[8:10] - prev_hr = YYYYMMDDHH - timedelta(hours=1) - prev_hr_str = prev_hr.strftime("%Y%m%d%H") - - source_restart_dir = os.path.join(nwges_dir, prev_hr_str, 'fcst_fv3lam', 'RESTART') - wildcard_name = '*.phy_data.nc' - - if len_restart_interval > 1: - print('ENTERING LOOP for len_restart_interval > 1') - if os.path.exists(source_restart_dir): - matching_files_found = False - print('PATH EXISTS') - for file in sorted(os.listdir(source_restart_dir)): - if fnmatch.fnmatch(file, wildcard_name): - matching_files_found = True - print('MATCHING FILES FOUND') - source_file_path = os.path.join(source_restart_dir, file) - target_file_path = os.path.join(hourly_hwpdir, file) - var1, var2 = 'rrfs_hwp_ave', 'totprcp_ave' - if os.path.exists(source_file_path): - with xr.open_dataset(source_file_path) as ds: - try: - if var1 in ds.variables and var2 in ds.variables: - ds = ds[[var1, var2]] - ds.to_netcdf(target_file_path) - restart_avail_hours.append(cycle) - print(f'Restart file copied: {file}') - else: - print(f'Missing variables {var1} or {var2} in {file}. Skipping file.') - except AttributeError as e: - print(f"AttributeError processing NetCDF file {source_file_path}: {e}") - else: - print(f"Source file not found: {source_file_path}") - if not matching_files_found: - print('No matching files found') - restart_nonavail_hours_test.append(cycle) - else: - print(f"Source directory not found: {source_restart_dir}") - restart_nonavail_hours_test.append(cycle) - else: - if os.path.exists(source_restart_dir): - try: - matching_files = [f for f in os.listdir(source_restart_dir) if fnmatch.fnmatch(f, wildcard_name)] - if not matching_files: - print(f"No matching files for cycle {cycle} in {source_restart_dir}") - restart_nonavail_hours_test.append(cycle) - continue - - for matching_file in matching_files: - source_file_path = os.path.join(source_restart_dir, matching_file) - target_file_path = os.path.join(hourly_hwpdir, matching_file) - var1, var2 = 'rrfs_hwp_ave', 'totprcp_ave' - - if os.path.exists(source_file_path): - try: - with xr.open_dataset(source_file_path) as ds: - if var1 in ds.variables and var2 in ds.variables: - ds = ds[[var1, var2]] - ds.to_netcdf(target_file_path) - restart_avail_hours.append(cycle) - print(f'Restart file copied: {matching_file}') - else: - print(f'Missing variables {var1} or {var2} in {matching_file}. Skipping file.') - except (FileNotFoundError, IOError, OSError, RuntimeError, ValueError, TypeError, KeyError, IndexError, MemoryError) as e: - print(f"Error processing NetCDF file {source_file_path}: {e}") - restart_nonavail_hours_test.append(cycle) - else: - print(f"Source file not found: {source_file_path}") - restart_nonavail_hours_test.append(cycle) - except (FileNotFoundError, IOError, OSError, RuntimeError) as e: - print(f"Error accessing directory {source_restart_dir}: {e}") - restart_nonavail_hours_test.append(cycle) - else: - print(f"Source directory not found: {source_restart_dir}") - restart_nonavail_hours_test.append(cycle) - - except (ValueError, TypeError) as e: - print(f"Error processing cycle {cycle}: {e}") - restart_nonavail_hours_test.append(cycle) - - return(restart_avail_hours, restart_nonavail_hours_test) - -def process_hwp(fcst_dates, hourly_hwpdir, cols, rows, intp_dir, rave_to_intp): - hwp_ave = [] - totprcp = np.zeros((cols*rows)) - var1, var2 = 'rrfs_hwp_ave', 'totprcp_ave' - - for cycle in fcst_dates: - try: - print(f'Processing restart file for date: {cycle}') - file_path = os.path.join(hourly_hwpdir, f"{cycle[:8]}.{cycle[8:10]}0000.phy_data.nc") - rave_path = os.path.join(intp_dir, f"{rave_to_intp}{cycle}00_{cycle}59.nc") - - if os.path.exists(file_path) and os.path.exists(rave_path): - try: - with xr.open_dataset(file_path) as nc: - if var1 in nc.variables and var2 in nc.variables: - hwp_values = nc.rrfs_hwp_ave.values.ravel() - tprcp_values = nc.totprcp_ave.values.ravel() - totprcp += np.where(tprcp_values > 0, tprcp_values, 0) - hwp_ave.append(hwp_values) - print(f'Restart file processed for: {cycle}') - else: - print(f'Missing variables {var1} or {var2} in file: {file_path}') - except (FileNotFoundError, IOError, OSError, RuntimeError, ValueError, TypeError, KeyError, IndexError, MemoryError) as e: - print(f"Error processing NetCDF file {file_path}: {e}") - else: - print(f'One or more files non-available for this cycle: {file_path}, {rave_path}') - except (ValueError, TypeError) as e: - print(f"Error processing cycle {cycle}: {e}") - - # Calculate the mean HWP values if available - if hwp_ave: - hwp_ave_arr = np.nanmean(hwp_ave, axis=0).reshape(cols, rows) - totprcp_ave_arr = totprcp.reshape(cols, rows) - else: - hwp_ave_arr = np.zeros((cols, rows)) - totprcp_ave_arr = np.zeros((cols, rows)) - - xarr_hwp = xr.DataArray(hwp_ave_arr) - xarr_totprcp = xr.DataArray(totprcp_ave_arr) - - return(hwp_ave_arr, xarr_hwp, totprcp_ave_arr, xarr_totprcp) - +#!/usr/bin/env python3 + +import numpy as np +import os +import datetime as dt +import shutil +from datetime import timedelta +import xarray as xr +import fnmatch + +def check_restart_files(hourly_hwpdir, fcst_dates): + hwp_avail_hours = [] + hwp_non_avail_hours = [] + + for cycle in fcst_dates: + restart_file = f"{cycle[:8]}.{cycle[8:10]}0000.phy_data.nc" + file_path = os.path.join(hourly_hwpdir, restart_file) + + if os.path.exists(file_path): + print(f'Restart file available for: {restart_file}') + hwp_avail_hours.append(cycle) + else: + print(f'Copy restart file for: {restart_file}') + hwp_non_avail_hours.append(cycle) + + print(f'Available restart at: {hwp_avail_hours}, Non-available restart files at: {hwp_non_avail_hours}') + return(hwp_avail_hours, hwp_non_avail_hours) + +def copy_missing_restart(nwges_dir, hwp_non_avail_hours, hourly_hwpdir, len_restart_interval): + restart_avail_hours = [] + restart_nonavail_hours_test = [] + + for cycle in hwp_non_avail_hours: + try: + YYYYMMDDHH = dt.datetime.strptime(cycle, "%Y%m%d%H") + HH = cycle[8:10] + prev_hr = YYYYMMDDHH - timedelta(hours=1) + prev_hr_str = prev_hr.strftime("%Y%m%d%H") + + source_restart_dir = os.path.join(nwges_dir, prev_hr_str, 'fcst_fv3lam', 'RESTART') + wildcard_name = '*.phy_data.nc' + + if len_restart_interval > 1: + print('ENTERING LOOP for len_restart_interval > 1') + if os.path.exists(source_restart_dir): + matching_files_found = False + print('PATH EXISTS') + for file in sorted(os.listdir(source_restart_dir)): + if fnmatch.fnmatch(file, wildcard_name): + matching_files_found = True + print('MATCHING FILES FOUND') + source_file_path = os.path.join(source_restart_dir, file) + target_file_path = os.path.join(hourly_hwpdir, file) + var1, var2 = 'rrfs_hwp_ave', 'totprcp_ave' + if os.path.exists(source_file_path): + with xr.open_dataset(source_file_path) as ds: + try: + if var1 in ds.variables and var2 in ds.variables: + ds = ds[[var1, var2]] + ds.to_netcdf(target_file_path) + restart_avail_hours.append(cycle) + print(f'Restart file copied: {file}') + else: + print(f'Missing variables {var1} or {var2} in {file}. Skipping file.') + except AttributeError as e: + print(f"AttributeError processing NetCDF file {source_file_path}: {e}") + else: + print(f"Source file not found: {source_file_path}") + if not matching_files_found: + print('No matching files found') + restart_nonavail_hours_test.append(cycle) + else: + print(f"Source directory not found: {source_restart_dir}") + restart_nonavail_hours_test.append(cycle) + else: + if os.path.exists(source_restart_dir): + try: + matching_files = [f for f in os.listdir(source_restart_dir) if fnmatch.fnmatch(f, wildcard_name)] + if not matching_files: + print(f"No matching files for cycle {cycle} in {source_restart_dir}") + restart_nonavail_hours_test.append(cycle) + continue + + for matching_file in matching_files: + source_file_path = os.path.join(source_restart_dir, matching_file) + target_file_path = os.path.join(hourly_hwpdir, matching_file) + var1, var2 = 'rrfs_hwp_ave', 'totprcp_ave' + + if os.path.exists(source_file_path): + try: + with xr.open_dataset(source_file_path) as ds: + if var1 in ds.variables and var2 in ds.variables: + ds = ds[[var1, var2]] + ds.to_netcdf(target_file_path) + restart_avail_hours.append(cycle) + print(f'Restart file copied: {matching_file}') + else: + print(f'Missing variables {var1} or {var2} in {matching_file}. Skipping file.') + except (FileNotFoundError, IOError, OSError, RuntimeError, ValueError, TypeError, KeyError, IndexError, MemoryError) as e: + print(f"Error processing NetCDF file {source_file_path}: {e}") + restart_nonavail_hours_test.append(cycle) + else: + print(f"Source file not found: {source_file_path}") + restart_nonavail_hours_test.append(cycle) + except (FileNotFoundError, IOError, OSError, RuntimeError) as e: + print(f"Error accessing directory {source_restart_dir}: {e}") + restart_nonavail_hours_test.append(cycle) + else: + print(f"Source directory not found: {source_restart_dir}") + restart_nonavail_hours_test.append(cycle) + + except (ValueError, TypeError) as e: + print(f"Error processing cycle {cycle}: {e}") + restart_nonavail_hours_test.append(cycle) + + return(restart_avail_hours, restart_nonavail_hours_test) + +def process_hwp(fcst_dates, hourly_hwpdir, cols, rows, intp_dir, rave_to_intp): + hwp_ave = [] + totprcp = np.zeros((cols*rows)) + var1, var2 = 'rrfs_hwp_ave', 'totprcp_ave' + + for cycle in fcst_dates: + try: + print(f'Processing restart file for date: {cycle}') + file_path = os.path.join(hourly_hwpdir, f"{cycle[:8]}.{cycle[8:10]}0000.phy_data.nc") + rave_path = os.path.join(intp_dir, f"{rave_to_intp}{cycle}00_{cycle}59.nc") + + if os.path.exists(file_path) and os.path.exists(rave_path): + try: + with xr.open_dataset(file_path) as nc: + if var1 in nc.variables and var2 in nc.variables: + hwp_values = nc.rrfs_hwp_ave.values.ravel() + tprcp_values = nc.totprcp_ave.values.ravel() + totprcp += np.where(tprcp_values > 0, tprcp_values, 0) + hwp_ave.append(hwp_values) + print(f'Restart file processed for: {cycle}') + else: + print(f'Missing variables {var1} or {var2} in file: {file_path}') + except (FileNotFoundError, IOError, OSError, RuntimeError, ValueError, TypeError, KeyError, IndexError, MemoryError) as e: + print(f"Error processing NetCDF file {file_path}: {e}") + else: + print(f'One or more files non-available for this cycle: {file_path}, {rave_path}') + except (ValueError, TypeError) as e: + print(f"Error processing cycle {cycle}: {e}") + + # Calculate the mean HWP values if available + if hwp_ave: + hwp_ave_arr = np.nanmean(hwp_ave, axis=0).reshape(cols, rows) + totprcp_ave_arr = totprcp.reshape(cols, rows) + else: + hwp_ave_arr = np.zeros((cols, rows)) + totprcp_ave_arr = np.zeros((cols, rows)) + + xarr_hwp = xr.DataArray(hwp_ave_arr) + xarr_totprcp = xr.DataArray(totprcp_ave_arr) + + return(hwp_ave_arr, xarr_hwp, totprcp_ave_arr, xarr_totprcp) + diff --git a/ush/fire_emiss_tools.py b/ush/fire_emiss_tools.py index 2e5d87739b..fa68628e10 100755 --- a/ush/fire_emiss_tools.py +++ b/ush/fire_emiss_tools.py @@ -1,194 +1,194 @@ -#!/usr/bin/env python3 - -import os -import numpy as np -import xarray as xr -from datetime import datetime -from netCDF4 import Dataset -import interp_tools as i_tools - -#Compute average FRP from raw RAVE for the previous 24 hours -def averaging_FRP(ebb_dcycle, fcst_dates, cols, rows, intp_dir, rave_to_intp, veg_map, tgt_area, beta, fg_to_ug, to_s): - base_array = np.zeros((cols*rows)) - frp_daily = base_array - ebb_smoke_total = [] - ebb_smoke_hr = [] - frp_avg_hr = [] - - try: - ef_map = xr.open_dataset(veg_map) - emiss_factor = ef_map.emiss_factor.values - target_area = tgt_area.values - except (FileNotFoundError, IOError, OSError, RuntimeError, ValueError, TypeError, KeyError, IndexError, MemoryError) as e: - print(f"Error loading vegetation map: {e}") - return np.zeros((cols, rows)), np.zeros((cols, rows)) - - num_files = 0 - for cycle in fcst_dates: - try: - file_path = os.path.join(intp_dir, f'{rave_to_intp}{cycle}00_{cycle}59.nc') - if os.path.exists(file_path): - try: - with xr.open_dataset(file_path) as nc: - open_fre = nc.FRE[0, :, :].values - open_frp = nc.frp_avg_hr[0, :, :].values - num_files += 1 - if ebb_dcycle == 1: - print('Processing emissions for ebb_dcyc 1') - print(file_path) - frp_avg_hr.append(open_frp) - ebb_hourly = (open_fre * emiss_factor * beta * fg_to_ug) / (target_area * to_s) - ebb_smoke_total.append(np.where(open_frp > 0, ebb_hourly, 0)) - else: - print('Processing emissions for ebb_dcyc 2') - ebb_hourly = open_fre * emiss_factor * beta * fg_to_ug / target_area - ebb_smoke_total.append(np.where(open_frp > 0, ebb_hourly, 0).ravel()) - frp_daily += np.where(open_frp > 0, open_frp, 0).ravel() - except (FileNotFoundError, IOError, OSError, RuntimeError, ValueError, TypeError, KeyError, IndexError, MemoryError) as e: - print(f"Error processing NetCDF file {file_path}: {e}") - if ebb_dcycle == 1: - frp_avg_hr.append(np.zeros((cols, rows))) - ebb_smoke_total.append(np.zeros((cols, rows))) - else: - if ebb_dcycle == 1: - frp_avg_hr.append(np.zeros((cols, rows))) - ebb_smoke_total.append(np.zeros((cols, rows))) - except Exception as e: - print(f"Error processing cycle {cycle}: {e}") - if ebb_dcycle == 1: - frp_avg_hr.append(np.zeros((cols, rows))) - ebb_smoke_total.append(np.zeros((cols, rows))) - - if num_files > 0: - if ebb_dcycle == 1: - frp_avg_reshaped = np.stack(frp_avg_hr, axis=0) - ebb_total_reshaped = np.stack(ebb_smoke_total, axis=0) - else: - summed_array = np.sum(np.array(ebb_smoke_total), axis=0) - num_zeros = len(ebb_smoke_total) - np.sum([arr == 0 for arr in ebb_smoke_total], axis=0) - safe_zero_count = np.where(num_zeros == 0, 1, num_zeros) - result_array = [summed_array[i] / 2 if safe_zero_count[i] == 1 else summed_array[i] / safe_zero_count[i] for i in range(len(safe_zero_count))] - result_array = np.array(result_array) - result_array[num_zeros == 0] = summed_array[num_zeros == 0] - ebb_total = result_array.reshape(cols, rows) - ebb_total_reshaped = ebb_total / 3600 - temp_frp = [frp_daily[i] / 2 if safe_zero_count[i] == 1 else frp_daily[i] / safe_zero_count[i] for i in range(len(safe_zero_count))] - temp_frp = np.array(temp_frp) - temp_frp[num_zeros == 0] = frp_daily[num_zeros == 0] - frp_avg_reshaped = temp_frp.reshape(cols, rows) - else: - if ebb_dcycle == 1: - frp_avg_reshaped = np.zeros((24, cols, rows)) - ebb_total_reshaped = np.zeros((24, cols, rows)) - else: - frp_avg_reshaped = np.zeros((cols, rows)) - ebb_total_reshaped = np.zeros((cols, rows)) - - return(frp_avg_reshaped, ebb_total_reshaped) - -def estimate_fire_duration(intp_avail_hours, intp_dir, fcst_dates, current_day, cols, rows, rave_to_intp): - # There are two steps here. - # 1) First day simulation no RAVE from previous 24 hours available (fire age is set to zero) - # 2) previus files are present (estimate fire age as the difference between the date of the current cycle and the date whe the fire was last observed whiting 24 hours) - t_fire = np.zeros((cols, rows)) - - for date_str in fcst_dates: - try: - date_file = int(date_str[:10]) - print('Date processing for fire duration', date_file) - file_path = os.path.join(intp_dir, f'{rave_to_intp}{date_str}00_{date_str}59.nc') - - if os.path.exists(file_path): - try: - with xr.open_dataset(file_path) as open_intp: - FRP = open_intp.frp_avg_hr[0, :, :].values - dates_filtered = np.where(FRP > 0, date_file, 0) - t_fire = np.maximum(t_fire, dates_filtered) - except (FileNotFoundError, IOError, OSError,RuntimeError,ValueError, TypeError, KeyError, IndexError, MemoryError) as e: - print(f"Error processing NetCDF file {file_path}: {e}") - except Exception as e: - print(f"Error processing date {date_str}: {e}") - - t_fire_flattened = t_fire.flatten() - t_fire_flattened = [int(i) if i != 0 else 0 for i in t_fire_flattened] - - try: - fcst_t = datetime.strptime(current_day, '%Y%m%d%H') - hr_ends = [datetime.strptime(str(hr), '%Y%m%d%H') if hr != 0 else 0 for hr in t_fire_flattened] - te = [(fcst_t - i).total_seconds() / 3600 if i != 0 else 0 for i in hr_ends] - except ValueError as e: - print(f"Error processing forecast time {current_day}: {e}") - te = np.zeros((rows, cols)) - - return(te) - -def save_fire_dur(cols, rows, te): - fire_dur = np.array(te).reshape(cols, rows) - return(fire_dur) - -def produce_emiss_24hr_file(ebb_dcycle, frp_reshaped, intp_dir, current_day, tgt_latt, tgt_lont, ebb_smoke_reshaped, cols, rows): - file_path = os.path.join(intp_dir, f'SMOKE_RRFS_data_{current_day}00.nc') - with Dataset(file_path, 'w') as fout: - i_tools.create_emiss_file(fout, cols, rows) - i_tools.Store_latlon_by_Level(fout, 'geolat', tgt_latt, 'cell center latitude', 'degrees_north', '2D', '-9999.f', '1.f') - i_tools.Store_latlon_by_Level(fout, 'geolon', tgt_lont, 'cell center longitude', 'degrees_east', '2D', '-9999.f', '1.f') - - i_tools.Store_by_Level(fout,'frp_avg_hr','mean Fire Radiative Power','MW','3D','0.f','1.f') - fout.variables['frp_avg_hr'][:, :, :] = frp_reshaped - i_tools.Store_by_Level(fout,'ebb_smoke_hr','EBB emissions','ug m-2 s-1','3D','0.f','1.f') - fout.variables['ebb_smoke_hr'][:, :, :] = ebb_smoke_reshaped - -def produce_emiss_file(xarr_hwp, frp_avg_reshaped, totprcp_ave_arr, xarr_totprcp, intp_dir, current_day, tgt_latt, tgt_lont, ebb_tot_reshaped, fire_age, cols, rows): - # Ensure arrays are not negative or NaN - frp_avg_reshaped = np.clip(frp_avg_reshaped, 0, None) - frp_avg_reshaped = np.nan_to_num(frp_avg_reshaped) - - ebb_tot_reshaped = np.clip(ebb_tot_reshaped, 0, None) - ebb_tot_reshaped = np.nan_to_num(ebb_tot_reshaped) - - fire_age = np.clip(fire_age, 0, None) - fire_age = np.nan_to_num(fire_age) - - # Filter HWP Prcp arrays to be non-negative and replace NaNs - filtered_hwp = xarr_hwp.where(frp_avg_reshaped > 0, 0).fillna(0) - filtered_prcp = xarr_totprcp.where(frp_avg_reshaped > 0, 0).fillna(0) - - # Filter based on ebb_rate - ebb_rate_threshold = 0 # Define an appropriate threshold if needed - mask = (ebb_tot_reshaped > ebb_rate_threshold) - - filtered_hwp = filtered_hwp.where(mask, 0).fillna(0) - filtered_prcp = filtered_prcp.where(mask, 0).fillna(0) - frp_avg_reshaped = frp_avg_reshaped * mask - ebb_tot_reshaped = ebb_tot_reshaped * mask - fire_age = fire_age * mask - - # Produce emiss file - file_path = os.path.join(intp_dir, f'SMOKE_RRFS_data_{current_day}00.nc') - - try: - with Dataset(file_path, 'w') as fout: - i_tools.create_emiss_file(fout, cols, rows) - i_tools.Store_latlon_by_Level(fout, 'geolat', tgt_latt, 'cell center latitude', 'degrees_north', '2D', '-9999.f', '1.f') - i_tools.Store_latlon_by_Level(fout, 'geolon', tgt_lont, 'cell center longitude', 'degrees_east', '2D', '-9999.f', '1.f') - - print('Storing different variables') - i_tools.Store_by_Level(fout, 'frp_davg', 'Daily mean Fire Radiative Power', 'MW', '3D', '0.f', '1.f') - fout.variables['frp_davg'][0, :, :] = frp_avg_reshaped - i_tools.Store_by_Level(fout, 'ebb_rate', 'Total EBB emission', 'ug m-2 s-1', '3D', '0.f', '1.f') - fout.variables['ebb_rate'][0, :, :] = ebb_tot_reshaped - i_tools.Store_by_Level(fout, 'fire_end_hr', 'Hours since fire was last detected', 'hrs', '3D', '0.f', '1.f') - fout.variables['fire_end_hr'][0, :, :] = fire_age - i_tools.Store_by_Level(fout, 'hwp_davg', 'Daily mean Hourly Wildfire Potential', 'none', '3D', '0.f', '1.f') - fout.variables['hwp_davg'][0, :, :] = filtered_hwp - i_tools.Store_by_Level(fout, 'totprcp_24hrs', 'Sum of precipitation', 'm', '3D', '0.f', '1.f') - fout.variables['totprcp_24hrs'][0, :, :] = filtered_prcp - - print("Emissions file created successfully") - return "Emissions file created successfully" - - except (OSError, IOError) as e: - print(f"Error creating or writing to NetCDF file {file_path}: {e}") - return f"Error creating or writing to NetCDF file {file_path}: {e}" - - return "Emissions file created successfully" +#!/usr/bin/env python3 + +import os +import numpy as np +import xarray as xr +from datetime import datetime +from netCDF4 import Dataset +import interp_tools as i_tools + +#Compute average FRP from raw RAVE for the previous 24 hours +def averaging_FRP(ebb_dcycle, fcst_dates, cols, rows, intp_dir, rave_to_intp, veg_map, tgt_area, beta, fg_to_ug, to_s): + base_array = np.zeros((cols*rows)) + frp_daily = base_array + ebb_smoke_total = [] + ebb_smoke_hr = [] + frp_avg_hr = [] + + try: + ef_map = xr.open_dataset(veg_map) + emiss_factor = ef_map.emiss_factor.values + target_area = tgt_area.values + except (FileNotFoundError, IOError, OSError, RuntimeError, ValueError, TypeError, KeyError, IndexError, MemoryError) as e: + print(f"Error loading vegetation map: {e}") + return np.zeros((cols, rows)), np.zeros((cols, rows)) + + num_files = 0 + for cycle in fcst_dates: + try: + file_path = os.path.join(intp_dir, f'{rave_to_intp}{cycle}00_{cycle}59.nc') + if os.path.exists(file_path): + try: + with xr.open_dataset(file_path) as nc: + open_fre = nc.FRE[0, :, :].values + open_frp = nc.frp_avg_hr[0, :, :].values + num_files += 1 + if ebb_dcycle == 1: + print('Processing emissions for ebb_dcyc 1') + print(file_path) + frp_avg_hr.append(open_frp) + ebb_hourly = (open_fre * emiss_factor * beta * fg_to_ug) / (target_area * to_s) + ebb_smoke_total.append(np.where(open_frp > 0, ebb_hourly, 0)) + else: + print('Processing emissions for ebb_dcyc 2') + ebb_hourly = open_fre * emiss_factor * beta * fg_to_ug / target_area + ebb_smoke_total.append(np.where(open_frp > 0, ebb_hourly, 0).ravel()) + frp_daily += np.where(open_frp > 0, open_frp, 0).ravel() + except (FileNotFoundError, IOError, OSError, RuntimeError, ValueError, TypeError, KeyError, IndexError, MemoryError) as e: + print(f"Error processing NetCDF file {file_path}: {e}") + if ebb_dcycle == 1: + frp_avg_hr.append(np.zeros((cols, rows))) + ebb_smoke_total.append(np.zeros((cols, rows))) + else: + if ebb_dcycle == 1: + frp_avg_hr.append(np.zeros((cols, rows))) + ebb_smoke_total.append(np.zeros((cols, rows))) + except Exception as e: + print(f"Error processing cycle {cycle}: {e}") + if ebb_dcycle == 1: + frp_avg_hr.append(np.zeros((cols, rows))) + ebb_smoke_total.append(np.zeros((cols, rows))) + + if num_files > 0: + if ebb_dcycle == 1: + frp_avg_reshaped = np.stack(frp_avg_hr, axis=0) + ebb_total_reshaped = np.stack(ebb_smoke_total, axis=0) + else: + summed_array = np.sum(np.array(ebb_smoke_total), axis=0) + num_zeros = len(ebb_smoke_total) - np.sum([arr == 0 for arr in ebb_smoke_total], axis=0) + safe_zero_count = np.where(num_zeros == 0, 1, num_zeros) + result_array = [summed_array[i] / 2 if safe_zero_count[i] == 1 else summed_array[i] / safe_zero_count[i] for i in range(len(safe_zero_count))] + result_array = np.array(result_array) + result_array[num_zeros == 0] = summed_array[num_zeros == 0] + ebb_total = result_array.reshape(cols, rows) + ebb_total_reshaped = ebb_total / 3600 + temp_frp = [frp_daily[i] / 2 if safe_zero_count[i] == 1 else frp_daily[i] / safe_zero_count[i] for i in range(len(safe_zero_count))] + temp_frp = np.array(temp_frp) + temp_frp[num_zeros == 0] = frp_daily[num_zeros == 0] + frp_avg_reshaped = temp_frp.reshape(cols, rows) + else: + if ebb_dcycle == 1: + frp_avg_reshaped = np.zeros((24, cols, rows)) + ebb_total_reshaped = np.zeros((24, cols, rows)) + else: + frp_avg_reshaped = np.zeros((cols, rows)) + ebb_total_reshaped = np.zeros((cols, rows)) + + return(frp_avg_reshaped, ebb_total_reshaped) + +def estimate_fire_duration(intp_avail_hours, intp_dir, fcst_dates, current_day, cols, rows, rave_to_intp): + # There are two steps here. + # 1) First day simulation no RAVE from previous 24 hours available (fire age is set to zero) + # 2) previus files are present (estimate fire age as the difference between the date of the current cycle and the date whe the fire was last observed whiting 24 hours) + t_fire = np.zeros((cols, rows)) + + for date_str in fcst_dates: + try: + date_file = int(date_str[:10]) + print('Date processing for fire duration', date_file) + file_path = os.path.join(intp_dir, f'{rave_to_intp}{date_str}00_{date_str}59.nc') + + if os.path.exists(file_path): + try: + with xr.open_dataset(file_path) as open_intp: + FRP = open_intp.frp_avg_hr[0, :, :].values + dates_filtered = np.where(FRP > 0, date_file, 0) + t_fire = np.maximum(t_fire, dates_filtered) + except (FileNotFoundError, IOError, OSError,RuntimeError,ValueError, TypeError, KeyError, IndexError, MemoryError) as e: + print(f"Error processing NetCDF file {file_path}: {e}") + except Exception as e: + print(f"Error processing date {date_str}: {e}") + + t_fire_flattened = t_fire.flatten() + t_fire_flattened = [int(i) if i != 0 else 0 for i in t_fire_flattened] + + try: + fcst_t = datetime.strptime(current_day, '%Y%m%d%H') + hr_ends = [datetime.strptime(str(hr), '%Y%m%d%H') if hr != 0 else 0 for hr in t_fire_flattened] + te = [(fcst_t - i).total_seconds() / 3600 if i != 0 else 0 for i in hr_ends] + except ValueError as e: + print(f"Error processing forecast time {current_day}: {e}") + te = np.zeros((rows, cols)) + + return(te) + +def save_fire_dur(cols, rows, te): + fire_dur = np.array(te).reshape(cols, rows) + return(fire_dur) + +def produce_emiss_24hr_file(ebb_dcycle, frp_reshaped, intp_dir, current_day, tgt_latt, tgt_lont, ebb_smoke_reshaped, cols, rows): + file_path = os.path.join(intp_dir, f'SMOKE_RRFS_data_{current_day}00.nc') + with Dataset(file_path, 'w') as fout: + i_tools.create_emiss_file(fout, cols, rows) + i_tools.Store_latlon_by_Level(fout, 'geolat', tgt_latt, 'cell center latitude', 'degrees_north', '2D', '-9999.f', '1.f') + i_tools.Store_latlon_by_Level(fout, 'geolon', tgt_lont, 'cell center longitude', 'degrees_east', '2D', '-9999.f', '1.f') + + i_tools.Store_by_Level(fout,'frp_avg_hr','mean Fire Radiative Power','MW','3D','0.f','1.f') + fout.variables['frp_avg_hr'][:, :, :] = frp_reshaped + i_tools.Store_by_Level(fout,'ebb_smoke_hr','EBB emissions','ug m-2 s-1','3D','0.f','1.f') + fout.variables['ebb_smoke_hr'][:, :, :] = ebb_smoke_reshaped + +def produce_emiss_file(xarr_hwp, frp_avg_reshaped, totprcp_ave_arr, xarr_totprcp, intp_dir, current_day, tgt_latt, tgt_lont, ebb_tot_reshaped, fire_age, cols, rows): + # Ensure arrays are not negative or NaN + frp_avg_reshaped = np.clip(frp_avg_reshaped, 0, None) + frp_avg_reshaped = np.nan_to_num(frp_avg_reshaped) + + ebb_tot_reshaped = np.clip(ebb_tot_reshaped, 0, None) + ebb_tot_reshaped = np.nan_to_num(ebb_tot_reshaped) + + fire_age = np.clip(fire_age, 0, None) + fire_age = np.nan_to_num(fire_age) + + # Filter HWP Prcp arrays to be non-negative and replace NaNs + filtered_hwp = xarr_hwp.where(frp_avg_reshaped > 0, 0).fillna(0) + filtered_prcp = xarr_totprcp.where(frp_avg_reshaped > 0, 0).fillna(0) + + # Filter based on ebb_rate + ebb_rate_threshold = 0 # Define an appropriate threshold if needed + mask = (ebb_tot_reshaped > ebb_rate_threshold) + + filtered_hwp = filtered_hwp.where(mask, 0).fillna(0) + filtered_prcp = filtered_prcp.where(mask, 0).fillna(0) + frp_avg_reshaped = frp_avg_reshaped * mask + ebb_tot_reshaped = ebb_tot_reshaped * mask + fire_age = fire_age * mask + + # Produce emiss file + file_path = os.path.join(intp_dir, f'SMOKE_RRFS_data_{current_day}00.nc') + + try: + with Dataset(file_path, 'w') as fout: + i_tools.create_emiss_file(fout, cols, rows) + i_tools.Store_latlon_by_Level(fout, 'geolat', tgt_latt, 'cell center latitude', 'degrees_north', '2D', '-9999.f', '1.f') + i_tools.Store_latlon_by_Level(fout, 'geolon', tgt_lont, 'cell center longitude', 'degrees_east', '2D', '-9999.f', '1.f') + + print('Storing different variables') + i_tools.Store_by_Level(fout, 'frp_davg', 'Daily mean Fire Radiative Power', 'MW', '3D', '0.f', '1.f') + fout.variables['frp_davg'][0, :, :] = frp_avg_reshaped + i_tools.Store_by_Level(fout, 'ebb_rate', 'Total EBB emission', 'ug m-2 s-1', '3D', '0.f', '1.f') + fout.variables['ebb_rate'][0, :, :] = ebb_tot_reshaped + i_tools.Store_by_Level(fout, 'fire_end_hr', 'Hours since fire was last detected', 'hrs', '3D', '0.f', '1.f') + fout.variables['fire_end_hr'][0, :, :] = fire_age + i_tools.Store_by_Level(fout, 'hwp_davg', 'Daily mean Hourly Wildfire Potential', 'none', '3D', '0.f', '1.f') + fout.variables['hwp_davg'][0, :, :] = filtered_hwp + i_tools.Store_by_Level(fout, 'totprcp_24hrs', 'Sum of precipitation', 'm', '3D', '0.f', '1.f') + fout.variables['totprcp_24hrs'][0, :, :] = filtered_prcp + + print("Emissions file created successfully") + return "Emissions file created successfully" + + except (OSError, IOError) as e: + print(f"Error creating or writing to NetCDF file {file_path}: {e}") + return f"Error creating or writing to NetCDF file {file_path}: {e}" + + return "Emissions file created successfully" diff --git a/ush/generate_fire_emissions.py b/ush/generate_fire_emissions.py index 5f9885fd09..45bd9a5265 100755 --- a/ush/generate_fire_emissions.py +++ b/ush/generate_fire_emissions.py @@ -1,110 +1,111 @@ -#!/usr/bin/env python3 - -######################################################################### -# # -# Python script for fire emissions preprocessing from RAVE FRP and FRE # -# (Li et al.,2022). # -# johana.romero-alvarez@noaa.gov # -# # -######################################################################### -import sys -import os -import time -import numpy as np -import fire_emiss_tools as femmi_tools -import HWP_tools -import interp_tools as i_tools - -#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -# Workflow -#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -def generate_emiss_workflow(staticdir, ravedir, newges_dir, predef_grid, ebb_dcycle, restart_interval): - - # ---------------------------------------------------------------------- - # Import envs from workflow and get the predifying grid - # Set variable names, constants and unit conversions - # Set predefined grid - # Set directories - # ---------------------------------------------------------------------- - beta = 0.3 - fg_to_ug = 1e6 - to_s = 3600 - current_day = os.environ.get("CDATE") - nwges_dir = os.environ.get("NWGES_DIR") - vars_emis = ["FRP_MEAN","FRE"] - cols, rows = (2700, 3950) if predef_grid == 'RRFS_NA_3km' else (1092, 1820) - print('PREDEF GRID',predef_grid,'cols,rows',cols,rows) - print('WARNING, EBB_DCYCLE set to', ebb_dcycle, 'emissions are comes from same day satellite obs') - #used later when working with ebb_dcyle 1 or 2 - ebb_dcycle = float(ebb_dcycle) - - #This is used later when copying the rrfs restart file - restart_interval = restart_interval.split() - restart_interval_list = [float(num) for num in restart_interval] - len_restart_interval = len(restart_interval_list) - - #Setting the directories - veg_map = staticdir+'/veg_map.nc' - RAVE= ravedir - rave_to_intp = predef_grid+"_intp_" - intp_dir = newges_dir - grid_in = staticdir+'/grid_in.nc' - weightfile = staticdir+'/weight_file.nc' - grid_out = staticdir+'/ds_out_base.nc' - hourly_hwpdir = os.path.join(nwges_dir,'HOURLY_HWP') - - # ---------------------------------------------------------------------- - # Workflow - # ---------------------------------------------------------------------- - - # ---------------------------------------------------------------------- - # Sort raw RAVE, create source and target filelds, and compute emissions - # ---------------------------------------------------------------------- - fcst_dates = i_tools.date_range(current_day, ebb_dcycle) - intp_avail_hours, intp_non_avail_hours, inp_files_2use = i_tools.check_for_intp_rave(intp_dir, fcst_dates, rave_to_intp) - rave_avail, rave_avail_hours, rave_nonavail_hours_test, first_day = i_tools.check_for_raw_rave(RAVE, intp_non_avail_hours, intp_avail_hours) - srcfield, tgtfield, tgt_latt, tgt_lont, srcgrid, tgtgrid, src_latt, tgt_area = i_tools.creates_st_fields(grid_in, grid_out, intp_dir, rave_avail_hours) - - if not first_day: - regridder, use_dummy_emiss = i_tools.generate_regrider(rave_avail_hours, srcfield, tgtfield, weightfile, inp_files_2use, intp_avail_hours) - if use_dummy_emiss: - print('RAVE files corrupted, no data to process') - i_tools.create_dummy(intp_dir, current_day, tgt_latt, tgt_lont, cols, rows) - else: - i_tools.interpolate_rave(RAVE, rave_avail, rave_avail_hours, - use_dummy_emiss, vars_emis, regridder, srcgrid, tgtgrid, rave_to_intp, - intp_dir, src_latt, tgt_latt, tgt_lont, cols, rows) - - if ebb_dcycle == 1: - print('Processing emissions for ebb_dcyc 1') - frp_avg_reshaped, ebb_total_reshaped = femmi_tools.averaging_FRP(ebb_dcycle, fcst_dates, cols, rows, intp_dir, rave_to_intp, veg_map, tgt_area, beta, fg_to_ug, to_s) - femmi_tools.produce_emiss_24hr_file(ebb_dcycle, frp_avg_reshaped, intp_dir, current_day, tgt_latt, tgt_lont, ebb_total_reshaped, cols, rows) - elif ebb_dcycle == 2: - print('Restart dates to process',fcst_dates) - hwp_avail_hours, hwp_non_avail_hours = HWP_tools.check_restart_files(hourly_hwpdir, fcst_dates) - restart_avail, restart_nonavail_hours_test = HWP_tools.copy_missing_restart(nwges_dir, hwp_non_avail_hours, hourly_hwpdir, len_restart_interval) - hwp_ave_arr, xarr_hwp, totprcp_ave_arr, xarr_totprcp = HWP_tools.process_hwp(fcst_dates, hourly_hwpdir, cols, rows, intp_dir, rave_to_intp) - frp_avg_reshaped, ebb_total_reshaped = femmi_tools.averaging_FRP(ebb_dcycle, fcst_dates, cols, rows, intp_dir, rave_to_intp, veg_map, tgt_area, beta, fg_to_ug, to_s) - #Fire end hours processing - te = femmi_tools.estimate_fire_duration(intp_avail_hours, intp_dir, fcst_dates, current_day, cols, rows, rave_to_intp) - fire_age = femmi_tools.save_fire_dur(cols, rows, te) - #produce emiss file - femmi_tools.produce_emiss_file(xarr_hwp, frp_avg_reshaped, totprcp_ave_arr, xarr_totprcp, intp_dir, current_day, tgt_latt, tgt_lont, ebb_total_reshaped, fire_age, cols, rows) - else: - print('First day true, no RAVE files available. Use dummy emissions file') - i_tools.create_dummy(intp_dir, current_day, tgt_latt, tgt_lont, cols, rows) - -if __name__ == '__main__': - - print('') - print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~') - print('Welcome to interpolating RAVE and processing fire emissions!') - print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~') - print('') - generate_emiss_workflow(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5], sys.argv[6]) - print('') - print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~') - print('Successful Completion. Bye!') - print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~') - print('') - +#!/usr/bin/env python3 + +######################################################################### +# # +# Python script for fire emissions preprocessing from RAVE FRP and FRE # +# (Li et al.,2022). # +# johana.romero-alvarez@noaa.gov # +# # +######################################################################### + +import sys +import os +import time +import numpy as np +import fire_emiss_tools as femmi_tools +import HWP_tools +import interp_tools as i_tools + +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +# Workflow +#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +def generate_emiss_workflow(staticdir, ravedir, newges_dir, predef_grid, ebb_dcycle, restart_interval): + + # ---------------------------------------------------------------------- + # Import envs from workflow and get the predifying grid + # Set variable names, constants and unit conversions + # Set predefined grid + # Set directories + # ---------------------------------------------------------------------- + beta = 0.3 + fg_to_ug = 1e6 + to_s = 3600 + current_day = os.environ.get("CDATE") + nwges_dir = os.environ.get("NWGES_DIR") + vars_emis = ["FRP_MEAN","FRE"] + cols, rows = (2700, 3950) if predef_grid == 'RRFS_NA_3km' else (1092, 1820) + print('PREDEF GRID',predef_grid,'cols,rows',cols,rows) + print('WARNING, EBB_DCYCLE set to', ebb_dcycle, 'emissions are comes from same day satellite obs') + #used later when working with ebb_dcyle 1 or 2 + ebb_dcycle = float(ebb_dcycle) + + #This is used later when copying the rrfs restart file + restart_interval = restart_interval.split() + restart_interval_list = [float(num) for num in restart_interval] + len_restart_interval = len(restart_interval_list) + + #Setting the directories + veg_map = staticdir+'/veg_map.nc' + RAVE= ravedir + rave_to_intp = predef_grid+"_intp_" + intp_dir = newges_dir + grid_in = staticdir+'/grid_in.nc' + weightfile = staticdir+'/weight_file.nc' + grid_out = staticdir+'/ds_out_base.nc' + hourly_hwpdir = os.path.join(nwges_dir,'HOURLY_HWP') + + # ---------------------------------------------------------------------- + # Workflow + # ---------------------------------------------------------------------- + + # ---------------------------------------------------------------------- + # Sort raw RAVE, create source and target filelds, and compute emissions + # ---------------------------------------------------------------------- + fcst_dates = i_tools.date_range(current_day, ebb_dcycle) + intp_avail_hours, intp_non_avail_hours, inp_files_2use = i_tools.check_for_intp_rave(intp_dir, fcst_dates, rave_to_intp) + rave_avail, rave_avail_hours, rave_nonavail_hours_test, first_day = i_tools.check_for_raw_rave(RAVE, intp_non_avail_hours, intp_avail_hours) + srcfield, tgtfield, tgt_latt, tgt_lont, srcgrid, tgtgrid, src_latt, tgt_area = i_tools.creates_st_fields(grid_in, grid_out, intp_dir, rave_avail_hours) + + if not first_day: + regridder, use_dummy_emiss = i_tools.generate_regrider(rave_avail_hours, srcfield, tgtfield, weightfile, inp_files_2use, intp_avail_hours) + if use_dummy_emiss: + print('RAVE files corrupted, no data to process') + i_tools.create_dummy(intp_dir, current_day, tgt_latt, tgt_lont, cols, rows) + else: + i_tools.interpolate_rave(RAVE, rave_avail, rave_avail_hours, + use_dummy_emiss, vars_emis, regridder, srcgrid, tgtgrid, rave_to_intp, + intp_dir, src_latt, tgt_latt, tgt_lont, cols, rows) + + if ebb_dcycle == 1: + print('Processing emissions for ebb_dcyc 1') + frp_avg_reshaped, ebb_total_reshaped = femmi_tools.averaging_FRP(ebb_dcycle, fcst_dates, cols, rows, intp_dir, rave_to_intp, veg_map, tgt_area, beta, fg_to_ug, to_s) + femmi_tools.produce_emiss_24hr_file(ebb_dcycle, frp_avg_reshaped, intp_dir, current_day, tgt_latt, tgt_lont, ebb_total_reshaped, cols, rows) + elif ebb_dcycle == 2: + print('Restart dates to process',fcst_dates) + hwp_avail_hours, hwp_non_avail_hours = HWP_tools.check_restart_files(hourly_hwpdir, fcst_dates) + restart_avail, restart_nonavail_hours_test = HWP_tools.copy_missing_restart(nwges_dir, hwp_non_avail_hours, hourly_hwpdir, len_restart_interval) + hwp_ave_arr, xarr_hwp, totprcp_ave_arr, xarr_totprcp = HWP_tools.process_hwp(fcst_dates, hourly_hwpdir, cols, rows, intp_dir, rave_to_intp) + frp_avg_reshaped, ebb_total_reshaped = femmi_tools.averaging_FRP(ebb_dcycle, fcst_dates, cols, rows, intp_dir, rave_to_intp, veg_map, tgt_area, beta, fg_to_ug, to_s) + #Fire end hours processing + te = femmi_tools.estimate_fire_duration(intp_avail_hours, intp_dir, fcst_dates, current_day, cols, rows, rave_to_intp) + fire_age = femmi_tools.save_fire_dur(cols, rows, te) + #produce emiss file + femmi_tools.produce_emiss_file(xarr_hwp, frp_avg_reshaped, totprcp_ave_arr, xarr_totprcp, intp_dir, current_day, tgt_latt, tgt_lont, ebb_total_reshaped, fire_age, cols, rows) + else: + print('First day true, no RAVE files available. Use dummy emissions file') + i_tools.create_dummy(intp_dir, current_day, tgt_latt, tgt_lont, cols, rows) + +if __name__ == '__main__': + + print('') + print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~') + print('Welcome to interpolating RAVE and processing fire emissions!') + print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~') + print('') + generate_emiss_workflow(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5], sys.argv[6]) + print('') + print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~') + print('Successful Completion. Bye!') + print('~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~') + print('') + diff --git a/ush/interp_tools.py b/ush/interp_tools.py index 855f7026f1..1e886aa06a 100755 --- a/ush/interp_tools.py +++ b/ush/interp_tools.py @@ -1,232 +1,232 @@ -#!/usr/bin/env python3 - -import datetime as dt -import pandas as pd -import os -import fnmatch -import ESMF -import xarray as xr -import numpy as np -from netCDF4 import Dataset - -#Create date range, this is later used to search for RAVE and HWP from previous 24 hours -def date_range(current_day, ebb_dcycle): - print(f'Searching for interpolated RAVE for {current_day}') - print('EBB CYCLE:',ebb_dcycle) - - fcst_datetime = dt.datetime.strptime(current_day, "%Y%m%d%H") - - if ebb_dcycle == 1: - print('Find RAVE for ebb_dcyc 1') - fcst_dates = pd.date_range(start=fcst_datetime, periods=24, freq='H').strftime("%Y%m%d%H") - else: - start_datetime = fcst_datetime - dt.timedelta(days=1, hours=1) - - fcst_dates = pd.date_range(start=start_datetime, periods=24, freq='H').strftime("%Y%m%d%H") - - print(f'Current cycle: {fcst_datetime}') - return(fcst_dates) - -# Check if interoplated RAVE is available for the previous 24 hours -def check_for_intp_rave(intp_dir, fcst_dates, rave_to_intp): - intp_avail_hours = [] - intp_non_avail_hours = [] - # There are four situations here. - # 1) the file is missing (interpolate a new file) - # 2) the file is present (use it) - # 3) there is a link, but it's broken (interpolate a new file) - # 4) there is a valid link (use it) - for date in fcst_dates: - file_name = f'{rave_to_intp}{date}00_{date}59.nc' - file_path = os.path.join(intp_dir, file_name) - file_exists = os.path.isfile(file_path) - is_link = os.path.islink(file_path) - is_valid_link = is_link and os.path.exists(file_path) - - if file_exists or is_valid_link: - print(f'RAVE interpolated file available for {file_name}') - intp_avail_hours.append(date) - else: - print(f'Interpolated file non available, interpolate RAVE for {file_name}') - intp_non_avail_hours.append(date) - - print(f'Available interpolated files for hours: {intp_avail_hours}, Non available interpolated files for hours: {intp_non_avail_hours}') - - inp_files_2use = len(intp_avail_hours) > 0 - - return(intp_avail_hours, intp_non_avail_hours, inp_files_2use) - -#Check if raw RAVE in intp_non_avail_hours list is available for interpolatation -def check_for_raw_rave(RAVE, intp_non_avail_hours, intp_avail_hours): - rave_avail = [] - rave_avail_hours = [] - rave_nonavail_hours_test = [] - for date in intp_non_avail_hours: - wildcard_name = f'*-3km*{date}*{date}59590*.nc' - name_retro = f'*3km*{date}*{date}*.nc' - matching_files = [f for f in os.listdir(RAVE) if fnmatch.fnmatch(f, wildcard_name) or fnmatch.fnmatch(f, name_retro)] - print(f'Find raw RAVE: {matching_files}') - if not matching_files: - print(f'Raw RAVE non_available for interpolation {date}') - rave_nonavail_hours_test.append(date) - else: - print(f'Raw RAVE available for interpolation {matching_files}') - rave_avail.append(matching_files) - rave_avail_hours.append(date) - - print(f"Raw RAVE available: {rave_avail_hours}, rave_nonavail_hours: {rave_nonavail_hours_test}") - first_day = not rave_avail_hours and not intp_avail_hours - - print(f'FIRST DAY?: {first_day}') - return(rave_avail, rave_avail_hours, rave_nonavail_hours_test, first_day) - -#Create source and target fields -def creates_st_fields(grid_in, grid_out, intp_dir, rave_avail_hours): - - # Open datasets with context managers - with xr.open_dataset(grid_in) as ds_in, xr.open_dataset(grid_out) as ds_out: - tgt_area = ds_out['area'] - tgt_latt = ds_out['grid_latt'] - tgt_lont = ds_out['grid_lont'] - src_latt = ds_in['grid_latt'] - - srcgrid = ESMF.Grid(np.array(src_latt.shape), staggerloc=[ESMF.StaggerLoc.CENTER, ESMF.StaggerLoc.CORNER], coord_sys=ESMF.CoordSys.SPH_DEG) - tgtgrid = ESMF.Grid(np.array(tgt_latt.shape), staggerloc=[ESMF.StaggerLoc.CENTER, ESMF.StaggerLoc.CORNER], coord_sys=ESMF.CoordSys.SPH_DEG) - - srcfield = ESMF.Field(srcgrid, name='test', staggerloc=ESMF.StaggerLoc.CENTER) - tgtfield = ESMF.Field(tgtgrid, name='test', staggerloc=ESMF.StaggerLoc.CENTER) - - print('Grid in and out files available. Generating target and source fields') - return(srcfield, tgtfield, tgt_latt, tgt_lont, srcgrid, tgtgrid, src_latt, tgt_area) - -#Define output and variable meta data -def create_emiss_file(fout, cols, rows): - """Create necessary dimensions for the emission file.""" - fout.createDimension('t', None) - fout.createDimension('lat', cols) - fout.createDimension('lon', rows) - setattr(fout, 'PRODUCT_ALGORITHM_VERSION', 'Beta') - setattr(fout, 'TIME_RANGE', '1 hour') - -def Store_latlon_by_Level(fout, varname, var, long_name, units, dim, fval, sfactor): - """Store a 2D variable (latitude/longitude) in the file.""" - var_out = fout.createVariable(varname, 'f4', ('lat','lon')) - var_out.units=units - var_out.long_name=long_name - var_out.standard_name=varname - fout.variables[varname][:]=var - var_out.FillValue=fval - var_out.coordinates='geolat geolon' - -def Store_by_Level(fout, varname, long_name, units, dim, fval, sfactor): - """Store a 3D variable (time, latitude/longitude) in the file.""" - var_out = fout.createVariable(varname, 'f4', ('t','lat','lon')) - var_out.units=units - var_out.long_name = long_name - var_out.standard_name=long_name - var_out.FillValue=fval - var_out.coordinates='t geolat geolon' - -#create a dummy rave interpolated file if first day or regrider fails -def create_dummy(intp_dir, current_day, tgt_latt, tgt_lont, cols, rows): - file_path = os.path.join(intp_dir, f'SMOKE_RRFS_data_{current_day}00.nc') - dummy_file = np.zeros((cols, rows)) # Changed to 3D to match the '3D' dimensions - with Dataset(file_path, 'w') as fout: - create_emiss_file(fout, cols, rows) - # Store latitude and longitude - Store_latlon_by_Level(fout, 'geolat', tgt_latt, 'cell center latitude', 'degrees_north', '2D','-9999.f','1.f') - Store_latlon_by_Level(fout, 'geolon', tgt_lont, 'cell center longitude', 'degrees_east', '2D','-9999.f','1.f') - - # Initialize and store each variable - Store_by_Level(fout,'frp_davg','Daily mean Fire Radiative Power','MW','3D','0.f','1.f') - fout.variables['frp_davg'][0, :, :] = dummy_file - Store_by_Level(fout,'ebb_rate','Total EBB emission','ug m-2 s-1','3D','0.f','1.f') - fout.variables['ebb_rate'][0, :, :] = dummy_file - Store_by_Level(fout,'fire_end_hr','Hours since fire was last detected','hrs','3D','0.f','1.f') - fout.variables['fire_end_hr'][0, :, :] = dummy_file - Store_by_Level(fout,'hwp_davg','Daily mean Hourly Wildfire Potential', 'none','3D','0.f','1.f') - fout.variables['hwp_davg'][0, :, :] = dummy_file - Store_by_Level(fout,'totprcp_24hrs','Sum of precipitation', 'm', '3D', '0.f','1.f') - fout.variables['totprcp_24hrs'][0, :, :] = dummy_file - - return "Emissions dummy file created successfully" - -#generate regridder -def generate_regrider(rave_avail_hours, srcfield, tgtfield, weightfile, inp_files_2use, intp_avail_hours): - print('Checking conditions for generating regridder.') - use_dummy_emiss = len(rave_avail_hours) == 0 and len(intp_avail_hours) == 0 - regridder = None - - if not use_dummy_emiss: - try: - print('Generating regridder.') - regridder = ESMF.RegridFromFile(srcfield, tgtfield, weightfile) - print('Regridder generated successfully.') - except ValueError as e: - print(f'Regridder failed due to a ValueError: {e}.') - except OSError as e: - print(f'Regridder failed due to an OSError: {e}. Check if the weight file exists and is accessible.') - except (FileNotFoundError, IOError, RuntimeError, TypeError, KeyError, IndexError, MemoryError) as e: - print(f'Regridder failed due to corrupted file: {e}. Check if RAVE file has a different grid or format. ') - except Exception as e: - print(f'An unexpected error occurred while generating regridder: {e}.') - else: - use_dummy_emiss = True - - return(regridder, use_dummy_emiss) - -#process RAVE available for interpolation -def interpolate_rave(RAVE, rave_avail, rave_avail_hours, use_dummy_emiss, vars_emis, regridder, - srcgrid, tgtgrid, rave_to_intp, intp_dir, src_latt, tgt_latt, tgt_lont, cols, rows): - for index, current_hour in enumerate(rave_avail_hours): - file_name = rave_avail[index] - rave_file_path = os.path.join(RAVE, file_name[0]) - - print(f"Processing file: {rave_file_path} for hour: {current_hour}") - - if not use_dummy_emiss and os.path.exists(rave_file_path): - try: - with xr.open_dataset(rave_file_path, decode_times=False) as ds_togrid: - try: - ds_togrid = ds_togrid[['FRP_MEAN', 'FRE']] - except KeyError as e: - print(f"Missing required variables in {rave_file_path}: {e}") - continue - - output_file_path = os.path.join(intp_dir, f'{rave_to_intp}{current_hour}00_{current_hour}59.nc') - print('=============before regridding===========', 'FRP_MEAN') - print(np.sum(ds_togrid['FRP_MEAN'], axis=(1, 2))) - - try: - with Dataset(output_file_path, 'w') as fout: - create_emiss_file(fout, cols, rows) - Store_latlon_by_Level(fout, 'geolat', tgt_latt, 'cell center latitude', 'degrees_north', '2D', '-9999.f', '1.f') - Store_latlon_by_Level(fout, 'geolon', tgt_lont, 'cell center longitude', 'degrees_east', '2D', '-9999.f', '1.f') - - for svar in vars_emis: - try: - srcfield = ESMF.Field(srcgrid, name=svar, staggerloc=ESMF.StaggerLoc.CENTER) - tgtfield = ESMF.Field(tgtgrid, name=svar, staggerloc=ESMF.StaggerLoc.CENTER) - src_rate = ds_togrid[svar].fillna(0) - src_QA = xr.where(ds_togrid['FRE'] > 1000, src_rate, 0.0) - srcfield.data[...] = src_QA[0, :, :] - tgtfield = regridder(srcfield, tgtfield) - - if svar == 'FRP_MEAN': - Store_by_Level(fout, 'frp_avg_hr', 'Mean Fire Radiative Power', 'MW', '3D', '0.f', '1.f') - tgt_rate = tgtfield.data - fout.variables['frp_avg_hr'][0, :, :] = tgt_rate - print('=============after regridding===========' + svar) - print(np.sum(tgt_rate)) - elif svar == 'FRE': - Store_by_Level(fout, 'FRE', 'FRE', 'MJ', '3D', '0.f', '1.f') - tgt_rate = tgtfield.data - fout.variables['FRE'][0, :, :] = tgt_rate - except (ValueError, KeyError) as e: - print(f"Error processing variable {svar} in {rave_file_path}: {e}") - except (OSError, IOError, RuntimeError, FileNotFoundError, TypeError, IndexError, MemoryError) as e: - print(f"Error creating or writing to NetCDF file {output_file_path}: {e}") - except (OSError, IOError, RuntimeError, FileNotFoundError, TypeError, IndexError, MemoryError) as e: - print(f"Error reading NetCDF file {rave_file_path}: {e}") - else: - print(f"File not found or dummy emissions required: {rave_file_path}") +#!/usr/bin/env python3 + +import datetime as dt +import pandas as pd +import os +import fnmatch +import ESMF +import xarray as xr +import numpy as np +from netCDF4 import Dataset + +#Create date range, this is later used to search for RAVE and HWP from previous 24 hours +def date_range(current_day, ebb_dcycle): + print(f'Searching for interpolated RAVE for {current_day}') + print('EBB CYCLE:',ebb_dcycle) + + fcst_datetime = dt.datetime.strptime(current_day, "%Y%m%d%H") + + if ebb_dcycle == 1: + print('Find RAVE for ebb_dcyc 1') + fcst_dates = pd.date_range(start=fcst_datetime, periods=24, freq='H').strftime("%Y%m%d%H") + else: + start_datetime = fcst_datetime - dt.timedelta(days=1, hours=1) + + fcst_dates = pd.date_range(start=start_datetime, periods=24, freq='H').strftime("%Y%m%d%H") + + print(f'Current cycle: {fcst_datetime}') + return(fcst_dates) + +# Check if interoplated RAVE is available for the previous 24 hours +def check_for_intp_rave(intp_dir, fcst_dates, rave_to_intp): + intp_avail_hours = [] + intp_non_avail_hours = [] + # There are four situations here. + # 1) the file is missing (interpolate a new file) + # 2) the file is present (use it) + # 3) there is a link, but it's broken (interpolate a new file) + # 4) there is a valid link (use it) + for date in fcst_dates: + file_name = f'{rave_to_intp}{date}00_{date}59.nc' + file_path = os.path.join(intp_dir, file_name) + file_exists = os.path.isfile(file_path) + is_link = os.path.islink(file_path) + is_valid_link = is_link and os.path.exists(file_path) + + if file_exists or is_valid_link: + print(f'RAVE interpolated file available for {file_name}') + intp_avail_hours.append(date) + else: + print(f'Interpolated file non available, interpolate RAVE for {file_name}') + intp_non_avail_hours.append(date) + + print(f'Available interpolated files for hours: {intp_avail_hours}, Non available interpolated files for hours: {intp_non_avail_hours}') + + inp_files_2use = len(intp_avail_hours) > 0 + + return(intp_avail_hours, intp_non_avail_hours, inp_files_2use) + +#Check if raw RAVE in intp_non_avail_hours list is available for interpolatation +def check_for_raw_rave(RAVE, intp_non_avail_hours, intp_avail_hours): + rave_avail = [] + rave_avail_hours = [] + rave_nonavail_hours_test = [] + for date in intp_non_avail_hours: + wildcard_name = f'*-3km*{date}*{date}59590*.nc' + name_retro = f'*3km*{date}*{date}*.nc' + matching_files = [f for f in os.listdir(RAVE) if fnmatch.fnmatch(f, wildcard_name) or fnmatch.fnmatch(f, name_retro)] + print(f'Find raw RAVE: {matching_files}') + if not matching_files: + print(f'Raw RAVE non_available for interpolation {date}') + rave_nonavail_hours_test.append(date) + else: + print(f'Raw RAVE available for interpolation {matching_files}') + rave_avail.append(matching_files) + rave_avail_hours.append(date) + + print(f"Raw RAVE available: {rave_avail_hours}, rave_nonavail_hours: {rave_nonavail_hours_test}") + first_day = not rave_avail_hours and not intp_avail_hours + + print(f'FIRST DAY?: {first_day}') + return(rave_avail, rave_avail_hours, rave_nonavail_hours_test, first_day) + +#Create source and target fields +def creates_st_fields(grid_in, grid_out, intp_dir, rave_avail_hours): + + # Open datasets with context managers + with xr.open_dataset(grid_in) as ds_in, xr.open_dataset(grid_out) as ds_out: + tgt_area = ds_out['area'] + tgt_latt = ds_out['grid_latt'] + tgt_lont = ds_out['grid_lont'] + src_latt = ds_in['grid_latt'] + + srcgrid = ESMF.Grid(np.array(src_latt.shape), staggerloc=[ESMF.StaggerLoc.CENTER, ESMF.StaggerLoc.CORNER], coord_sys=ESMF.CoordSys.SPH_DEG) + tgtgrid = ESMF.Grid(np.array(tgt_latt.shape), staggerloc=[ESMF.StaggerLoc.CENTER, ESMF.StaggerLoc.CORNER], coord_sys=ESMF.CoordSys.SPH_DEG) + + srcfield = ESMF.Field(srcgrid, name='test', staggerloc=ESMF.StaggerLoc.CENTER) + tgtfield = ESMF.Field(tgtgrid, name='test', staggerloc=ESMF.StaggerLoc.CENTER) + + print('Grid in and out files available. Generating target and source fields') + return(srcfield, tgtfield, tgt_latt, tgt_lont, srcgrid, tgtgrid, src_latt, tgt_area) + +#Define output and variable meta data +def create_emiss_file(fout, cols, rows): + """Create necessary dimensions for the emission file.""" + fout.createDimension('t', None) + fout.createDimension('lat', cols) + fout.createDimension('lon', rows) + setattr(fout, 'PRODUCT_ALGORITHM_VERSION', 'Beta') + setattr(fout, 'TIME_RANGE', '1 hour') + +def Store_latlon_by_Level(fout, varname, var, long_name, units, dim, fval, sfactor): + """Store a 2D variable (latitude/longitude) in the file.""" + var_out = fout.createVariable(varname, 'f4', ('lat','lon')) + var_out.units=units + var_out.long_name=long_name + var_out.standard_name=varname + fout.variables[varname][:]=var + var_out.FillValue=fval + var_out.coordinates='geolat geolon' + +def Store_by_Level(fout, varname, long_name, units, dim, fval, sfactor): + """Store a 3D variable (time, latitude/longitude) in the file.""" + var_out = fout.createVariable(varname, 'f4', ('t','lat','lon')) + var_out.units=units + var_out.long_name = long_name + var_out.standard_name=long_name + var_out.FillValue=fval + var_out.coordinates='t geolat geolon' + +#create a dummy rave interpolated file if first day or regrider fails +def create_dummy(intp_dir, current_day, tgt_latt, tgt_lont, cols, rows): + file_path = os.path.join(intp_dir, f'SMOKE_RRFS_data_{current_day}00.nc') + dummy_file = np.zeros((cols, rows)) # Changed to 3D to match the '3D' dimensions + with Dataset(file_path, 'w') as fout: + create_emiss_file(fout, cols, rows) + # Store latitude and longitude + Store_latlon_by_Level(fout, 'geolat', tgt_latt, 'cell center latitude', 'degrees_north', '2D','-9999.f','1.f') + Store_latlon_by_Level(fout, 'geolon', tgt_lont, 'cell center longitude', 'degrees_east', '2D','-9999.f','1.f') + + # Initialize and store each variable + Store_by_Level(fout,'frp_davg','Daily mean Fire Radiative Power','MW','3D','0.f','1.f') + fout.variables['frp_davg'][0, :, :] = dummy_file + Store_by_Level(fout,'ebb_rate','Total EBB emission','ug m-2 s-1','3D','0.f','1.f') + fout.variables['ebb_rate'][0, :, :] = dummy_file + Store_by_Level(fout,'fire_end_hr','Hours since fire was last detected','hrs','3D','0.f','1.f') + fout.variables['fire_end_hr'][0, :, :] = dummy_file + Store_by_Level(fout,'hwp_davg','Daily mean Hourly Wildfire Potential', 'none','3D','0.f','1.f') + fout.variables['hwp_davg'][0, :, :] = dummy_file + Store_by_Level(fout,'totprcp_24hrs','Sum of precipitation', 'm', '3D', '0.f','1.f') + fout.variables['totprcp_24hrs'][0, :, :] = dummy_file + + return "Emissions dummy file created successfully" + +#generate regridder +def generate_regrider(rave_avail_hours, srcfield, tgtfield, weightfile, inp_files_2use, intp_avail_hours): + print('Checking conditions for generating regridder.') + use_dummy_emiss = len(rave_avail_hours) == 0 and len(intp_avail_hours) == 0 + regridder = None + + if not use_dummy_emiss: + try: + print('Generating regridder.') + regridder = ESMF.RegridFromFile(srcfield, tgtfield, weightfile) + print('Regridder generated successfully.') + except ValueError as e: + print(f'Regridder failed due to a ValueError: {e}.') + except OSError as e: + print(f'Regridder failed due to an OSError: {e}. Check if the weight file exists and is accessible.') + except (FileNotFoundError, IOError, RuntimeError, TypeError, KeyError, IndexError, MemoryError) as e: + print(f'Regridder failed due to corrupted file: {e}. Check if RAVE file has a different grid or format. ') + except Exception as e: + print(f'An unexpected error occurred while generating regridder: {e}.') + else: + use_dummy_emiss = True + + return(regridder, use_dummy_emiss) + +#process RAVE available for interpolation +def interpolate_rave(RAVE, rave_avail, rave_avail_hours, use_dummy_emiss, vars_emis, regridder, + srcgrid, tgtgrid, rave_to_intp, intp_dir, src_latt, tgt_latt, tgt_lont, cols, rows): + for index, current_hour in enumerate(rave_avail_hours): + file_name = rave_avail[index] + rave_file_path = os.path.join(RAVE, file_name[0]) + + print(f"Processing file: {rave_file_path} for hour: {current_hour}") + + if not use_dummy_emiss and os.path.exists(rave_file_path): + try: + with xr.open_dataset(rave_file_path, decode_times=False) as ds_togrid: + try: + ds_togrid = ds_togrid[['FRP_MEAN', 'FRE']] + except KeyError as e: + print(f"Missing required variables in {rave_file_path}: {e}") + continue + + output_file_path = os.path.join(intp_dir, f'{rave_to_intp}{current_hour}00_{current_hour}59.nc') + print('=============before regridding===========', 'FRP_MEAN') + print(np.sum(ds_togrid['FRP_MEAN'], axis=(1, 2))) + + try: + with Dataset(output_file_path, 'w') as fout: + create_emiss_file(fout, cols, rows) + Store_latlon_by_Level(fout, 'geolat', tgt_latt, 'cell center latitude', 'degrees_north', '2D', '-9999.f', '1.f') + Store_latlon_by_Level(fout, 'geolon', tgt_lont, 'cell center longitude', 'degrees_east', '2D', '-9999.f', '1.f') + + for svar in vars_emis: + try: + srcfield = ESMF.Field(srcgrid, name=svar, staggerloc=ESMF.StaggerLoc.CENTER) + tgtfield = ESMF.Field(tgtgrid, name=svar, staggerloc=ESMF.StaggerLoc.CENTER) + src_rate = ds_togrid[svar].fillna(0) + src_QA = xr.where(ds_togrid['FRE'] > 1000, src_rate, 0.0) + srcfield.data[...] = src_QA[0, :, :] + tgtfield = regridder(srcfield, tgtfield) + + if svar == 'FRP_MEAN': + Store_by_Level(fout, 'frp_avg_hr', 'Mean Fire Radiative Power', 'MW', '3D', '0.f', '1.f') + tgt_rate = tgtfield.data + fout.variables['frp_avg_hr'][0, :, :] = tgt_rate + print('=============after regridding===========' + svar) + print(np.sum(tgt_rate)) + elif svar == 'FRE': + Store_by_Level(fout, 'FRE', 'FRE', 'MJ', '3D', '0.f', '1.f') + tgt_rate = tgtfield.data + fout.variables['FRE'][0, :, :] = tgt_rate + except (ValueError, KeyError) as e: + print(f"Error processing variable {svar} in {rave_file_path}: {e}") + except (OSError, IOError, RuntimeError, FileNotFoundError, TypeError, IndexError, MemoryError) as e: + print(f"Error creating or writing to NetCDF file {output_file_path}: {e}") + except (OSError, IOError, RuntimeError, FileNotFoundError, TypeError, IndexError, MemoryError) as e: + print(f"Error reading NetCDF file {rave_file_path}: {e}") + else: + print(f"File not found or dummy emissions required: {rave_file_path}") From 9f14138a96fdf1685fe7304a29d2cabb531cb275 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Wed, 21 Aug 2024 13:10:25 +0000 Subject: [PATCH 23/61] fix python packages and script issues --- environment.yml | 7 +++++++ parm/wflow/smoke_dust.yaml | 2 +- scripts/exsrw_smoke_dust.sh | 12 ++++++++++-- ush/generate_fire_emissions.py | 10 +++++++++- ush/interp_tools.py | 3 ++- 5 files changed, 29 insertions(+), 5 deletions(-) diff --git a/environment.yml b/environment.yml index a735213198..e05a1e7cee 100644 --- a/environment.yml +++ b/environment.yml @@ -6,3 +6,10 @@ dependencies: - pylint=2.17* - pytest=7.2* - uwtools=2.3* + - esmpy=8.6.* + - netcdf4=1.6.* + - numpy=1.23.* + - pandas=1.5.* + - scipy=1.10.* + - xarray=2022.11.* + diff --git a/parm/wflow/smoke_dust.yaml b/parm/wflow/smoke_dust.yaml index bb054a6be2..37f2c8a1a4 100644 --- a/parm/wflow/smoke_dust.yaml +++ b/parm/wflow/smoke_dust.yaml @@ -31,7 +31,7 @@ task_smoke_dust: <<: *default_smoke_dust command: '&LOAD_MODULES_RUN_TASK; "smoke_dust" "&HOMEdir;/jobs/JSRW_SMOKE_DUST"' join: !cycstr '&LOGDIR;/{{ jobname }}_@Y@m@d@H&LOGEXT;' - memory: 2G + memory: 120G dependency: and: or_grid: diff --git a/scripts/exsrw_smoke_dust.sh b/scripts/exsrw_smoke_dust.sh index 70555b5696..3b6848f77e 100755 --- a/scripts/exsrw_smoke_dust.sh +++ b/scripts/exsrw_smoke_dust.sh @@ -47,9 +47,17 @@ In directory: \"${scrfunc_dir}\" This is the ex-script for the task that runs Smoke and Dust. ========================================================================" +# +export CDATE="${PDY}${cyc}" +# +# Create sub-directory for HOURLY_HWP and link restart files +# +mkdir -p ${DATA}/HOURLY_HWP + # # Check if the fire file exists in the designated directory -smokeFile="${SMOKE_DUST_FILE_PREFIX}_${PDY}${cyc}00.nc" +# +smokeFile="${SMOKE_DUST_FILE_PREFIX}_${CDATE}00.nc" if [ -e "${COMINsmoke}/${smokeFile}" ]; then cp -p "${COMINsmoke}/${smokeFile}" ${COMOUT} else @@ -95,8 +103,8 @@ else # ${USHsrw}/generate_fire_emissions.py \ "${FIXsmoke}/${PREDEF_GRID_NAME}" \ - "${COMINfire}" \ "${DATA}" \ + "${COMIN}" \ "${PREDEF_GRID_NAME}" \ "${EBB_DCYCLE}" \ "${RESTART_INTERVAL}" diff --git a/ush/generate_fire_emissions.py b/ush/generate_fire_emissions.py index 45bd9a5265..768ef62c64 100755 --- a/ush/generate_fire_emissions.py +++ b/ush/generate_fire_emissions.py @@ -21,6 +21,10 @@ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def generate_emiss_workflow(staticdir, ravedir, newges_dir, predef_grid, ebb_dcycle, restart_interval): + # staticdir: path to FIX files + # ravedir: path to RAVE fire data files (hourly), typically workding directory (DATA) + # newges_dir: path to interpolated RAVE data file for previous cycles (COMIN) + # nwges_dir: path to restart files, working directory (DATA) # ---------------------------------------------------------------------- # Import envs from workflow and get the predifying grid # Set variable names, constants and unit conversions @@ -31,7 +35,8 @@ def generate_emiss_workflow(staticdir, ravedir, newges_dir, predef_grid, ebb_dcy fg_to_ug = 1e6 to_s = 3600 current_day = os.environ.get("CDATE") - nwges_dir = os.environ.get("NWGES_DIR") +# nwges_dir = os.environ.get("NWGES_DIR") + nwges_dir = os.environ.get("DATA") vars_emis = ["FRP_MEAN","FRE"] cols, rows = (2700, 3950) if predef_grid == 'RRFS_NA_3km' else (1092, 1820) print('PREDEF GRID',predef_grid,'cols,rows',cols,rows) @@ -39,6 +44,9 @@ def generate_emiss_workflow(staticdir, ravedir, newges_dir, predef_grid, ebb_dcy #used later when working with ebb_dcyle 1 or 2 ebb_dcycle = float(ebb_dcycle) + print("CDATE:",current_day) + print("DATA:", nwges_dir) + #This is used later when copying the rrfs restart file restart_interval = restart_interval.split() restart_interval_list = [float(num) for num in restart_interval] diff --git a/ush/interp_tools.py b/ush/interp_tools.py index 1e886aa06a..df2f495bbb 100755 --- a/ush/interp_tools.py +++ b/ush/interp_tools.py @@ -4,7 +4,8 @@ import pandas as pd import os import fnmatch -import ESMF +#import ESMF +import esmpy as ESMF import xarray as xr import numpy as np from netCDF4 import Dataset From 711fc17a36882e58dc69fc9117271266f4b6bdab Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Wed, 21 Aug 2024 15:22:26 +0000 Subject: [PATCH 24/61] change path to results --- jobs/JSRW_SMOKE_DUST | 4 +++ scripts/exsrw_smoke_dust.sh | 54 ++++++---------------------------- ush/config.smoke_dust.yaml | 1 - ush/config_defaults.yaml | 4 --- ush/generate_fire_emissions.py | 13 ++++---- 5 files changed, 19 insertions(+), 57 deletions(-) diff --git a/jobs/JSRW_SMOKE_DUST b/jobs/JSRW_SMOKE_DUST index 6dd7cd6882..3eec0c2648 100755 --- a/jobs/JSRW_SMOKE_DUST +++ b/jobs/JSRW_SMOKE_DUST @@ -115,6 +115,10 @@ mkdir -p ${COMOUT} export COMINsmoke="${COMINsmoke:-${COMINsmoke_default}}" export COMINfire="${COMINfire:-${COMINfire_default}}" +# Create a teomporary share directory for RAVE interpolated data files +export DATA_SHARE="${DATA_SHARE:-${DATAROOT}/DATA_SHARE/RAVE_fire_intp}" +mkdir -p ${DATA_SHARE} + # Run setpdy to initialize PDYm and PDYp variables export cycle="${cycle:-t${cyc}z}" setpdy.sh diff --git a/scripts/exsrw_smoke_dust.sh b/scripts/exsrw_smoke_dust.sh index 3b6848f77e..1c49a5825d 100755 --- a/scripts/exsrw_smoke_dust.sh +++ b/scripts/exsrw_smoke_dust.sh @@ -62,23 +62,22 @@ if [ -e "${COMINsmoke}/${smokeFile}" ]; then cp -p "${COMINsmoke}/${smokeFile}" ${COMOUT} else # Check whether the RAVE files need to be split into hourly files - # Format the current day and hour properly for UTC if [ "${EBB_DCYCLE}" -eq 1 ]; then ddhh_to_use="${PDY}${cyc}" - dd_to_use="${PDY}" else ddhh_to_use="${PDYm1}${cyc}" - dd_to_use="${PDYm1}" fi for hour in {00..23}; do - fire_hr_fn="Hourly_Emissions_3km_${dd_to_use}${hour}00_${dd_to_use}${hour}00.nc" + fire_hr_cdate=$($NDATE +${hour} ${ddhh_to_use}) + fire_hr_pdy="${fire_hr_cdate:0:8}" + fire_hr_fn="Hourly_Emissions_3km_${fire_hr_cdate}00_${fire_hr_cdate}00.nc" if [ -f "${COMINfire}/${fire_hr_fn}" ]; then - echo "Hourly emission file for $hour was found." + echo "Hourly emission file for $hour was found: ${fire_hr_fn}" ln -nsf ${COMINfire}/${fire_hr_fn} . else # Check various version of RAVE raw data files (new and old) - rave_raw_fn1="RAVE-HrlyEmiss-3km_v2r0_blend_s${ddhh_to_use}00000_e${dd_to_use}23*" - rave_raw_fn2="Hourly_Emissions_3km_${ddhh_to_use}00_${dd_to_use}23*" + rave_raw_fn1="RAVE-HrlyEmiss-3km_v2r0_blend_s${fire_hr_cdate}00000_e${fire_hr_pdy}23*" + rave_raw_fn2="Hourly_Emissions_3km_${fire_hr_cdate}00_${fire_hr_pdy}23*" # Find files matching the specified patterns files_found=$(find "${COMINfire}" -type f \( -name "${rave_raw_fn1##*/}" -o -name "${rave_raw_fn2##*/}" \)) # Splitting 24-hour RAVE raw data into houly data @@ -104,7 +103,7 @@ else ${USHsrw}/generate_fire_emissions.py \ "${FIXsmoke}/${PREDEF_GRID_NAME}" \ "${DATA}" \ - "${COMIN}" \ + "${DATA_SHARE}" \ "${PREDEF_GRID_NAME}" \ "${EBB_DCYCLE}" \ "${RESTART_INTERVAL}" @@ -115,44 +114,9 @@ else print_err_msg_exit "${message_txt}" fi - #Copy the the hourly, interpolated RAVE data to $rave_nwges_dir so it - # is maintained there for future cycles. - # Function to check if all files in the directory are older than 15 days - - are_all_files_older_than_15_days() { - find "$1" -type f -mtime -15 | read - return $? - } - - # Check if all files in the rave_nwges_dir are older than 5 days - if are_all_files_older_than_15_days "${rave_intp_dir}"; then - echo "All files are older than 5 days. Replacing all files." - # Loop through all files in the work directory and replace them in rave_nwges_dir - for file in ${DATA}/*; do - filename=$(basename "$file") - target_file="${COMINsmoke}/${filename}" - - cp "${file}" "${target_file}" - echo "Copied file: $filename" - done - else - echo "Not all files are older than 5 days. Checking individual files." - # Loop through all files in the work directory - for file in ${DATA}/*; do - filename=$(basename "$file") - target_file="${COMINsmoke}/${filename}" - # Check if the file matches the pattern or is missing in the target directory - if [[ "$filename" =~ SMOKE_RRFS_data_.*\.nc ]]; then - cp "${file}" "${target_file}" - echo "Copied file: $filename" - elif [ ! -f "${target_file}" ]; then - cp "${file}" "${target_file}" - echo "Copied missing file: $filename" - fi - done - fi + # Copy Smoke file to COMOUT + cp -p ${DATA}/${smokeFile} ${COMOUT} fi -echo "Copy RAVE interpolated files completed" # #----------------------------------------------------------------------- # diff --git a/ush/config.smoke_dust.yaml b/ush/config.smoke_dust.yaml index b33c94c95c..d13f11ac91 100644 --- a/ush/config.smoke_dust.yaml +++ b/ush/config.smoke_dust.yaml @@ -63,5 +63,4 @@ smoke_dust_parm: DO_SMOKE_DUST: true EBB_DCYCLE: 1 SMOKE_DUST_FILE_PREFIX: "SMOKE_RRFS_data" - RAVE_FIRE_FILE_PREFIX: "RAVE-HrlyEmiss-3km" diff --git a/ush/config_defaults.yaml b/ush/config_defaults.yaml index 3e7ad01819..7256cebfc0 100644 --- a/ush/config_defaults.yaml +++ b/ush/config_defaults.yaml @@ -2703,9 +2703,6 @@ smoke_dust_parm: # SMOKE_DUST_FILE_PREFIX: # Prefix of Smoke and Dust file name # - # RAVE_FIRE_FILE_PREFIX: - # Prefix of RAVE fire file name - # #----------------------------------------------------------------------- # DO_SMOKE_DUST: false @@ -2713,7 +2710,6 @@ smoke_dust_parm: COMINsmoke_default: "" COMINfire_default: "" SMOKE_DUST_FILE_PREFIX: "SMOKE_RRFS_data" - RAVE_FIRE_FILE_PREFIX: "Hourly_Emission_3km" rocoto: attrs: "" diff --git a/ush/generate_fire_emissions.py b/ush/generate_fire_emissions.py index 768ef62c64..7d3c7eb3f7 100755 --- a/ush/generate_fire_emissions.py +++ b/ush/generate_fire_emissions.py @@ -19,11 +19,11 @@ #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Workflow #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -def generate_emiss_workflow(staticdir, ravedir, newges_dir, predef_grid, ebb_dcycle, restart_interval): +def generate_emiss_workflow(staticdir, ravedir, intp_dir, predef_grid, ebb_dcycle, restart_interval): # staticdir: path to FIX files # ravedir: path to RAVE fire data files (hourly), typically workding directory (DATA) - # newges_dir: path to interpolated RAVE data file for previous cycles (COMIN) + # intp_dir: path to interpolated RAVE data file for previous cycles (DATA_SHARE) # nwges_dir: path to restart files, working directory (DATA) # ---------------------------------------------------------------------- # Import envs from workflow and get the predifying grid @@ -55,8 +55,7 @@ def generate_emiss_workflow(staticdir, ravedir, newges_dir, predef_grid, ebb_dcy #Setting the directories veg_map = staticdir+'/veg_map.nc' RAVE= ravedir - rave_to_intp = predef_grid+"_intp_" - intp_dir = newges_dir + rave_to_intp = predef_grid+"_intp_" grid_in = staticdir+'/grid_in.nc' weightfile = staticdir+'/weight_file.nc' grid_out = staticdir+'/ds_out_base.nc' @@ -85,9 +84,9 @@ def generate_emiss_workflow(staticdir, ravedir, newges_dir, predef_grid, ebb_dcy intp_dir, src_latt, tgt_latt, tgt_lont, cols, rows) if ebb_dcycle == 1: - print('Processing emissions for ebb_dcyc 1') + print('Processing emissions forebb_dcyc 1') frp_avg_reshaped, ebb_total_reshaped = femmi_tools.averaging_FRP(ebb_dcycle, fcst_dates, cols, rows, intp_dir, rave_to_intp, veg_map, tgt_area, beta, fg_to_ug, to_s) - femmi_tools.produce_emiss_24hr_file(ebb_dcycle, frp_avg_reshaped, intp_dir, current_day, tgt_latt, tgt_lont, ebb_total_reshaped, cols, rows) + femmi_tools.produce_emiss_24hr_file(ebb_dcycle, frp_avg_reshaped, nwges_dir, current_day, tgt_latt, tgt_lont, ebb_total_reshaped, cols, rows) elif ebb_dcycle == 2: print('Restart dates to process',fcst_dates) hwp_avail_hours, hwp_non_avail_hours = HWP_tools.check_restart_files(hourly_hwpdir, fcst_dates) @@ -98,7 +97,7 @@ def generate_emiss_workflow(staticdir, ravedir, newges_dir, predef_grid, ebb_dcy te = femmi_tools.estimate_fire_duration(intp_avail_hours, intp_dir, fcst_dates, current_day, cols, rows, rave_to_intp) fire_age = femmi_tools.save_fire_dur(cols, rows, te) #produce emiss file - femmi_tools.produce_emiss_file(xarr_hwp, frp_avg_reshaped, totprcp_ave_arr, xarr_totprcp, intp_dir, current_day, tgt_latt, tgt_lont, ebb_total_reshaped, fire_age, cols, rows) + femmi_tools.produce_emiss_file(xarr_hwp, frp_avg_reshaped, totprcp_ave_arr, xarr_totprcp, nwges_dir, current_day, tgt_latt, tgt_lont, ebb_total_reshaped, fire_age, cols, rows) else: print('First day true, no RAVE files available. Use dummy emissions file') i_tools.create_dummy(intp_dir, current_day, tgt_latt, tgt_lont, cols, rows) From 9e2ab850c57c16af134883dfcc8683958fdc9fec Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Thu, 22 Aug 2024 12:50:05 +0000 Subject: [PATCH 25/61] fix missing fix files --- parm/FV3.input.yml | 128 +++++++++++++++++++++++---------- parm/wflow/coldstart.yaml | 9 +++ parm/wflow/smoke_dust.yaml | 13 +++- scripts/exregional_run_fcst.sh | 8 +-- ush/config.smoke_dust.yaml | 2 +- ush/config_defaults.yaml | 2 +- 6 files changed, 114 insertions(+), 48 deletions(-) diff --git a/parm/FV3.input.yml b/parm/FV3.input.yml index cfc0b3e23e..8df167128a 100644 --- a/parm/FV3.input.yml +++ b/parm/FV3.input.yml @@ -109,6 +109,7 @@ FV3_HRRR_gf: d_con: 0.5 d2_bg_k2: 0.04 dz_min: 2.0 + fv_sg_adj: 7200 hord_dp: 6 hord_mt: 6 hord_tm: 6 @@ -120,41 +121,75 @@ FV3_HRRR_gf: kord_tr: 9 kord_wz: 9 n_split: 5 - psm_bc: 1 + n_sponge: 65 nord_tr: 0 - nrows_blend: 10 + psm_bc: 1 range_warn: False regional_bcs_from_gsi: false rf_cutoff: 2000.0 + sg_cutoff: -1 vtdm4: 0.02 write_restart_with_bcs: false - gfs_physics_nml: + gfs_physics_nml: + addsmoke_flag: 1 + aero_dir_fdb: true + aero_ind_fdb: false + bl_mynn_edmf: 1 + bl_mynn_edmf_mom: 1 + bl_mynn_tkeadvect: true + cal_pre: false cdmbgwd: [3.5, 1.0] + clm_debug_print: false + clm_lake_debug: false + cnvcld: false + cnvgwd: false + coarsepm_settling: 1 + debug: false diag_log: true do_deep: true do_gsl_drag_ls_bl: true do_gsl_drag_ss: true do_gsl_drag_tofd: true + do_mynnedmf: true do_mynnsfclay: true + do_plumerise: true do_sfcperts: null - do_tofd : false - do_ugwp : false - do_ugwp_v0 : false - do_ugwp_v0_nst_only : false - do_ugwp_v0_orog_only : false - dt_inner : 36 - ebb_dcycle : 1 + do_smoke_transport: true + do_tofd: false + do_ugwp: false + do_ugwp_v0: false + do_ugwp_v0_nst_only: false + do_ugwp_v0_orog_only: false + drydep_opt: 1 + dspheat: true + dt_inner: 36 + dust_alpha: 10.0 + dust_drylimit_factor: 0.5 + dust_gamma: 1.3 + dust_moist_correction: 2.0 + dust_opt: 1 + ebb_dcycle: 1 effr_in: true - gwd_opt: 3 + enh_mix : false + fhcyc: 0.0 fhlwr: 900.0 fhswr: 900.0 + fhzero: 1.0 + frac_ice: true + gwd_opt: 3 + h2o_phys: true + hwp_method : 1 + hybedmf: false iaer: 1011 - ialb: 2 + ialb: 2 + iau_delthrs: 6 + iaufhrs: 30 iccn: 2 icliq_sw: 2 iems: 2 imfdeepcnv: 3 imfshalcnv: -1 + imp_physics: 8 iopt_alb: 2 iopt_btr: 1 iopt_crs: 1 @@ -168,43 +203,58 @@ FV3_HRRR_gf: iopt_stc: 1 iopt_tbot: 2 iovr: 3 + isncond_opt: 2 + isncovr_opt: 3 + isol: 2 + isot: 1 + isubc_lw: 2 + isubc_sw: 2 + ivegsrc: 1 + kice: 9 + ldiag3d: false ldiag_ugwp: false lgfdlmprad: false + lheatstrg: false lightning_threat: true + lkm: 1 + lradar: true + lrefres: true + lsm: 3 + lsoil: 9 + lsoil_lsm: 9 + ltaerosol: true + lwhtr: true + min_lakeice: 0.15 + min_seaice: 0.15 + mix_chem : true mosaic_lu: 1 mosaic_soil: 1 - isncond_opt: 2 - isncovr_opt: 3 - sfclay_compute_flux: true - thsfc_loc: false - # Smoke/dust options + nsfullradar_diag: 3600 + oz_phys: false + oz_phys_2015: true + pdfcld: false + plume_wind_eff : 1 + plumerisefire_frq : 30 + pre_rad: false + print_diff_pgr: true + prslrd0: 0.0 + random_clds: false + redrag: true rrfs_sd : false rrfs_smoke_debug : false + satmedmf: false + sc_factor : 1.0 seas_opt : 0 - mix_chem : true - dust_opt : 1 - coarsepm_settling : 1 + sfclay_compute_flux: true + shal_cnv: false smoke_conv_wet_coef : [0.5, 0.5, 0.5] - hwp_method : 1 - aero_ind_fdb : false - aero_dir_fdb : true - addsmoke_flag : 1 - wetdep_ls_opt : 1 - do_plumerise : true - do_smoke_transport : true - plumerisefire_frq : 30 - plume_wind_eff : 1 - dust_moist_correction : 2.0 - dust_drylimit_factor : 0.5 - dust_alpha : 10.0 - dust_gamma : 1.3 - drydep_opt : 1 - enh_mix : false + swhtr: true + thsfc_loc: false + trans_trac: true + ttendlim: -999 + use_ufo: true wetdep_ls_alpha : 0.5 - smoke_conv_wet_coef : [ 0.50, 0.50, 0.50 ] - do_smoke_transport : true - ebb_dcycle : 2 - sc_factor : 1.0 + wetdep_ls_opt : 1 fv_diagnostics_nml: do_hailcast: true diff --git a/parm/wflow/coldstart.yaml b/parm/wflow/coldstart.yaml index 29e0c26229..6ac09066a5 100644 --- a/parm/wflow/coldstart.yaml +++ b/parm/wflow/coldstart.yaml @@ -217,4 +217,13 @@ metatask_run_ensemble: taskdep: attrs: task: smoke_dust + or_prepstart: + not: + taskvalid: + attrs: + task: prepstart + taskdep: + attrs: + task: prepstart + diff --git a/parm/wflow/smoke_dust.yaml b/parm/wflow/smoke_dust.yaml index 37f2c8a1a4..a0df5c664f 100644 --- a/parm/wflow/smoke_dust.yaml +++ b/parm/wflow/smoke_dust.yaml @@ -61,11 +61,18 @@ task_smoke_dust: task_prepstart: <<: *default_smoke_dust + attrs: + cycledefs: forecast command: '&LOAD_MODULES_RUN_TASK; "prepstart" "&HOMEdir;/jobs/JSRW_PREPSTART"' join: !cycstr '&LOGDIR;/{{ jobname }}_@Y@m@d@H&LOGEXT;' memory: 2G dependency: - taskdep: - attrs: - task: smoke_dust + or_smoke_dust: + not: + taskvalid: + attrs: + task: smoke_dust + taskdep: + attrs: + task: smoke_dust diff --git a/scripts/exregional_run_fcst.sh b/scripts/exregional_run_fcst.sh index 3826666e46..e2dc191e76 100755 --- a/scripts/exregional_run_fcst.sh +++ b/scripts/exregional_run_fcst.sh @@ -392,17 +392,17 @@ else fi # Smoke and Dust if [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then - ln -snf ${FIX_SMOKE_DUST}/${PREDEF_GRID_NAME}/dust12m_data.nc . - ln -snf ${FIX_SMOKE_DUST}/${PREDEF_GRID_NAME}/emi_data.nc . + ln -snf ${FIXsmoke}/${PREDEF_GRID_NAME}/dust12m_data.nc . + ln -snf ${FIXsmoke}/${PREDEF_GRID_NAME}/emi_data.nc . smokefile="${COMIN}/${SMOKE_DUST_FILE_PREFIX}_${PDY}${cyc}00.nc" if [ -f ${smokefile} ]; then ln -snf ${smokefile} ${SMOKE_DUST_FILE_PREFIX}.nc else if [ "${EBB_DCYCLE}" = "1" ]; then - ln -snf ${FIX_SMOKE_DUST}/${PREDEF_GRID_NAME}/dummy_24hr_smoke_ebbdc1.nc ${SMOKE_DUST_FILE_PREFIX}.nc + ln -snf ${FIXsmoke}/${PREDEF_GRID_NAME}/dummy_24hr_smoke_ebbdc1.nc ${SMOKE_DUST_FILE_PREFIX}.nc echo "WARNING: Smoke file is not available, use dummy_24hr_smoke_ebbdc1.nc instead" else - ln -snf ${FIX_SMOKE_DUST}/${PREDEF_GRID_NAME}/dummy_24hr_smoke.nc ${SMOKE_DUST_FILE_PREFIX}.nc + ln -snf ${FIXsmoke}/${PREDEF_GRID_NAME}/dummy_24hr_smoke.nc ${SMOKE_DUST_FILE_PREFIX}.nc echo "WARNING: Smoke file is not available, use dummy_24hr_smoke.nc instead" fi fi diff --git a/ush/config.smoke_dust.yaml b/ush/config.smoke_dust.yaml index d13f11ac91..fc4f878288 100644 --- a/ush/config.smoke_dust.yaml +++ b/ush/config.smoke_dust.yaml @@ -58,7 +58,7 @@ task_run_post: global: DO_ENSEMBLE: false NUM_ENS_MEMBERS: 2 - HALO_BLEND: 0 + HALO_BLEND: 20 smoke_dust_parm: DO_SMOKE_DUST: true EBB_DCYCLE: 1 diff --git a/ush/config_defaults.yaml b/ush/config_defaults.yaml index 7256cebfc0..47b98f68e3 100644 --- a/ush/config_defaults.yaml +++ b/ush/config_defaults.yaml @@ -1969,7 +1969,7 @@ task_run_fcst: # #----------------------------------------------------------------------- # - USE_MERRA_CLIMO: '{{ workflow.CCPP_PHYS_SUITE == "FV3_GFS_v15_thompson_mynn_lam3km" or workflow.CCPP_PHYS_SUITE == "FV3_GFS_v17_p8" }}' + USE_MERRA_CLIMO: '{{ workflow.CCPP_PHYS_SUITE == "FV3_GFS_v15_thompson_mynn_lam3km" or workflow.CCPP_PHYS_SUITE == "FV3_HRRR_gf" or workflow.CCPP_PHYS_SUITE == "FV3_GFS_v17_p8" }}' # #----------------------------------------------------------------------- # From dcc62a520f2e1480fb84984a063f17aa626be84f Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Thu, 22 Aug 2024 15:59:34 +0000 Subject: [PATCH 26/61] update prepstart scripts --- jobs/JSRW_PREPSTART | 4 +- modulefiles/tasks/hera/prepstart.local.lua | 2 + parm/wflow/smoke_dust.yaml | 6 +- scripts/exsrw_prepstart.sh | 220 ++++++--------------- scripts/exsrw_smoke_dust.sh | 129 ++++++------ 5 files changed, 130 insertions(+), 231 deletions(-) create mode 100644 modulefiles/tasks/hera/prepstart.local.lua diff --git a/jobs/JSRW_PREPSTART b/jobs/JSRW_PREPSTART index f70bb60ae9..4f8dcce7d4 100755 --- a/jobs/JSRW_PREPSTART +++ b/jobs/JSRW_PREPSTART @@ -103,10 +103,10 @@ export RUN="${RUN:-${RUN_default}}" [[ "$WORKFLOW_MANAGER" = "rocoto" ]] && export COMROOT=$COMROOT if [ "${MACHINE}" = "WCOSS2" ]; then - export COMIN="${COMIN:-$(compath.py -o ${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR})}" + export COMIN="${COMIN:-$(compath.py -o ${NET}/${model_ver})}" export COMOUT="${COMOUT:-$(compath.py -o ${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR})}" else - export COMIN="${COMIN:-${COMROOT}/${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR}}" + export COMIN="${COMIN:-${COMROOT}/${NET}/${model_ver}}" export COMOUT="${COMOUT:-${COMROOT}/${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR}}" fi diff --git a/modulefiles/tasks/hera/prepstart.local.lua b/modulefiles/tasks/hera/prepstart.local.lua new file mode 100644 index 0000000000..63063d4fab --- /dev/null +++ b/modulefiles/tasks/hera/prepstart.local.lua @@ -0,0 +1,2 @@ +load("python_srw") +load(pathJoin("nco", os.getenv("nco_ver") or "5.1.6")) diff --git a/parm/wflow/smoke_dust.yaml b/parm/wflow/smoke_dust.yaml index a0df5c664f..aa064dd053 100644 --- a/parm/wflow/smoke_dust.yaml +++ b/parm/wflow/smoke_dust.yaml @@ -1,7 +1,7 @@ default_smoke_dust_task: &default_smoke_dust account: '&ACCOUNT;' attrs: - cycledefs: cycled_from_second + cycledefs: forecast maxtries: '2' envars: &default_vars GLOBAL_VAR_DEFNS_FP: '&GLOBAL_VAR_DEFNS_FP;' @@ -61,11 +61,9 @@ task_smoke_dust: task_prepstart: <<: *default_smoke_dust - attrs: - cycledefs: forecast command: '&LOAD_MODULES_RUN_TASK; "prepstart" "&HOMEdir;/jobs/JSRW_PREPSTART"' join: !cycstr '&LOGDIR;/{{ jobname }}_@Y@m@d@H&LOGEXT;' - memory: 2G + memory: 120G dependency: or_smoke_dust: not: diff --git a/scripts/exsrw_prepstart.sh b/scripts/exsrw_prepstart.sh index a24ae4e1e3..1c052759ed 100755 --- a/scripts/exsrw_prepstart.sh +++ b/scripts/exsrw_prepstart.sh @@ -48,181 +48,75 @@ In directory: \"${scrfunc_dir}\" This is the ex-script for the task that runs prepstart. ========================================================================" -# -#----------------------------------------------------------------------- -# -# Extract from CDATE the starting year, month, day, and hour of the -# forecast. These are needed below for various operations. -# -#----------------------------------------------------------------------- -# -START_DATE=$(echo "${CDATE}" | sed 's/\([[:digit:]]\{2\}\)$/ \1/') - -YYYYMMDDHH=$(date +%Y%m%d%H -d "${START_DATE}") -JJJ=$(date +%j -d "${START_DATE}") - -YYYY=${YYYYMMDDHH:0:4} -MM=${YYYYMMDDHH:4:2} -DD=${YYYYMMDDHH:6:2} -HH=${YYYYMMDDHH:8:2} -YYYYMMDD=${YYYYMMDDHH:0:8} -YYYYJJJHH=${YYYY}${JJJ}${HH} - -current_time=$(date "+%T") -cdate_crnt_fhr=$( date --utc --date "${YYYYMMDD} ${HH} UTC" "+%Y%m%d%H" ) - -YYYYMMDDm1=$(date +%Y%m%d -d "${START_DATE} 1 days ago") -YYYYMMDDm2=$(date +%Y%m%d -d "${START_DATE} 2 days ago") -YYYYMMDDm3=$(date +%Y%m%d -d "${START_DATE} 3 days ago") - #----------------------------------------------------------------------- # # smoke/dust cycling # #----------------------------------------------------------------------- -if [ "${DO_SMOKE_DUST}" = "TRUE" ] && [ "${CYCLE_TYPE}" = "spinup" ]; then # cycle smoke/dust fields - if_cycle_smoke_dust="FALSE" - if [ ${HH} -eq 4 ] || [ ${HH} -eq 16 ] ; then - if_cycle_smoke_dust="TRUE" - elif [ ${HH} -eq 6 ] && [ -f ${COMOUT}/../04_spinup/cycle_smoke_dust_skipped.txt ]; then - if_cycle_smoke_dust="TRUE" - elif [ ${HH} -eq 18 ] && [ -f ${COMOUT}/../16_spinup/cycle_smoke_dust_skipped.txt ]; then - if_cycle_smoke_dust="TRUE" - fi - if [ "${if_cycle_smoke_dust}" = "TRUE" ] ; then - # figure out which surface is available - surface_file_dir_name=fcst_fv3lam - bkpath_find="missing" - restart_prefix_find="missing" - restart_prefix=$( date +%Y%m%d.%H0000. -d "${START_DATE}" ) - if [ "${bkpath_find}" = "missing" ]; then - - offset_hours=${DA_CYCLE_INTERV} - YYYYMMDDHHmInterv=$( date +%Y%m%d%H -d "${START_DATE} ${offset_hours} hours ago" ) - bkpath=${fg_root}/${YYYYMMDDHHmInterv}${SLASH_ENSMEM_SUBDIR}/${surface_file_dir_name}/RESTART - - n=${DA_CYCLE_INTERV} - while [[ $n -le 25 ]] ; do - if [ "${IO_LAYOUT_Y}" = "1" ]; then - checkfile=${bkpath}/${restart_prefix}fv_tracer.res.tile1.nc - else - checkfile=${bkpath}/${restart_prefix}fv_tracer.res.tile1.nc.0000 - fi - if [ -r "${checkfile}" ] && [ "${bkpath_find}" = "missing" ]; then - bkpath_find=${bkpath} - restart_prefix_find=${restart_prefix} - print_info_msg "$VERBOSE" "Found ${checkfile}; Use it for smoke/dust cycle " - break - fi - - n=$((n + ${DA_CYCLE_INTERV})) - offset_hours=${n} - YYYYMMDDHHmInterv=$( date +%Y%m%d%H -d "${START_DATE} ${offset_hours} hours ago" ) - bkpath=${fg_root}/${YYYYMMDDHHmInterv}${SLASH_ENSMEM_SUBDIR}/${surface_file_dir_name}/RESTART # cycling, use background from RESTART - print_info_msg "$VERBOSE" "Trying this path: ${bkpath}" - done - fi - - # check if there are tracer file in continue cycle data space: - if [ "${bkpath_find}" = "missing" ]; then - checkfile=${CONT_CYCLE_DATA_ROOT}/tracer/${restart_prefix}fv_tracer.res.tile1.nc - if [ -r "${checkfile}" ]; then - bkpath_find=${CONT_CYCLE_DATA_ROOT}/tracer - restart_prefix_find=${restart_prefix} - print_info_msg "$VERBOSE" "Found ${checkfile}; Use it for smoke/dust cycle " - fi - fi - - # cycle smoke/dust - rm -f cycle_smoke_dust.done - if [ "${bkpath_find}" = "missing" ]; then - print_info_msg "Warning: cannot find smoke/dust files from previous cycle" - touch ${COMOUT}/cycle_smoke_dust_skipped.txt - else +if [ $(bookify "${COLDSTART}") = "TRUE" ] && [ "${PDY}${cyc}" = "${DATE_FIRST_CYCL:0:10}" ]; then + echo "This step is skipped for the first cycle of COLDSTART." +else + if [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then + bkpath_find="missing" + if [ "${bkpath_find}" = "missing" ]; then + restart_prefix="${PDY}.${cyc}0000." + CDATEprev=$($NDATE -${INCR_CYCL_FREQ} ${PDY}${cyc}) + PDYprev=${CDATEprev:0:8} + cycprev=${CDATEprev:8:2} + path_restart=${COMIN}/${RUN}.${PDYprev}/${cycprev}${SLASH_ENSMEM_SUBDIR}/RESTART + + n=${INCR_CYCL_FREQ} + while [[ $n -le 25 ]] ; do if [ "${IO_LAYOUT_Y}" = "1" ]; then - checkfile=${bkpath_find}/${restart_prefix_find}fv_tracer.res.tile1.nc - if [ -r "${checkfile}" ]; then - ncks -A -v smoke,dust,coarsepm ${checkfile} fv_tracer.res.tile1.nc - fi + checkfile=${path_restart}/${restart_prefix}fv_tracer.res.tile1.nc else - for ii in ${list_iolayout} - do - iii=$(printf %4.4i $ii) - checkfile=${bkpath_find}/${restart_prefix_find}fv_tracer.res.tile1.nc.${iii} - if [ -r "${checkfile}" ]; then - ncks -A -v smoke,dust,coarsepm ${checkfile} fv_tracer.res.tile1.nc.${iii} - fi - done + checkfile=${path_restart}/${restart_prefix}fv_tracer.res.tile1.nc.0000 + fi + if [ -r "${checkfile}" ] && [ "${bkpath_find}" = "missing" ]; then + bkpath_find=${path_restart} + print_info_msg "$VERBOSE" "Found ${checkfile}; Use it for smoke/dust cycle " + break + fi + n=$((n + ${DA_CYCLE_INTERV})) + CDATEprev=$($NDATE -$n ${PDY}${cyc}) + PDYprev=${CDATEprev:0:8} + cycprev=${CDATEprev:8:2} + path_restart=${COMIN}/${RUN}.${PDYprev}/${cycprev}${SLASH_ENSMEM_SUBDIR}/RESTART + print_info_msg "$VERBOSE" "Trying this path: ${path_restart}" + done + fi + + # cycle smoke/dust + if [ "${bkpath_find}" = "missing" ]; then + print_info_msg "WARNING: cannot find smoke/dust files from previous cycle" + else + if [ "${IO_LAYOUT_Y}" = "1" ]; then + checkfile=${bkpath_find}/${restart_prefix}fv_tracer.res.tile1.nc + if [ -r "${checkfile}" ]; then + ncks -A -v smoke,dust,coarsepm ${checkfile} fv_tracer.res.tile1.nc fi - echo "${YYYYMMDDHH}(${CYCLE_TYPE}): cycle smoke/dust from ${checkfile} " >> ${EXPTDIR}/log.cycles - fi - fi -fi - -#----------------------------------------------------------------------- -# -# smoke/dust cycling for Retros -# -#----------------------------------------------------------------------- - -if [ "${DO_SMOKE_DUST}" = "TRUE" ]; then - surface_file_dir_name=fcst_fv3lam - bkpath_find="missing" - restart_prefix_find="missing" - if [ "${bkpath_find}" = "missing" ]; then - restart_prefix=$( date +%Y%m%d.%H0000. -d "${START_DATE}" ) - - offset_hours=${DA_CYCLE_INTERV} - YYYYMMDDHHmInterv=$( date +%Y%m%d%H -d "${START_DATE} ${offset_hours} hours ago" ) - bkpath=${fg_root}/${YYYYMMDDHHmInterv}${SLASH_ENSMEM_SUBDIR}/${surface_file_dir_name}/RESTART - - n=${DA_CYCLE_INTERV} - while [[ $n -le 25 ]] ; do - if [ "${IO_LAYOUT_Y}" = "1" ]; then - checkfile=${bkpath}/${restart_prefix}fv_tracer.res.tile1.nc - else - checkfile=${bkpath}/${restart_prefix}fv_tracer.res.tile1.nc.0000 - fi - if [ -r "${checkfile}" ] && [ "${bkpath_find}" = "missing" ]; then - bkpath_find=${bkpath} - restart_prefix_find=${restart_prefix} - print_info_msg "$VERBOSE" "Found ${checkfile}; Use it for smoke/dust cycle " - break - fi - n=$((n + ${DA_CYCLE_INTERV})) - offset_hours=${n} - YYYYMMDDHHmInterv=$( date +%Y%m%d%H -d "${START_DATE} ${offset_hours} hours ago" ) - bkpath=${fg_root}/${YYYYMMDDHHmInterv}${SLASH_ENSMEM_SUBDIR}/${surface_file_dir_name}/RESTART # cycling, use background from RESTART - print_info_msg "$VERBOSE" "Trying this path: ${bkpath}" - done - fi - - # cycle smoke/dust - rm -f cycle_smoke_dust.done - if [ "${bkpath_find}" = "missing" ]; then - print_info_msg "Warning: cannot find smoke/dust files from previous cycle" else - if [ "${IO_LAYOUT_Y}" = "1" ]; then - checkfile=${bkpath_find}/${restart_prefix_find}fv_tracer.res.tile1.nc + for ii in ${list_iolayout} + do + iii=$(printf %4.4i $ii) + checkfile=${bkpath_find}/${restart_prefix}fv_tracer.res.tile1.nc.${iii} if [ -r "${checkfile}" ]; then - ncks -A -v smoke,dust,coarsepm ${checkfile} fv_tracer.res.tile1.nc + ncks -A -v smoke,dust,coarsepm ${checkfile} fv_tracer.res.tile1.nc.${iii} fi - else - for ii in ${list_iolayout} - do - iii=$(printf %4.4i $ii) - checkfile=${bkpath_find}/${restart_prefix_find}fv_tracer.res.tile1.nc.${iii} - if [ -r "${checkfile}" ]; then - ncks -A -v smoke,dust,coarsepm ${checkfile} fv_tracer.res.tile1.nc.${iii} - fi - done - fi - echo "${YYYYMMDDHH}(${CYCLE_TYPE}): cycle smoke/dust from ${checkfile} " >> ${EXPTDIR}/log.cycles + done fi - - ${USHsrw}/add_smoke.py -fi - + echo "${PDY}${cyc}: cycle smoke/dust from ${checkfile} " + fi + + ${USHsrw}/add_smoke.py + export err=$? + if [ $err -ne 0 ]; then + message_txt="add_smoke.py failed with return code $err" + err_exit "${message_txt}" + print_err_msg_exit "${message_txt}" + fi + fi +fi # #----------------------------------------------------------------------- # diff --git a/scripts/exsrw_smoke_dust.sh b/scripts/exsrw_smoke_dust.sh index 1c49a5825d..5e66fe8ee1 100755 --- a/scripts/exsrw_smoke_dust.sh +++ b/scripts/exsrw_smoke_dust.sh @@ -47,75 +47,80 @@ In directory: \"${scrfunc_dir}\" This is the ex-script for the task that runs Smoke and Dust. ========================================================================" -# -export CDATE="${PDY}${cyc}" -# -# Create sub-directory for HOURLY_HWP and link restart files -# -mkdir -p ${DATA}/HOURLY_HWP -# -# Check if the fire file exists in the designated directory -# -smokeFile="${SMOKE_DUST_FILE_PREFIX}_${CDATE}00.nc" -if [ -e "${COMINsmoke}/${smokeFile}" ]; then - cp -p "${COMINsmoke}/${smokeFile}" ${COMOUT} +if [ $(boolify "${COLDSTART}") = "TRUE" ] && [ "${PDY}${cyc}" = "${DATE_FIRST_CYCL:0:10}" ]; then + echo "This step is skipped for the first cycle of COLDSTART." else - # Check whether the RAVE files need to be split into hourly files - if [ "${EBB_DCYCLE}" -eq 1 ]; then - ddhh_to_use="${PDY}${cyc}" - else - ddhh_to_use="${PDYm1}${cyc}" - fi - for hour in {00..23}; do - fire_hr_cdate=$($NDATE +${hour} ${ddhh_to_use}) - fire_hr_pdy="${fire_hr_cdate:0:8}" - fire_hr_fn="Hourly_Emissions_3km_${fire_hr_cdate}00_${fire_hr_cdate}00.nc" - if [ -f "${COMINfire}/${fire_hr_fn}" ]; then - echo "Hourly emission file for $hour was found: ${fire_hr_fn}" - ln -nsf ${COMINfire}/${fire_hr_fn} . - else - # Check various version of RAVE raw data files (new and old) - rave_raw_fn1="RAVE-HrlyEmiss-3km_v2r0_blend_s${fire_hr_cdate}00000_e${fire_hr_pdy}23*" - rave_raw_fn2="Hourly_Emissions_3km_${fire_hr_cdate}00_${fire_hr_pdy}23*" - # Find files matching the specified patterns - files_found=$(find "${COMINfire}" -type f \( -name "${rave_raw_fn1##*/}" -o -name "${rave_raw_fn2##*/}" \)) - # Splitting 24-hour RAVE raw data into houly data - for file_to_use in $files_found; do - echo "Using file: $file_to_use" - echo "Splitting data for hour $hour..." - ncks -d time,$hour,$hour "${COMINfire}/${file_to_use}" "${DATA}/${fire_hr_fn}" - if [ -f "${DATA}/${fire_hr_fn}" ]; then - break - else - echo "WARNING: Hourly emission file for $hour was NOT created from ${file_to_use}." - fi - done - fi - done # - #----------------------------------------------------------------------- + export CDATE="${PDY}${cyc}" # - # Call python script to generate fire emission files. + # Create sub-directory for HOURLY_HWP and link restart files # - #----------------------------------------------------------------------- + mkdir -p ${DATA}/HOURLY_HWP + # - ${USHsrw}/generate_fire_emissions.py \ - "${FIXsmoke}/${PREDEF_GRID_NAME}" \ - "${DATA}" \ - "${DATA_SHARE}" \ - "${PREDEF_GRID_NAME}" \ - "${EBB_DCYCLE}" \ - "${RESTART_INTERVAL}" - export err=$? - if [ $err -ne 0 ]; then - message_txt="Generate_fire_emissions.py failed with return code $err" - err_exit "${message_txt}" - print_err_msg_exit "${message_txt}" - fi + # Check if the fire file exists in the designated directory + # + smokeFile="${SMOKE_DUST_FILE_PREFIX}_${CDATE}00.nc" + if [ -e "${COMINsmoke}/${smokeFile}" ]; then + cp -p "${COMINsmoke}/${smokeFile}" ${COMOUT} + else + # Check whether the RAVE files need to be split into hourly files + if [ "${EBB_DCYCLE}" -eq 1 ]; then + ddhh_to_use="${PDY}${cyc}" + else + ddhh_to_use="${PDYm1}${cyc}" + fi + for hour in {00..23}; do + fire_hr_cdate=$($NDATE +${hour} ${ddhh_to_use}) + fire_hr_pdy="${fire_hr_cdate:0:8}" + fire_hr_fn="Hourly_Emissions_3km_${fire_hr_cdate}00_${fire_hr_cdate}00.nc" + if [ -f "${COMINfire}/${fire_hr_fn}" ]; then + echo "Hourly emission file for $hour was found: ${fire_hr_fn}" + ln -nsf ${COMINfire}/${fire_hr_fn} . + else + # Check various version of RAVE raw data files (new and old) + rave_raw_fn1="RAVE-HrlyEmiss-3km_v2r0_blend_s${fire_hr_cdate}00000_e${fire_hr_pdy}23*" + rave_raw_fn2="Hourly_Emissions_3km_${fire_hr_cdate}00_${fire_hr_pdy}23*" + # Find files matching the specified patterns + files_found=$(find "${COMINfire}" -type f \( -name "${rave_raw_fn1##*/}" -o -name "${rave_raw_fn2##*/}" \)) + # Splitting 24-hour RAVE raw data into houly data + for file_to_use in $files_found; do + echo "Using file: $file_to_use" + echo "Splitting data for hour $hour..." + ncks -d time,$hour,$hour "${COMINfire}/${file_to_use}" "${DATA}/${fire_hr_fn}" + if [ -f "${DATA}/${fire_hr_fn}" ]; then + break + else + echo "WARNING: Hourly emission file for $hour was NOT created from ${file_to_use}." + fi + done + fi + done + # + #----------------------------------------------------------------------- + # + # Call python script to generate fire emission files. + # + #----------------------------------------------------------------------- + # + ${USHsrw}/generate_fire_emissions.py \ + "${FIXsmoke}/${PREDEF_GRID_NAME}" \ + "${DATA}" \ + "${DATA_SHARE}" \ + "${PREDEF_GRID_NAME}" \ + "${EBB_DCYCLE}" \ + "${RESTART_INTERVAL}" + export err=$? + if [ $err -ne 0 ]; then + message_txt="generate_fire_emissions.py failed with return code $err" + err_exit "${message_txt}" + print_err_msg_exit "${message_txt}" + fi - # Copy Smoke file to COMOUT - cp -p ${DATA}/${smokeFile} ${COMOUT} + # Copy Smoke file to COMOUT + cp -p ${DATA}/${smokeFile} ${COMOUT} + fi fi # #----------------------------------------------------------------------- From bf636940a499b5aeaed24bccdbb42930fbd26e2b Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Fri, 23 Aug 2024 17:08:58 +0000 Subject: [PATCH 27/61] add dependency for smoke dust in first cycle --- parm/FV3.input.yml | 5 +++-- parm/input.nml.FV3 | 2 +- parm/wflow/smoke_dust.yaml | 13 +++++++++++++ scripts/exsrw_prepstart.sh | 8 ++++---- ush/setup.py | 6 ++++-- 5 files changed, 25 insertions(+), 9 deletions(-) diff --git a/parm/FV3.input.yml b/parm/FV3.input.yml index 8df167128a..802f51ad95 100644 --- a/parm/FV3.input.yml +++ b/parm/FV3.input.yml @@ -104,6 +104,8 @@ FV3_HRRR_gf: atmos_model_nml: avg_max_length: 3600. ignore_rst_cksum: true + external_ic_nml: + levp: 66 fv_core_nml: agrid_vel_rst: true d_con: 0.5 @@ -123,6 +125,7 @@ FV3_HRRR_gf: n_split: 5 n_sponge: 65 nord_tr: 0 + npz: 65 psm_bc: 1 range_warn: False regional_bcs_from_gsi: false @@ -210,7 +213,6 @@ FV3_HRRR_gf: isubc_lw: 2 isubc_sw: 2 ivegsrc: 1 - kice: 9 ldiag3d: false ldiag_ugwp: false lgfdlmprad: false @@ -220,7 +222,6 @@ FV3_HRRR_gf: lradar: true lrefres: true lsm: 3 - lsoil: 9 lsoil_lsm: 9 ltaerosol: true lwhtr: true diff --git a/parm/input.nml.FV3 b/parm/input.nml.FV3 index bd6244d2d9..53cd6e5a1d 100644 --- a/parm/input.nml.FV3 +++ b/parm/input.nml.FV3 @@ -28,7 +28,7 @@ / &diag_manager_nml - max_output_fields = 450 + max_output_fields = 500 prepend_date = .false. / diff --git a/parm/wflow/smoke_dust.yaml b/parm/wflow/smoke_dust.yaml index aa064dd053..ca2c2b4e7f 100644 --- a/parm/wflow/smoke_dust.yaml +++ b/parm/wflow/smoke_dust.yaml @@ -58,6 +58,19 @@ task_smoke_dust: streq: left: staged_sfc_climo right: '{% if not rocoto.get("tasks", {}).get("task_make_sfc_climo") %}staged_sfc_climo{% endif %}' + or: + datadep_coldstart: + attrs: + age: 00:00:00:05 + text: !cycstr '{{ workflow.EXPTDIR }}/task_skip_coldstart_@Y@m@d@H00.txt' + datadep_date_tag_tracer: + attrs: + age: 00:00:00:05 + text: '&COMIN_DIR;/RESTART/@Y@m@d.@H@M@S.fv_tracer.res.tile1.nc' + datadep_tracer: + attrs: + age: 00:00:00:05 + text: '&COMIN_DIR;/RESTART/fv_tracer.res.tile1.nc' task_prepstart: <<: *default_smoke_dust diff --git a/scripts/exsrw_prepstart.sh b/scripts/exsrw_prepstart.sh index 1c052759ed..0e7765b8e4 100755 --- a/scripts/exsrw_prepstart.sh +++ b/scripts/exsrw_prepstart.sh @@ -53,7 +53,7 @@ This is the ex-script for the task that runs prepstart. # smoke/dust cycling # #----------------------------------------------------------------------- -if [ $(bookify "${COLDSTART}") = "TRUE" ] && [ "${PDY}${cyc}" = "${DATE_FIRST_CYCL:0:10}" ]; then +if [ $(boolify "${COLDSTART}") = "TRUE" ] && [ "${PDY}${cyc}" = "${DATE_FIRST_CYCL:0:10}" ]; then echo "This step is skipped for the first cycle of COLDSTART." else if [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then @@ -77,7 +77,7 @@ else print_info_msg "$VERBOSE" "Found ${checkfile}; Use it for smoke/dust cycle " break fi - n=$((n + ${DA_CYCLE_INTERV})) + n=$((n + ${INCR_CYCL_FREQ})) CDATEprev=$($NDATE -$n ${PDY}${cyc}) PDYprev=${CDATEprev:0:8} cycprev=${CDATEprev:8:2} @@ -93,7 +93,7 @@ else if [ "${IO_LAYOUT_Y}" = "1" ]; then checkfile=${bkpath_find}/${restart_prefix}fv_tracer.res.tile1.nc if [ -r "${checkfile}" ]; then - ncks -A -v smoke,dust,coarsepm ${checkfile} fv_tracer.res.tile1.nc + ncks -A -v smoke,dust,coarsepm ${checkfile} fv_tracer.res.tile1.nc fi else for ii in ${list_iolayout} @@ -101,7 +101,7 @@ else iii=$(printf %4.4i $ii) checkfile=${bkpath_find}/${restart_prefix}fv_tracer.res.tile1.nc.${iii} if [ -r "${checkfile}" ]; then - ncks -A -v smoke,dust,coarsepm ${checkfile} fv_tracer.res.tile1.nc.${iii} + ncks -A -v smoke,dust,coarsepm ${checkfile} fv_tracer.res.tile1.nc.${iii} fi done fi diff --git a/ush/setup.py b/ush/setup.py index 51d5b2a084..81d9e95825 100644 --- a/ush/setup.py +++ b/ush/setup.py @@ -1462,7 +1462,6 @@ def dict_find(user_dict, substring): logging.debug(f'New fix file list:\n{fixed_files["FIXgsm_FILES_TO_COPY_TO_FIXam"]=}') logging.debug(f'New fix file mapping:\n{fixed_files["CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING"]=}') - # # ----------------------------------------------------------------------- # @@ -1509,7 +1508,10 @@ def dict_find(user_dict, substring): var_defns_cfg["workflow"][dates] = date_to_str(var_defns_cfg["workflow"][dates]) var_defns_cfg.dump(global_var_defns_fp) - + if expt_config["workflow"].get("COLDSTART"): + coldstart_date=workflow_config["DATE_FIRST_CYCL"] + fn_pass=f"task_skip_coldstart_{coldstart_date}.txt" + open(os.path.join(exptdir,fn_pass), 'a').close() # # ----------------------------------------------------------------------- # From 581d7d541f4a1c78ce82e6dbd97ac1a580caa561 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Fri, 23 Aug 2024 20:02:07 +0000 Subject: [PATCH 28/61] fix ccpp namelist --- parm/FV3.input.yml | 4 ++-- parm/model_configure | 7 +++++-- ush/config.smoke_dust.yaml | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/parm/FV3.input.yml b/parm/FV3.input.yml index 802f51ad95..d0e0db09ce 100644 --- a/parm/FV3.input.yml +++ b/parm/FV3.input.yml @@ -228,8 +228,8 @@ FV3_HRRR_gf: min_lakeice: 0.15 min_seaice: 0.15 mix_chem : true - mosaic_lu: 1 - mosaic_soil: 1 + mosaic_lu: 0 + mosaic_soil: 0 nsfullradar_diag: 3600 oz_phys: false oz_phys_2015: true diff --git a/parm/model_configure b/parm/model_configure index aeb45f4719..2f4c1ec603 100644 --- a/parm/model_configure +++ b/parm/model_configure @@ -17,8 +17,10 @@ atmos_nthreads: {{ atmos_nthreads }} restart_interval: {{ restart_interval }} output_1st_tstep_rst: .false. write_dopost: {{ write_dopost }} +zstandard_level: 0 ideflate: 0 -nbits: 0 +quantize_mode: quantize_bitround +quantize_nsd: 0 ichunk2d: -1 jchunk2d: -1 ichunk3d: -1 @@ -26,6 +28,7 @@ jchunk3d: -1 kchunk3d: -1 itasks: {{ itasks }} quilting: {{ quilting }} +quilting_restart: {{ quilting }} {% if quilting %} # # Write-component (quilting) computational parameters. @@ -34,7 +37,7 @@ write_groups: {{ write_groups }} write_tasks_per_group: {{ write_tasks_per_group }} num_files: 2 filename_base: 'dyn' 'phy' -output_file: 'netcdf' 'netcdf' +output_file: 'netcdf_parallel' # # Write-component output frequency parameter definitions: # diff --git a/ush/config.smoke_dust.yaml b/ush/config.smoke_dust.yaml index fc4f878288..856ed386e0 100644 --- a/ush/config.smoke_dust.yaml +++ b/ush/config.smoke_dust.yaml @@ -50,7 +50,7 @@ task_run_fcst: WRTCMP_write_tasks_per_group: 40 RESTART_INTERVAL: 6 12 18 24 QUILTING: true - PRINT_ESMF: false + PRINT_ESMF: true DO_FCST_RESTART: false task_run_post: POST_OUTPUT_DOMAIN_NAME: conus3km From 69877d3615b714a48d501523eda0d956b9d8f1ad Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Fri, 23 Aug 2024 20:19:23 +0000 Subject: [PATCH 29/61] adjust forecast walltime --- ush/config.smoke_dust.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ush/config.smoke_dust.yaml b/ush/config.smoke_dust.yaml index 856ed386e0..289e680f3f 100644 --- a/ush/config.smoke_dust.yaml +++ b/ush/config.smoke_dust.yaml @@ -34,7 +34,7 @@ rocoto: taskgroups: '{{ ["parm/wflow/prep.yaml", "parm/wflow/smoke_dust.yaml", "parm/wflow/coldstart.yaml", "parm/wflow/post.yaml"]|include }}' metatask_run_ensemble: task_run_fcst_mem#mem#: - walltime: 03:00:00 + walltime: 02:00:00 task_get_extrn_ics: EXTRN_MDL_NAME_ICS: RAP EXTRN_MDL_ICS_OFFSET_HRS: 0 @@ -42,6 +42,10 @@ task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: RAP LBC_SPEC_INTVL_HRS: 6 EXTRN_MDL_LBCS_OFFSET_HRS: 0 +task_make_ics: + VCOORD_FILE: "{{ workflow.FIXam }}/global_hyblev_fcst_rrfsL65.txt" +task_make_lbcs: + VCOORD_FILE: "{{ workflow.FIXam }}/global_hyblev_fcst_rrfsL65.txt" task_run_fcst: DT_ATMOS: 36 LAYOUT_X: 15 From 81a77dbc48553b429944b191aaebc6eeea2097f9 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Sat, 24 Aug 2024 22:21:46 +0000 Subject: [PATCH 30/61] add separate post script --- jobs/JSRW_POST | 205 ++++++++++++++++++++ jobs/JSRW_PREPSTART | 2 +- jobs/JSRW_SMOKE_DUST | 2 +- parm/wflow/smoke_dust.yaml | 30 ++- scripts/exregional_run_fcst.sh | 25 +++ scripts/exregional_run_post.sh | 3 +- scripts/exsrw_post.sh | 330 +++++++++++++++++++++++++++++++++ scripts/exsrw_prepstart.sh | 2 +- scripts/exsrw_smoke_dust.sh | 2 +- ush/config.smoke_dust.yaml | 2 +- ush/config_defaults.yaml | 6 +- ush/machine/hera.yaml | 2 + 12 files changed, 598 insertions(+), 13 deletions(-) create mode 100755 jobs/JSRW_POST create mode 100755 scripts/exsrw_post.sh diff --git a/jobs/JSRW_POST b/jobs/JSRW_POST new file mode 100755 index 0000000000..927e26558b --- /dev/null +++ b/jobs/JSRW_POST @@ -0,0 +1,205 @@ +#!/usr/bin/env bash + +# +#----------------------------------------------------------------------- +# +# This script processes Post +# +#----------------------------------------------------------------------- +# +date +export PS4='+ $SECONDS + ' +set -xue +# +#----------------------------------------------------------------------- +# +# Set the NCO standard environment variables (Table 1, pp.4) +# +#----------------------------------------------------------------------- +# +export USHsrw="${HOMEdir}/ush" +export EXECsrw="${HOMEdir}/exec" +export PARMsrw="${HOMEdir}/parm" +export SCRIPTSsrw="${HOMEdir}/scripts" +# +#----------------------------------------------------------------------- +# +# Source the variable definitions file and the bash utility functions. +# +#----------------------------------------------------------------------- +# +export USHdir="${USHsrw}" # should be removed later +. ${USHsrw}/source_util_funcs.sh +for sect in user nco platform workflow global task_run_post smoke_dust_parm ; do + source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} +done +# +#----------------------------------------------------------------------- +# +# Get the full path to the file in which this script/function is located +# (scrfunc_fp), the name of that file (scrfunc_fn), and the directory in +# which the file is located (scrfunc_dir). +# +#----------------------------------------------------------------------- +# +scrfunc_fp=$( $READLINK -f "${BASH_SOURCE[0]}" ) +scrfunc_fn=$( basename "${scrfunc_fp}" ) +scrfunc_dir=$( dirname "${scrfunc_fp}" ) +# +#----------------------------------------------------------------------- +# +# Print message indicating entry into script. +# +#----------------------------------------------------------------------- +# +print_info_msg " +======================================================================== +Entering script: \"${scrfunc_fn}\" +In directory: \"${scrfunc_dir}\" + +This is the J-job script for Post-processing. +========================================================================" +# +#----------------------------------------------------------------------- +# +# Define job and jobid by default for rocoto +# +#----------------------------------------------------------------------- +# +WORKFLOW_MANAGER="${WORKFLOW_MANAGER:-rocoto}" +if [ "${WORKFLOW_MANAGER}" = "rocoto" ]; then + if [ "${SCHED}" = "slurm" ]; then + job=${SLURM_JOB_NAME} + pid=${SLURM_JOB_ID} + elif [ "${SCHED}" = "pbspro" ]; then + job=${PBS_JOBNAME} + pid=${PBS_JOBID} + else + job="task" + pid=$$ + fi + jobid="${job}.${PDY}${cyc}.${pid}" +fi +# +#----------------------------------------------------------------------- +# +# Create a temp working directory (DATA) and cd into it. +# +#----------------------------------------------------------------------- +# +export DATA="${DATA:-${DATAROOT}/${jobid}}" +mkdir -p $DATA +cd $DATA +# +#----------------------------------------------------------------------- +# +# Define NCO environment variables and set COM type definitions. +# +#----------------------------------------------------------------------- +# +export NET="${NET:-${NET_default}}" +export RUN="${RUN:-${RUN_default}}" + +[[ "$WORKFLOW_MANAGER" = "rocoto" ]] && export COMROOT=$COMROOT +if [ "${MACHINE}" = "WCOSS2" ]; then + export COMIN="${COMIN:-$(compath.py -o ${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR})}" + export COMOUT="${COMOUT:-$(compath.py -o ${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR})}" +else + export COMIN="${COMIN:-${COMROOT}/${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR}}" + export COMOUT="${COMOUT:-${COMROOT}/${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR}}" +fi + +mkdir -p ${COMOUT} + +export COMINsmoke="${COMINsmoke:-${COMINsmoke_default}}" +export COMINfire="${COMINfire:-${COMINfire_default}}" + +# Create a teomporary share directory for RAVE interpolated data files +export DATA_SHARE="${DATA_SHARE:-${DATAROOT}/DATA_SHARE/RAVE_fire_intp}" +mkdir -p ${DATA_SHARE} + +# Run setpdy to initialize PDYm and PDYp variables +export cycle="${cycle:-t${cyc}z}" +setpdy.sh +. ./PDY +# +#----------------------------------------------------------------------- +# +# Set sub-cycle and ensemble member names in file/diectory names +# +#----------------------------------------------------------------------- +# +if [ ${subcyc} -ne 0 ]; then + export cycle="t${cyc}${subcyc}z" +fi +if [ $(boolify "${DO_ENSEMBLE}") = "TRUE" ] && [ ! -z ${ENSMEM_INDX} ]; then + export dot_ensmem=".mem${ENSMEM_INDX}" +else + export dot_ensmem= +fi +# +#----------------------------------------------------------------------- +# +# Make sure that fhr is a non-empty string consisting of only digits. +# +#----------------------------------------------------------------------- +# +export fhr=$( printf "%s" "${fhr}" | $SED -n -r -e "s/^([0-9]+)$/\1/p" ) +if [ -z "$fhr" ]; then + print_err_msg_exit "\ +The forecast hour (fhr) must be a non-empty string consisting of only +digits: + fhr = \"${fhr}\"" +fi +if [ $(boolify "${SUB_HOURLY_POST}") != "TRUE" ]; then + export fmn="00" +fi +# +#----------------------------------------------------------------------- +# +# Call the ex-script for this J-job. +# +#----------------------------------------------------------------------- +# +export pgmout="${DATA}/OUTPUT.$$" +env + +${SCRIPTSsrw}/exsrw_post.sh +export err=$?; err_chk + +if [ -e "$pgmout" ]; then + cat $pgmout +fi +# +#----------------------------------------------------------------------- +# +# Create a flag file to make rocoto aware that the run_post task has +# successfully completed. This flag is necessary for varying forecast +# hours (FCST_LEN_HRS: -1) +# +#----------------------------------------------------------------------- +# +if [ ${#FCST_LEN_CYCL[@]} -gt 1 ]; then + cyc_mod=$(( ${cyc} - ${DATE_FIRST_CYCL:8:2} )) + CYCLE_IDX=$(( ${cyc_mod} / ${INCR_CYCL_FREQ} )) + FCST_LEN_HRS=${FCST_LEN_CYCL[$CYCLE_IDX]} + + if [ "${WORKFLOW_MANAGER}" = "rocoto" ]; then + fcst_len_hrs=$( printf "%03d" "${FCST_LEN_HRS}" ) + if [ "${fhr}" = "${fcst_len_hrs}" ]; then + touch "${DATAROOT}/DATA_SHARE/${PDY}${cyc}/post_${PDY}${cyc}_task_complete.txt" + fi + fi +fi +# +#----------------------------------------------------------------------- +# +# Whether or not working directory DATA should be kept. +# +#----------------------------------------------------------------------- +# +if [ "${KEEPDATA}" = "NO" ]; then + rm -rf ${DATA} +fi +date + diff --git a/jobs/JSRW_PREPSTART b/jobs/JSRW_PREPSTART index 4f8dcce7d4..772983d75e 100755 --- a/jobs/JSRW_PREPSTART +++ b/jobs/JSRW_PREPSTART @@ -30,7 +30,7 @@ export SCRIPTSsrw="${HOMEdir}/scripts" # export USHdir="${USHsrw}" # should be removed later . ${USHsrw}/source_util_funcs.sh -for sect in user nco platform workflow nco global smoke_dust_parm ; do +for sect in user nco platform workflow global smoke_dust_parm ; do source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} done # diff --git a/jobs/JSRW_SMOKE_DUST b/jobs/JSRW_SMOKE_DUST index 3eec0c2648..87fafc9caf 100755 --- a/jobs/JSRW_SMOKE_DUST +++ b/jobs/JSRW_SMOKE_DUST @@ -30,7 +30,7 @@ export SCRIPTSsrw="${HOMEdir}/scripts" # export USHdir="${USHsrw}" # should be removed later . ${USHsrw}/source_util_funcs.sh -for sect in user nco platform workflow nco global smoke_dust_parm ; do +for sect in user nco platform workflow global smoke_dust_parm ; do source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} done # diff --git a/parm/wflow/smoke_dust.yaml b/parm/wflow/smoke_dust.yaml index ca2c2b4e7f..58f55f1e51 100644 --- a/parm/wflow/smoke_dust.yaml +++ b/parm/wflow/smoke_dust.yaml @@ -19,6 +19,7 @@ default_smoke_dust_task: &default_smoke_dust nprocs: '{{ parent.nnodes * parent.ppn // 1 }}' subcyc: !cycstr "@M" SLASH_ENSMEM_SUBDIR: '&SLASH_ENSMEM_SUBDIR;' + ENSMEM_INDX: '#mem#' native: '{{ platform.SCHED_NATIVE_CMD }}' nnodes: 1 nodes: '{{ nnodes }}:ppn={{ ppn }}' @@ -65,11 +66,11 @@ task_smoke_dust: text: !cycstr '{{ workflow.EXPTDIR }}/task_skip_coldstart_@Y@m@d@H00.txt' datadep_date_tag_tracer: attrs: - age: 00:00:00:05 - text: '&COMIN_DIR;/RESTART/@Y@m@d.@H@M@S.fv_tracer.res.tile1.nc' + age: 00:00:05:00 + text: '&COMIN_DIR;/RESTART/@Y@m@d.@H0000.fv_tracer.res.tile1.nc' datadep_tracer: attrs: - age: 00:00:00:05 + age: 00:00:05:00 text: '&COMIN_DIR;/RESTART/fv_tracer.res.tile1.nc' task_prepstart: @@ -87,3 +88,26 @@ task_prepstart: attrs: task: smoke_dust +metatask_post: + var: + mem: '{% if global.DO_ENSEMBLE %}{%- for m in range(1, global.NUM_ENS_MEMBERS+1) -%}{{ "%03d "%m }}{%- endfor -%} {% else %}{{ "000"|string }}{% endif %}' + metatask_post_mem#mem#_all_fhrs: + var: + fhr: '{% for h in range(0, workflow.LONG_FCST_LEN+1) %}{{ " %03d" % h }}{% endfor %}' + cycledef: '{% for h in range(0, workflow.LONG_FCST_LEN+1) %}{% if h <= workflow.FCST_LEN_CYCL|min %}forecast {% else %}long_forecast {% endif %}{% endfor %}' + task_post_mem#mem#_f#fhr#: + <<: *default_smoke_dust + attrs: + cycledefs: '#cycledef#' + envars: + fhr: '#fhr#' + command: '&LOAD_MODULES_RUN_TASK; "post" "&HOMEdir;/jobs/JSRW_POST"' + join: !cycstr '&LOGDIR;/{{ jobname }}_@Y@m@d@H&LOGEXT;' + nnodes: 2 + ppn: 24 + memory: 120G + dependency: + taskdep: + attrs: + task: run_fcst_mem#mem# + diff --git a/scripts/exregional_run_fcst.sh b/scripts/exregional_run_fcst.sh index e2dc191e76..48b9a5ce29 100755 --- a/scripts/exregional_run_fcst.sh +++ b/scripts/exregional_run_fcst.sh @@ -394,6 +394,8 @@ fi if [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then ln -snf ${FIXsmoke}/${PREDEF_GRID_NAME}/dust12m_data.nc . ln -snf ${FIXsmoke}/${PREDEF_GRID_NAME}/emi_data.nc . + + COMIN="${COMROOT}/${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR}" #temporary path, should be removed later smokefile="${COMIN}/${SMOKE_DUST_FILE_PREFIX}_${PDY}${cyc}00.nc" if [ -f ${smokefile} ]; then ln -snf ${smokefile} ${SMOKE_DUST_FILE_PREFIX}.nc @@ -950,6 +952,29 @@ if [ $(boolify ${WRITE_DOPOST}) = "TRUE" ]; then done fi + +# +#----------------------------------------------------------------------- +# +# Copy RESTART directory and dyn/phy output files to COMOUT +# +#----------------------------------------------------------------------- +# +if [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then + COMOUT="${COMROOT}/${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR}" #temporary path + cp -Rp RESTART ${COMOUT} + fhr=0 + while [ $fhr -le ${FCST_LEN_HRS} ]; do + fhr_3d=$(printf "%03d" $fhr) + source_dyn="dynf${fhr_3d}.nc" + source_phy="phyf${fhr_3d}.nc" + target_dyn="${COMOUT}/${NET}.${cycle}${dot_ensmem}.dyn.f${fhr_3d}.nc" + target_phy="${COMOUT}/${NET}.${cycle}${dot_ensmem}.phy.f${fhr_3d}.nc" + [ -f ${source_dyn} ] && cp -p ${source_dyn} ${target_dyn} + [ -f ${source_phy} ] && cp -p ${source_phy} ${target_phy} + (( fhr=fhr+1 )) + done +fi # #----------------------------------------------------------------------- # diff --git a/scripts/exregional_run_post.sh b/scripts/exregional_run_post.sh index f7db102788..93d6804231 100755 --- a/scripts/exregional_run_post.sh +++ b/scripts/exregional_run_post.sh @@ -65,7 +65,7 @@ #----------------------------------------------------------------------- # . $USHdir/source_util_funcs.sh -for sect in user nco platform workflow global cpl_aqm_parm smoke_dust_parm \ +for sect in user nco platform workflow global cpl_aqm_parm \ task_run_fcst task_run_post ; do source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} done @@ -377,4 +377,3 @@ In directory: \"${scrfunc_dir}\" #----------------------------------------------------------------------- # { restore_shell_opts; } > /dev/null 2>&1 - diff --git a/scripts/exsrw_post.sh b/scripts/exsrw_post.sh new file mode 100755 index 0000000000..ec943375c4 --- /dev/null +++ b/scripts/exsrw_post.sh @@ -0,0 +1,330 @@ +#!/usr/bin/env bash + +# +#----------------------------------------------------------------------- +# +# Source the variable definitions file and the bash utility functions. +# +#----------------------------------------------------------------------- +# +. ${USHsrw}/source_util_funcs.sh +for sect in user nco platform workflow global cpl_aqm_parm smoke_dust_parm \ + task_run_fcst task_run_post ; do + source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} +done +# +#----------------------------------------------------------------------- +# +# Save current shell options (in a global array). Then set new options +# for this script/function. +# +#----------------------------------------------------------------------- +# +{ save_shell_opts; set -xue; } > /dev/null 2>&1 +# +#----------------------------------------------------------------------- +# +# Get the full path to the file in which this script/function is located +# (scrfunc_fp), the name of that file (scrfunc_fn), and the directory in +# which the file is located (scrfunc_dir). +# +#----------------------------------------------------------------------- +# +scrfunc_fp=$( $READLINK -f "${BASH_SOURCE[0]}" ) +scrfunc_fn=$( basename "${scrfunc_fp}" ) +scrfunc_dir=$( dirname "${scrfunc_fp}" ) +# +#----------------------------------------------------------------------- +# +# Print message indicating entry into script. +# +#----------------------------------------------------------------------- +# +print_info_msg " +======================================================================== +Entering script: \"${scrfunc_fn}\" +In directory: \"${scrfunc_dir}\" + +This is the ex-script for the task that runs Smoke and Dust. +========================================================================" +# +#----------------------------------------------------------------------- +# +# Set OpenMP variables. +# +#----------------------------------------------------------------------- +# +export KMP_AFFINITY=${KMP_AFFINITY_RUN_POST} +export OMP_NUM_THREADS=${OMP_NUM_THREADS_RUN_POST} +export OMP_STACKSIZE=${OMP_STACKSIZE_RUN_POST} +# +#----------------------------------------------------------------------- +# +# Load modules. +# +#----------------------------------------------------------------------- +# +eval ${PRE_TASK_CMDS} + +if [ -z "${RUN_CMD_POST:-}" ] ; then + print_err_msg_exit "\ + Run command was not set in machine file. \ + Please set RUN_CMD_POST for your platform" +else + print_info_msg "$VERBOSE" " + All executables will be submitted with command \'${RUN_CMD_POST}\'." +fi +# +#----------------------------------------------------------------------- +# +# Stage necessary files in the working directory. +# +#----------------------------------------------------------------------- +# +cp ${PARMsrw}/upp/nam_micro_lookup.dat ./eta_micro_lookup.dat +if [ $(boolify ${USE_CUSTOM_POST_CONFIG_FILE}) = "TRUE" ]; then + post_config_fp="${CUSTOM_POST_CONFIG_FP}" + print_info_msg " +==================================================================== +Copying the user-defined file specified by CUSTOM_POST_CONFIG_FP: + CUSTOM_POST_CONFIG_FP = \"${CUSTOM_POST_CONFIG_FP}\" +====================================================================" +else + if [ $(boolify "${CPL_AQM}") = "TRUE" ]; then + post_config_fp="${PARMsrw}/upp/postxconfig-NT-AQM.txt" + else + post_config_fp="${PARMsrw}/upp/postxconfig-NT-rrfs.txt" + fi + print_info_msg " +==================================================================== +Copying the default post flat file specified by post_config_fp: + post_config_fp = \"${post_config_fp}\" +====================================================================" +fi +cp ${post_config_fp} ./postxconfig-NT.txt +cp ${PARMsrw}/upp/params_grib2_tbl_new . + +if [ $(boolify ${DO_SMOKE_DUST}) = "TRUE" ] || [ $(boolify ${USE_CRTM}) = "TRUE" ]; then + cp ${FIXcrtm}/Nalli.IRwater.EmisCoeff.bin . + cp ${FIXcrtm}/FAST*.bin . + cp ${FIXcrtm}/NPOESS.IRland.EmisCoeff.bin . + cp ${FIXcrtm}/NPOESS.IRsnow.EmisCoeff.bin . + cp ${FIXcrtm}/NPOESS.IRice.EmisCoeff.bin . + cp ${FIXcrtm}/AerosolCoeff.bin . + cp ${FIXcrtm}/CloudCoeff.bin . + cp ${FIXcrtm}/*.SpcCoeff.bin . + cp ${FIXcrtm}/*.TauCoeff.bin . + print_info_msg " +==================================================================== +Copying the CRTM fix files from FIXcrtm: + FIXcrtm = \"${FIXcrtm}\" +====================================================================" +fi + +# +#----------------------------------------------------------------------- +# +# Get the cycle date and hour (in formats of yyyymmdd and hh, respectively) +# from CDATE. +# +#----------------------------------------------------------------------- +# +yyyymmdd=${PDY} +hh=${cyc} +# +#----------------------------------------------------------------------- +# +# Create the namelist file (itag) containing arguments to pass to the post- +# processor's executable. +# +#----------------------------------------------------------------------- +# +# Set the variable (mnts_secs_str) that determines the suffix in the names +# of the forecast model's write-component output files that specifies the +# minutes and seconds of the corresponding output forecast time. +# +# Note that if the forecast model is instructed to output at some hourly +# interval (via the output_fh parameter in the MODEL_CONFIG_FN file, +# with nsout set to a non-positive value), then the write-component +# output file names will not contain any suffix for the minutes and seconds. +# For this reason, when SUB_HOURLY_POST is not set to "TRUE", mnts_sec_str +# must be set to a null string. +# +mnts_secs_str="" +if [ $(boolify "${SUB_HOURLY_POST}") = "TRUE" ]; then + if [ ${fhr}${fmn} = "00000" ]; then + mnts_secs_str=":"$( $DATE_UTIL --utc --date "${yyyymmdd} ${hh} UTC + ${DT_ATMOS} seconds" "+%M:%S" ) + else + mnts_secs_str=":${fmn}:00" + fi +fi +# +# Set namelist of upp. +# +if [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then + dyn_file="${COMIN}/${NET}.${cycle}${dot_ensmem}.dyn.f${fhr}.nc" + phy_file="${COMIN}/${NET}.${cycle}${dot_ensmem}.phy.f${fhr}.nc" +else + dyn_file="${COMIN}/dynf${fhr}${mnts_secs_str}.nc" + phy_file="${COMIN}/phyf${fhr}${mnts_secs_str}.nc" +fi + +post_time=$( $DATE_UTIL --utc --date "${yyyymmdd} ${hh} UTC + ${fhr} hours + ${fmn} minutes" "+%Y%m%d%H%M" ) +post_yyyy=${post_time:0:4} +post_mm=${post_time:4:2} +post_dd=${post_time:6:2} +post_hh=${post_time:8:2} +post_mn=${post_time:10:2} + +if [ $(boolify "${CPL_AQM}") = "TRUE" ] && [ $(bookify "${DO_SMOKE_DUST}") = "FALSE" ]; then + post_itag_add="aqf_on=.true.," +elif [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then + post_itag_add="slrutah_on=.true.,gtg_on=.true." +else + post_itag_add="" +fi +cat > itag <>$pgmout 2>errfile +export err=$?; err_chk +if [ $err -ne 0 ]; then + message_txt="upp.x failed with return code $err" + err_exit "${message_txt}" + print_err_msg_exit "${message_txt}" +fi +# +#----------------------------------------------------------------------- +# +# A separate ${post_fhr} forecast hour variable is required for the post +# files, since they may or may not be three digits long, depending on the +# length of the forecast. +# +# A separate ${subh_fhr} is needed for subhour post. +#----------------------------------------------------------------------- +# +# get the length of the fhr string to decide format of forecast time stamp. +# 9 is sub-houry forecast and 3 is full hour forecast only. +len_fhr=${#fhr} +if [ ${len_fhr} -eq 9 ]; then + post_min=${fhr:4:2} + if [ ${post_min} -lt ${nsout_min} ]; then + post_min=00 + fi +else + post_min=00 +fi + +subh_fhr=${fhr} +if [ ${len_fhr} -eq 2 ]; then + post_fhr=${fhr} +elif [ ${len_fhr} -eq 3 ]; then + if [ "${fhr:0:1}" = "0" ]; then + post_fhr="${fhr:1}" + else + post_fhr=${fhr} + fi +elif [ ${len_fhr} -eq 9 ]; then + if [ "${fhr:0:1}" = "0" ]; then + if [ ${post_min} -eq 00 ]; then + post_fhr="${fhr:1:2}" + subh_fhr="${fhr:0:3}" + else + post_fhr="${fhr:1:2}.${fhr:4:2}" + fi + else + if [ ${post_min} -eq 00 ]; then + post_fhr="${fhr:0:3}" + subh_fhr="${fhr:0:3}" + else + post_fhr="${fhr:0:3}.${fhr:4:2}" + fi + fi +else + err_exit "\ +The \${fhr} variable contains too few or too many characters: + fhr = \"$fhr\"" +fi + +# replace fhr with subh_fhr +echo "fhr=${fhr} and subh_fhr=${subh_fhr}" +fhr=${subh_fhr} + +bgdawp=${NET}.${cycle}.prslev.f${fhr}.${POST_OUTPUT_DOMAIN_NAME}.grib2 +bgrd3d=${NET}.${cycle}.natlev.f${fhr}.${POST_OUTPUT_DOMAIN_NAME}.grib2 +bgifi=${NET}.${cycle}.ififip.f${fhr}.${POST_OUTPUT_DOMAIN_NAME}.grib2 +bgavi=${NET}.${cycle}.aviati.f${fhr}.${POST_OUTPUT_DOMAIN_NAME}.grib2 + +if [ -f "PRSLEV.GrbF${post_fhr}" ]; then + wgrib2 PRSLEV.GrbF${post_fhr} -set center 7 -grib ${bgdawp} >>$pgmout 2>>errfile +fi +if [ -f "NATLEV.GrbF${post_fhr}" ]; then + wgrib2 NATLEV.GrbF${post_fhr} -set center 7 -grib ${bgrd3d} >>$pgmout 2>>errfile +fi +if [ -f "IFIFIP.GrbF${post_fhr}" ]; then + wgrib2 IFIFIP.GrbF${post_fhr} -set center 7 -grib ${bgifi} >>$pgmout 2>>errfile +fi +if [ -f "AVIATI.GrbF${post_fhr}" ]; then + wgrib2 AVIATI.GrbF${post_fhr} -set center 7 -grib ${bgavi} >>$pgmout 2>>errfile +fi + +cp -p ${bgdawp} ${COMOUT} +cp -p ${bgrd3d} ${COMOUT} +cp -p ${bgifi} ${COMOUT} +cp -p ${bgavi} ${COMOUT} +# +#----------------------------------------------------------------------- +# +# Print message indicating successful completion of script. +# +#----------------------------------------------------------------------- +# +print_info_msg " +======================================================================== +UPP post-processing has successfully generated output files !!!! + +Exiting script: \"${scrfunc_fn}\" +In directory: \"${scrfunc_dir}\" +========================================================================" +# +#----------------------------------------------------------------------- +# +{ restore_shell_opts; } > /dev/null 2>&1 diff --git a/scripts/exsrw_prepstart.sh b/scripts/exsrw_prepstart.sh index 0e7765b8e4..a46ee8cf18 100755 --- a/scripts/exsrw_prepstart.sh +++ b/scripts/exsrw_prepstart.sh @@ -8,7 +8,7 @@ #----------------------------------------------------------------------- # . ${USHsrw}/source_util_funcs.sh -for sect in user nco platform workflow nco global smoke_dust_parm \ +for sect in user nco platform workflow global smoke_dust_parm \ constants fixed_files grid_params task_run_fcst ; do source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} done diff --git a/scripts/exsrw_smoke_dust.sh b/scripts/exsrw_smoke_dust.sh index 5e66fe8ee1..9a7a12b72c 100755 --- a/scripts/exsrw_smoke_dust.sh +++ b/scripts/exsrw_smoke_dust.sh @@ -8,7 +8,7 @@ #----------------------------------------------------------------------- # . ${USHsrw}/source_util_funcs.sh -for sect in user nco platform workflow nco global smoke_dust_parm \ +for sect in user nco platform workflow global smoke_dust_parm \ constants fixed_files grid_params task_run_fcst ; do source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} done diff --git a/ush/config.smoke_dust.yaml b/ush/config.smoke_dust.yaml index 289e680f3f..582d908e2c 100644 --- a/ush/config.smoke_dust.yaml +++ b/ush/config.smoke_dust.yaml @@ -31,7 +31,7 @@ nco: RUN_default: smoke_dust rocoto: tasks: - taskgroups: '{{ ["parm/wflow/prep.yaml", "parm/wflow/smoke_dust.yaml", "parm/wflow/coldstart.yaml", "parm/wflow/post.yaml"]|include }}' + taskgroups: '{{ ["parm/wflow/prep.yaml", "parm/wflow/smoke_dust.yaml", "parm/wflow/coldstart.yaml"]|include }}' metatask_run_ensemble: task_run_fcst_mem#mem#: walltime: 02:00:00 diff --git a/ush/config_defaults.yaml b/ush/config_defaults.yaml index 47b98f68e3..d1924ae896 100644 --- a/ush/config_defaults.yaml +++ b/ush/config_defaults.yaml @@ -432,8 +432,8 @@ platform: # FIXcrtm: # System directory where CRTM fixed files are located # - # FIXcrtmupp: - # System directory where CRTM fixed files specifically for UPP are located + # FIXupp: + # System directory where UPP fixed files are located # #----------------------------------------------------------------------- # @@ -446,8 +446,8 @@ platform: FIXaqm: "" FIXemis: "" FIXsmoke: "" + FIXupp: "" FIXcrtm: "" - FIXcrtmupp: "" # #----------------------------------------------------------------------- # diff --git a/ush/machine/hera.yaml b/ush/machine/hera.yaml index e6f8ce6e8d..ca031f02f8 100644 --- a/ush/machine/hera.yaml +++ b/ush/machine/hera.yaml @@ -38,6 +38,8 @@ platform: FIXaqm: /scratch2/NAGAPE/epic/SRW-AQM_DATA/fix_aqm FIXemis: /scratch1/RDARCH/rda-arl-gpu/Barry.Baker/emissions/nexus FIXsmoke: /scratch2/NAGAPE/epic/SRW-AQM_DATA/fix_smoke + FIXupp: /scratch2/NAGAPE/epic/SRW-AQM_DATA/fix_upp + FIXcrtm: /scratch2/NAGAPE/epic/SRW-AQM_DATA/fix_crtm EXTRN_MDL_DATA_STORES: hpss aws nomads cpl_aqm_parm: From 50083a645c5bf18c2755ba2f5afa859e6906b458 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Sat, 24 Aug 2024 22:38:01 +0000 Subject: [PATCH 31/61] change output file name --- parm/wflow/smoke_dust.yaml | 2 +- scripts/exregional_run_fcst.sh | 4 ++-- scripts/exregional_run_post.sh | 1 + scripts/exsrw_post.sh | 4 ++-- ush/config.smoke_dust.yaml | 2 +- 5 files changed, 7 insertions(+), 6 deletions(-) diff --git a/parm/wflow/smoke_dust.yaml b/parm/wflow/smoke_dust.yaml index 58f55f1e51..e26ed3ea08 100644 --- a/parm/wflow/smoke_dust.yaml +++ b/parm/wflow/smoke_dust.yaml @@ -105,7 +105,7 @@ metatask_post: join: !cycstr '&LOGDIR;/{{ jobname }}_@Y@m@d@H&LOGEXT;' nnodes: 2 ppn: 24 - memory: 120G + memory: 64G dependency: taskdep: attrs: diff --git a/scripts/exregional_run_fcst.sh b/scripts/exregional_run_fcst.sh index 48b9a5ce29..9f18aa4be3 100755 --- a/scripts/exregional_run_fcst.sh +++ b/scripts/exregional_run_fcst.sh @@ -968,8 +968,8 @@ if [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then fhr_3d=$(printf "%03d" $fhr) source_dyn="dynf${fhr_3d}.nc" source_phy="phyf${fhr_3d}.nc" - target_dyn="${COMOUT}/${NET}.${cycle}${dot_ensmem}.dyn.f${fhr_3d}.nc" - target_phy="${COMOUT}/${NET}.${cycle}${dot_ensmem}.phy.f${fhr_3d}.nc" + target_dyn="${COMOUT}/${NET}.${cycle}${dot_ensmem}.dyn.f${fhr_3d}.${POST_OUTPUT_DOMAIN_NAME}.nc" + target_phy="${COMOUT}/${NET}.${cycle}${dot_ensmem}.phy.f${fhr_3d}.${POST_OUTPUT_DOMAIN_NAME}.nc" [ -f ${source_dyn} ] && cp -p ${source_dyn} ${target_dyn} [ -f ${source_phy} ] && cp -p ${source_phy} ${target_phy} (( fhr=fhr+1 )) diff --git a/scripts/exregional_run_post.sh b/scripts/exregional_run_post.sh index 93d6804231..3f0ca93df9 100755 --- a/scripts/exregional_run_post.sh +++ b/scripts/exregional_run_post.sh @@ -377,3 +377,4 @@ In directory: \"${scrfunc_dir}\" #----------------------------------------------------------------------- # { restore_shell_opts; } > /dev/null 2>&1 + diff --git a/scripts/exsrw_post.sh b/scripts/exsrw_post.sh index ec943375c4..dc138b0b1f 100755 --- a/scripts/exsrw_post.sh +++ b/scripts/exsrw_post.sh @@ -162,8 +162,8 @@ fi # Set namelist of upp. # if [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then - dyn_file="${COMIN}/${NET}.${cycle}${dot_ensmem}.dyn.f${fhr}.nc" - phy_file="${COMIN}/${NET}.${cycle}${dot_ensmem}.phy.f${fhr}.nc" + dyn_file="${COMIN}/${NET}.${cycle}${dot_ensmem}.dyn.f${fhr}.${POST_OUTPUT_DOMAIN_NAME}.nc" + phy_file="${COMIN}/${NET}.${cycle}${dot_ensmem}.phy.f${fhr}.${POST_OUTPUT_DOMAIN_NAME}.nc" else dyn_file="${COMIN}/dynf${fhr}${mnts_secs_str}.nc" phy_file="${COMIN}/phyf${fhr}${mnts_secs_str}.nc" diff --git a/ush/config.smoke_dust.yaml b/ush/config.smoke_dust.yaml index 582d908e2c..5f73628fef 100644 --- a/ush/config.smoke_dust.yaml +++ b/ush/config.smoke_dust.yaml @@ -31,7 +31,7 @@ nco: RUN_default: smoke_dust rocoto: tasks: - taskgroups: '{{ ["parm/wflow/prep.yaml", "parm/wflow/smoke_dust.yaml", "parm/wflow/coldstart.yaml"]|include }}' + taskgroups: '{{ ["parm/wflow/prep.yaml", "parm/wflow/coldstart.yaml", "parm/wflow/smoke_dust.yaml"]|include }}' metatask_run_ensemble: task_run_fcst_mem#mem#: walltime: 02:00:00 From 2e5f440283faf34cacad6bd6a4f997a03cacb294 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Sun, 25 Aug 2024 01:46:01 +0000 Subject: [PATCH 32/61] fix post xml issue --- parm/wflow/smoke_dust.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/parm/wflow/smoke_dust.yaml b/parm/wflow/smoke_dust.yaml index e26ed3ea08..e51807ac86 100644 --- a/parm/wflow/smoke_dust.yaml +++ b/parm/wflow/smoke_dust.yaml @@ -99,7 +99,9 @@ metatask_post: <<: *default_smoke_dust attrs: cycledefs: '#cycledef#' + maxtries: '2' envars: + <<: *default_vars fhr: '#fhr#' command: '&LOAD_MODULES_RUN_TASK; "post" "&HOMEdir;/jobs/JSRW_POST"' join: !cycstr '&LOGDIR;/{{ jobname }}_@Y@m@d@H&LOGEXT;' From 40a10c92cc1c7a9fd495a84e2dc3b7f2648698e5 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Sun, 25 Aug 2024 02:15:57 +0000 Subject: [PATCH 33/61] change cp to ln --- scripts/exsrw_post.sh | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/scripts/exsrw_post.sh b/scripts/exsrw_post.sh index dc138b0b1f..f43d21fe11 100755 --- a/scripts/exsrw_post.sh +++ b/scripts/exsrw_post.sh @@ -105,15 +105,15 @@ cp ${post_config_fp} ./postxconfig-NT.txt cp ${PARMsrw}/upp/params_grib2_tbl_new . if [ $(boolify ${DO_SMOKE_DUST}) = "TRUE" ] || [ $(boolify ${USE_CRTM}) = "TRUE" ]; then - cp ${FIXcrtm}/Nalli.IRwater.EmisCoeff.bin . - cp ${FIXcrtm}/FAST*.bin . - cp ${FIXcrtm}/NPOESS.IRland.EmisCoeff.bin . - cp ${FIXcrtm}/NPOESS.IRsnow.EmisCoeff.bin . - cp ${FIXcrtm}/NPOESS.IRice.EmisCoeff.bin . - cp ${FIXcrtm}/AerosolCoeff.bin . - cp ${FIXcrtm}/CloudCoeff.bin . - cp ${FIXcrtm}/*.SpcCoeff.bin . - cp ${FIXcrtm}/*.TauCoeff.bin . + ln -nsf ${FIXcrtm}/Nalli.IRwater.EmisCoeff.bin . + ln -nsf ${FIXcrtm}/FAST*.bin . + ln -nsf ${FIXcrtm}/NPOESS.IRland.EmisCoeff.bin . + ln -nsf ${FIXcrtm}/NPOESS.IRsnow.EmisCoeff.bin . + ln -nsf ${FIXcrtm}/NPOESS.IRice.EmisCoeff.bin . + ln -nsf ${FIXcrtm}/AerosolCoeff.bin . + ln -nsf ${FIXcrtm}/CloudCoeff.bin . + ln -nsf ${FIXcrtm}/*.SpcCoeff.bin . + ln -nsf ${FIXcrtm}/*.TauCoeff.bin . print_info_msg " ==================================================================== Copying the CRTM fix files from FIXcrtm: From cb6e67c19b0169e0c2e13f7838e5b8e669cf38af Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Sun, 25 Aug 2024 02:28:59 +0000 Subject: [PATCH 34/61] parameterize ebb_dcycle --- parm/FV3.input.yml | 1 - ush/generate_FV3LAM_wflow.py | 5 +++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/parm/FV3.input.yml b/parm/FV3.input.yml index d0e0db09ce..b157b19009 100644 --- a/parm/FV3.input.yml +++ b/parm/FV3.input.yml @@ -171,7 +171,6 @@ FV3_HRRR_gf: dust_gamma: 1.3 dust_moist_correction: 2.0 dust_opt: 1 - ebb_dcycle: 1 effr_in: true enh_mix : false fhcyc: 0.0 diff --git a/ush/generate_FV3LAM_wflow.py b/ush/generate_FV3LAM_wflow.py index c671a69da8..fa214f93b4 100755 --- a/ush/generate_FV3LAM_wflow.py +++ b/ush/generate_FV3LAM_wflow.py @@ -418,6 +418,11 @@ def generate_FV3LAM_wflow( "print_diff_pgr": PRINT_DIFF_PGR, }) + if DO_SMOKE_DUST: + gfs_physics_nml_dict.update({ + "ebb_dcycle": EBB_DCYCLE, + }) + if CPL_AQM: gfs_physics_nml_dict.update({ "cplaqm": True, From 9f46fac2d2cced02e8d22932eac20e97fb88e09b Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Sun, 25 Aug 2024 19:02:59 +0000 Subject: [PATCH 35/61] add link to restart dir --- jobs/JSRW_SMOKE_DUST | 2 +- scripts/exsrw_smoke_dust.sh | 9 ++++++--- ush/generate_fire_emissions.py | 2 +- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/jobs/JSRW_SMOKE_DUST b/jobs/JSRW_SMOKE_DUST index 87fafc9caf..4341fda03c 100755 --- a/jobs/JSRW_SMOKE_DUST +++ b/jobs/JSRW_SMOKE_DUST @@ -106,7 +106,7 @@ if [ "${MACHINE}" = "WCOSS2" ]; then export COMIN="${COMIN:-$(compath.py -o ${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR})}" export COMOUT="${COMOUT:-$(compath.py -o ${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR})}" else - export COMIN="${COMIN:-${COMROOT}/${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR}}" + export COMIN="${COMIN:-${COMROOT}/${NET}/${model_ver}}" export COMOUT="${COMOUT:-${COMROOT}/${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR}}" fi diff --git a/scripts/exsrw_smoke_dust.sh b/scripts/exsrw_smoke_dust.sh index 9a7a12b72c..cc691ccb06 100755 --- a/scripts/exsrw_smoke_dust.sh +++ b/scripts/exsrw_smoke_dust.sh @@ -54,10 +54,13 @@ else # export CDATE="${PDY}${cyc}" # - # Create sub-directory for HOURLY_HWP and link restart files + # Link restart directory of the previous cycle in COMIN/COMOUT # - mkdir -p ${DATA}/HOURLY_HWP - + CDATEprev=$($NDATE -${INCR_CYCL_FREQ} ${PDY}${cyc}) + PDYprev=${CDATEprev:0:8} + cycprev=${CDATEprev:8:2} + path_restart=${COMIN}/${RUN}.${PDYprev}/${cycprev}${SLASH_ENSMEM_SUBDIR}/RESTART + ln -nsf ${path_restart} . # # Check if the fire file exists in the designated directory # diff --git a/ush/generate_fire_emissions.py b/ush/generate_fire_emissions.py index 7d3c7eb3f7..d5634c671c 100755 --- a/ush/generate_fire_emissions.py +++ b/ush/generate_fire_emissions.py @@ -59,7 +59,7 @@ def generate_emiss_workflow(staticdir, ravedir, intp_dir, predef_grid, ebb_dcycl grid_in = staticdir+'/grid_in.nc' weightfile = staticdir+'/weight_file.nc' grid_out = staticdir+'/ds_out_base.nc' - hourly_hwpdir = os.path.join(nwges_dir,'HOURLY_HWP') + hourly_hwpdir = os.path.join(nwges_dir,'RESTART') # ---------------------------------------------------------------------- # Workflow From b98d4be62949d14ca8a33eab165ab650d37ba8c6 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Sun, 25 Aug 2024 19:21:33 +0000 Subject: [PATCH 36/61] change restart link command loc --- scripts/exsrw_smoke_dust.sh | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/scripts/exsrw_smoke_dust.sh b/scripts/exsrw_smoke_dust.sh index cc691ccb06..b33ef6c6b5 100755 --- a/scripts/exsrw_smoke_dust.sh +++ b/scripts/exsrw_smoke_dust.sh @@ -52,15 +52,9 @@ if [ $(boolify "${COLDSTART}") = "TRUE" ] && [ "${PDY}${cyc}" = "${DATE_FIRST_CY echo "This step is skipped for the first cycle of COLDSTART." else # - export CDATE="${PDY}${cyc}" - # - # Link restart directory of the previous cycle in COMIN/COMOUT + # Set CDATE used in the fire emission generation python script # - CDATEprev=$($NDATE -${INCR_CYCL_FREQ} ${PDY}${cyc}) - PDYprev=${CDATEprev:0:8} - cycprev=${CDATEprev:8:2} - path_restart=${COMIN}/${RUN}.${PDYprev}/${cycprev}${SLASH_ENSMEM_SUBDIR}/RESTART - ln -nsf ${path_restart} . + export CDATE="${PDY}${cyc}" # # Check if the fire file exists in the designated directory # @@ -68,6 +62,15 @@ else if [ -e "${COMINsmoke}/${smokeFile}" ]; then cp -p "${COMINsmoke}/${smokeFile}" ${COMOUT} else + # + # Link restart directory of the previous cycle in COMIN/COMOUT + # + CDATEprev=$($NDATE -${INCR_CYCL_FREQ} ${PDY}${cyc}) + PDYprev=${CDATEprev:0:8} + cycprev=${CDATEprev:8:2} + path_restart=${COMIN}/${RUN}.${PDYprev}/${cycprev}${SLASH_ENSMEM_SUBDIR}/RESTART + ln -nsf ${path_restart} . + # Check whether the RAVE files need to be split into hourly files if [ "${EBB_DCYCLE}" -eq 1 ]; then ddhh_to_use="${PDY}${cyc}" From 3676a4b95a9a61af722d0a74ea5e49b626a73198 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Mon, 26 Aug 2024 21:54:50 +0000 Subject: [PATCH 37/61] add separate forecast script to meet nco standard --- jobs/JSRW_FORECAST | 187 ++++++ jobs/JSRW_PREPSTART | 4 + parm/wflow/coldstart.yaml | 2 +- scripts/exregional_make_ics.sh | 4 +- scripts/exregional_make_lbcs.sh | 5 +- scripts/exregional_run_fcst.sh | 115 ++-- scripts/exsrw_aqm_lbcs.sh | 2 +- scripts/exsrw_forecast.sh | 786 ++++++++++++++++++++++++++ scripts/exsrw_nexus_emission.sh | 2 +- scripts/exsrw_prepstart.sh | 9 + ush/add_smoke.py | 4 +- ush/create_aqm_rc_file.py | 0 ush/create_diag_table_file.py | 0 ush/create_model_configure_file.py | 0 ush/create_ufs_configure_file.py | 0 ush/get_crontab_contents.py | 0 ush/mrms_pull_topofhour.py | 0 ush/set_cycle_dates.py | 0 ush/set_fv3nml_ens_stoch_seeds.py | 0 ush/set_fv3nml_sfc_climo_filenames.py | 0 ush/set_gridparams_ESGgrid.py | 0 ush/set_gridparams_GFDLgrid.py | 0 ush/set_predef_grid_params.py | 0 ush/setup.py | 0 ush/update_input_nml.py | 0 25 files changed, 1040 insertions(+), 80 deletions(-) create mode 100755 jobs/JSRW_FORECAST create mode 100755 scripts/exsrw_forecast.sh mode change 100644 => 100755 ush/create_aqm_rc_file.py mode change 100644 => 100755 ush/create_diag_table_file.py mode change 100644 => 100755 ush/create_model_configure_file.py mode change 100644 => 100755 ush/create_ufs_configure_file.py mode change 100644 => 100755 ush/get_crontab_contents.py mode change 100644 => 100755 ush/mrms_pull_topofhour.py mode change 100644 => 100755 ush/set_cycle_dates.py mode change 100644 => 100755 ush/set_fv3nml_ens_stoch_seeds.py mode change 100644 => 100755 ush/set_fv3nml_sfc_climo_filenames.py mode change 100644 => 100755 ush/set_gridparams_ESGgrid.py mode change 100644 => 100755 ush/set_gridparams_GFDLgrid.py mode change 100644 => 100755 ush/set_predef_grid_params.py mode change 100644 => 100755 ush/setup.py mode change 100644 => 100755 ush/update_input_nml.py diff --git a/jobs/JSRW_FORECAST b/jobs/JSRW_FORECAST new file mode 100755 index 0000000000..64cff6e7c2 --- /dev/null +++ b/jobs/JSRW_FORECAST @@ -0,0 +1,187 @@ +#!/usr/bin/env bash + +# +#----------------------------------------------------------------------- +# +# The J-Job that runs the forecast +# +#----------------------------------------------------------------------- +# +date +export PS4='+ $SECONDS + ' +set -xue +# +#----------------------------------------------------------------------- +# +# Set the NCO standard environment variables (Table 1, pp.4) +# +#----------------------------------------------------------------------- +# +export USHsrw="${HOMEdir}/ush" +export EXECsrw="${HOMEdir}/exec" +export PARMsrw="${HOMEdir}/parm" +export SCRIPTSsrw="${HOMEdir}/scripts" +# +#----------------------------------------------------------------------- +# +# Source the variable definitions file and the bash utility functions. +# +#----------------------------------------------------------------------- +# +export USHdir="${USHsrw}" # should be removed later +. ${USHsrw}/source_util_funcs.sh +# +#----------------------------------------------------------------------- +# +# Run-time environment variables: +# +# CDATE +# COMIN +# DATA +# GLOBAL_VAR_DEFNS_FP +# SLASH_ENSMEM_SUBDIR +# +# Experiment variables +# +# user: +# SCRIPTSdir +# USHdir +# +#----------------------------------------------------------------------- +# +for sect in user nco platform workflow global ; do + source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} +done +# +#----------------------------------------------------------------------- +# +# Get the full path to the file in which this script/function is located +# (scrfunc_fp), the name of that file (scrfunc_fn), and the directory in +# which the file is located (scrfunc_dir). +# +#----------------------------------------------------------------------- +# +scrfunc_fp=$( $READLINK -f "${BASH_SOURCE[0]}" ) +scrfunc_fn=$( basename "${scrfunc_fp}" ) +scrfunc_dir=$( dirname "${scrfunc_fp}" ) +# +#----------------------------------------------------------------------- +# +# Print message indicating entry into script. +# +#----------------------------------------------------------------------- +# +print_info_msg " +======================================================================== +Entering script: \"${scrfunc_fn}\" +In directory: \"${scrfunc_dir}\" + +This is the J-job script for the task that runs a forecast with FV3 for +the specified cycle. +========================================================================" +# +#----------------------------------------------------------------------- +# +# Define job and jobid by default for rocoto +# +#----------------------------------------------------------------------- +# +WORKFLOW_MANAGER="${WORKFLOW_MANAGER:-rocoto}" +if [ "${WORKFLOW_MANAGER}" = "rocoto" ]; then + if [ "${SCHED}" = "slurm" ]; then + job=${SLURM_JOB_NAME} + pid=${SLURM_JOB_ID} + elif [ "${SCHED}" = "pbspro" ]; then + job=${PBS_JOBNAME} + pid=${PBS_JOBID} + else + job="task" + pid=$$ + fi + jobid="${job}.${PDY}${cyc}.${pid}" +fi +# +#----------------------------------------------------------------------- +# +# Create a temp working directory (DATA) and cd into it. +# +#----------------------------------------------------------------------- +# +export DATA="${DATA:-${DATAROOT}/${jobid}}" +mkdir -p $DATA +cd $DATA +# +#----------------------------------------------------------------------- +# +# Define NCO environment variables and set COM type definitions. +# +#----------------------------------------------------------------------- +# +export NET="${NET:-${NET_default}}" +export RUN="${RUN:-${RUN_default}}" + +[[ "$WORKFLOW_MANAGER" = "rocoto" ]] && export COMROOT=$COMROOT +if [ "${MACHINE}" = "WCOSS2" ]; then + export COMIN="${COMIN:-$(compath.py -o ${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR})}" + export COMOUT="${COMOUT:-$(compath.py -o ${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR})}" +else + export COMIN="${COMIN:-${COMROOT}/${NET}/${model_ver}}" + export COMOUT="${COMOUT:-${COMROOT}/${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR}}" +fi + +mkdir -p ${COMOUT} + +export COMINsmoke="${COMINsmoke:-${COMINsmoke_default}}" +export COMINfire="${COMINfire:-${COMINfire_default}}" + +# Create a teomporary share directory for RAVE interpolated data files +export DATA_SHARE="${DATA_SHARE:-${DATAROOT}/DATA_SHARE/RAVE_fire_intp}" +mkdir -p ${DATA_SHARE} + +# Run setpdy to initialize PDYm and PDYp variables +export cycle="${cycle:-t${cyc}z}" +setpdy.sh +. ./PDY +# +#----------------------------------------------------------------------- +# +# Set sub-cycle and ensemble member names in file/diectory names +# +#----------------------------------------------------------------------- +# +if [ ${subcyc} -ne 0 ]; then + export cycle="t${cyc}${subcyc}z" +fi +if [ $(boolify "${DO_ENSEMBLE}") = "TRUE" ] && [ ! -z ${ENSMEM_INDX} ]; then + export dot_ensmem=".mem${ENSMEM_INDX}" +else + export dot_ensmem= +fi +# +#----------------------------------------------------------------------- +# +# Call the ex-script for this J-job. +# +#----------------------------------------------------------------------- +# +export pgmout="${DATA}/OUTPUT.$$" +env + +${SCRIPTSsrw}/exsrw_forecast.sh +export err=$?; err_chk + +if [ -e "$pgmout" ]; then + cat $pgmout +fi +# +#----------------------------------------------------------------------- +# +# Whether or not working directory DATA should be kept. +# +#----------------------------------------------------------------------- +# +if [ "${KEEPDATA}" = "NO" ]; then + rm -rf ${DATA} +fi +date + diff --git a/jobs/JSRW_PREPSTART b/jobs/JSRW_PREPSTART index 772983d75e..30b961513d 100755 --- a/jobs/JSRW_PREPSTART +++ b/jobs/JSRW_PREPSTART @@ -112,6 +112,10 @@ fi mkdir -p ${COMOUT} +# Create a teomporary share directory +export DATA_SHARE="${DATA_SHARE:-${DATAROOT}/DATA_SHARE/${PDY}${cyc}}" +mkdir -p ${DATA_SHARE} + # Run setpdy to initialize PDYm and PDYp variables export cycle="${cycle:-t${cyc}z}" setpdy.sh diff --git a/parm/wflow/coldstart.yaml b/parm/wflow/coldstart.yaml index 6ac09066a5..60efb4aa2a 100644 --- a/parm/wflow/coldstart.yaml +++ b/parm/wflow/coldstart.yaml @@ -142,7 +142,7 @@ metatask_run_ensemble: task_run_fcst_mem#mem#: <<: *default_task - command: '&LOAD_MODULES_RUN_TASK; "run_fcst" "&JOBSdir;/JREGIONAL_RUN_FCST"' + command: '{% if smoke_dust_parm.get("DO_SMOKE_DUST") %}&LOAD_MODULES_RUN_TASK; "forecast" "&JOBSdir;/JSRW_FORECAST"{% else %}&LOAD_MODULES_RUN_TASK; "run_fcst" "&JOBSdir;/JREGIONAL_RUN_FCST"{% endif %}' envars: <<: *default_vars SLASH_ENSMEM_SUBDIR: '&SLASH_ENSMEM_SUBDIR;' diff --git a/scripts/exregional_make_ics.sh b/scripts/exregional_make_ics.sh index 8a8aade972..4d57d826c1 100755 --- a/scripts/exregional_make_ics.sh +++ b/scripts/exregional_make_ics.sh @@ -86,7 +86,7 @@ #----------------------------------------------------------------------- # . $USHdir/source_util_funcs.sh -for sect in user nco platform workflow global cpl_aqm_parm constants task_get_extrn_ics task_make_ics ; do +for sect in user nco platform workflow global cpl_aqm_parm smoke_dust_parm constants task_get_extrn_ics task_make_ics ; do source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} done # @@ -724,7 +724,7 @@ POST_STEP # #----------------------------------------------------------------------- # -if [ $(boolify "${CPL_AQM}") = "TRUE" ]; then +if [ $(boolify "${CPL_AQM}") = "TRUE" ] || [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then COMOUT="${COMROOT}/${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR}" #temporary path, should be removed later if [ $(boolify "${COLDSTART}") = "TRUE" ] && [ "${PDY}${cyc}" = "${DATE_FIRST_CYCL:0:10}" ]; then data_trans_path="${COMOUT}" diff --git a/scripts/exregional_make_lbcs.sh b/scripts/exregional_make_lbcs.sh index d174ba2933..24fb99de74 100755 --- a/scripts/exregional_make_lbcs.sh +++ b/scripts/exregional_make_lbcs.sh @@ -87,7 +87,7 @@ # . $USHdir/source_util_funcs.sh set -x -for sect in user nco platform workflow global cpl_aqm_parm constants task_get_extrn_lbcs task_make_lbcs ; do +for sect in user nco platform workflow global cpl_aqm_parm smoke_dust_parm constants task_get_extrn_lbcs task_make_lbcs ; do source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} done # @@ -644,6 +644,9 @@ located in the following directory: fcst_hhh_FV3LAM=$( printf "%03d" "$fcst_hhh" ) if [ $(boolify "${CPL_AQM}") = "TRUE" ]; then cp -p gfs.bndy.nc ${DATA_SHARE}/${NET}.${cycle}${dot_ensmem}.gfs_bndy.tile7.f${fcst_hhh_FV3LAM}.nc + elif [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then + COMOUT="${COMROOT}/${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR}" #temporary path, should be removed later + cp -p gfs.bndy.nc ${COMOUT}/${NET}.${cycle}${dot_ensmem}.gfs_bndy.tile7.f${fcst_hhh_FV3LAM}.nc else mv gfs.bndy.nc ${INPUT_DATA}/${NET}.${cycle}${dot_ensmem}.gfs_bndy.tile7.f${fcst_hhh_FV3LAM}.nc fi diff --git a/scripts/exregional_run_fcst.sh b/scripts/exregional_run_fcst.sh index 9f18aa4be3..bbe9c6c47c 100755 --- a/scripts/exregional_run_fcst.sh +++ b/scripts/exregional_run_fcst.sh @@ -340,7 +340,7 @@ cd ${DATA}/INPUT # relative_link_flag="FALSE" -if [ $(boolify "${CPL_AQM}") = "TRUE" ]; then +if [ $(boolify "${CPL_AQM}") = "TRUE" ] || [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then COMIN="${COMROOT}/${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR}" #temporary path, should be removed later target="${COMIN}/${NET}.${cycle}${dot_ensmem}.gfs_data.tile${TILE_RGNL}.halo${NH0}.nc" @@ -360,17 +360,35 @@ if [ $(boolify "${CPL_AQM}") = "TRUE" ]; then symlink="gfs_bndy.tile${TILE_RGNL}.${fhr}.nc" create_symlink_to_file $target $symlink ${relative_link_flag} done - target="${COMIN}/${NET}.${cycle}${dot_ensmem}.NEXUS_Expt.nc" - symlink="NEXUS_Expt.nc" - create_symlink_to_file $target $symlink ${relative_link_flag} - # create symlink to PT for point source in SRW-AQM - target="${COMIN}/${NET}.${cycle}${dot_ensmem}.PT.nc" - if [ -f ${target} ]; then - symlink="PT.nc" + if [ $(boolify "${CPL_AQM}") = "TRUE" ]; then + target="${COMIN}/${NET}.${cycle}${dot_ensmem}.NEXUS_Expt.nc" + symlink="NEXUS_Expt.nc" create_symlink_to_file $target $symlink ${relative_link_flag} - fi + # create symlink to PT for point source in SRW-AQM + target="${COMIN}/${NET}.${cycle}${dot_ensmem}.PT.nc" + if [ -f ${target} ]; then + symlink="PT.nc" + create_symlink_to_file $target $symlink ${relative_link_flag} + fi + else + ln -snf ${FIXsmoke}/${PREDEF_GRID_NAME}/dust12m_data.nc . + ln -snf ${FIXsmoke}/${PREDEF_GRID_NAME}/emi_data.nc . + + smokefile="${COMIN}/${SMOKE_DUST_FILE_PREFIX}_${PDY}${cyc}00.nc" + if [ -f ${smokefile} ]; then + ln -snf ${smokefile} ${SMOKE_DUST_FILE_PREFIX}.nc + else + if [ "${EBB_DCYCLE}" = "1" ]; then + ln -snf ${FIXsmoke}/${PREDEF_GRID_NAME}/dummy_24hr_smoke_ebbdc1.nc ${SMOKE_DUST_FILE_PREFIX}.nc + echo "WARNING: Smoke file is not available, use dummy_24hr_smoke_ebbdc1.nc instead" + else + ln -snf ${FIXsmoke}/${PREDEF_GRID_NAME}/dummy_24hr_smoke.nc ${SMOKE_DUST_FILE_PREFIX}.nc + echo "WARNING: Smoke file is not available, use dummy_24hr_smoke.nc instead" + fi + fi + fi else target="${INPUT_DATA}/${NET}.${cycle}${dot_ensmem}.gfs_data.tile${TILE_RGNL}.halo${NH0}.nc" symlink="gfs_data.nc" @@ -390,25 +408,6 @@ else create_symlink_to_file $target $symlink ${relative_link_flag} done fi -# Smoke and Dust -if [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then - ln -snf ${FIXsmoke}/${PREDEF_GRID_NAME}/dust12m_data.nc . - ln -snf ${FIXsmoke}/${PREDEF_GRID_NAME}/emi_data.nc . - - COMIN="${COMROOT}/${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR}" #temporary path, should be removed later - smokefile="${COMIN}/${SMOKE_DUST_FILE_PREFIX}_${PDY}${cyc}00.nc" - if [ -f ${smokefile} ]; then - ln -snf ${smokefile} ${SMOKE_DUST_FILE_PREFIX}.nc - else - if [ "${EBB_DCYCLE}" = "1" ]; then - ln -snf ${FIXsmoke}/${PREDEF_GRID_NAME}/dummy_24hr_smoke_ebbdc1.nc ${SMOKE_DUST_FILE_PREFIX}.nc - echo "WARNING: Smoke file is not available, use dummy_24hr_smoke_ebbdc1.nc instead" - else - ln -snf ${FIXsmoke}/${PREDEF_GRID_NAME}/dummy_24hr_smoke.nc ${SMOKE_DUST_FILE_PREFIX}.nc - echo "WARNING: Smoke file is not available, use dummy_24hr_smoke.nc instead" - fi - fi -fi # #----------------------------------------------------------------------- # @@ -854,38 +853,31 @@ POST_STEP # #----------------------------------------------------------------------- # -# Move RESTART directory to COMIN and create symlink in DATA only for -# NCO mode and when it is not empty. -# -# Move AQM output product file to COMOUT only for NCO mode in Online-CMAQ. -# Move dyn and phy files to COMIN only if run_post and write_dopost are off. +# Copy RESTART directory to COMOUT. +# Move dyn and phy files to COMOUT. +# Copy AQM output product file to COMOUT only for AQM. # #----------------------------------------------------------------------- # -if [ $(boolify "${CPL_AQM}") = "TRUE" ]; then - if [ "${RUN_ENVIR}" = "nco" ]; then - if [ -d "${COMIN}/RESTART" ] && [ "$(ls -A ${DATA}/RESTART)" ]; then - rm -rf "${COMIN}/RESTART" - fi - if [ "$(ls -A ${DATA}/RESTART)" ]; then - cp -Rp ${DATA}/RESTART ${COMIN} - fi - fi - - cp -p ${DATA}/${AQM_RC_PRODUCT_FN} ${COMOUT}/${NET}.${cycle}${dot_ensmem}.${AQM_RC_PRODUCT_FN} +if [ $(boolify "${CPL_AQM}") = "TRUE" ] || [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ] ; then + COMOUT="${COMROOT}/${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR}" #temporary path + cp -Rp RESTART ${COMOUT} - fhr_ct=0 fhr=0 while [ $fhr -le ${FCST_LEN_HRS} ]; do fhr_ct=$(printf "%03d" $fhr) source_dyn="${DATA}/dynf${fhr_ct}.nc" source_phy="${DATA}/phyf${fhr_ct}.nc" - target_dyn="${COMIN}/${NET}.${cycle}${dot_ensmem}.dyn.f${fhr_ct}.nc" - target_phy="${COMIN}/${NET}.${cycle}${dot_ensmem}.phy.f${fhr_ct}.nc" - [ -f ${source_dyn} ] && cp -p ${source_dyn} ${target_dyn} - [ -f ${source_phy} ] && cp -p ${source_phy} ${target_phy} + target_dyn="${COMIN}/${NET}.${cycle}${dot_ensmem}.dyn.f${fhr_ct}.${POST_OUTPUT_DOMAIN_NAME}.nc" + target_phy="${COMIN}/${NET}.${cycle}${dot_ensmem}.phy.f${fhr_ct}.${POST_OUTPUT_DOMAIN_NAME}.nc" + [ -f ${source_dyn} ] && mv ${source_dyn} ${target_dyn} + [ -f ${source_phy} ] && mv ${source_phy} ${target_phy} (( fhr=fhr+1 )) - done + done + + if [ $(boolify "${CPL_AQM}") = "TRUE" ]; then + cp -p ${DATA}/${AQM_RC_PRODUCT_FN} ${COMOUT}/${NET}.${cycle}${dot_ensmem}.${AQM_RC_PRODUCT_FN} + fi fi # #----------------------------------------------------------------------- @@ -952,29 +944,6 @@ if [ $(boolify ${WRITE_DOPOST}) = "TRUE" ]; then done fi - -# -#----------------------------------------------------------------------- -# -# Copy RESTART directory and dyn/phy output files to COMOUT -# -#----------------------------------------------------------------------- -# -if [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then - COMOUT="${COMROOT}/${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR}" #temporary path - cp -Rp RESTART ${COMOUT} - fhr=0 - while [ $fhr -le ${FCST_LEN_HRS} ]; do - fhr_3d=$(printf "%03d" $fhr) - source_dyn="dynf${fhr_3d}.nc" - source_phy="phyf${fhr_3d}.nc" - target_dyn="${COMOUT}/${NET}.${cycle}${dot_ensmem}.dyn.f${fhr_3d}.${POST_OUTPUT_DOMAIN_NAME}.nc" - target_phy="${COMOUT}/${NET}.${cycle}${dot_ensmem}.phy.f${fhr_3d}.${POST_OUTPUT_DOMAIN_NAME}.nc" - [ -f ${source_dyn} ] && cp -p ${source_dyn} ${target_dyn} - [ -f ${source_phy} ] && cp -p ${source_phy} ${target_phy} - (( fhr=fhr+1 )) - done -fi # #----------------------------------------------------------------------- # diff --git a/scripts/exsrw_aqm_lbcs.sh b/scripts/exsrw_aqm_lbcs.sh index 7b3058ef34..e8fdf6620f 100755 --- a/scripts/exsrw_aqm_lbcs.sh +++ b/scripts/exsrw_aqm_lbcs.sh @@ -221,7 +221,7 @@ EOF export pgm="gefs2lbc_para" . prep_step - eval ${RUN_CMD_AQMLBC} ${EXECdir}/$pgm >>$pgmout 2>errfile + eval ${RUN_CMD_AQMLBC} ${EXECsrw}/$pgm >>$pgmout 2>errfile export err=$?; err_chk print_info_msg " diff --git a/scripts/exsrw_forecast.sh b/scripts/exsrw_forecast.sh new file mode 100755 index 0000000000..98cc82514d --- /dev/null +++ b/scripts/exsrw_forecast.sh @@ -0,0 +1,786 @@ +#!/usr/bin/env bash + + +# +#----------------------------------------------------------------------- +# +# This ex-script is responsible for running the FV3 regional forecast. +# +# Run-time environment variables: +# +# CDATE +# COMIN +# COMOUT +# COMROOT +# DATA +# DBNROOT +# GLOBAL_VAR_DEFNS_FP +# INPUT_DATA +# NET +# PDY +# REDIRECT_OUT_ERR +# RUN +# SENDDBN +# SLASH_ENSMEM_SUBDIR +# +# Experiment variables +# +# user: +# MACHINE +# PARMdir +# RUN_ENVIR +# USHdir +# +# platform: +# PRE_TASK_CMDS +# RUN_CMD_FCST +# +# workflow: +# CCPP_PHYS_DIR +# CCPP_PHYS_SUITE +# COLDSTART +# CRES +# DATA_TABLE_FN +# DATA_TABLE_FP +# DATE_FIRST_CYCL +# DOT_OR_USCORE +# EXPTDIR +# FCST_LEN_CYCL +# FCST_LEN_HRS +# FIELD_DICT_FP +# FIELD_DICT_FN +# FIELD_TABLE_FN +# FIELD_TABLE_FP +# FIXam +# FIXclim +# FIXlam +# FV3_NML_FN +# FV3_NML_FP +# FV3_NML_STOCH_FP +# INCR_CYCL_FREQ +# PREDEF_GRID_NAME +# SYMLINK_FIX_FILES +# VERBOSE +# +# task_get_extrn_lbcs: +# LBC_SPEC_INTVL_HRS +# +# task_run_fcst: +# DO_FCST_RESTART +# DT_ATMOS +# FV3_EXEC_FP +# KMP_AFFINITY_RUN_FCST +# OMP_NUM_THREADS_RUN_FCST +# OMP_STACKSIZE_RUN_FCST +# PRINT_ESMF +# RESTART_INTERVAL +# USE_MERRA_CLIMO +# WRITE_DOPOST +# +# task_run_post: +# CUSTOM_POST_CONFIG_FP +# DT_SUBHOURLY_POST_MNTS +# POST_OUTPUT_DOMAIN_NAME +# SUB_HOURLY_POST +# USE_CUSTOM_POST_CONFIG_FILE +# +# global: +# DO_ENSEMBLE +# DO_LSM_SPP +# DO_SHUM +# DO_SKEB +# DO_SPP +# DO_SPPT +# +# cpl_aqm_parm: +# AQM_RC_PRODUCT_FN +# CPL_AQM +# +# constants: +# NH0 +# NH3 +# NH4 +# TILE_RGNL +# +# fixed_files: +# CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING +# +#----------------------------------------------------------------------- +# + +# +#----------------------------------------------------------------------- +# +# Source the variable definitions file and the bash utility functions. +# +#----------------------------------------------------------------------- +# +. ${USHsrw}/source_util_funcs.sh +for sect in user nco platform workflow global cpl_aqm_parm smoke_dust_parm constants fixed_files \ + task_get_extrn_lbcs task_run_fcst task_run_post ; do + source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} +done +# +#----------------------------------------------------------------------- +# +# Save current shell options (in a global array). Then set new options +# for this script/function. +# +#----------------------------------------------------------------------- +# +{ save_shell_opts; set -xue; } > /dev/null 2>&1 +# +#----------------------------------------------------------------------- +# +# Get the full path to the file in which this script/function is located +# (scrfunc_fp), the name of that file (scrfunc_fn), and the directory in +# which the file is located (scrfunc_dir). +# +#----------------------------------------------------------------------- +# +scrfunc_fp=$( $READLINK -f "${BASH_SOURCE[0]}" ) +scrfunc_fn=$( basename "${scrfunc_fp}" ) +scrfunc_dir=$( dirname "${scrfunc_fp}" ) +# +#----------------------------------------------------------------------- +# +# Print message indicating entry into script. +# +#----------------------------------------------------------------------- +# +print_info_msg " +======================================================================== +Entering script: \"${scrfunc_fn}\" +In directory: \"${scrfunc_dir}\" + +This is the ex-script for the task that runs a forecast with FV3 for the +specified cycle. +========================================================================" +# +#----------------------------------------------------------------------- +# +# Set environment variables. +# +#----------------------------------------------------------------------- +# +export KMP_AFFINITY=${KMP_AFFINITY_RUN_FCST} +export OMP_NUM_THREADS=${OMP_NUM_THREADS_RUN_FCST} +export OMP_STACKSIZE=${OMP_STACKSIZE_RUN_FCST} +export MPI_TYPE_DEPTH=20 +export ESMF_RUNTIME_COMPLIANCECHECK=OFF:depth=4 +if [ $(boolify "${PRINT_ESMF}") = "TRUE" ]; then + export ESMF_RUNTIME_PROFILE=ON + export ESMF_RUNTIME_PROFILE_OUTPUT="SUMMARY" +fi +# +#----------------------------------------------------------------------- +# +# Load modules. +# +#----------------------------------------------------------------------- +# +eval ${PRE_TASK_CMDS} + +if [ -z "${RUN_CMD_FCST:-}" ] ; then + print_err_msg_exit "\ + Run command was not set in machine file. \ + Please set RUN_CMD_FCST for your platform" +else + print_info_msg "$VERBOSE" " + All executables will be submitted with command \'${RUN_CMD_FCST}\'." +fi + +if [ ${#FCST_LEN_CYCL[@]} -gt 1 ]; then + cyc_mod=$(( ${cyc} - ${DATE_FIRST_CYCL:8:2} )) + CYCLE_IDX=$(( ${cyc_mod} / ${INCR_CYCL_FREQ} )) + FCST_LEN_HRS=${FCST_LEN_CYCL[$CYCLE_IDX]} +fi +export CDATE="${PDY}${cyc}" +# +#----------------------------------------------------------------------- +# +# Create and set up INPUT subdirectory of the current working directory +# to run the ufs weather model +# +#----------------------------------------------------------------------- +# +print_info_msg "$VERBOSE" " +Creating links with names that FV3 looks for in the INPUT subdirectory +of the current working directory (DATA), where + DATA = \"${DATA}\" +..." + +# Create and set up INPUT directory for ufs-weather-model. +mkdir -p ${DATA}/INPUT +cd ${DATA}/INPUT + +# Symlink to mosaic file with a completely different name. +target="${FIXlam}/${CRES}${DOT_OR_USCORE}mosaic.halo${NH3}.nc" +symlink="grid_spec.nc" +ln -nsf $target $symlink + +# Symlink to halo-3 grid file with "halo3" stripped from name. +mosaic_fn="grid_spec.nc" +grid_fn=$( get_charvar_from_netcdf "${mosaic_fn}" "gridfiles" ) +target="${FIXlam}/${grid_fn}" +symlink="${grid_fn}" +ln -nsf $target $symlink + +# Symlink to halo-4 grid file with "${CRES}_" stripped from name. +target="${FIXlam}/${CRES}${DOT_OR_USCORE}grid.tile${TILE_RGNL}.halo${NH4}.nc" +symlink="grid.tile${TILE_RGNL}.halo${NH4}.nc" +ln -nsf $target $symlink + +# Symlink to halo-0 orography file with "${CRES}_" and "halo0" stripped from name. +target="${FIXlam}/${CRES}${DOT_OR_USCORE}oro_data.tile${TILE_RGNL}.halo${NH0}.nc" +symlink="oro_data.nc" +ln -nsf $target $symlink + +# Symlink to halo-4 orography file with "${CRES}_" stripped from name. +target="${FIXlam}/${CRES}${DOT_OR_USCORE}oro_data.tile${TILE_RGNL}.halo${NH4}.nc" +symlink="oro_data.tile${TILE_RGNL}.halo${NH4}.nc" +ln -nsf $target $symlink +# +# When using some specific physics suite, there are two files (that contain +# statistics of the orography) that are needed by the gravity wave drag +# parameterization in that suite. +# +suites=( "FV3_RAP" "FV3_HRRR" "FV3_HRRR_gf" "FV3_GFS_v15_thompson_mynn_lam3km" "FV3_GFS_v17_p8" ) +if [[ ${suites[@]} =~ "${CCPP_PHYS_SUITE}" ]] ; then + file_ids=( "ss" "ls" ) + for file_id in "${file_ids[@]}"; do + target="${FIXlam}/${CRES}${DOT_OR_USCORE}oro_data_${file_id}.tile${TILE_RGNL}.halo${NH0}.nc" + symlink="oro_data_${file_id}.nc" + ln -nsf $target $symlink + done +fi + +target="${COMIN}/${NET}.${cycle}${dot_ensmem}.gfs_data.tile${TILE_RGNL}.halo${NH0}.nc" +symlink="gfs_data.nc" +ln -nsf $target $symlink + +target="${COMIN}/${NET}.${cycle}${dot_ensmem}.sfc_data.tile${TILE_RGNL}.halo${NH0}.nc" +symlink="sfc_data.nc" +ln -nsf $target $symlink + +target="${COMIN}/${NET}.${cycle}${dot_ensmem}.gfs_ctrl.nc" +symlink="gfs_ctrl.nc" +ln -nsf $target $symlink + +for fhr in $(seq -f "%03g" 0 ${LBC_SPEC_INTVL_HRS} ${FCST_LEN_HRS}); do + target="${COMIN}/${NET}.${cycle}${dot_ensmem}.gfs_bndy.tile${TILE_RGNL}.f${fhr}.nc" + symlink="gfs_bndy.tile${TILE_RGNL}.${fhr}.nc" + ln -nsf $target $symlink +done + +if [ $(boolify "${CPL_AQM}") = "TRUE" ]; then + target="${COMIN}/${NET}.${cycle}${dot_ensmem}.NEXUS_Expt.nc" + symlink="NEXUS_Expt.nc" + ln -nsf $target $symlink + + # create symlink to PT for point source in SRW-AQM + target="${COMIN}/${NET}.${cycle}${dot_ensmem}.PT.nc" + if [ -f ${target} ]; then + symlink="PT.nc" + ln -nsf $target $symlink + fi +fi +if [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then + ln -nsf ${FIXsmoke}/${PREDEF_GRID_NAME}/dust12m_data.nc . + ln -nsf ${FIXsmoke}/${PREDEF_GRID_NAME}/emi_data.nc . + + smokefile="${COMIN}/${SMOKE_DUST_FILE_PREFIX}_${PDY}${cyc}00.nc" + if [ -f ${smokefile} ]; then + ln -nsf ${smokefile} ${SMOKE_DUST_FILE_PREFIX}.nc + else + if [ "${EBB_DCYCLE}" = "1" ]; then + ln -nsf ${FIXsmoke}/${PREDEF_GRID_NAME}/dummy_24hr_smoke_ebbdc1.nc ${SMOKE_DUST_FILE_PREFIX}.nc + echo "WARNING: Smoke file is not available, use dummy_24hr_smoke_ebbdc1.nc instead" + else + ln -nsf ${FIXsmoke}/${PREDEF_GRID_NAME}/dummy_24hr_smoke.nc ${SMOKE_DUST_FILE_PREFIX}.nc + echo "WARNING: Smoke file is not available, use dummy_24hr_smoke.nc instead" + fi + fi +fi +# +#----------------------------------------------------------------------- +# +# Create links in the current working directory to fixed (i.e. static) files +# in the FIXam directory. These links have names that are set to the +# names of files that the forecast model expects to exist in the current +# working directory when the forecast model executable is called. +# +#----------------------------------------------------------------------- +# +cd ${DATA} + +print_info_msg "$VERBOSE" " +Creating links in the current run directory (DATA) to fixed (i.e. +static) files in the FIXam directory: + FIXam = \"${FIXam}\" + DATA = \"${DATA}\"" + +regex_search="^[ ]*([^| ]+)[ ]*[|][ ]*([^| ]+)[ ]*$" +num_symlinks=${#CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING[@]} +for (( i=0; i<${num_symlinks}; i++ )); do + + mapping="${CYCLEDIR_LINKS_TO_FIXam_FILES_MAPPING[$i]}" + symlink=$( printf "%s\n" "$mapping" | \ + $SED -n -r -e "s/${regex_search}/\1/p" ) + target=$( printf "%s\n" "$mapping" | \ + $SED -n -r -e "s/${regex_search}/\2/p" ) + + symlink="${DATA}/$symlink" + target="$FIXam/$target" + ln -nsf $target $symlink + +done +# +#----------------------------------------------------------------------- +# +# Create links in the current working directory to the MERRA2 aerosol +# climatology data files and lookup table for optics properties. +# +#----------------------------------------------------------------------- +# +if [ $(boolify "${USE_MERRA_CLIMO}") = "TRUE" ]; then + for f_nm_path in ${FIXclim}/*; do + f_nm=$( basename "${f_nm_path}" ) + pre_f="${f_nm%%.*}" + + if [ "${pre_f}" = "merra2" ]; then + mnth=$( printf "%s\n" "${f_nm}" | grep -o -P '(?<=2014.m).*(?=.nc)' ) + symlink="${DATA}/aeroclim.m${mnth}.nc" + else + symlink="${DATA}/${pre_f}.dat" + fi + target="${f_nm_path}" + ln -nsf $target $symlink + done +fi +# +#----------------------------------------------------------------------- +# +# Create links in the current working directory to cycle-independent (and +# ensemble-member-independent) model input files in the main experiment +# directory. +# +#----------------------------------------------------------------------- +# +print_info_msg "$VERBOSE" " +Creating links in the current run directory to cycle-independent model +input files in the main experiment directory..." + +ln -nsf ${DATA_TABLE_FP} ${DATA}/${DATA_TABLE_FN} + +ln -nsf ${FIELD_TABLE_FP} ${DATA}/${FIELD_TABLE_FN} + +ln -nsf ${FIELD_DICT_FP} ${DATA}/${FIELD_DICT_FN} + +if [ $(boolify ${WRITE_DOPOST}) = "TRUE" ]; then + cp -p ${PARMdir}/upp/nam_micro_lookup.dat ./eta_micro_lookup.dat + if [ $(boolify ${USE_CUSTOM_POST_CONFIG_FILE}) = "TRUE" ]; then + post_config_fp="${CUSTOM_POST_CONFIG_FP}" + print_info_msg " +==================================================================== + CUSTOM_POST_CONFIG_FP = \"${CUSTOM_POST_CONFIG_FP}\" +====================================================================" + else + if [ $(boolify "${CPL_AQM}") = "TRUE" ]; then + post_config_fp="${PARMdir}/upp/postxconfig-NT-AQM.txt" + else + post_config_fp="${PARMdir}/upp/postxconfig-NT-fv3lam.txt" + fi + print_info_msg " +==================================================================== + post_config_fp = \"${post_config_fp}\" +====================================================================" + fi + cp -p ${post_config_fp} ./postxconfig-NT_FH00.txt + cp -p ${post_config_fp} ./postxconfig-NT.txt + cp -p ${PARMdir}/upp/params_grib2_tbl_new . + # Set itag for inline-post: + if [ $(boolify "${CPL_AQM}") = "TRUE" ]; then + post_itag_add="aqf_on=.true.," + else + post_itag_add="" + fi +cat > itag <=0; ih_rst-- )); do + cdate_restart_hr=$( $DATE_UTIL --utc --date "${PDY} ${cyc} UTC + ${restart_hrs[ih_rst]} hours" "+%Y%m%d%H" ) + rst_yyyymmdd="${cdate_restart_hr:0:8}" + rst_hh="${cdate_restart_hr:8:2}" + + num_rst_files=0 + for file_id in "${file_ids[@]}"; do + if [ -e "${DATA}/RESTART/${rst_yyyymmdd}.${rst_hh}0000.${file_id}" ]; then + (( num_rst_files=num_rst_files+1 )) + fi + done + if [ "${num_rst_files}" = "${num_file_ids}" ]; then + FHROT="${restart_hrs[ih_rst]}" + break + fi + done + + # Create soft-link of restart files in INPUT directory + cd ${DATA}/INPUT + for file_id in "${file_ids[@]}"; do + rm "${file_id}" + target="${DATA}/RESTART/${rst_yyyymmdd}.${rst_hh}0000.${file_id}" + symlink="${file_id}" + ln -nsf $target $symlink + done + cd ${DATA} +fi +# +#----------------------------------------------------------------------- +# +# Setup air quality model cold/warm start +# +#----------------------------------------------------------------------- +# +if [ $(boolify "${CPL_AQM}") = "TRUE" ]; then + if [ $(boolify "${COLDSTART}") = "TRUE" ] && \ + [ "${PDY}${cyc}" = "${DATE_FIRST_CYCL:0:10}" ] && \ + [ $(boolify "${flag_fcst_restart}") = "FALSE" ]; then + init_concentrations="true" + else + init_concentrations="false" + fi +# +#----------------------------------------------------------------------- +# +# Call the function that creates the aqm.rc file within each +# cycle directory. +# +#----------------------------------------------------------------------- +# + ${USHsrw}/create_aqm_rc_file.py \ + --path-to-defns ${GLOBAL_VAR_DEFNS_FP} \ + --cdate "$CDATE" \ + --run-dir "${DATA}" \ + --init_concentrations "${init_concentrations}" + export err=$? + if [ $err -ne 0 ]; then + message_txt="Call to function to create an aqm.rc file for the current +cycle's (cdate) run directory (DATA) failed: + cdate = \"${CDATE}\" + DATA = \"${DATA}\"" + err_exit "${message_txt}" + print_err_msg_exit "${message_txt}" + fi +fi +# +#----------------------------------------------------------------------- +# +# Call the function that creates the model configuration file within each +# cycle directory. +# +#----------------------------------------------------------------------- +# +${USHsrw}/create_model_configure_file.py \ + --path-to-defns ${GLOBAL_VAR_DEFNS_FP} \ + --cdate "$CDATE" \ + --fcst_len_hrs "${FCST_LEN_HRS}" \ + --fhrot "${FHROT}" \ + --run-dir "${DATA}" \ + --sub-hourly-post "${SUB_HOURLY_POST}" \ + --dt-subhourly-post-mnts "${DT_SUBHOURLY_POST_MNTS}" \ + --dt-atmos "${DT_ATMOS}" +export err=$? +if [ $err -ne 0 ]; then + message_txt="Call to function to create a model configuration file +for the current cycle's (cdate) run directory (DATA) failed: + cdate = \"${CDATE}\" + DATA = \"${DATA}\"" + err_exit "${message_txt}" + print_err_msg_exit "${message_txt}" +fi +# +#----------------------------------------------------------------------- +# +# Call the function that creates the diag_table file within each cycle +# directory. +# +#----------------------------------------------------------------------- +# +${USHsrw}/create_diag_table_file.py \ + --path-to-defns ${GLOBAL_VAR_DEFNS_FP} \ + --run-dir "${DATA}" +export err=$? +if [ $err -ne 0 ]; then + message_txt="Call to function to create a diag table file for the current +cycle's (cdate) run directory (DATA) failed: + DATA = \"${DATA}\"" + err_exit "${message_txt}" + print_err_msg_exit "${message_txt}" +fi +# +#----------------------------------------------------------------------- +# +# Pre-generate symlink to forecast RESTART in DATA for early start of +# the next cycle in SRW-AQM +# +#----------------------------------------------------------------------- +# +if [ $(boolify "${CPL_AQM}") = "TRUE" ]; then + ln -nsf "${DATA}/RESTART" "${COMIN}/RESTART" +fi +# +#----------------------------------------------------------------------- +# +# Call the function that creates the NEMS configuration file within each +# cycle directory. +# +#----------------------------------------------------------------------- +# +${USHsrw}/create_ufs_configure_file.py \ + --path-to-defns ${GLOBAL_VAR_DEFNS_FP} \ + --run-dir "${DATA}" +export err=$? +if [ $err -ne 0 ]; then + message_txt="Call to function to create a NEMS configuration file for +the current cycle's (cdate) run directory (DATA) failed: + DATA = \"${DATA}\"" + err_exit "${message_txt}" + print_err_msg_exit "${message_txt}" +fi +# +#----------------------------------------------------------------------- +# +# Run the FV3-LAM model. +# +#----------------------------------------------------------------------- +# +export pgm="${FV3_EXEC_FN}" + +. prep_step +eval ${RUN_CMD_FCST} ${EXECsrw}/$pgm >>$pgmout 2>errfile +export err=$?; err_chk +# +#----------------------------------------------------------------------- +# +# Copy RESTART directory to COMOUT. +# Move dyn and phy files to COMOUT. +# Copy AQM output product file to COMOUT only for AQM. +# +#----------------------------------------------------------------------- +# +if [ $(boolify "${CPL_AQM}") = "TRUE" ] || [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ] ; then + cp -Rp RESTART ${COMOUT} + + fhr=0 + while [ $fhr -le ${FCST_LEN_HRS} ]; do + fhr_ct=$(printf "%03d" $fhr) + source_dyn="${DATA}/dynf${fhr_ct}.nc" + source_phy="${DATA}/phyf${fhr_ct}.nc" + target_dyn="${COMIN}/${NET}.${cycle}${dot_ensmem}.dyn.f${fhr_ct}.${POST_OUTPUT_DOMAIN_NAME}.nc" + target_phy="${COMIN}/${NET}.${cycle}${dot_ensmem}.phy.f${fhr_ct}.${POST_OUTPUT_DOMAIN_NAME}.nc" + [ -f ${source_dyn} ] && mv ${source_dyn} ${target_dyn} + [ -f ${source_phy} ] && mv ${source_phy} ${target_phy} + (( fhr=fhr+1 )) + done + + if [ $(boolify "${CPL_AQM}") = "TRUE" ]; then + cp -p ${DATA}/${AQM_RC_PRODUCT_FN} ${COMOUT}/${NET}.${cycle}${dot_ensmem}.${AQM_RC_PRODUCT_FN} + fi +fi +# +#----------------------------------------------------------------------- +# +# If doing inline post, create the directory in which the post-processing +# output will be stored (postprd_dir). +# +#----------------------------------------------------------------------- +# +if [ $(boolify ${WRITE_DOPOST}) = "TRUE" ]; then + + yyyymmdd=${PDY} + hh=${cyc} + fmn="00" + + if [ "${RUN_ENVIR}" != "nco" ]; then + export COMOUT="${DATA}/postprd" + fi + mkdir -p "${COMOUT}" + + cd ${COMOUT} + + for fhr in $(seq -f "%03g" 0 ${FCST_LEN_HRS}); do + + if [ ${fhr:0:1} = "0" ]; then + fhr_d=${fhr:1:2} + else + fhr_d=${fhr} + fi + + post_time=$( $DATE_UTIL --utc --date "${yyyymmdd} ${hh} UTC + ${fhr_d} hours + ${fmn} minutes" "+%Y%m%d%H%M" ) + post_mn=${post_time:10:2} + post_mn_or_null="" + post_fn_suffix="GrbF${fhr_d}" + post_renamed_fn_suffix="f${fhr}${post_mn_or_null}.${POST_OUTPUT_DOMAIN_NAME}.grib2" + + if [ $(boolify "${CPL_AQM}") = "TRUE" ]; then + fids=( "cmaq" ) + else + fids=( "prslev" "natlev" ) + fi + + for fid in "${fids[@]}"; do + FID=$(echo_uppercase $fid) + post_orig_fn="${FID}.${post_fn_suffix}" + post_renamed_fn="${NET}.${cycle}${dot_ensmem}.${fid}.${post_renamed_fn_suffix}" + + mv ${DATA}/${post_orig_fn} ${post_renamed_fn} + if [ $RUN_ENVIR != "nco" ]; then + basetime=$( $DATE_UTIL --date "$yyyymmdd $hh" +%y%j%H%M ) + symlink_suffix="_${basetime}f${fhr}${post_mn}" + ln -nsf ${post_renamed_fn} ${FID}${symlink_suffix} + fi + # DBN alert + if [ "$SENDDBN" = "YES" ]; then + $DBNROOT/bin/dbn_alert MODEL rrfs_post ${job} ${COMOUT}/${post_renamed_fn} + fi + done + + if [ $(boolify "${CPL_AQM}") = "TRUE" ]; then + mv ${DATA}/dynf${fhr}.nc ${COMIN}/${NET}.${cycle}${dot_ensmem}.dyn.f${fhr}.${POST_OUTPUT_DOMAIN_NAME}.nc + mv ${DATA}/phyf${fhr}.nc ${COMIN}/${NET}.${cycle}${dot_ensmem}.phy.f${fhr}.${POST_OUTPUT_DOMAIN_NAME}.nc + fi + done + +fi +# +#----------------------------------------------------------------------- +# +# Print message indicating successful completion of script. +# +#----------------------------------------------------------------------- +# +print_info_msg " +======================================================================== +FV3 forecast completed successfully!!! + +Exiting script: \"${scrfunc_fn}\" +In directory: \"${scrfunc_dir}\" +========================================================================" +# +#----------------------------------------------------------------------- +# +# Restore the shell options saved at the beginning of this script/func- +# tion. +# +#----------------------------------------------------------------------- +# +{ restore_shell_opts; } > /dev/null 2>&1 + diff --git a/scripts/exsrw_nexus_emission.sh b/scripts/exsrw_nexus_emission.sh index 0fa8c48754..6c0476dd8d 100755 --- a/scripts/exsrw_nexus_emission.sh +++ b/scripts/exsrw_nexus_emission.sh @@ -315,7 +315,7 @@ fi export pgm="nexus" . prep_step -eval ${RUN_CMD_NEXUS} ${EXECdir}/$pgm -c NEXUS_Config.rc -r grid_spec.nc -o NEXUS_Expt_split.nc >>$pgmout 2>${DATA}/errfile +eval ${RUN_CMD_NEXUS} ${EXECsrw}/$pgm -c NEXUS_Config.rc -r grid_spec.nc -o NEXUS_Expt_split.nc >>$pgmout 2>${DATA}/errfile export err=$?; err_chk if [ $err -ne 0 ]; then print_err_msg_exit "Call to execute nexus failed." diff --git a/scripts/exsrw_prepstart.sh b/scripts/exsrw_prepstart.sh index a46ee8cf18..32881aae2e 100755 --- a/scripts/exsrw_prepstart.sh +++ b/scripts/exsrw_prepstart.sh @@ -57,6 +57,13 @@ if [ $(boolify "${COLDSTART}") = "TRUE" ] && [ "${PDY}${cyc}" = "${DATE_FIRST_CY echo "This step is skipped for the first cycle of COLDSTART." else if [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then + # IC gfs data file: gfs_data.tile7.halo0.nc + gfs_ic_fn="${NET}.${cycle}${dot_ensmem}.gfs_data.tile${TILE_RGNL}.halo${NH0}.nc" + gfs_ic_fp="${DATA_SHARE}/${gfs_ic_fn}" + gfs_ic_mod_fn="gfs_data.tile7.halo0.nc" + cp -p ${gfs_ic_fp} ${gfs_ic_mod_fn} + + # restart tracer file: fv_tracer.res.tile1.nc bkpath_find="missing" if [ "${bkpath_find}" = "missing" ]; then restart_prefix="${PDY}.${cyc}0000." @@ -115,6 +122,8 @@ else err_exit "${message_txt}" print_err_msg_exit "${message_txt}" fi + # copy output to COMOUT + cp -p ${gfs_ic_mod_fn} ${COMOUT}/${gfs_ic_fn} fi fi # diff --git a/ush/add_smoke.py b/ush/add_smoke.py index 036871dc4e..046073f970 100755 --- a/ush/add_smoke.py +++ b/ush/add_smoke.py @@ -32,6 +32,8 @@ def main(): # Open the source file and extract data data_to_extract = xr.open_dataset(source_file) + print("DATA FILE:",data_to_extract) + smoke_2_add = data_to_extract['smoke'][0,:,:, :] dust_2_add = data_to_extract['dust'][0,:,:, :] coarsepm_2_add = data_to_extract['coarsepm'][0,:, :, :] @@ -40,7 +42,7 @@ def main(): # Open the target file and load it into memory file_input = xr.open_dataset(target_file).load() - + print("TARGET FILE:",file_input) # Drop the 'smoke' variable if it exists in both the source and target files if 'smoke' in file_input.variables and 'smoke' in data_to_extract.variables: file_input = file_input.drop('smoke') diff --git a/ush/create_aqm_rc_file.py b/ush/create_aqm_rc_file.py old mode 100644 new mode 100755 diff --git a/ush/create_diag_table_file.py b/ush/create_diag_table_file.py old mode 100644 new mode 100755 diff --git a/ush/create_model_configure_file.py b/ush/create_model_configure_file.py old mode 100644 new mode 100755 diff --git a/ush/create_ufs_configure_file.py b/ush/create_ufs_configure_file.py old mode 100644 new mode 100755 diff --git a/ush/get_crontab_contents.py b/ush/get_crontab_contents.py old mode 100644 new mode 100755 diff --git a/ush/mrms_pull_topofhour.py b/ush/mrms_pull_topofhour.py old mode 100644 new mode 100755 diff --git a/ush/set_cycle_dates.py b/ush/set_cycle_dates.py old mode 100644 new mode 100755 diff --git a/ush/set_fv3nml_ens_stoch_seeds.py b/ush/set_fv3nml_ens_stoch_seeds.py old mode 100644 new mode 100755 diff --git a/ush/set_fv3nml_sfc_climo_filenames.py b/ush/set_fv3nml_sfc_climo_filenames.py old mode 100644 new mode 100755 diff --git a/ush/set_gridparams_ESGgrid.py b/ush/set_gridparams_ESGgrid.py old mode 100644 new mode 100755 diff --git a/ush/set_gridparams_GFDLgrid.py b/ush/set_gridparams_GFDLgrid.py old mode 100644 new mode 100755 diff --git a/ush/set_predef_grid_params.py b/ush/set_predef_grid_params.py old mode 100644 new mode 100755 diff --git a/ush/setup.py b/ush/setup.py old mode 100644 new mode 100755 diff --git a/ush/update_input_nml.py b/ush/update_input_nml.py old mode 100644 new mode 100755 From a260463b8aa744c3ca84e80d6fb1a8982604d1a7 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Tue, 27 Aug 2024 02:30:31 +0000 Subject: [PATCH 38/61] fix new forecast script issues --- jobs/JREGIONAL_MAKE_ICS | 1 + jobs/JREGIONAL_MAKE_LBCS | 1 + jobs/JSRW_FORECAST | 5 +---- parm/wflow/coldstart.yaml | 10 +++++++++- scripts/exregional_make_ics.sh | 7 ++++++- scripts/exregional_make_lbcs.sh | 1 + scripts/exsrw_forecast.sh | 3 +++ ush/job_preamble.sh | 2 ++ 8 files changed, 24 insertions(+), 6 deletions(-) diff --git a/jobs/JREGIONAL_MAKE_ICS b/jobs/JREGIONAL_MAKE_ICS index 10a3b36fb7..b33481d6a3 100755 --- a/jobs/JREGIONAL_MAKE_ICS +++ b/jobs/JREGIONAL_MAKE_ICS @@ -103,6 +103,7 @@ if [ $RUN_ENVIR = "community" ]; then mkdir -p $DATA cd $DATA fi +mkdir -p ${DATA_SHARE} # #----------------------------------------------------------------------- # diff --git a/jobs/JREGIONAL_MAKE_LBCS b/jobs/JREGIONAL_MAKE_LBCS index 91d9d3edbe..f90248f213 100755 --- a/jobs/JREGIONAL_MAKE_LBCS +++ b/jobs/JREGIONAL_MAKE_LBCS @@ -100,6 +100,7 @@ if [ "${RUN_ENVIR}" = "community" ]; then mkdir -p $DATA cd $DATA fi +mkdir -p ${DATA_SHARE} # #----------------------------------------------------------------------- # diff --git a/jobs/JSRW_FORECAST b/jobs/JSRW_FORECAST index 64cff6e7c2..0cf602e689 100755 --- a/jobs/JSRW_FORECAST +++ b/jobs/JSRW_FORECAST @@ -125,15 +125,12 @@ if [ "${MACHINE}" = "WCOSS2" ]; then export COMIN="${COMIN:-$(compath.py -o ${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR})}" export COMOUT="${COMOUT:-$(compath.py -o ${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR})}" else - export COMIN="${COMIN:-${COMROOT}/${NET}/${model_ver}}" + export COMIN="${COMIN:-${COMROOT}/${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR}}" export COMOUT="${COMOUT:-${COMROOT}/${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR}}" fi mkdir -p ${COMOUT} -export COMINsmoke="${COMINsmoke:-${COMINsmoke_default}}" -export COMINfire="${COMINfire:-${COMINfire_default}}" - # Create a teomporary share directory for RAVE interpolated data files export DATA_SHARE="${DATA_SHARE:-${DATAROOT}/DATA_SHARE/RAVE_fire_intp}" mkdir -p ${DATA_SHARE} diff --git a/parm/wflow/coldstart.yaml b/parm/wflow/coldstart.yaml index 60efb4aa2a..c3e024ea2a 100644 --- a/parm/wflow/coldstart.yaml +++ b/parm/wflow/coldstart.yaml @@ -10,6 +10,14 @@ default_task: &default_task cyc: !cycstr "@H" nprocs: '{{ parent.nnodes * parent.ppn }}' subcyc: !cycstr "@M" + HOMEdir: '&HOMEdir;' + envir: '&envir;' + model_ver: '&model_ver;' + KEEPDATA: '&KEEPDATA;' + SENDCOM: '&SENDCOM;' + COMROOT: '&COMROOT;' + DATAROOT: '&DATAROOT;' + DCOMROOT: '&DCOMROOT;' LOGDIR: !cycstr "&LOGDIR;" ENSMEM_INDX: '#mem#' native: '{{ platform.SCHED_NATIVE_CMD }}' @@ -142,7 +150,7 @@ metatask_run_ensemble: task_run_fcst_mem#mem#: <<: *default_task - command: '{% if smoke_dust_parm.get("DO_SMOKE_DUST") %}&LOAD_MODULES_RUN_TASK; "forecast" "&JOBSdir;/JSRW_FORECAST"{% else %}&LOAD_MODULES_RUN_TASK; "run_fcst" "&JOBSdir;/JREGIONAL_RUN_FCST"{% endif %}' + command: '{% if smoke_dust_parm.get("DO_SMOKE_DUST") %}&LOAD_MODULES_RUN_TASK; "forecast" "&JOBSdir;/JSRW_FORECAST" {% else %}&LOAD_MODULES_RUN_TASK; "run_fcst" "&JOBSdir;/JREGIONAL_RUN_FCST"{% endif %}' envars: <<: *default_vars SLASH_ENSMEM_SUBDIR: '&SLASH_ENSMEM_SUBDIR;' diff --git a/scripts/exregional_make_ics.sh b/scripts/exregional_make_ics.sh index 4d57d826c1..4e21eb33ce 100755 --- a/scripts/exregional_make_ics.sh +++ b/scripts/exregional_make_ics.sh @@ -726,6 +726,7 @@ POST_STEP # if [ $(boolify "${CPL_AQM}") = "TRUE" ] || [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then COMOUT="${COMROOT}/${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR}" #temporary path, should be removed later + mkdir -p ${COMOUT} if [ $(boolify "${COLDSTART}") = "TRUE" ] && [ "${PDY}${cyc}" = "${DATE_FIRST_CYCL:0:10}" ]; then data_trans_path="${COMOUT}" else @@ -734,7 +735,11 @@ if [ $(boolify "${CPL_AQM}") = "TRUE" ] || [ $(boolify "${DO_SMOKE_DUST}") = "TR cp -p out.atm.tile${TILE_RGNL}.nc "${data_trans_path}/${NET}.${cycle}${dot_ensmem}.gfs_data.tile${TILE_RGNL}.halo${NH0}.nc" cp -p out.sfc.tile${TILE_RGNL}.nc "${COMOUT}/${NET}.${cycle}${dot_ensmem}.sfc_data.tile${TILE_RGNL}.halo${NH0}.nc" cp -p gfs_ctrl.nc "${COMOUT}/${NET}.${cycle}${dot_ensmem}.gfs_ctrl.nc" - cp -p gfs.bndy.nc "${DATA_SHARE}/${NET}.${cycle}${dot_ensmem}.gfs_bndy.tile${TILE_RGNL}.f000.nc" + if [ $(boolify "${CPL_AQM}") = "TRUE" ]; then + cp -p gfs.bndy.nc "${DATA_SHARE}/${NET}.${cycle}${dot_ensmem}.gfs_bndy.tile${TILE_RGNL}.f000.nc" + else + cp -p gfs.bndy.nc "${COMOUT}/${NET}.${cycle}${dot_ensmem}.gfs_bndy.tile${TILE_RGNL}.f000.nc" + fi else mv out.atm.tile${TILE_RGNL}.nc ${INPUT_DATA}/${NET}.${cycle}${dot_ensmem}.gfs_data.tile${TILE_RGNL}.halo${NH0}.nc mv out.sfc.tile${TILE_RGNL}.nc ${INPUT_DATA}/${NET}.${cycle}${dot_ensmem}.sfc_data.tile${TILE_RGNL}.halo${NH0}.nc diff --git a/scripts/exregional_make_lbcs.sh b/scripts/exregional_make_lbcs.sh index 24fb99de74..768a6e5947 100755 --- a/scripts/exregional_make_lbcs.sh +++ b/scripts/exregional_make_lbcs.sh @@ -646,6 +646,7 @@ located in the following directory: cp -p gfs.bndy.nc ${DATA_SHARE}/${NET}.${cycle}${dot_ensmem}.gfs_bndy.tile7.f${fcst_hhh_FV3LAM}.nc elif [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then COMOUT="${COMROOT}/${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR}" #temporary path, should be removed later + mkdir -p ${COMOUT} cp -p gfs.bndy.nc ${COMOUT}/${NET}.${cycle}${dot_ensmem}.gfs_bndy.tile7.f${fcst_hhh_FV3LAM}.nc else mv gfs.bndy.nc ${INPUT_DATA}/${NET}.${cycle}${dot_ensmem}.gfs_bndy.tile7.f${fcst_hhh_FV3LAM}.nc diff --git a/scripts/exsrw_forecast.sh b/scripts/exsrw_forecast.sh index 98cc82514d..6d05fe4d36 100755 --- a/scripts/exsrw_forecast.sh +++ b/scripts/exsrw_forecast.sh @@ -195,7 +195,10 @@ if [ ${#FCST_LEN_CYCL[@]} -gt 1 ]; then CYCLE_IDX=$(( ${cyc_mod} / ${INCR_CYCL_FREQ} )) FCST_LEN_HRS=${FCST_LEN_CYCL[$CYCLE_IDX]} fi +# Set CDATE export CDATE="${PDY}${cyc}" +# Create RESTART directory in the working directory DATA +mkdir -p ${DATA}/RESTART # #----------------------------------------------------------------------- # diff --git a/ush/job_preamble.sh b/ush/job_preamble.sh index ecfb94fb50..4c4fff2478 100644 --- a/ush/job_preamble.sh +++ b/ush/job_preamble.sh @@ -32,6 +32,8 @@ export DATAROOT="${DATAROOT:-${PTMP}/${envir}/tmp}" export DCOMROOT="${DCOMROOT:-${PTMP}/${envir}/dcom}" export DATA_SHARE="${DATA_SHARE:-${DATAROOT}/DATA_SHARE/${PDY}${cyc}}" +mkdir -p $DATA_SHARE + export DBNROOT="${DBNROOT:-${DBNROOT_default}}" export SENDECF="${SENDECF:-${SENDECF_default}}" export SENDDBN="${SENDDBN:-${SENDDBN_default}}" From 746610c40bc9abbb1ee34361d33373b40e01a821 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Tue, 27 Aug 2024 10:19:53 +0000 Subject: [PATCH 39/61] run_fcst script back to origin --- scripts/exregional_run_fcst.sh | 78 ++++++++++++++-------------------- 1 file changed, 33 insertions(+), 45 deletions(-) diff --git a/scripts/exregional_run_fcst.sh b/scripts/exregional_run_fcst.sh index bbe9c6c47c..0241dbd728 100755 --- a/scripts/exregional_run_fcst.sh +++ b/scripts/exregional_run_fcst.sh @@ -116,7 +116,7 @@ #----------------------------------------------------------------------- # . $USHdir/source_util_funcs.sh -for sect in user nco platform workflow global cpl_aqm_parm smoke_dust_parm constants fixed_files \ +for sect in user nco platform workflow global cpl_aqm_parm constants fixed_files \ task_get_extrn_lbcs task_run_fcst task_run_post ; do source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} done @@ -130,7 +130,6 @@ done #----------------------------------------------------------------------- # { save_shell_opts; . $USHdir/preamble.sh; } > /dev/null 2>&1 -set -xue # #----------------------------------------------------------------------- # @@ -300,7 +299,7 @@ create_symlink_to_file $target $symlink ${relative_link_flag} # that the FV3 model is hardcoded to recognize, and those are the names # we use below. # -suites=( "FV3_RAP" "FV3_HRRR" "FV3_HRRR_gf" "FV3_GFS_v15_thompson_mynn_lam3km" "FV3_GFS_v17_p8" ) +suites=( "FV3_RAP" "FV3_HRRR" "FV3_GFS_v15_thompson_mynn_lam3km" "FV3_GFS_v17_p8" ) if [[ ${suites[@]} =~ "${CCPP_PHYS_SUITE}" ]] ; then file_ids=( "ss" "ls" ) for file_id in "${file_ids[@]}"; do @@ -340,7 +339,7 @@ cd ${DATA}/INPUT # relative_link_flag="FALSE" -if [ $(boolify "${CPL_AQM}") = "TRUE" ] || [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then +if [ $(boolify "${CPL_AQM}") = "TRUE" ]; then COMIN="${COMROOT}/${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR}" #temporary path, should be removed later target="${COMIN}/${NET}.${cycle}${dot_ensmem}.gfs_data.tile${TILE_RGNL}.halo${NH0}.nc" @@ -360,35 +359,17 @@ if [ $(boolify "${CPL_AQM}") = "TRUE" ] || [ $(boolify "${DO_SMOKE_DUST}") = "TR symlink="gfs_bndy.tile${TILE_RGNL}.${fhr}.nc" create_symlink_to_file $target $symlink ${relative_link_flag} done + target="${COMIN}/${NET}.${cycle}${dot_ensmem}.NEXUS_Expt.nc" + symlink="NEXUS_Expt.nc" + create_symlink_to_file $target $symlink ${relative_link_flag} - if [ $(boolify "${CPL_AQM}") = "TRUE" ]; then - target="${COMIN}/${NET}.${cycle}${dot_ensmem}.NEXUS_Expt.nc" - symlink="NEXUS_Expt.nc" + # create symlink to PT for point source in SRW-AQM + target="${COMIN}/${NET}.${cycle}${dot_ensmem}.PT.nc" + if [ -f ${target} ]; then + symlink="PT.nc" create_symlink_to_file $target $symlink ${relative_link_flag} - - # create symlink to PT for point source in SRW-AQM - target="${COMIN}/${NET}.${cycle}${dot_ensmem}.PT.nc" - if [ -f ${target} ]; then - symlink="PT.nc" - create_symlink_to_file $target $symlink ${relative_link_flag} - fi - else - ln -snf ${FIXsmoke}/${PREDEF_GRID_NAME}/dust12m_data.nc . - ln -snf ${FIXsmoke}/${PREDEF_GRID_NAME}/emi_data.nc . - - smokefile="${COMIN}/${SMOKE_DUST_FILE_PREFIX}_${PDY}${cyc}00.nc" - if [ -f ${smokefile} ]; then - ln -snf ${smokefile} ${SMOKE_DUST_FILE_PREFIX}.nc - else - if [ "${EBB_DCYCLE}" = "1" ]; then - ln -snf ${FIXsmoke}/${PREDEF_GRID_NAME}/dummy_24hr_smoke_ebbdc1.nc ${SMOKE_DUST_FILE_PREFIX}.nc - echo "WARNING: Smoke file is not available, use dummy_24hr_smoke_ebbdc1.nc instead" - else - ln -snf ${FIXsmoke}/${PREDEF_GRID_NAME}/dummy_24hr_smoke.nc ${SMOKE_DUST_FILE_PREFIX}.nc - echo "WARNING: Smoke file is not available, use dummy_24hr_smoke.nc instead" - fi - fi fi + else target="${INPUT_DATA}/${NET}.${cycle}${dot_ensmem}.gfs_data.tile${TILE_RGNL}.halo${NH0}.nc" symlink="gfs_data.nc" @@ -853,31 +834,38 @@ POST_STEP # #----------------------------------------------------------------------- # -# Copy RESTART directory to COMOUT. -# Move dyn and phy files to COMOUT. -# Copy AQM output product file to COMOUT only for AQM. +# Move RESTART directory to COMIN and create symlink in DATA only for +# NCO mode and when it is not empty. +# +# Move AQM output product file to COMOUT only for NCO mode in Online-CMAQ. +# Move dyn and phy files to COMIN only if run_post and write_dopost are off. # #----------------------------------------------------------------------- # -if [ $(boolify "${CPL_AQM}") = "TRUE" ] || [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ] ; then - COMOUT="${COMROOT}/${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR}" #temporary path - cp -Rp RESTART ${COMOUT} +if [ $(boolify "${CPL_AQM}") = "TRUE" ]; then + if [ "${RUN_ENVIR}" = "nco" ]; then + if [ -d "${COMIN}/RESTART" ] && [ "$(ls -A ${DATA}/RESTART)" ]; then + rm -rf "${COMIN}/RESTART" + fi + if [ "$(ls -A ${DATA}/RESTART)" ]; then + cp -Rp ${DATA}/RESTART ${COMIN} + fi + fi + cp -p ${DATA}/${AQM_RC_PRODUCT_FN} ${COMOUT}/${NET}.${cycle}${dot_ensmem}.${AQM_RC_PRODUCT_FN} + + fhr_ct=0 fhr=0 while [ $fhr -le ${FCST_LEN_HRS} ]; do fhr_ct=$(printf "%03d" $fhr) source_dyn="${DATA}/dynf${fhr_ct}.nc" source_phy="${DATA}/phyf${fhr_ct}.nc" - target_dyn="${COMIN}/${NET}.${cycle}${dot_ensmem}.dyn.f${fhr_ct}.${POST_OUTPUT_DOMAIN_NAME}.nc" - target_phy="${COMIN}/${NET}.${cycle}${dot_ensmem}.phy.f${fhr_ct}.${POST_OUTPUT_DOMAIN_NAME}.nc" - [ -f ${source_dyn} ] && mv ${source_dyn} ${target_dyn} - [ -f ${source_phy} ] && mv ${source_phy} ${target_phy} + target_dyn="${COMIN}/${NET}.${cycle}${dot_ensmem}.dyn.f${fhr_ct}.nc" + target_phy="${COMIN}/${NET}.${cycle}${dot_ensmem}.phy.f${fhr_ct}.nc" + [ -f ${source_dyn} ] && cp -p ${source_dyn} ${target_dyn} + [ -f ${source_phy} ] && cp -p ${source_phy} ${target_phy} (( fhr=fhr+1 )) - done - - if [ $(boolify "${CPL_AQM}") = "TRUE" ]; then - cp -p ${DATA}/${AQM_RC_PRODUCT_FN} ${COMOUT}/${NET}.${cycle}${dot_ensmem}.${AQM_RC_PRODUCT_FN} - fi + done fi # #----------------------------------------------------------------------- From 90e092c005dcaa54bbdf3824f89466674c07dc1f Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Tue, 27 Aug 2024 10:29:35 +0000 Subject: [PATCH 40/61] add if statement --- jobs/JREGIONAL_MAKE_ICS | 6 ++++-- jobs/JREGIONAL_MAKE_LBCS | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/jobs/JREGIONAL_MAKE_ICS b/jobs/JREGIONAL_MAKE_ICS index b33481d6a3..04ba1aa1ac 100755 --- a/jobs/JREGIONAL_MAKE_ICS +++ b/jobs/JREGIONAL_MAKE_ICS @@ -34,7 +34,7 @@ #----------------------------------------------------------------------- # . $USHdir/source_util_funcs.sh -for sect in user nco workflow ; do +for sect in user nco workflow cpl_aqm_parm smoke_dust_parm ; do source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} done . $USHdir/job_preamble.sh @@ -103,7 +103,9 @@ if [ $RUN_ENVIR = "community" ]; then mkdir -p $DATA cd $DATA fi -mkdir -p ${DATA_SHARE} +if [ $(boolify "${CPL_AQM}") = "TRUE" ] || [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ] ; then + mkdir -p ${DATA_SHARE} +fi # #----------------------------------------------------------------------- # diff --git a/jobs/JREGIONAL_MAKE_LBCS b/jobs/JREGIONAL_MAKE_LBCS index f90248f213..0d204ff3be 100755 --- a/jobs/JREGIONAL_MAKE_LBCS +++ b/jobs/JREGIONAL_MAKE_LBCS @@ -32,7 +32,7 @@ #----------------------------------------------------------------------- # . $USHdir/source_util_funcs.sh -for sect in user nco workflow ; do +for sect in user nco workflow cpl_aqm_parm smoke_dust_parm ; do source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} done . $USHdir/job_preamble.sh @@ -100,7 +100,9 @@ if [ "${RUN_ENVIR}" = "community" ]; then mkdir -p $DATA cd $DATA fi -mkdir -p ${DATA_SHARE} +if [ $(boolify "${CPL_AQM}") = "TRUE" ] || [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ] ; then + mkdir -p ${DATA_SHARE} +fi # #----------------------------------------------------------------------- # From be3423b0366f5b8b661984d5bad4b75e88022f15 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Tue, 27 Aug 2024 11:00:32 +0000 Subject: [PATCH 41/61] fix dependency issue in xml --- jobs/JREGIONAL_MAKE_ICS | 2 +- jobs/JREGIONAL_MAKE_LBCS | 2 +- parm/wflow/coldstart.yaml | 2 +- parm/wflow/default_workflow.yaml | 4 ++-- scripts/exsrw_forecast.sh | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/jobs/JREGIONAL_MAKE_ICS b/jobs/JREGIONAL_MAKE_ICS index 04ba1aa1ac..fa8f6a5d44 100755 --- a/jobs/JREGIONAL_MAKE_ICS +++ b/jobs/JREGIONAL_MAKE_ICS @@ -103,7 +103,7 @@ if [ $RUN_ENVIR = "community" ]; then mkdir -p $DATA cd $DATA fi -if [ $(boolify "${CPL_AQM}") = "TRUE" ] || [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ] ; then +if [ $(boolify "${CPL_AQM}") = "TRUE" ] || [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then mkdir -p ${DATA_SHARE} fi # diff --git a/jobs/JREGIONAL_MAKE_LBCS b/jobs/JREGIONAL_MAKE_LBCS index 0d204ff3be..b05051ae33 100755 --- a/jobs/JREGIONAL_MAKE_LBCS +++ b/jobs/JREGIONAL_MAKE_LBCS @@ -100,7 +100,7 @@ if [ "${RUN_ENVIR}" = "community" ]; then mkdir -p $DATA cd $DATA fi -if [ $(boolify "${CPL_AQM}") = "TRUE" ] || [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ] ; then +if [ $(boolify "${CPL_AQM}") = "TRUE" ] || [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then mkdir -p ${DATA_SHARE} fi # diff --git a/parm/wflow/coldstart.yaml b/parm/wflow/coldstart.yaml index c3e024ea2a..980feaee3d 100644 --- a/parm/wflow/coldstart.yaml +++ b/parm/wflow/coldstart.yaml @@ -150,7 +150,7 @@ metatask_run_ensemble: task_run_fcst_mem#mem#: <<: *default_task - command: '{% if smoke_dust_parm.get("DO_SMOKE_DUST") %}&LOAD_MODULES_RUN_TASK; "forecast" "&JOBSdir;/JSRW_FORECAST" {% else %}&LOAD_MODULES_RUN_TASK; "run_fcst" "&JOBSdir;/JREGIONAL_RUN_FCST"{% endif %}' + command: '{% if smoke_dust_parm.get("DO_SMOKE_DUST") or cpl_aqm_parm.get("CPL_AQM") %}&LOAD_MODULES_RUN_TASK; "forecast" "&JOBSdir;/JSRW_FORECAST" {% else %}&LOAD_MODULES_RUN_TASK; "run_fcst" "&JOBSdir;/JREGIONAL_RUN_FCST"{% endif %}' envars: <<: *default_vars SLASH_ENSMEM_SUBDIR: '&SLASH_ENSMEM_SUBDIR;' diff --git a/parm/wflow/default_workflow.yaml b/parm/wflow/default_workflow.yaml index e37fdae1ea..755cc357fc 100644 --- a/parm/wflow/default_workflow.yaml +++ b/parm/wflow/default_workflow.yaml @@ -37,9 +37,9 @@ rocoto: COMROOT: '{{ nco.PTMP }}/&envir;/com' DATAROOT: '{{ nco.PTMP }}/&envir;/tmp' DCOMROOT: '{{ nco.PTMP }}/&envir;/dcom' - COMIN_DIR: '{% if user.RUN_ENVIR == "nco" %}&COMROOT;/&NET;/&model_ver;/&RUN;.@Y@m@d/@H{% else %}{{ workflow.EXPTDIR }}/@Y@m@d@H{% endif %}' + COMIN_DIR: '{% if smoke_dust_parm.get("DO_SMOKE_DUST") or cpl_aqm_parm.get("CPL_AQM") %}&COMROOT;/&NET;/&model_ver;/&RUN;.@Y@m@d/@H{% else %}{{ workflow.EXPTDIR }}/@Y@m@d@H{% endif %}' FCST_DIR: '{% if user.RUN_ENVIR == "nco" %}&DATAROOT;/run_fcst_mem#mem#_@Y@m@d@H{% else %}{{ workflow.EXPTDIR }}/@Y@m@d@H{% endif %}' - LOGDIR: '{% if user.RUN_ENVIR == "nco" %}&COMROOT;/output/logs/@Y@m@d{% else %}{{ workflow.EXPTDIR }}/log{% endif %}' + LOGDIR: '{% if smoke_dust_parm.get("DO_SMOKE_DUST") or cpl_aqm_parm.get("CPL_AQM") %}&COMROOT;/output/logs/@Y@m@d{% else %}{{ workflow.EXPTDIR }}/log{% endif %}' attrs: cyclethrottle: "200" realtime: "F" diff --git a/scripts/exsrw_forecast.sh b/scripts/exsrw_forecast.sh index 6d05fe4d36..e270f47c5a 100755 --- a/scripts/exsrw_forecast.sh +++ b/scripts/exsrw_forecast.sh @@ -679,7 +679,7 @@ export err=$?; err_chk # #----------------------------------------------------------------------- # -if [ $(boolify "${CPL_AQM}") = "TRUE" ] || [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ] ; then +if [ $(boolify "${CPL_AQM}") = "TRUE" ] || [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then cp -Rp RESTART ${COMOUT} fhr=0 From 733c3cb0df790d53433382b6e548ba424ac150a8 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Tue, 27 Aug 2024 12:04:42 +0000 Subject: [PATCH 42/61] fix xarray file permission issue --- ush/add_smoke.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ush/add_smoke.py b/ush/add_smoke.py index 046073f970..17a9e751fa 100755 --- a/ush/add_smoke.py +++ b/ush/add_smoke.py @@ -42,6 +42,7 @@ def main(): # Open the target file and load it into memory file_input = xr.open_dataset(target_file).load() + file_input.close() # to remove permission error below print("TARGET FILE:",file_input) # Drop the 'smoke' variable if it exists in both the source and target files if 'smoke' in file_input.variables and 'smoke' in data_to_extract.variables: From cc93bd37a0d554f963b7926489861778f756eee7 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Tue, 27 Aug 2024 12:35:09 +0000 Subject: [PATCH 43/61] add print to python script --- ush/add_smoke.py | 1 + 1 file changed, 1 insertion(+) diff --git a/ush/add_smoke.py b/ush/add_smoke.py index 17a9e751fa..b49f672e6d 100755 --- a/ush/add_smoke.py +++ b/ush/add_smoke.py @@ -75,6 +75,7 @@ def main(): file_input['dust'][1:66,:,:] = dust_2_add file_input['coarsepm'][1:66,:,:] = coarsepm_2_add + print("FINAL FILE:", file_input) # Save the modified dataset back to the file file_input.to_netcdf(target_file, mode='w') From 55d8d936a156060b241434d36967a882e1567bdc Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Tue, 27 Aug 2024 14:00:16 +0000 Subject: [PATCH 44/61] add smoke flag to devbuild --- devbuild.sh | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/devbuild.sh b/devbuild.sh index 61b20fecaf..e52951653f 100755 --- a/devbuild.sh +++ b/devbuild.sh @@ -15,7 +15,7 @@ OPTIONS compiler to use; default depends on platform (e.g. intel | gnu | cray | gccgfortran) -a, --app=APPLICATION - weather model application to build; for example, ATMAQ for Online-CMAQ + weather model application to build; for example, ATMAQ for SRW-AQM (e.g. ATM | ATMAQ | ATMW | S2S | S2SW) --ccpp="CCPP_SUITE1,CCPP_SUITE2..." CCPP suites (CCPP_SUITES) to include in build; delimited with ',' @@ -50,6 +50,8 @@ OPTIONS number of build jobs; defaults to 4 --use-sub-modules Use sub-component modules instead of top-level level SRW modules + --smoke + Build the app for Smoke and Dust (with production branch) -v, --verbose build with verbose output @@ -82,6 +84,7 @@ Settings: DISABLE_OPTIONS=${DISABLE_OPTIONS} REMOVE=${REMOVE} CONTINUE=${CONTINUE} + SMOKE=${SMOKE} BUILD_TYPE=${BUILD_TYPE} BUILD_JOBS=${BUILD_JOBS} VERBOSE=${VERBOSE} @@ -114,6 +117,7 @@ BUILD_TYPE="RELEASE" BUILD_JOBS=4 REMOVE=false CONTINUE=false +SMOKE=false VERBOSE=false # Turn off all apps to build and choose default later @@ -160,6 +164,7 @@ while :; do --clean) CLEAN=true ;; --build) BUILD=true ;; --move) MOVE=true ;; + --smoke) SMOKE=true ;; --build-dir=?*) BUILD_DIR=${1#*=} ;; --build-dir|--build-dir=) usage_error "$1 requires argument." ;; --install-dir=?*) INSTALL_DIR=${1#*=} ;; @@ -314,7 +319,11 @@ if [ -f ${RUN_VERSION_FILE} ]; then fi # set MODULE_FILE for this platform/compiler combination -MODULE_FILE="build_${PLATFORM}_${COMPILER}_prod" +if [ "${SMOKE}" = true ]; then + MODULE_FILE="build_${PLATFORM}_${COMPILER}_prod" +else + MODULE_FILE="build_${PLATFORM}_${COMPILER}" +fi if [ ! -f "${SRW_DIR}/modulefiles/${MODULE_FILE}.lua" ]; then printf "ERROR: module file does not exist for platform/compiler\n" >&2 printf " MODULE_FILE=${MODULE_FILE}\n" >&2 From 6f135d71b04a8a56ff55c4528d78442bde695d96 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Tue, 27 Aug 2024 15:31:24 +0000 Subject: [PATCH 45/61] update log script to reduce file size --- ush/launch_FV3LAM_wflow.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ush/launch_FV3LAM_wflow.sh b/ush/launch_FV3LAM_wflow.sh index 7c26511f4f..d9369c631e 100644 --- a/ush/launch_FV3LAM_wflow.sh +++ b/ush/launch_FV3LAM_wflow.sh @@ -222,7 +222,7 @@ Output of rocotostat_cmd is: ~~~~~~~~~~~~~~~~~~~~~~~~~~~ ${rocotostat_output} -" >> "${WFLOW_LAUNCH_LOG_FN}" 2>&1 +" > "${WFLOW_LAUNCH_LOG_FN}" 2>&1 # #----------------------------------------------------------------------- # From 5979d184ef375d390abfdc21d087ca5c7469d720 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Tue, 27 Aug 2024 17:44:56 +0000 Subject: [PATCH 46/61] remove duplicates from aqm scripts --- scripts/exsrw_aqm_ics.sh | 2 +- scripts/exsrw_aqm_lbcs.sh | 2 +- scripts/exsrw_bias_correction_o3.sh | 2 +- scripts/exsrw_bias_correction_pm25.sh | 2 +- scripts/exsrw_fire_emission.sh | 2 +- scripts/exsrw_nexus_emission.sh | 2 +- scripts/exsrw_nexus_gfs_sfc.sh | 2 +- scripts/exsrw_nexus_post_split.sh | 2 +- scripts/exsrw_point_source.sh | 2 +- scripts/exsrw_post_stat_o3.sh | 2 +- scripts/exsrw_post_stat_pm25.sh | 2 +- scripts/exsrw_pre_post_stat.sh | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/scripts/exsrw_aqm_ics.sh b/scripts/exsrw_aqm_ics.sh index 4fd040e597..f2b3d471f8 100755 --- a/scripts/exsrw_aqm_ics.sh +++ b/scripts/exsrw_aqm_ics.sh @@ -8,7 +8,7 @@ #----------------------------------------------------------------------- # . ${USHsrw}/source_util_funcs.sh -for sect in user nco platform workflow nco global verification cpl_aqm_parm \ +for sect in user nco platform workflow global verification cpl_aqm_parm \ constants fixed_files grid_params ; do source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} done diff --git a/scripts/exsrw_aqm_lbcs.sh b/scripts/exsrw_aqm_lbcs.sh index e8fdf6620f..416413abcc 100755 --- a/scripts/exsrw_aqm_lbcs.sh +++ b/scripts/exsrw_aqm_lbcs.sh @@ -8,7 +8,7 @@ #----------------------------------------------------------------------- # . ${USHsrw}/source_util_funcs.sh -for sect in user nco platform workflow nco global verification cpl_aqm_parm \ +for sect in user nco platform workflow global verification cpl_aqm_parm \ constants fixed_files grid_params \ task_get_extrn_lbcs task_make_lbcs task_make_orog ; do source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} diff --git a/scripts/exsrw_bias_correction_o3.sh b/scripts/exsrw_bias_correction_o3.sh index 343e7e6f2b..f09626dfbb 100755 --- a/scripts/exsrw_bias_correction_o3.sh +++ b/scripts/exsrw_bias_correction_o3.sh @@ -8,7 +8,7 @@ #----------------------------------------------------------------------- # . ${USHsrw}/source_util_funcs.sh -for sect in user nco platform workflow nco global verification cpl_aqm_parm \ +for sect in user nco platform workflow global verification cpl_aqm_parm \ constants fixed_files grid_params \ task_bias_correction_o3 ; do source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} diff --git a/scripts/exsrw_bias_correction_pm25.sh b/scripts/exsrw_bias_correction_pm25.sh index 70cf512589..fbde40ecde 100755 --- a/scripts/exsrw_bias_correction_pm25.sh +++ b/scripts/exsrw_bias_correction_pm25.sh @@ -8,7 +8,7 @@ #----------------------------------------------------------------------- # . ${USHsrw}/source_util_funcs.sh -for sect in user nco platform workflow nco global verification cpl_aqm_parm \ +for sect in user nco platform workflow global verification cpl_aqm_parm \ constants fixed_files grid_params \ task_bias_correction_pm25 ; do source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} diff --git a/scripts/exsrw_fire_emission.sh b/scripts/exsrw_fire_emission.sh index 3ae78422f5..f92d8a43e8 100755 --- a/scripts/exsrw_fire_emission.sh +++ b/scripts/exsrw_fire_emission.sh @@ -8,7 +8,7 @@ #----------------------------------------------------------------------- # . ${USHsrw}/source_util_funcs.sh -for sect in user nco platform workflow nco global verification cpl_aqm_parm \ +for sect in user nco platform workflow global verification cpl_aqm_parm \ constants fixed_files grid_params ; do source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} done diff --git a/scripts/exsrw_nexus_emission.sh b/scripts/exsrw_nexus_emission.sh index 6c0476dd8d..92891ca163 100755 --- a/scripts/exsrw_nexus_emission.sh +++ b/scripts/exsrw_nexus_emission.sh @@ -8,7 +8,7 @@ #----------------------------------------------------------------------- # . ${USHsrw}/source_util_funcs.sh -for sect in user nco platform workflow nco global verification cpl_aqm_parm \ +for sect in user nco platform workflow global verification cpl_aqm_parm \ constants fixed_files grid_params \ task_nexus_emission ; do source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} diff --git a/scripts/exsrw_nexus_gfs_sfc.sh b/scripts/exsrw_nexus_gfs_sfc.sh index cadc27b89c..77e6a072e1 100755 --- a/scripts/exsrw_nexus_gfs_sfc.sh +++ b/scripts/exsrw_nexus_gfs_sfc.sh @@ -8,7 +8,7 @@ #----------------------------------------------------------------------- # . ${USHsrw}/source_util_funcs.sh -for sect in user nco platform workflow nco global verification cpl_aqm_parm \ +for sect in user nco platform workflow global verification cpl_aqm_parm \ constants fixed_files grid_params ; do source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} done diff --git a/scripts/exsrw_nexus_post_split.sh b/scripts/exsrw_nexus_post_split.sh index 151e0a2ea5..a49ed4399e 100755 --- a/scripts/exsrw_nexus_post_split.sh +++ b/scripts/exsrw_nexus_post_split.sh @@ -8,7 +8,7 @@ #----------------------------------------------------------------------- # . ${USHsrw}/source_util_funcs.sh -for sect in user nco platform workflow nco global verification cpl_aqm_parm \ +for sect in user nco platform workflow global verification cpl_aqm_parm \ constants fixed_files grid_params ; do source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} done diff --git a/scripts/exsrw_point_source.sh b/scripts/exsrw_point_source.sh index 4cd693506c..caafbec5ef 100755 --- a/scripts/exsrw_point_source.sh +++ b/scripts/exsrw_point_source.sh @@ -8,7 +8,7 @@ #----------------------------------------------------------------------- # . ${USHsrw}/source_util_funcs.sh -for sect in user nco platform workflow nco global verification cpl_aqm_parm \ +for sect in user nco platform workflow global verification cpl_aqm_parm \ constants fixed_files grid_params \ task_point_source task_run_fcst ; do source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} diff --git a/scripts/exsrw_post_stat_o3.sh b/scripts/exsrw_post_stat_o3.sh index dfcdd24ffa..edf44e15c9 100755 --- a/scripts/exsrw_post_stat_o3.sh +++ b/scripts/exsrw_post_stat_o3.sh @@ -8,7 +8,7 @@ #----------------------------------------------------------------------- # . ${USHsrw}/source_util_funcs.sh -for sect in user nco platform workflow nco global verification cpl_aqm_parm \ +for sect in user nco platform workflow global verification cpl_aqm_parm \ constants fixed_files grid_params \ task_run_post ; do source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} diff --git a/scripts/exsrw_post_stat_pm25.sh b/scripts/exsrw_post_stat_pm25.sh index bdbf1fcbc5..7160f9caea 100755 --- a/scripts/exsrw_post_stat_pm25.sh +++ b/scripts/exsrw_post_stat_pm25.sh @@ -8,7 +8,7 @@ #----------------------------------------------------------------------- # . ${USHsrw}/source_util_funcs.sh -for sect in user nco platform workflow nco global verification cpl_aqm_parm \ +for sect in user nco platform workflow global verification cpl_aqm_parm \ constants fixed_files grid_params \ task_run_post ; do source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} diff --git a/scripts/exsrw_pre_post_stat.sh b/scripts/exsrw_pre_post_stat.sh index f6ec6a9a7d..1290c30bcd 100755 --- a/scripts/exsrw_pre_post_stat.sh +++ b/scripts/exsrw_pre_post_stat.sh @@ -8,7 +8,7 @@ #----------------------------------------------------------------------- # . ${USHsrw}/source_util_funcs.sh -for sect in user nco platform workflow nco global verification cpl_aqm_parm \ +for sect in user nco platform workflow global verification cpl_aqm_parm \ constants fixed_files grid_params \ task_run_post ; do source_yaml ${GLOBAL_VAR_DEFNS_FP} ${sect} From a2a7b946e4f457c92341afcd943714db39238ec8 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Tue, 27 Aug 2024 18:04:31 +0000 Subject: [PATCH 47/61] introduct upp_post yaml --- jobs/{JSRW_POST => JSRW_UPP_POST} | 2 +- parm/wflow/smoke_dust.yaml | 25 --------- parm/wflow/upp_post.yaml | 55 ++++++++++++++++++++ scripts/{exsrw_post.sh => exsrw_upp_post.sh} | 0 ush/config.aqm.yaml | 2 +- ush/config.smoke_dust.yaml | 2 +- 6 files changed, 58 insertions(+), 28 deletions(-) rename jobs/{JSRW_POST => JSRW_UPP_POST} (99%) create mode 100644 parm/wflow/upp_post.yaml rename scripts/{exsrw_post.sh => exsrw_upp_post.sh} (100%) diff --git a/jobs/JSRW_POST b/jobs/JSRW_UPP_POST similarity index 99% rename from jobs/JSRW_POST rename to jobs/JSRW_UPP_POST index 927e26558b..09f58eed4e 100755 --- a/jobs/JSRW_POST +++ b/jobs/JSRW_UPP_POST @@ -164,7 +164,7 @@ fi export pgmout="${DATA}/OUTPUT.$$" env -${SCRIPTSsrw}/exsrw_post.sh +${SCRIPTSsrw}/exsrw_upp_post.sh export err=$?; err_chk if [ -e "$pgmout" ]; then diff --git a/parm/wflow/smoke_dust.yaml b/parm/wflow/smoke_dust.yaml index e51807ac86..701ea012a4 100644 --- a/parm/wflow/smoke_dust.yaml +++ b/parm/wflow/smoke_dust.yaml @@ -88,28 +88,3 @@ task_prepstart: attrs: task: smoke_dust -metatask_post: - var: - mem: '{% if global.DO_ENSEMBLE %}{%- for m in range(1, global.NUM_ENS_MEMBERS+1) -%}{{ "%03d "%m }}{%- endfor -%} {% else %}{{ "000"|string }}{% endif %}' - metatask_post_mem#mem#_all_fhrs: - var: - fhr: '{% for h in range(0, workflow.LONG_FCST_LEN+1) %}{{ " %03d" % h }}{% endfor %}' - cycledef: '{% for h in range(0, workflow.LONG_FCST_LEN+1) %}{% if h <= workflow.FCST_LEN_CYCL|min %}forecast {% else %}long_forecast {% endif %}{% endfor %}' - task_post_mem#mem#_f#fhr#: - <<: *default_smoke_dust - attrs: - cycledefs: '#cycledef#' - maxtries: '2' - envars: - <<: *default_vars - fhr: '#fhr#' - command: '&LOAD_MODULES_RUN_TASK; "post" "&HOMEdir;/jobs/JSRW_POST"' - join: !cycstr '&LOGDIR;/{{ jobname }}_@Y@m@d@H&LOGEXT;' - nnodes: 2 - ppn: 24 - memory: 64G - dependency: - taskdep: - attrs: - task: run_fcst_mem#mem# - diff --git a/parm/wflow/upp_post.yaml b/parm/wflow/upp_post.yaml new file mode 100644 index 0000000000..5b791118c6 --- /dev/null +++ b/parm/wflow/upp_post.yaml @@ -0,0 +1,55 @@ +default_upp_post_task: &default_upp_post + account: '&ACCOUNT;' + attrs: + cycledefs: forecast + maxtries: '2' + envars: &default_vars + GLOBAL_VAR_DEFNS_FP: '&GLOBAL_VAR_DEFNS_FP;' + HOMEdir: '&HOMEdir;' + envir: '&envir;' + model_ver: '&model_ver;' + KEEPDATA: '&KEEPDATA;' + SENDCOM: '&SENDCOM;' + COMROOT: '&COMROOT;' + DATAROOT: '&DATAROOT;' + DCOMROOT: '&DCOMROOT;' + LOGDIR: !cycstr "&LOGDIR;" + PDY: !cycstr "@Y@m@d" + cyc: !cycstr "@H" + nprocs: '{{ parent.nnodes * parent.ppn // 1 }}' + subcyc: !cycstr "@M" + SLASH_ENSMEM_SUBDIR: '&SLASH_ENSMEM_SUBDIR;' + ENSMEM_INDX: '#mem#' + native: '{{ platform.SCHED_NATIVE_CMD }}' + nnodes: 1 + nodes: '{{ nnodes }}:ppn={{ ppn }}' + partition: '{% if platform.get("PARTITION_DEFAULT") %}&PARTITION_DEFAULT;{% else %}None{% endif %}' + ppn: 1 + queue: '&QUEUE_DEFAULT;' + walltime: 00:30:00 + +metatask_post: + var: + mem: '{% if global.DO_ENSEMBLE %}{%- for m in range(1, global.NUM_ENS_MEMBERS+1) -%}{{ "%03d "%m }}{%- endfor -%} {% else %}{{ "000"|string }}{% endif %}' + metatask_post_mem#mem#_all_fhrs: + var: + fhr: '{% for h in range(0, workflow.LONG_FCST_LEN+1) %}{{ " %03d" % h }}{% endfor %}' + cycledef: '{% for h in range(0, workflow.LONG_FCST_LEN+1) %}{% if h <= workflow.FCST_LEN_CYCL|min %}forecast {% else %}long_forecast {% endif %}{% endfor %}' + task_post_mem#mem#_f#fhr#: + <<: *default_upp_post + attrs: + cycledefs: '#cycledef#' + maxtries: '2' + envars: + <<: *default_vars + fhr: '#fhr#' + command: '&LOAD_MODULES_RUN_TASK; "upp_post" "&HOMEdir;/jobs/JSRW_UPP_POST"' + join: !cycstr '&LOGDIR;/{{ jobname }}_@Y@m@d@H&LOGEXT;' + nnodes: 2 + ppn: 24 + memory: 64G + dependency: + taskdep: + attrs: + task: run_fcst_mem#mem# + diff --git a/scripts/exsrw_post.sh b/scripts/exsrw_upp_post.sh similarity index 100% rename from scripts/exsrw_post.sh rename to scripts/exsrw_upp_post.sh diff --git a/ush/config.aqm.yaml b/ush/config.aqm.yaml index 21a73591ee..649b857b1d 100644 --- a/ush/config.aqm.yaml +++ b/ush/config.aqm.yaml @@ -31,7 +31,7 @@ nco: RUN_default: aqm rocoto: tasks: - taskgroups: '{{ ["parm/wflow/prep.yaml", "parm/wflow/aqm_prep.yaml", "parm/wflow/coldstart.yaml", "parm/wflow/post.yaml"]|include }}' + taskgroups: '{{ ["parm/wflow/prep.yaml", "parm/wflow/aqm_prep.yaml", "parm/wflow/coldstart.yaml", "parm/wflow/upp_post.yaml"]|include }}' # task_aqm_ics_ext: # uncomment this in case of COLDSTART: true metatask_run_ensemble: task_run_fcst_mem#mem#: diff --git a/ush/config.smoke_dust.yaml b/ush/config.smoke_dust.yaml index 5f73628fef..f6b415dbd7 100644 --- a/ush/config.smoke_dust.yaml +++ b/ush/config.smoke_dust.yaml @@ -31,7 +31,7 @@ nco: RUN_default: smoke_dust rocoto: tasks: - taskgroups: '{{ ["parm/wflow/prep.yaml", "parm/wflow/coldstart.yaml", "parm/wflow/smoke_dust.yaml"]|include }}' + taskgroups: '{{ ["parm/wflow/prep.yaml", "parm/wflow/smoke_dust.yaml", "parm/wflow/coldstart.yaml", "parm/wflow/upp_post.yaml"]|include }}' metatask_run_ensemble: task_run_fcst_mem#mem#: walltime: 02:00:00 From e7eda1a6d1a2173ee30d3ce388a3e5ac211682fa Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Wed, 28 Aug 2024 02:37:35 +0000 Subject: [PATCH 48/61] fix crontab issue --- ush/get_crontab_contents.py | 2 +- ush/launch_FV3LAM_wflow.sh | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ush/get_crontab_contents.py b/ush/get_crontab_contents.py index 6b0548141c..fbdf80dae9 100755 --- a/ush/get_crontab_contents.py +++ b/ush/get_crontab_contents.py @@ -162,7 +162,7 @@ def delete_crontab_line(called_from_cron, machine, crontab_line, debug): crontab_contents = crontab_contents.replace(crontab_line + "\n", "") crontab_contents = crontab_contents.replace(crontab_line, "") else: - print(f"\nWARNING: line not found in crontab, nothing to remove:\n {crontab_line}\n") + print(f"\nWARNING: line not found in crontab, nothing to remove:\n{crontab_line}\n") run_command(f"""echo '{crontab_contents}' | {crontab_cmd}""") diff --git a/ush/launch_FV3LAM_wflow.sh b/ush/launch_FV3LAM_wflow.sh index d9369c631e..a733d0a6c2 100644 --- a/ush/launch_FV3LAM_wflow.sh +++ b/ush/launch_FV3LAM_wflow.sh @@ -353,9 +353,9 @@ script for this experiment: # Remove CRONTAB_LINE from cron table # if [ "${called_from_cron}" = "TRUE" ]; then - python3 $USHdir/get_crontab_contents.py --remove -m=${machine} -l="${CRONTAB_LINE}" -c -d + $USHdir/get_crontab_contents.py --remove -m=${machine} -l='${CRONTAB_LINE}' -c -d else - python3 $USHdir/get_crontab_contents.py --remove -m=${machine} -l="${CRONTAB_LINE}" -d + $USHdir/get_crontab_contents.py --remove -m=${machine} -l='${CRONTAB_LINE}' -d fi fi # From 2aa28a5a5e67d310d9ace863e107684049c23d52 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Wed, 28 Aug 2024 15:39:30 +0000 Subject: [PATCH 49/61] remove aqm_ics_ext --- jobs/JSRW_AQM_ICS | 14 -- jobs/JSRW_AQM_LBCS | 14 -- jobs/JSRW_PREPSTART | 2 +- parm/wflow/aqm_prep.yaml | 37 +--- parm/wflow/coldstart.yaml | 2 +- parm/wflow/default_workflow.yaml | 1 + parm/wflow/smoke_dust.yaml | 12 +- scripts/exsrw_aqm_ics.sh | 174 +++++++++--------- scripts/exsrw_forecast.sh | 6 +- scripts/exsrw_upp_post.sh | 4 +- ...fig.aqm_grid_AQM_NA13km_suite_GFS_v16.yaml | 4 +- ush/config.aqm.yaml | 1 - ush/config.smoke_dust.yaml | 2 +- 13 files changed, 115 insertions(+), 158 deletions(-) diff --git a/jobs/JSRW_AQM_ICS b/jobs/JSRW_AQM_ICS index 5d5f6d970e..177eb7c2ad 100755 --- a/jobs/JSRW_AQM_ICS +++ b/jobs/JSRW_AQM_ICS @@ -140,20 +140,6 @@ fi # #----------------------------------------------------------------------- # -# Set the name of and create the directory in which the output from this -# script will be placed (if it doesn't already exist). -# -#----------------------------------------------------------------------- -# -if [ $RUN_ENVIR = "nco" ]; then - export INPUT_DATA="${COMIN}" -else - export INPUT_DATA="${COMIN}${SLASH_ENSMEM_SUBDIR}/INPUT" -fi -mkdir -p "${INPUT_DATA}" -# -#----------------------------------------------------------------------- -# # Call the ex-script for this J-job. # #----------------------------------------------------------------------- diff --git a/jobs/JSRW_AQM_LBCS b/jobs/JSRW_AQM_LBCS index 9279dbe190..3e7332d865 100755 --- a/jobs/JSRW_AQM_LBCS +++ b/jobs/JSRW_AQM_LBCS @@ -142,20 +142,6 @@ fi # #----------------------------------------------------------------------- # -# Set the name of and create the directory in which the output from this -# script will be placed (if it doesn't already exist). -# -#----------------------------------------------------------------------- -# -if [ $RUN_ENVIR = "nco" ]; then - export INPUT_DATA="${COMIN}" -else - export INPUT_DATA="${EXPTDIR}/${PDY}${cyc}${SLASH_ENSMEM_SUBDIR}/INPUT" -fi -mkdir -p "${INPUT_DATA}" -# -#----------------------------------------------------------------------- -# # Call the ex-script for this J-job. # #----------------------------------------------------------------------- diff --git a/jobs/JSRW_PREPSTART b/jobs/JSRW_PREPSTART index 30b961513d..50476d6f45 100755 --- a/jobs/JSRW_PREPSTART +++ b/jobs/JSRW_PREPSTART @@ -3,7 +3,7 @@ # #----------------------------------------------------------------------- # -# This script runs prepstart +# This script runs prepstart to update IC files for Smoke/Dust # #----------------------------------------------------------------------- # diff --git a/parm/wflow/aqm_prep.yaml b/parm/wflow/aqm_prep.yaml index d90bbde60f..d8c6b7a9f4 100644 --- a/parm/wflow/aqm_prep.yaml +++ b/parm/wflow/aqm_prep.yaml @@ -96,15 +96,14 @@ task_point_source: left: staged_grid right: '{% if not rocoto.get("tasks", {}).get("task_make_grid") %}staged_grid{% endif %}' -task_aqm_ics_ext: +task_aqm_ics: <<: *default_aqm attrs: - cycledefs: at_start + cycledefs: forecast maxtries: '2' command: '&LOAD_MODULES_RUN_TASK; "aqm_ics" "&HOMEdir;/jobs/JSRW_AQM_ICS"' envars: <<: *default_vars - PREV_CYCLE_DIR: '&WARMSTART_CYCLE_DIR;' join: !cycstr '&LOGDIR;/{{ jobname }}_@Y@m@d@H&LOGEXT;' memory: 64G dependency: @@ -113,40 +112,22 @@ task_aqm_ics_ext: attrs: task: make_ics_mem000 or: - datadep_date_tag_tracer: + datadep_coldstart: attrs: age: 00:00:00:05 - text: !cycstr '&WARMSTART_CYCLE_DIR;/RESTART/@Y@m@d.@H@M@S.fv_tracer.res.tile1.nc' - datadep_tracer: + text: !cycstr '{{ workflow.EXPTDIR }}/task_skip_coldstart_@Y@m@d@H00.txt' + datadep_warmstart_tracer: attrs: age: 00:00:00:05 - text: !cycstr '&WARMSTART_CYCLE_DIR;/RESTART/fv_tracer.res.tile1.nc' - -task_aqm_ics: - <<: *default_aqm - attrs: - cycledefs: cycled_from_second - maxtries: '2' - command: '&LOAD_MODULES_RUN_TASK; "aqm_ics" "&HOMEdir;/jobs/JSRW_AQM_ICS"' - envars: - <<: *default_vars - PREV_CYCLE_DIR: '&COMIN_DIR;' - join: !cycstr '&LOGDIR;/{{ jobname }}_@Y@m@d@H&LOGEXT;' - memory: 64G - dependency: - and: - taskdep: - attrs: - task: make_ics_mem000 - or: - datadep_date_tag_tracer: + text: !cycstr '&WARMSTART_CYCLE_DIR;/RESTART/@Y@m@d.@H@M@S.fv_tracer.res.tile1.nc' + datadep_comin_tracer: attrs: age: 00:00:00:05 text: '&COMIN_DIR;/RESTART/@Y@m@d.@H@M@S.fv_tracer.res.tile1.nc' - datadep_tracer: + datadep_datashare_tracer: attrs: age: 00:00:00:05 - text: '&COMIN_DIR;/RESTART/fv_tracer.res.tile1.nc' + text: '&DATASHARE_DIR;/RESTART/@Y@m@d.@H@M@S.fv_tracer.res.tile1.nc' task_aqm_lbcs: <<: *default_aqm diff --git a/parm/wflow/coldstart.yaml b/parm/wflow/coldstart.yaml index 980feaee3d..53a685c76e 100644 --- a/parm/wflow/coldstart.yaml +++ b/parm/wflow/coldstart.yaml @@ -150,7 +150,7 @@ metatask_run_ensemble: task_run_fcst_mem#mem#: <<: *default_task - command: '{% if smoke_dust_parm.get("DO_SMOKE_DUST") or cpl_aqm_parm.get("CPL_AQM") %}&LOAD_MODULES_RUN_TASK; "forecast" "&JOBSdir;/JSRW_FORECAST" {% else %}&LOAD_MODULES_RUN_TASK; "run_fcst" "&JOBSdir;/JREGIONAL_RUN_FCST"{% endif %}' + command: '{% if smoke_dust_parm.DO_SMOKE_DUST or cpl_aqm_parm.CPL_AQM %}&LOAD_MODULES_RUN_TASK; "forecast" "&JOBSdir;/JSRW_FORECAST" {% else %}&LOAD_MODULES_RUN_TASK; "run_fcst" "&JOBSdir;/JREGIONAL_RUN_FCST"{% endif %}' envars: <<: *default_vars SLASH_ENSMEM_SUBDIR: '&SLASH_ENSMEM_SUBDIR;' diff --git a/parm/wflow/default_workflow.yaml b/parm/wflow/default_workflow.yaml index 755cc357fc..efc945f51a 100644 --- a/parm/wflow/default_workflow.yaml +++ b/parm/wflow/default_workflow.yaml @@ -38,6 +38,7 @@ rocoto: DATAROOT: '{{ nco.PTMP }}/&envir;/tmp' DCOMROOT: '{{ nco.PTMP }}/&envir;/dcom' COMIN_DIR: '{% if smoke_dust_parm.get("DO_SMOKE_DUST") or cpl_aqm_parm.get("CPL_AQM") %}&COMROOT;/&NET;/&model_ver;/&RUN;.@Y@m@d/@H{% else %}{{ workflow.EXPTDIR }}/@Y@m@d@H{% endif %}' + DATASHARE_DIR: '&DATAROOT;/DATA_SHARE/@Y@m@d@H' FCST_DIR: '{% if user.RUN_ENVIR == "nco" %}&DATAROOT;/run_fcst_mem#mem#_@Y@m@d@H{% else %}{{ workflow.EXPTDIR }}/@Y@m@d@H{% endif %}' LOGDIR: '{% if smoke_dust_parm.get("DO_SMOKE_DUST") or cpl_aqm_parm.get("CPL_AQM") %}&COMROOT;/output/logs/@Y@m@d{% else %}{{ workflow.EXPTDIR }}/log{% endif %}' attrs: diff --git a/parm/wflow/smoke_dust.yaml b/parm/wflow/smoke_dust.yaml index 701ea012a4..18bab50787 100644 --- a/parm/wflow/smoke_dust.yaml +++ b/parm/wflow/smoke_dust.yaml @@ -64,14 +64,14 @@ task_smoke_dust: attrs: age: 00:00:00:05 text: !cycstr '{{ workflow.EXPTDIR }}/task_skip_coldstart_@Y@m@d@H00.txt' - datadep_date_tag_tracer: + datadep_warmstart_tracer: attrs: - age: 00:00:05:00 - text: '&COMIN_DIR;/RESTART/@Y@m@d.@H0000.fv_tracer.res.tile1.nc' - datadep_tracer: + age: 00:00:00:05 + text: !cycstr '&WARMSTART_CYCLE_DIR;/RESTART/@Y@m@d.@H@M@S.fv_tracer.res.tile1.nc' + datadep_comin_tracer: attrs: - age: 00:00:05:00 - text: '&COMIN_DIR;/RESTART/fv_tracer.res.tile1.nc' + age: 00:00:00:05 + text: '&COMIN_DIR;/RESTART/@Y@m@d.@H@M@S.fv_tracer.res.tile1.nc' task_prepstart: <<: *default_smoke_dust diff --git a/scripts/exsrw_aqm_ics.sh b/scripts/exsrw_aqm_ics.sh index f2b3d471f8..005b8a3cb2 100755 --- a/scripts/exsrw_aqm_ics.sh +++ b/scripts/exsrw_aqm_ics.sh @@ -50,108 +50,112 @@ tory (either from disk or HPSS) the external model files from which ini- tial or boundary condition files for the FV3 will be generated. ========================================================================" # -#----------------------------------------------------------------------- -# -# Check if restart file exists -# -#----------------------------------------------------------------------- -# -rst_dir="${PREV_CYCLE_DIR}/RESTART" -rst_file="fv_tracer.res.tile1.nc" -rst_file_with_date="${PDY}.${cyc}0000.${rst_file}" -if [ -e "${rst_dir}/${rst_file_with_date}" ]; then - fv_tracer_file="${rst_dir}/${rst_file_with_date}" -elif [ -e "${rst_dir}/${rst_file}" ]; then - fv_tracer_file="${rst_dir}/${rst_file}" -else - message_txt="Tracer restart file: \"${fv_tracer_file}\" is NOT found" - err_exit "${message_txt}" - print_err_msg_exit "${message_txt}" -fi -print_info_msg "Tracer restart file: \"${fv_tracer_file}\"" - -cplr_file="coupler.res" -cplr_file_with_date="${PDY}.${cyc}0000.${cplr_file}" -if [ -e "${rst_dir}/${cplr_file_with_date}" ]; then - coupler_file="${rst_dir}/${cplr_file_with_date}" -elif [ -e "${rst_dir}/${cplr_file}" ]; then - coupler_file="${rst_dir}/${cplr_file}" +if [ $(boolify "${COLDSTART}") = "TRUE" ] && [ "${PDY}${cyc}" = "${DATE_FIRST_CYCL:0:10}" ]; then + echo "This step is skipped for the first cycle of COLDSTART." else - message_txt="Coupler file: \"${coupler_file}\" is NOT found" - err_exit "${message_txt}" - print_err_msg_exit "${message_txt}" -fi -print_info_msg "Coupler file: \"${coupler_file}\"" + # Check if restart file exists + rst_file="fv_tracer.res.tile1.nc" + rst_file_with_date="${PDY}.${cyc}0000.${rst_file}" -if [ -r ${coupler_file} ]; then - rst_info=( $( tail -n 1 ${coupler_file} ) ) - # Remove leading zeros from ${rst_info[1]} - month="${rst_info[1]#"${rst_info[1]%%[!0]*}"}" - # Remove leading zeros from ${rst_info[2]} - day="${rst_info[2]#"${rst_info[2]%%[!0]*}"}" - # Format the date without leading zeros - rst_date=$(printf "%04d%02d%02d%02d" ${rst_info[0]} $((10#$month)) $((10#$day)) ${rst_info[3]}) - if [ "${rst_date}" = "${PDY}${cyc}" ]; then - if [ -r ${fv_tracer_file} ]; then - print_info_msg "Tracer restart file is for ${PDY}${cyc}" + # Warm start + if [ $(boolify "${COLDSTART}") = "FALSE" ]; then + rst_dir="${WARMSTART_CYCLE_DIR}/RESTART" + else + # after the first cycle + if [ -e "${DATA_SHARE}/RESTART/${rst_file_with_date}" ]; then + rst_dir="${DATA_SHARE}/RESTART" else - message_txt="Tracer restart file \"${fv_tracer_file}\" is NOT readable." - err_exit "${message_txt}" - print_err_msg_exit "${message_txt}" + rst_dir="${COMINprev}/RESTART" fi + fi + + if [ -e "${rst_dir}/${rst_file_with_date}" ]; then + fv_tracer_file="${rst_dir}/${rst_file_with_date}" + else + message_txt="Tracer restart file: \"${fv_tracer_file}\" is NOT found" + err_exit "${message_txt}" + print_err_msg_exit "${message_txt}" + fi + print_info_msg "Tracer restart file: \"${fv_tracer_file}\"" + + cplr_file="coupler.res" + cplr_file_with_date="${PDY}.${cyc}0000.${cplr_file}" + if [ -e "${rst_dir}/${cplr_file_with_date}" ]; then + coupler_file="${rst_dir}/${cplr_file_with_date}" else - message_txt="Tracer restart file is NOT for ${PDY}${cyc}. + message_txt="Coupler file: \"${coupler_file}\" is NOT found" + err_exit "${message_txt}" + print_err_msg_exit "${message_txt}" + fi + print_info_msg "Coupler file: \"${coupler_file}\"" + + if [ -r ${coupler_file} ]; then + rst_info=( $( tail -n 1 ${coupler_file} ) ) + # Remove leading zeros from ${rst_info[1]} + month="${rst_info[1]#"${rst_info[1]%%[!0]*}"}" + # Remove leading zeros from ${rst_info[2]} + day="${rst_info[2]#"${rst_info[2]%%[!0]*}"}" + # Format the date without leading zeros + rst_date=$(printf "%04d%02d%02d%02d" ${rst_info[0]} $((10#$month)) $((10#$day)) ${rst_info[3]}) + if [ "${rst_date}" = "${PDY}${cyc}" ]; then + if [ -r ${fv_tracer_file} ]; then + print_info_msg "Tracer restart file is for ${PDY}${cyc}" + else + message_txt="Tracer restart file \"${fv_tracer_file}\" is NOT readable." + err_exit "${message_txt}" + print_err_msg_exit "${message_txt}" + fi + else + message_txt="Tracer restart file is NOT for ${PDY}${cyc}. Checking available restart date: requested date: \"${PDY}${cyc}\" available date: \"${rst_date}\"" - err_exit "${message_txt}" - print_err_msg_exit "${message_txt}" + err_exit "${message_txt}" + print_err_msg_exit "${message_txt}" + fi fi -fi -# -#----------------------------------------------------------------------- -# -# Add air quality tracer variables from previous cycle's restart output -# to atmosphere's initial condition file according to the steps below: -# -# a. Python script to manipulate the files (see comments inside for details) -# b. Remove checksum attribute to prevent overflow -# c. Rename reulting file as the expected atmospheric IC file -# -#----------------------------------------------------------------------- -# -gfs_ic_fn="${NET}.${cycle}${dot_ensmem}.gfs_data.tile${TILE_RGNL}.halo${NH0}.nc" -gfs_ic_fp="${DATA_SHARE}/${gfs_ic_fn}" -wrk_ic_fp="${DATA}/gfs.nc" + # + #----------------------------------------------------------------------- + # + # Add air quality tracer variables from previous cycle's restart output + # to atmosphere's initial condition file according to the steps below: + # + # a. Python script to manipulate the files (see comments inside for details) + # b. Remove checksum attribute to prevent overflow + # c. Rename reulting file as the expected atmospheric IC file + # + #----------------------------------------------------------------------- + # + gfs_ic_fn="${NET}.${cycle}${dot_ensmem}.gfs_data.tile${TILE_RGNL}.halo${NH0}.nc" + gfs_ic_fp="${DATA_SHARE}/${gfs_ic_fn}" + wrk_ic_fp="${DATA}/gfs.nc" -print_info_msg " + print_info_msg " Adding air quality tracers to atmospheric initial condition file: tracer file: \"${fv_tracer_file}\" FV3 IC file: \"${gfs_ic_fp}\"" -cp -p ${gfs_ic_fp} ${wrk_ic_fp} -${USHsrw}/aqm_utils_python/add_aqm_ics.py --fv_tracer_file "${fv_tracer_file}" --wrk_ic_file "${wrk_ic_fp}" -export err=$? -if [ $err -ne 0 ]; then - message_txt="Call to python script \"add_aqm_ics.py\" failed." - err_exit "${message_txt}" - print_err_msg_exit "${message_txt}" -fi - -ncatted -a checksum,,d,s, tmp1.nc -export err=$? -if [ $err -ne 0 ]; then - message_txt="Call to NCATTED returned with nonzero exit code." - err_exit "${message_txt}" - print_err_msg_exit "${message_txt}" -fi + cp -p ${gfs_ic_fp} ${wrk_ic_fp} + ${USHsrw}/aqm_utils_python/add_aqm_ics.py --fv_tracer_file "${fv_tracer_file}" --wrk_ic_file "${wrk_ic_fp}" + export err=$? + if [ $err -ne 0 ]; then + message_txt="Call to python script \"add_aqm_ics.py\" failed." + err_exit "${message_txt}" + print_err_msg_exit "${message_txt}" + fi -mv tmp1.nc ${gfs_ic_fn} + ncatted -a checksum,,d,s, tmp1.nc + export err=$? + if [ $err -ne 0 ]; then + message_txt="Call to NCATTED returned with nonzero exit code." + err_exit "${message_txt}" + print_err_msg_exit "${message_txt}" + fi -cp -p ${gfs_ic_fn} ${COMOUT} + mv tmp1.nc ${gfs_ic_fn} -unset fv_tracer_file -unset wrk_ic_file + cp -p ${gfs_ic_fn} ${COMOUT} +fi # #----------------------------------------------------------------------- # diff --git a/scripts/exsrw_forecast.sh b/scripts/exsrw_forecast.sh index e270f47c5a..ffd889257a 100755 --- a/scripts/exsrw_forecast.sh +++ b/scripts/exsrw_forecast.sh @@ -636,8 +636,8 @@ fi # #----------------------------------------------------------------------- # -if [ $(boolify "${CPL_AQM}") = "TRUE" ]; then - ln -nsf "${DATA}/RESTART" "${COMIN}/RESTART" +if [ $(boolify "${CPL_AQM}") = "TRUE" ] || [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then + ln -nsf "${DATA}/RESTART" "${DATA_SHARE}/RESTART" fi # #----------------------------------------------------------------------- @@ -680,7 +680,7 @@ export err=$?; err_chk #----------------------------------------------------------------------- # if [ $(boolify "${CPL_AQM}") = "TRUE" ] || [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then - cp -Rp RESTART ${COMOUT} + cp -rp RESTART ${COMOUT} fhr=0 while [ $fhr -le ${FCST_LEN_HRS} ]; do diff --git a/scripts/exsrw_upp_post.sh b/scripts/exsrw_upp_post.sh index f43d21fe11..06c908a311 100755 --- a/scripts/exsrw_upp_post.sh +++ b/scripts/exsrw_upp_post.sh @@ -161,7 +161,7 @@ fi # # Set namelist of upp. # -if [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then +if [ $(boolify "${CPL_AQM}") = "TRUE" ] || [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then dyn_file="${COMIN}/${NET}.${cycle}${dot_ensmem}.dyn.f${fhr}.${POST_OUTPUT_DOMAIN_NAME}.nc" phy_file="${COMIN}/${NET}.${cycle}${dot_ensmem}.phy.f${fhr}.${POST_OUTPUT_DOMAIN_NAME}.nc" else @@ -176,7 +176,7 @@ post_dd=${post_time:6:2} post_hh=${post_time:8:2} post_mn=${post_time:10:2} -if [ $(boolify "${CPL_AQM}") = "TRUE" ] && [ $(bookify "${DO_SMOKE_DUST}") = "FALSE" ]; then +if [ $(boolify "${CPL_AQM}") = "TRUE" ] && [ $(boolify "${DO_SMOKE_DUST}") = "FALSE" ]; then post_itag_add="aqf_on=.true.," elif [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then post_itag_add="slrutah_on=.true.,gtg_on=.true." diff --git a/tests/WE2E/test_configs/aqm/config.aqm_grid_AQM_NA13km_suite_GFS_v16.yaml b/tests/WE2E/test_configs/aqm/config.aqm_grid_AQM_NA13km_suite_GFS_v16.yaml index 2901d1ebf1..46a0fdf49d 100644 --- a/tests/WE2E/test_configs/aqm/config.aqm_grid_AQM_NA13km_suite_GFS_v16.yaml +++ b/tests/WE2E/test_configs/aqm/config.aqm_grid_AQM_NA13km_suite_GFS_v16.yaml @@ -13,12 +13,12 @@ workflow: DIAG_TABLE_TMPL_FN: diag_table_aqm.FV3_GFS_v16 FIELD_TABLE_TMPL_FN: field_table_aqm.FV3_GFS_v16 DO_REAL_TIME: false + COLDSTART: true nco: NET_default: aqm rocoto: tasks: - taskgroups: '{{ ["parm/wflow/prep.yaml", "parm/wflow/aqm_prep.yaml", "parm/wflow/coldstart.yaml", "parm/wflow/post.yaml", "parm/wflow/test.yaml"]|include }}' - task_aqm_ics_ext: + taskgroups: '{{ ["parm/wflow/prep.yaml", "parm/wflow/aqm_prep.yaml", "parm/wflow/coldstart.yaml", "parm/wflow/upp_post.yaml", "parm/wflow/test.yaml"]|include }}' metatask_run_ensemble: task_run_fcst_mem#mem#: walltime: 01:20:00 diff --git a/ush/config.aqm.yaml b/ush/config.aqm.yaml index 649b857b1d..e3e5707bc5 100644 --- a/ush/config.aqm.yaml +++ b/ush/config.aqm.yaml @@ -32,7 +32,6 @@ nco: rocoto: tasks: taskgroups: '{{ ["parm/wflow/prep.yaml", "parm/wflow/aqm_prep.yaml", "parm/wflow/coldstart.yaml", "parm/wflow/upp_post.yaml"]|include }}' -# task_aqm_ics_ext: # uncomment this in case of COLDSTART: true metatask_run_ensemble: task_run_fcst_mem#mem#: walltime: 01:20:00 diff --git a/ush/config.smoke_dust.yaml b/ush/config.smoke_dust.yaml index f6b415dbd7..062ddefedf 100644 --- a/ush/config.smoke_dust.yaml +++ b/ush/config.smoke_dust.yaml @@ -54,7 +54,7 @@ task_run_fcst: WRTCMP_write_tasks_per_group: 40 RESTART_INTERVAL: 6 12 18 24 QUILTING: true - PRINT_ESMF: true + PRINT_ESMF: false DO_FCST_RESTART: false task_run_post: POST_OUTPUT_DOMAIN_NAME: conus3km From 4bcd126d48699e92ebbc84427b74b6c2a264e304 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Wed, 28 Aug 2024 16:25:49 +0000 Subject: [PATCH 50/61] fix missing file issue on aqm_ics --- scripts/exsrw_aqm_ics.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/exsrw_aqm_ics.sh b/scripts/exsrw_aqm_ics.sh index 005b8a3cb2..9c99c48eaa 100755 --- a/scripts/exsrw_aqm_ics.sh +++ b/scripts/exsrw_aqm_ics.sh @@ -71,6 +71,8 @@ else if [ -e "${rst_dir}/${rst_file_with_date}" ]; then fv_tracer_file="${rst_dir}/${rst_file_with_date}" + elif [ -e "${rst_dir}/${rst_file}" ]; then + fv_tracer_file="${rst_dir}/${rst_file}" else message_txt="Tracer restart file: \"${fv_tracer_file}\" is NOT found" err_exit "${message_txt}" @@ -82,6 +84,8 @@ else cplr_file_with_date="${PDY}.${cyc}0000.${cplr_file}" if [ -e "${rst_dir}/${cplr_file_with_date}" ]; then coupler_file="${rst_dir}/${cplr_file_with_date}" + elif [ -e "${rst_dir}/${cplr_file}" ]; then + coupler_file="${rst_dir}/${cplr_file}" else message_txt="Coupler file: \"${coupler_file}\" is NOT found" err_exit "${message_txt}" From 8aec48b71c18c3ad5bae29fa640b973791c8f57d Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Wed, 28 Aug 2024 18:09:39 +0000 Subject: [PATCH 51/61] fix issues on aqm_ics and upp_post --- jobs/JSRW_AQM_ICS | 4 +-- jobs/JSRW_FORECAST | 2 +- jobs/JSRW_UPP_POST | 4 +-- scripts/exsrw_aqm_ics.sh | 17 ++++++---- scripts/exsrw_upp_post.sh | 69 +++++++++++++++++++++++++++------------ 5 files changed, 63 insertions(+), 33 deletions(-) diff --git a/jobs/JSRW_AQM_ICS b/jobs/JSRW_AQM_ICS index 177eb7c2ad..d9ffd6c5c1 100755 --- a/jobs/JSRW_AQM_ICS +++ b/jobs/JSRW_AQM_ICS @@ -105,10 +105,10 @@ export RUN="${RUN:-${RUN_default}}" [[ "$WORKFLOW_MANAGER" = "rocoto" ]] && export COMROOT=$COMROOT if [ "${MACHINE}" = "WCOSS2" ]; then - export COMIN="${COMIN:-$(compath.py -o ${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR})}" + export COMIN="${COMIN:-$(compath.py -o ${NET}/${model_ver})}" export COMOUT="${COMOUT:-$(compath.py -o ${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR})}" else - export COMIN="${COMIN:-${COMROOT}/${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR}}" + export COMIN="${COMIN:-${COMROOT}/${NET}/${model_ver}}" export COMOUT="${COMOUT:-${COMROOT}/${NET}/${model_ver}/${RUN}.${PDY}/${cyc}${SLASH_ENSMEM_SUBDIR}}" fi diff --git a/jobs/JSRW_FORECAST b/jobs/JSRW_FORECAST index 0cf602e689..ef213fbca8 100755 --- a/jobs/JSRW_FORECAST +++ b/jobs/JSRW_FORECAST @@ -132,7 +132,7 @@ fi mkdir -p ${COMOUT} # Create a teomporary share directory for RAVE interpolated data files -export DATA_SHARE="${DATA_SHARE:-${DATAROOT}/DATA_SHARE/RAVE_fire_intp}" +export DATA_SHARE="${DATA_SHARE:-${DATAROOT}/DATA_SHARE/${PDY}${cyc}}" mkdir -p ${DATA_SHARE} # Run setpdy to initialize PDYm and PDYp variables diff --git a/jobs/JSRW_UPP_POST b/jobs/JSRW_UPP_POST index 09f58eed4e..0522695c2d 100755 --- a/jobs/JSRW_UPP_POST +++ b/jobs/JSRW_UPP_POST @@ -115,7 +115,7 @@ export COMINsmoke="${COMINsmoke:-${COMINsmoke_default}}" export COMINfire="${COMINfire:-${COMINfire_default}}" # Create a teomporary share directory for RAVE interpolated data files -export DATA_SHARE="${DATA_SHARE:-${DATAROOT}/DATA_SHARE/RAVE_fire_intp}" +export DATA_SHARE="${DATA_SHARE:-${DATAROOT}/DATA_SHARE/${PDY}${cyc}}" mkdir -p ${DATA_SHARE} # Run setpdy to initialize PDYm and PDYp variables @@ -187,7 +187,7 @@ if [ ${#FCST_LEN_CYCL[@]} -gt 1 ]; then if [ "${WORKFLOW_MANAGER}" = "rocoto" ]; then fcst_len_hrs=$( printf "%03d" "${FCST_LEN_HRS}" ) if [ "${fhr}" = "${fcst_len_hrs}" ]; then - touch "${DATAROOT}/DATA_SHARE/${PDY}${cyc}/post_${PDY}${cyc}_task_complete.txt" + touch "${DATA_SHARE}/post_${PDY}${cyc}_task_complete.txt" fi fi fi diff --git a/scripts/exsrw_aqm_ics.sh b/scripts/exsrw_aqm_ics.sh index 9c99c48eaa..030983a0fa 100755 --- a/scripts/exsrw_aqm_ics.sh +++ b/scripts/exsrw_aqm_ics.sh @@ -58,23 +58,26 @@ else rst_file_with_date="${PDY}.${cyc}0000.${rst_file}" # Warm start - if [ $(boolify "${COLDSTART}") = "FALSE" ]; then + if [ $(boolify "${COLDSTART}") = "FALSE" ] && [ "${PDY}${cyc}" = "${DATE_FIRST_CYCL:0:10}" ]; then rst_dir="${WARMSTART_CYCLE_DIR}/RESTART" else # after the first cycle - if [ -e "${DATA_SHARE}/RESTART/${rst_file_with_date}" ]; then - rst_dir="${DATA_SHARE}/RESTART" - else + CDATEprev=$($NDATE -${INCR_CYCL_FREQ} ${PDY}${cyc}) + PDYprev=${CDATEprev:0:8} + cycprev=${CDATEprev:8:2} + COMINprev=${COMIN}/${RUN}.${PDYprev}/${cycprev}${SLASH_ENSMEM_SUBDIR} + if [ -e "${COMINprev}/RESTART/${rst_file_with_date}" ]; then rst_dir="${COMINprev}/RESTART" + elif [ -e "${DATA_SHARE}/RESTART/${rst_file_with_date}" ]; then + rst_dir="${DATA_SHARE}/RESTART" fi fi - if [ -e "${rst_dir}/${rst_file_with_date}" ]; then fv_tracer_file="${rst_dir}/${rst_file_with_date}" elif [ -e "${rst_dir}/${rst_file}" ]; then fv_tracer_file="${rst_dir}/${rst_file}" else - message_txt="Tracer restart file: \"${fv_tracer_file}\" is NOT found" + message_txt="WARNING: Tracer restart file: \"${fv_tracer_file}\" is NOT found" err_exit "${message_txt}" print_err_msg_exit "${message_txt}" fi @@ -87,7 +90,7 @@ else elif [ -e "${rst_dir}/${cplr_file}" ]; then coupler_file="${rst_dir}/${cplr_file}" else - message_txt="Coupler file: \"${coupler_file}\" is NOT found" + message_txt="WARNING: Coupler file: \"${coupler_file}\" is NOT found" err_exit "${message_txt}" print_err_msg_exit "${message_txt}" fi diff --git a/scripts/exsrw_upp_post.sh b/scripts/exsrw_upp_post.sh index 06c908a311..902516bc52 100755 --- a/scripts/exsrw_upp_post.sh +++ b/scripts/exsrw_upp_post.sh @@ -120,7 +120,6 @@ Copying the CRTM fix files from FIXcrtm: FIXcrtm = \"${FIXcrtm}\" ====================================================================" fi - # #----------------------------------------------------------------------- # @@ -288,28 +287,56 @@ fi echo "fhr=${fhr} and subh_fhr=${subh_fhr}" fhr=${subh_fhr} -bgdawp=${NET}.${cycle}.prslev.f${fhr}.${POST_OUTPUT_DOMAIN_NAME}.grib2 -bgrd3d=${NET}.${cycle}.natlev.f${fhr}.${POST_OUTPUT_DOMAIN_NAME}.grib2 -bgifi=${NET}.${cycle}.ififip.f${fhr}.${POST_OUTPUT_DOMAIN_NAME}.grib2 -bgavi=${NET}.${cycle}.aviati.f${fhr}.${POST_OUTPUT_DOMAIN_NAME}.grib2 +if [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then + bgdawp=${NET}.${cycle}.prslev.f${fhr}.${POST_OUTPUT_DOMAIN_NAME}.grib2 + bgrd3d=${NET}.${cycle}.natlev.f${fhr}.${POST_OUTPUT_DOMAIN_NAME}.grib2 + bgifi=${NET}.${cycle}.ififip.f${fhr}.${POST_OUTPUT_DOMAIN_NAME}.grib2 + bgavi=${NET}.${cycle}.aviati.f${fhr}.${POST_OUTPUT_DOMAIN_NAME}.grib2 -if [ -f "PRSLEV.GrbF${post_fhr}" ]; then - wgrib2 PRSLEV.GrbF${post_fhr} -set center 7 -grib ${bgdawp} >>$pgmout 2>>errfile -fi -if [ -f "NATLEV.GrbF${post_fhr}" ]; then - wgrib2 NATLEV.GrbF${post_fhr} -set center 7 -grib ${bgrd3d} >>$pgmout 2>>errfile -fi -if [ -f "IFIFIP.GrbF${post_fhr}" ]; then - wgrib2 IFIFIP.GrbF${post_fhr} -set center 7 -grib ${bgifi} >>$pgmout 2>>errfile -fi -if [ -f "AVIATI.GrbF${post_fhr}" ]; then - wgrib2 AVIATI.GrbF${post_fhr} -set center 7 -grib ${bgavi} >>$pgmout 2>>errfile -fi + if [ -f "PRSLEV.GrbF${post_fhr}" ]; then + wgrib2 PRSLEV.GrbF${post_fhr} -set center 7 -grib ${bgdawp} >>$pgmout 2>>errfile + fi + if [ -f "NATLEV.GrbF${post_fhr}" ]; then + wgrib2 NATLEV.GrbF${post_fhr} -set center 7 -grib ${bgrd3d} >>$pgmout 2>>errfile + fi + if [ -f "IFIFIP.GrbF${post_fhr}" ]; then + wgrib2 IFIFIP.GrbF${post_fhr} -set center 7 -grib ${bgifi} >>$pgmout 2>>errfile + fi + if [ -f "AVIATI.GrbF${post_fhr}" ]; then + wgrib2 AVIATI.GrbF${post_fhr} -set center 7 -grib ${bgavi} >>$pgmout 2>>errfile + fi -cp -p ${bgdawp} ${COMOUT} -cp -p ${bgrd3d} ${COMOUT} -cp -p ${bgifi} ${COMOUT} -cp -p ${bgavi} ${COMOUT} + cp -p ${bgdawp} ${COMOUT} + cp -p ${bgrd3d} ${COMOUT} + cp -p ${bgifi} ${COMOUT} + cp -p ${bgavi} ${COMOUT} + +else + + post_mn_or_null="" + dot_post_mn_or_null="" + if [ "${post_mn}" != "00" ]; then + post_mn_or_null="${post_mn}" + dot_post_mn_or_null=".${post_mn}" + fi + post_fn_suffix="GrbF${post_fhr}${dot_post_mn_or_null}" + post_renamed_fn_suffix="f${fhr}${post_mn_or_null}.${POST_OUTPUT_DOMAIN_NAME}.grib2" + basetime=$( $DATE_UTIL --date "$yyyymmdd $hh" +%y%j%H%M ) + symlink_suffix="${dot_ensmem}.${basetime}f${fhr}${post_mn}" + if [ $(boolify "${CPL_AQM}") = "TRUE" ]; then + fids=( "cmaq" ) + else + fids=( "prslev" "natlev" ) + fi + for fid in "${fids[@]}"; do + FID=$(echo_uppercase $fid) + post_orig_fn="${FID}.${post_fn_suffix}" + post_renamed_fn="${NET}.${cycle}${dot_ensmem}.${fid}.${post_renamed_fn_suffix}" + mv ${post_orig_fn} ${post_renamed_fn} + cp -p ${post_renamed_fn} ${COMOUT} + done + +fi # #----------------------------------------------------------------------- # From 113500d0a36ee20c71ba9bbc0404f3800003e19e Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Wed, 28 Aug 2024 19:17:41 +0000 Subject: [PATCH 52/61] increase file age for aqm_ics dependency --- parm/wflow/aqm_prep.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/parm/wflow/aqm_prep.yaml b/parm/wflow/aqm_prep.yaml index d8c6b7a9f4..384da120ba 100644 --- a/parm/wflow/aqm_prep.yaml +++ b/parm/wflow/aqm_prep.yaml @@ -122,11 +122,11 @@ task_aqm_ics: text: !cycstr '&WARMSTART_CYCLE_DIR;/RESTART/@Y@m@d.@H@M@S.fv_tracer.res.tile1.nc' datadep_comin_tracer: attrs: - age: 00:00:00:05 + age: 00:00:03:00 text: '&COMIN_DIR;/RESTART/@Y@m@d.@H@M@S.fv_tracer.res.tile1.nc' datadep_datashare_tracer: attrs: - age: 00:00:00:05 + age: 00:00:03:00 text: '&DATASHARE_DIR;/RESTART/@Y@m@d.@H@M@S.fv_tracer.res.tile1.nc' task_aqm_lbcs: From 4f42898a245a5b38f4cf510054d2c6c9bf93905d Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Fri, 30 Aug 2024 20:36:45 +0000 Subject: [PATCH 53/61] add smoke_dust to we2e --- ...ust_grid_RRFS_CONUS_3km_suite_HRRR_gf.yaml | 66 +++++++++++++++++++ .../config.different_vcoord.yaml | 24 ------- 2 files changed, 66 insertions(+), 24 deletions(-) create mode 100644 tests/WE2E/test_configs/smoke_dust/config.smoke_dust_grid_RRFS_CONUS_3km_suite_HRRR_gf.yaml delete mode 100644 tests/WE2E/test_configs/wflow_features/config.different_vcoord.yaml diff --git a/tests/WE2E/test_configs/smoke_dust/config.smoke_dust_grid_RRFS_CONUS_3km_suite_HRRR_gf.yaml b/tests/WE2E/test_configs/smoke_dust/config.smoke_dust_grid_RRFS_CONUS_3km_suite_HRRR_gf.yaml new file mode 100644 index 0000000000..a06ec13dce --- /dev/null +++ b/tests/WE2E/test_configs/smoke_dust/config.smoke_dust_grid_RRFS_CONUS_3km_suite_HRRR_gf.yaml @@ -0,0 +1,66 @@ +metadata: + description: config for Smoke and Dust, RRFS_CONUS_3km +user: + RUN_ENVIR: community +platform: + BUILD_MOD_FN: 'build_{{ user.MACHINE|lower() }}_intel_prod' +workflow: + PREDEF_GRID_NAME: RRFS_CONUS_3km + CCPP_PHYS_SUITE: FV3_HRRR_gf + DATE_FIRST_CYCL: '2019072200' + DATE_LAST_CYCL: '2019072206' + INCR_CYCL_FREQ: 6 + FCST_LEN_HRS: 6 + PREEXISTING_DIR_METHOD: rename + VERBOSE: true + DEBUG: false + COMPILER: intel + DIAG_TABLE_TMPL_FN: diag_table_smoke_dust.FV3_HRRR_gf + FIELD_TABLE_TMPL_FN: field_table_smoke_dust.FV3_HRRR_gf + DO_REAL_TIME: false + COLDSTART: true +nco: + envir_default: test_smoke_dust + NET_default: smoke_dust + RUN_default: smoke_dust +rocoto: + tasks: + taskgroups: '{{ ["parm/wflow/prep.yaml", "parm/wflow/smoke_dust.yaml", "parm/wflow/coldstart.yaml", "parm/wflow/upp_post.yaml"]|include }}' + metatask_run_ensemble: + task_run_fcst_mem#mem#: + walltime: 02:00:00 +task_get_extrn_ics: + EXTRN_MDL_NAME_ICS: RAP + EXTRN_MDL_ICS_OFFSET_HRS: 0 + USE_USER_STAGED_EXTRN_FILES: true +task_get_extrn_lbcs: + EXTRN_MDL_NAME_LBCS: RAP + LBC_SPEC_INTVL_HRS: 6 + EXTRN_MDL_LBCS_OFFSET_HRS: 0 + USE_USER_STAGED_EXTRN_FILES: true +task_make_ics: + VCOORD_FILE: "{{ workflow.FIXam }}/global_hyblev_fcst_rrfsL65.txt" +task_make_lbcs: + VCOORD_FILE: "{{ workflow.FIXam }}/global_hyblev_fcst_rrfsL65.txt" +task_run_fcst: + DT_ATMOS: 36 + LAYOUT_X: 15 + LAYOUT_Y: 20 + BLOCKSIZE: 32 + WRTCMP_write_tasks_per_group: 40 + RESTART_INTERVAL: 6 12 18 24 + QUILTING: true + PRINT_ESMF: false + DO_FCST_RESTART: false +task_run_post: + POST_OUTPUT_DOMAIN_NAME: conus3km + USE_CUSTOM_POST_CONFIG_FILE: false +global: + DO_ENSEMBLE: false + NUM_ENS_MEMBERS: 2 + HALO_BLEND: 20 +smoke_dust_parm: + DO_SMOKE_DUST: true + EBB_DCYCLE: 1 + SMOKE_DUST_FILE_PREFIX: "SMOKE_RRFS_data" + diff --git a/tests/WE2E/test_configs/wflow_features/config.different_vcoord.yaml b/tests/WE2E/test_configs/wflow_features/config.different_vcoord.yaml deleted file mode 100644 index 16f2d10e74..0000000000 --- a/tests/WE2E/test_configs/wflow_features/config.different_vcoord.yaml +++ /dev/null @@ -1,24 +0,0 @@ -metadata: - description: |- - This test is to ensure that the workflow running in community mode - completes successfully when the RRFS vertical coordinates are chosen. -user: - RUN_ENVIR: community -workflow: - CCPP_PHYS_SUITE: FV3_HRRR - PREDEF_GRID_NAME: RRFS_CONUS_25km - DATE_FIRST_CYCL: '2019070100' - DATE_LAST_CYCL: '2019070100' - FCST_LEN_HRS: 3 - PREEXISTING_DIR_METHOD: rename -task_get_extrn_ics: - EXTRN_MDL_NAME_ICS: FV3GFS - USE_USER_STAGED_EXTRN_FILES: true -task_get_extrn_lbcs: - EXTRN_MDL_NAME_LBCS: FV3GFS - LBC_SPEC_INTVL_HRS: 3 - USE_USER_STAGED_EXTRN_FILES: true -task_make_ics: - VCOORD_FILE: "{{ user.PARMdir }}/global_hyblev_fcst_rrfsL65.txt" -task_make_lbcs: - VCOORD_FILE: "{{ user.PARMdir }}/global_hyblev_fcst_rrfsL65.txt" From e73952e7028dc6d38b6aa2f5e7336afca50331ef Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Tue, 3 Sep 2024 15:58:53 +0000 Subject: [PATCH 54/61] update we2e test scripts fro aqm and smoke/dust --- .../aqm/config.aqm_grid_AQM_NA13km_suite_GFS_v16.yaml | 4 +++- ...config.smoke_dust_grid_RRFS_CONUS_3km_suite_HRRR_gf.yaml | 6 +++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/WE2E/test_configs/aqm/config.aqm_grid_AQM_NA13km_suite_GFS_v16.yaml b/tests/WE2E/test_configs/aqm/config.aqm_grid_AQM_NA13km_suite_GFS_v16.yaml index 46a0fdf49d..8e742486a6 100644 --- a/tests/WE2E/test_configs/aqm/config.aqm_grid_AQM_NA13km_suite_GFS_v16.yaml +++ b/tests/WE2E/test_configs/aqm/config.aqm_grid_AQM_NA13km_suite_GFS_v16.yaml @@ -15,7 +15,9 @@ workflow: DO_REAL_TIME: false COLDSTART: true nco: - NET_default: aqm + envir_default: we2e_aqm + NET_default: we2e_aqm + RUN_default: we2e_aqm rocoto: tasks: taskgroups: '{{ ["parm/wflow/prep.yaml", "parm/wflow/aqm_prep.yaml", "parm/wflow/coldstart.yaml", "parm/wflow/upp_post.yaml", "parm/wflow/test.yaml"]|include }}' diff --git a/tests/WE2E/test_configs/smoke_dust/config.smoke_dust_grid_RRFS_CONUS_3km_suite_HRRR_gf.yaml b/tests/WE2E/test_configs/smoke_dust/config.smoke_dust_grid_RRFS_CONUS_3km_suite_HRRR_gf.yaml index a06ec13dce..a6ae67df6f 100644 --- a/tests/WE2E/test_configs/smoke_dust/config.smoke_dust_grid_RRFS_CONUS_3km_suite_HRRR_gf.yaml +++ b/tests/WE2E/test_configs/smoke_dust/config.smoke_dust_grid_RRFS_CONUS_3km_suite_HRRR_gf.yaml @@ -20,9 +20,9 @@ workflow: DO_REAL_TIME: false COLDSTART: true nco: - envir_default: test_smoke_dust - NET_default: smoke_dust - RUN_default: smoke_dust + envir_default: we2e_smoke_dust + NET_default: we2e_smoke_dust + RUN_default: we2e_smoke_dust rocoto: tasks: taskgroups: '{{ ["parm/wflow/prep.yaml", "parm/wflow/smoke_dust.yaml", "parm/wflow/coldstart.yaml", "parm/wflow/upp_post.yaml"]|include }}' From 69cde179037336cccd4feae7179fd2de14df684e Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Wed, 4 Sep 2024 11:21:34 +0000 Subject: [PATCH 55/61] update sample smoke config file --- ush/config.smoke_dust.yaml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/ush/config.smoke_dust.yaml b/ush/config.smoke_dust.yaml index 062ddefedf..97d908e28f 100644 --- a/ush/config.smoke_dust.yaml +++ b/ush/config.smoke_dust.yaml @@ -6,6 +6,7 @@ user: ACCOUNT: [account name] platform: BUILD_MOD_FN: 'build_{{ user.MACHINE|lower() }}_intel_prod' +# EXTRN_MDL_DATA_STORES: disk workflow: USE_CRON_TO_RELAUNCH: true CRON_RELAUNCH_INTVL_MNTS: 3 @@ -24,7 +25,7 @@ workflow: FIELD_TABLE_TMPL_FN: field_table_smoke_dust.FV3_HRRR_gf DO_REAL_TIME: false COLDSTART: true # set to true for cold start -# WARMSTART_CYCLE_DIR: '/path/to/warm/start/files' # for hera +# WARMSTART_CYCLE_DIR: '/path/to/warm/start/files' nco: envir_default: test_smoke_dust NET_default: smoke_dust @@ -38,10 +39,14 @@ rocoto: task_get_extrn_ics: EXTRN_MDL_NAME_ICS: RAP EXTRN_MDL_ICS_OFFSET_HRS: 0 +# USE_USER_STAGED_EXTRN_FILES: true +# EXTRN_MDL_SOURCE_BASEDIR_ICS: /scratch1/NCEPDEV/nems/role.epic/UFS_SRW_data/develop/input_model_data/RAP/${yyyymmddhh} task_get_extrn_lbcs: EXTRN_MDL_NAME_LBCS: RAP LBC_SPEC_INTVL_HRS: 6 EXTRN_MDL_LBCS_OFFSET_HRS: 0 +# USE_USER_STAGED_EXTRN_FILES: true +# EXTRN_MDL_SOURCE_BASEDIR_LBCS: /scratch1/NCEPDEV/nems/role.epic/UFS_SRW_data/develop/input_model_data/RAP/${yyyymmddhh} task_make_ics: VCOORD_FILE: "{{ workflow.FIXam }}/global_hyblev_fcst_rrfsL65.txt" task_make_lbcs: @@ -66,5 +71,5 @@ global: smoke_dust_parm: DO_SMOKE_DUST: true EBB_DCYCLE: 1 - SMOKE_DUST_FILE_PREFIX: "SMOKE_RRFS_data" + SMOKE_DUST_FILE_PREFIX: SMOKE_RRFS_data From 5e6db810aeb9bf4759a3c4ba7be0daf771042a0c Mon Sep 17 00:00:00 2001 From: Chan-Hoo Jeon Date: Wed, 4 Sep 2024 07:55:26 -0500 Subject: [PATCH 56/61] update machine files for other machines --- ush/machine/derecho.yaml | 9 +++++++++ ush/machine/hercules.yaml | 8 ++++++++ ush/machine/orion.yaml | 8 ++++++++ 3 files changed, 25 insertions(+) diff --git a/ush/machine/derecho.yaml b/ush/machine/derecho.yaml index 8bc768732f..f82e57cfd3 100644 --- a/ush/machine/derecho.yaml +++ b/ush/machine/derecho.yaml @@ -33,6 +33,9 @@ platform: FIXshp: /glade/work/epicufsrt/contrib/UFS_SRW_data/develop/NaturalEarth FIXaqm: /glade/work/chanhooj/SRW-AQM_DATA/fix_aqm FIXemis: /glade/work/chanhooj/SRW-AQM_DATA/fix_emis + FIXsmoke: /glade/work/chanhooj/SRW-AQM_DATA/fix_smoke + FIXupp: /glade/work/chanhooj/SRW-AQM_DATA/fix_upp + FIXcrtm: /glade/work/chanhooj/SRW-AQM_DATA/fix_crtm EXTRN_MDL_DATA_STORES: aws data: ics_lbcs: @@ -44,7 +47,13 @@ data: HRRR: /glade/work/epicufsrt/contrib/UFS_SRW_data/develop/input_model_data/HRRR/${yyyymmdd}${hh} RAP: /glade/work/epicufsrt/contrib/UFS_SRW_data/develop/input_model_data/RAP/${yyyymmdd}${hh} GSMGFS: /glade/work/epicufsrt/contrib/UFS_SRW_data/develop/input_model_data/GSMGFS/${yyyymmdd}${hh} + cpl_aqm_parm: COMINfire_default: /glade/work/chanhooj/SRW-AQM_DATA/aqm_data/RAVE_fire COMINgefs_default: /glade/work/chanhooj/SRW-AQM_DATA/aqm_data/GEFS_DATA NEXUS_GFS_SFC_DIR: /glade/work/chanhooj/SRW-AQM_DATA/aqm_data/GFS_SFC_DATA + +smoke_dust_parm: + COMINsmoke_default: /glade/work/chanhooj/SRW-AQM_DATA/data_smoke_dust/RAVE_smoke_dust + COMINfire_default: /glade/work/chanhooj/SRW-AQM_DATA/data_smoke_dust/RAVE_fire + diff --git a/ush/machine/hercules.yaml b/ush/machine/hercules.yaml index e29801dd49..c995229db0 100644 --- a/ush/machine/hercules.yaml +++ b/ush/machine/hercules.yaml @@ -35,6 +35,9 @@ platform: FIXshp: /work/noaa/epic/role-epic/contrib/UFS_SRW_data/develop/NaturalEarth FIXaqm: /work/noaa/epic/SRW-AQM_DATA/fix_aqm FIXemis: /work/noaa/epic/SRW-AQM_DATA/fix_emis + FIXsmoke: /work/noaa/epic/SRW-AQM_DATA/fix_smoke + FIXupp: /work/noaa/epic/SRW-AQM_DATA/fix_upp + FIXcrtm: /work/noaa/epic/SRW-AQM_DATA/fix_crtm EXTRN_MDL_DATA_STORES: aws data: ics_lbcs: @@ -51,3 +54,8 @@ cpl_aqm_parm: COMINfire_default: /work/noaa/epic/SRW-AQM_DATA/aqm_data/RAVE_fire COMINgefs_default: /work/noaa/epic/SRW-AQM_DATA/aqm_data/GEFS_DATA NEXUS_GFS_SFC_DIR: /work/noaa/epic/SRW-AQM_DATA/aqm_data/GFS_SFC_DATA + +smoke_dust_parm: + COMINsmoke_default: /work/noaa/epic/SRW-AQM_DATA/data_smoke_dust/RAVE_smoke_dust + COMINfire_default: /work/noaa/epic/SRW-AQM_DATA/data_smoke_dust/RAVE_fire + diff --git a/ush/machine/orion.yaml b/ush/machine/orion.yaml index 3f756e2836..619a879b7e 100644 --- a/ush/machine/orion.yaml +++ b/ush/machine/orion.yaml @@ -34,6 +34,9 @@ platform: FIXshp: /work/noaa/epic/role-epic/contrib/UFS_SRW_data/develop/NaturalEarth FIXaqm: /work/noaa/epic/SRW-AQM_DATA/fix_aqm FIXemis: /work/noaa/epic/SRW-AQM_DATA/fix_emis + FIXsmoke: /work/noaa/epic/SRW-AQM_DATA/fix_smoke + FIXupp: /work/noaa/epic/SRW-AQM_DATA/fix_upp + FIXcrtm: /work/noaa/epic/SRW-AQM_DATA/fix_crtm EXTRN_MDL_DATA_STORES: aws nomads data: ics_lbcs: @@ -50,3 +53,8 @@ cpl_aqm_parm: COMINfire_default: /work/noaa/epic/SRW-AQM_DATA/aqm_data/RAVE_fire COMINgefs_default: /work/noaa/epic/SRW-AQM_DATA/aqm_data/GEFS_DATA NEXUS_GFS_SFC_DIR: /work/noaa/epic/SRW-AQM_DATA/aqm_data/GFS_SFC_DATA + +smoke_dust_parm: + COMINsmoke_default: /work/noaa/epic/SRW-AQM_DATA/data_smoke_dust/RAVE_smoke_dust + COMINfire_default: /work/noaa/epic/SRW-AQM_DATA/data_smoke_dust/RAVE_fire + From 3b8842946e4ca6d3837d41b072efba46df2c609e Mon Sep 17 00:00:00 2001 From: Chan-Hoo Jeon Date: Wed, 4 Sep 2024 15:18:11 -0500 Subject: [PATCH 57/61] update module files for orion --- modulefiles/build_hera_intel_prod.lua | 5 +-- modulefiles/build_orion_intel_prod.lua | 57 ++++++++++++++++++++++++++ 2 files changed, 58 insertions(+), 4 deletions(-) create mode 100644 modulefiles/build_orion_intel_prod.lua diff --git a/modulefiles/build_hera_intel_prod.lua b/modulefiles/build_hera_intel_prod.lua index b44ca2467b..7280a735fc 100644 --- a/modulefiles/build_hera_intel_prod.lua +++ b/modulefiles/build_hera_intel_prod.lua @@ -3,7 +3,7 @@ This module loads libraries for building the production branch on the NOAA RDHPC machine Hera using Intel-2022.1.2 ]]) -whatis([===[Loads libraries needed for building the RRFS workflow on Hera ]===]) +whatis([===[Loads libraries needed for building SRW-smoke/dust on Hera ]===]) prepend_path("MODULEPATH", "/scratch1/NCEPDEV/nems/role.epic/spack-stack/spack-stack-1.5.1/envs/gsi-addon-env-rocky8/install/modulefiles/Core") load(pathJoin("stack-intel", os.getenv("stack_intel_ver") or "2021.5.0")) @@ -40,8 +40,6 @@ load(pathJoin("w3emc", os.getenv("w3emc_ver") or "2.10.0")) load(pathJoin("w3nco", os.getenv("w3nco_ver") or "2.4.1")) load(pathJoin("nco", os.getenv("nco_ver") or "5.0.6")) ---load(pathJoin("prod_util", os.getenv("prod_util_ver") or "1.2.2")) ---load(pathJoin("wgrib2", os.getenv("wgrib2_ver") or "2.0.8")) load(pathJoin("wgrib2", os.getenv("wgrib2_ver") or "2.0.8")) @@ -57,4 +55,3 @@ setenv("CMAKE_C_COMPILER","mpiicc") setenv("CMAKE_CXX_COMPILER","mpiicpc") setenv("CMAKE_Fortran_COMPILER","mpiifort") setenv("CMAKE_Platform","hera.intel") -setenv("BLENDINGPYTHON","/contrib/miniconda3/4.5.12/envs/pygraf/bin/python") diff --git a/modulefiles/build_orion_intel_prod.lua b/modulefiles/build_orion_intel_prod.lua new file mode 100644 index 0000000000..a4c656a2be --- /dev/null +++ b/modulefiles/build_orion_intel_prod.lua @@ -0,0 +1,57 @@ +help([[ +This module loads libraries for building the production branch on +the MSU machine Orion using Intel compiler +]]) + +whatis([===[Loads libraries needed for building SRW-smoke/dust on Orion ]===]) + +load("contrib") +load("noaatools") + +prepend_path("MODULEPATH", "/work/noaa/epic/role-epic/spack-stack/orion/spack-stack-1.5.1/envs/gsi-addon-rocky9/install/modulefiles/Core") +load(pathJoin("stack-intel", os.getenv("stack_intel_ver") or "2021.9.0")) +load(pathJoin("stack-intel-oneapi-mpi", os.getenv("stack_impi_ver") or "2021.9.0")) +load(pathJoin("cmake", os.getenv("cmake_ver") or "3.23.1")) + +load(pathJoin("jasper", os.getenv("jasper_ver") or "2.0.32")) +load(pathJoin("zlib", os.getenv("zlib_ver") or "1.2.13")) +load(pathJoin("libpng", os.getenv("libpng_ver") or "1.6.37")) +load(pathJoin("parallelio", os.getenv("pio_ver") or "2.5.10")) +--loading parallelio will load netcdf_c, netcdf_fortran, hdf5, zlib, etc +load(pathJoin("esmf", os.getenv("esmf_ver") or "8.5.0")) +--load(pathJoin("fms", os.getenv("fms_ver") or "2023.02.01")) + +load(pathJoin("bacio", os.getenv("bacio_ver") or "2.4.1")) +load(pathJoin("crtm", os.getenv("crtm_ver") or "2.4.0")) +load(pathJoin("g2", os.getenv("g2_ver") or "3.4.5")) +--load(pathJoin("g2tmpl", os.getenv("g2tmpl_ver") or "1.10.2")) +load(pathJoin("ip", os.getenv("ip_ver") or "4.3.0")) +load(pathJoin("sp", os.getenv("sp_ver") or "2.3.3")) + +load(pathJoin("gftl-shared", os.getenv("gftl-shared_ver") or "1.6.1")) +load(pathJoin("mapl", os.getenv("mapl_ver") or "2.40.3-esmf-8.5.0")) +load(pathJoin("scotch", os.getenv("scotch_ver") or "7.0.4")) + +load(pathJoin("bufr", os.getenv("bufr_ver") or "11.7.0")) +load(pathJoin("sigio", os.getenv("sigio_ver") or "2.3.2")) +load(pathJoin("sfcio", os.getenv("sfcio_ver") or "1.4.1")) +load(pathJoin("nemsio", os.getenv("nemsio_ver") or "2.5.4")) +load(pathJoin("wrf-io", os.getenv("wrf_io_ver") or "1.2.0")) +load(pathJoin("ncio", os.getenv("ncio_ver") or "1.1.2")) +load(pathJoin("gsi-ncdiag", os.getenv("gsi-ncdiag_ver") or "1.1.2")) +load(pathJoin("w3emc", os.getenv("w3emc_ver") or "2.10.0")) +load(pathJoin("w3nco", os.getenv("w3nco_ver") or "2.4.1")) + +load(pathJoin("nco", os.getenv("nco_ver") or "5.0.6")) +load(pathJoin("wgrib2", os.getenv("wgrib2_ver") or "3.1.1")) + +setenv("FMS_ROOT","/work/noaa/epic/chjeon/FMS_2.4.1_orion/FMS/build") +setenv("g2tmpl_ROOT","/work/noaa/epic/chjeon/LIB_g2tmpl_1.13.0_orion/NCEPLIBS-g2tmpl") + +prepend_path("MODULEPATH", "/work/noaa/rtrr/gge/lua") +load("prod_util/2.0.15") + +setenv("CMAKE_C_COMPILER","mpiicc") +setenv("CMAKE_CXX_COMPILER","mpiicpc") +setenv("CMAKE_Fortran_COMPILER","mpiifort") +setenv("CMAKE_Platform","orion.intel") From 45b57f53246a9118e8e605ebfc93a4cbdd8e17a5 Mon Sep 17 00:00:00 2001 From: Chan-Hoo Jeon Date: Wed, 4 Sep 2024 21:01:24 -0500 Subject: [PATCH 58/61] add pre_task_cmds to smoke/dust --- scripts/exsrw_prepstart.sh | 1 + scripts/exsrw_smoke_dust.sh | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/exsrw_prepstart.sh b/scripts/exsrw_prepstart.sh index 32881aae2e..9d8fd599f8 100755 --- a/scripts/exsrw_prepstart.sh +++ b/scripts/exsrw_prepstart.sh @@ -56,6 +56,7 @@ This is the ex-script for the task that runs prepstart. if [ $(boolify "${COLDSTART}") = "TRUE" ] && [ "${PDY}${cyc}" = "${DATE_FIRST_CYCL:0:10}" ]; then echo "This step is skipped for the first cycle of COLDSTART." else + eval ${PRE_TASK_CMDS} if [ $(boolify "${DO_SMOKE_DUST}") = "TRUE" ]; then # IC gfs data file: gfs_data.tile7.halo0.nc gfs_ic_fn="${NET}.${cycle}${dot_ensmem}.gfs_data.tile${TILE_RGNL}.halo${NH0}.nc" diff --git a/scripts/exsrw_smoke_dust.sh b/scripts/exsrw_smoke_dust.sh index b33ef6c6b5..df900e2c2b 100755 --- a/scripts/exsrw_smoke_dust.sh +++ b/scripts/exsrw_smoke_dust.sh @@ -50,7 +50,7 @@ This is the ex-script for the task that runs Smoke and Dust. if [ $(boolify "${COLDSTART}") = "TRUE" ] && [ "${PDY}${cyc}" = "${DATE_FIRST_CYCL:0:10}" ]; then echo "This step is skipped for the first cycle of COLDSTART." -else +else # # Set CDATE used in the fire emission generation python script # @@ -62,6 +62,7 @@ else if [ -e "${COMINsmoke}/${smokeFile}" ]; then cp -p "${COMINsmoke}/${smokeFile}" ${COMOUT} else + eval ${PRE_TASK_CMDS} # # Link restart directory of the previous cycle in COMIN/COMOUT # From 29125e69d96717f104dc2bf041c7f5207f265bdd Mon Sep 17 00:00:00 2001 From: Chan-Hoo Jeon Date: Thu, 5 Sep 2024 12:37:18 -0500 Subject: [PATCH 59/61] fix modulefile issue on we2e run script --- tests/WE2E/run_WE2E_tests.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/WE2E/run_WE2E_tests.py b/tests/WE2E/run_WE2E_tests.py index 5d4bd81105..663aa04497 100755 --- a/tests/WE2E/run_WE2E_tests.py +++ b/tests/WE2E/run_WE2E_tests.py @@ -172,7 +172,6 @@ def run_we2e_tests(homedir, args) -> None: # if platform section was not in input config, initialize as empty dict if 'platform' not in test_cfg: test_cfg['platform'] = dict() - test_cfg['platform'].update({"BUILD_MOD_FN": args.modulefile}) test_cfg['workflow'].update({"COMPILER": args.compiler}) if args.expt_basedir: test_cfg['workflow'].update({"EXPT_BASEDIR": args.expt_basedir}) @@ -502,8 +501,6 @@ def setup_logging(logfile: str = "log.run_WE2E_tests", debug: bool = False) -> N ' none: Do not launch experiments; only create experiment directories', default="python") - - ap.add_argument('--modulefile', type=str, help='Modulefile used for building the app') ap.add_argument('--run_envir', type=str, help='Overrides RUN_ENVIR variable to a new value ("nco" or "community") '\ 'for all experiments', default='') @@ -533,8 +530,6 @@ def setup_logging(logfile: str = "log.run_WE2E_tests", debug: bool = False) -> N "--launch=cron\nPlease update your workflow accordingly") #Set defaults that need other argument values - if args.modulefile is None: - args.modulefile = f'build_{args.machine.lower()}_{args.compiler}' if args.procs < 1: raise argparse.ArgumentTypeError('You can not have less than one parallel process; select a valid value '\ 'for --procs') From ea6f79c77b61f84ffc25c2f8e9197e382f6a395e Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Fri, 6 Sep 2024 10:28:01 +0000 Subject: [PATCH 60/61] fix typo in coldstart.yaml --- parm/wflow/coldstart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parm/wflow/coldstart.yaml b/parm/wflow/coldstart.yaml index 53a685c76e..493de95bf8 100644 --- a/parm/wflow/coldstart.yaml +++ b/parm/wflow/coldstart.yaml @@ -150,7 +150,7 @@ metatask_run_ensemble: task_run_fcst_mem#mem#: <<: *default_task - command: '{% if smoke_dust_parm.DO_SMOKE_DUST or cpl_aqm_parm.CPL_AQM %}&LOAD_MODULES_RUN_TASK; "forecast" "&JOBSdir;/JSRW_FORECAST" {% else %}&LOAD_MODULES_RUN_TASK; "run_fcst" "&JOBSdir;/JREGIONAL_RUN_FCST"{% endif %}' + command: '{% if smoke_dust_parm.DO_SMOKE_DUST or cpl_aqm_parm.CPL_AQM %}&LOAD_MODULES_RUN_TASK; "forecast" "&JOBSdir;/JSRW_FORECAST" {% else %}&LOAD_MODULES_RUN_TASK; "run_fcst" "&JOBSdir;/JREGIONAL_RUN_FCST" {% endif %}' envars: <<: *default_vars SLASH_ENSMEM_SUBDIR: '&SLASH_ENSMEM_SUBDIR;' From d47b1fe49533fa0a1b85b0547392f0abeed8bc68 Mon Sep 17 00:00:00 2001 From: "Chan-hoo.Jeon" Date: Mon, 9 Sep 2024 19:38:31 +0000 Subject: [PATCH 61/61] activate smoke_dust for first cycle --- scripts/exsrw_prepstart.sh | 2 +- scripts/exsrw_smoke_dust.sh | 145 +++++++++++++++++------------------- 2 files changed, 71 insertions(+), 76 deletions(-) diff --git a/scripts/exsrw_prepstart.sh b/scripts/exsrw_prepstart.sh index 9d8fd599f8..c454989628 100755 --- a/scripts/exsrw_prepstart.sh +++ b/scripts/exsrw_prepstart.sh @@ -50,7 +50,7 @@ This is the ex-script for the task that runs prepstart. #----------------------------------------------------------------------- # -# smoke/dust cycling +# update IC files # #----------------------------------------------------------------------- if [ $(boolify "${COLDSTART}") = "TRUE" ] && [ "${PDY}${cyc}" = "${DATE_FIRST_CYCL:0:10}" ]; then diff --git a/scripts/exsrw_smoke_dust.sh b/scripts/exsrw_smoke_dust.sh index df900e2c2b..9fff8fb743 100755 --- a/scripts/exsrw_smoke_dust.sh +++ b/scripts/exsrw_smoke_dust.sh @@ -47,87 +47,82 @@ In directory: \"${scrfunc_dir}\" This is the ex-script for the task that runs Smoke and Dust. ========================================================================" - -if [ $(boolify "${COLDSTART}") = "TRUE" ] && [ "${PDY}${cyc}" = "${DATE_FIRST_CYCL:0:10}" ]; then - echo "This step is skipped for the first cycle of COLDSTART." -else - # - # Set CDATE used in the fire emission generation python script - # - export CDATE="${PDY}${cyc}" +# +# Set CDATE used in the fire emission generation python script +# +export CDATE="${PDY}${cyc}" +# +# Check if the fire file exists in the designated directory +# +smokeFile="${SMOKE_DUST_FILE_PREFIX}_${CDATE}00.nc" +if [ -e "${COMINsmoke}/${smokeFile}" ]; then + cp -p "${COMINsmoke}/${smokeFile}" ${COMOUT} +else + eval ${PRE_TASK_CMDS} # - # Check if the fire file exists in the designated directory + # Link restart directory of the previous cycle in COMIN/COMOUT # - smokeFile="${SMOKE_DUST_FILE_PREFIX}_${CDATE}00.nc" - if [ -e "${COMINsmoke}/${smokeFile}" ]; then - cp -p "${COMINsmoke}/${smokeFile}" ${COMOUT} - else - eval ${PRE_TASK_CMDS} - # - # Link restart directory of the previous cycle in COMIN/COMOUT - # - CDATEprev=$($NDATE -${INCR_CYCL_FREQ} ${PDY}${cyc}) - PDYprev=${CDATEprev:0:8} - cycprev=${CDATEprev:8:2} - path_restart=${COMIN}/${RUN}.${PDYprev}/${cycprev}${SLASH_ENSMEM_SUBDIR}/RESTART - ln -nsf ${path_restart} . + CDATEprev=$($NDATE -${INCR_CYCL_FREQ} ${PDY}${cyc}) + PDYprev=${CDATEprev:0:8} + cycprev=${CDATEprev:8:2} + path_restart=${COMIN}/${RUN}.${PDYprev}/${cycprev}${SLASH_ENSMEM_SUBDIR}/RESTART + ln -nsf ${path_restart} . - # Check whether the RAVE files need to be split into hourly files - if [ "${EBB_DCYCLE}" -eq 1 ]; then - ddhh_to_use="${PDY}${cyc}" + # Check whether the RAVE files need to be split into hourly files + if [ "${EBB_DCYCLE}" -eq 1 ]; then + ddhh_to_use="${PDY}${cyc}" + else + ddhh_to_use="${PDYm1}${cyc}" + fi + for hour in {00..23}; do + fire_hr_cdate=$($NDATE +${hour} ${ddhh_to_use}) + fire_hr_pdy="${fire_hr_cdate:0:8}" + fire_hr_fn="Hourly_Emissions_3km_${fire_hr_cdate}00_${fire_hr_cdate}00.nc" + if [ -f "${COMINfire}/${fire_hr_fn}" ]; then + echo "Hourly emission file for $hour was found: ${fire_hr_fn}" + ln -nsf ${COMINfire}/${fire_hr_fn} . else - ddhh_to_use="${PDYm1}${cyc}" - fi - for hour in {00..23}; do - fire_hr_cdate=$($NDATE +${hour} ${ddhh_to_use}) - fire_hr_pdy="${fire_hr_cdate:0:8}" - fire_hr_fn="Hourly_Emissions_3km_${fire_hr_cdate}00_${fire_hr_cdate}00.nc" - if [ -f "${COMINfire}/${fire_hr_fn}" ]; then - echo "Hourly emission file for $hour was found: ${fire_hr_fn}" - ln -nsf ${COMINfire}/${fire_hr_fn} . - else - # Check various version of RAVE raw data files (new and old) - rave_raw_fn1="RAVE-HrlyEmiss-3km_v2r0_blend_s${fire_hr_cdate}00000_e${fire_hr_pdy}23*" - rave_raw_fn2="Hourly_Emissions_3km_${fire_hr_cdate}00_${fire_hr_pdy}23*" - # Find files matching the specified patterns - files_found=$(find "${COMINfire}" -type f \( -name "${rave_raw_fn1##*/}" -o -name "${rave_raw_fn2##*/}" \)) - # Splitting 24-hour RAVE raw data into houly data - for file_to_use in $files_found; do - echo "Using file: $file_to_use" - echo "Splitting data for hour $hour..." - ncks -d time,$hour,$hour "${COMINfire}/${file_to_use}" "${DATA}/${fire_hr_fn}" - if [ -f "${DATA}/${fire_hr_fn}" ]; then - break - else - echo "WARNING: Hourly emission file for $hour was NOT created from ${file_to_use}." - fi - done - fi - done - # - #----------------------------------------------------------------------- - # - # Call python script to generate fire emission files. - # - #----------------------------------------------------------------------- - # - ${USHsrw}/generate_fire_emissions.py \ - "${FIXsmoke}/${PREDEF_GRID_NAME}" \ - "${DATA}" \ - "${DATA_SHARE}" \ - "${PREDEF_GRID_NAME}" \ - "${EBB_DCYCLE}" \ - "${RESTART_INTERVAL}" - export err=$? - if [ $err -ne 0 ]; then - message_txt="generate_fire_emissions.py failed with return code $err" - err_exit "${message_txt}" - print_err_msg_exit "${message_txt}" + # Check various version of RAVE raw data files (new and old) + rave_raw_fn1="RAVE-HrlyEmiss-3km_v2r0_blend_s${fire_hr_cdate}00000_e${fire_hr_pdy}23*" + rave_raw_fn2="Hourly_Emissions_3km_${fire_hr_cdate}00_${fire_hr_pdy}23*" + # Find files matching the specified patterns + files_found=$(find "${COMINfire}" -type f \( -name "${rave_raw_fn1##*/}" -o -name "${rave_raw_fn2##*/}" \)) + # Splitting 24-hour RAVE raw data into houly data + for file_to_use in $files_found; do + echo "Using file: $file_to_use" + echo "Splitting data for hour $hour..." + ncks -d time,$hour,$hour "${COMINfire}/${file_to_use}" "${DATA}/${fire_hr_fn}" + if [ -f "${DATA}/${fire_hr_fn}" ]; then + break + else + echo "WARNING: Hourly emission file for $hour was NOT created from ${file_to_use}." + fi + done fi - - # Copy Smoke file to COMOUT - cp -p ${DATA}/${smokeFile} ${COMOUT} + done + # + #----------------------------------------------------------------------- + # + # Call python script to generate fire emission files. + # + #----------------------------------------------------------------------- + # + ${USHsrw}/generate_fire_emissions.py \ + "${FIXsmoke}/${PREDEF_GRID_NAME}" \ + "${DATA}" \ + "${DATA_SHARE}" \ + "${PREDEF_GRID_NAME}" \ + "${EBB_DCYCLE}" \ + "${RESTART_INTERVAL}" + export err=$? + if [ $err -ne 0 ]; then + message_txt="generate_fire_emissions.py failed with return code $err" + err_exit "${message_txt}" + print_err_msg_exit "${message_txt}" fi + + # Copy Smoke file to COMOUT + cp -p ${DATA}/${smokeFile} ${COMOUT} fi # #-----------------------------------------------------------------------