SCREAM v1 Data Generation Example
In developing SCREAM v1, the team made a concerted effort to generalize and streamline variable output capability to allow for flexible and hopefully scientifically valuable capabilities. In this example, we will use SCREAM v1 data to generate all the data we need to train ACE2 on the fly (during runtime) without the need for post-processing or outputing expensive 3D variables. Please refer to ACE2-ERA5 Training Workflow for more information about ACE2 training.
Key insights
We use the following capabilities from SCREAM v1:
- binary operations (
plus,over) - vertical reduction (
vert_avg) - conditional sampling (
where) - process tendencies (
homme_[x]_tend) - io aliasing (
:=)
All these capabilities are documented in EAMxx user guide.
The over by constants is not yet in the mainline code. As of this writing, it is only available in the mahf708:hbc2 branch.
Specific examples
air_temperature_2:=T_mid_where_lev_ge_28_where_lev_lt_46_vert_avg_dp_weighteddefines a new variableair_temperature_2. It takes theT_mid(temperature at mid-levels) variable, applies a conditional filter to include only levels greater than or equal to 28 and less than 46, and then performs a vertical average weighted by pressure thickness (dp)total_specific_humidity_0:=qc_plus_qv_plus_qi_plus_qr_where_lev_ge_0_where_lev_lt_15_vert_avg_dp_weighteddefines a new variabletotal_specific_humidity_0. It takes theqc(cloud water),qv(water vapor),qi(ice), andqr(rain) variables, applies a conditional filter to include only levels greater than or equal to 0 and less than 15, and then performs a vertical average weighted by pressure thickness (dp).tendency_of_total_water_path_due_to_advection:=homme_qc_tend_plus_homme_qv_tend_plus_homme_qi_tend_plus_homme_qr_tend_vert_avg_dp_weighteddefines a new variabletendency_of_total_water_path_due_to_advection. It takes thehomme_qc_tend(cloud water tendency),homme_qv_tend(water vapor tendency),homme_qi_tend(ice tendency), andhomme_qr_tend(rain tendency) variables, and then performs a vertical average weighted by pressure thickness (dp).HGTsfc:=phis_over_gravitdefines a new variableHGTsfc. It takes thephis(surface geopotential) variable, and dvides by the gravitation acceleration (taken as constantgravit) to get surface height.
Full script
A full script can be found below.
SCREAM v1 run script
#!/bin/bash -fe
# EAMxx template run script
main() {
do_fetch_code=false
do_create_newcase=true
do_case_setup=true
do_case_build=true
do_case_submit=true
readonly MACHINE="pm-gpu"
readonly CHECKOUT="10022025"
readonly BRANCH="hbc2"
readonly CHERRY=( )
readonly COMPILER="gnugpu"
readonly DEBUG_COMPILE=FALSE
readonly Q=debug
readonly QUEUE=${Q}
# Simulation
readonly COMPSET="F2010-SCREAMv1"
readonly RESOLUTION="ne30pg2_ne30pg2"
readonly CODE_ROOT="/pscratch/sd/m/mahf708/e3sm-repo/test-pr"
readonly PROJECT="e3sm"
readonly TUNINGSET="default" # also plus4k and minus4k are options
readonly CASE_NAME=${RESOLUTION}.${COMPSET}.${CHECKOUT}.${TUNINGSET}
readonly CASE_ROOT="${SCRATCH}/e3sm_scratch/${MACHINE}/${CASE_NAME}"
githash_eamxx=`git --git-dir ${CODE_ROOT}/.git rev-parse HEAD`
# ****************** Lines to be modified ********************************
# ****************** Lines to be modified ********************************
# History file frequency (if using default above)
readonly HIST_OPTION="nmonths"
readonly HIST_N="1"
# Run options
readonly MODEL_START_TYPE="initial" # "initial", "continue", "branch", "hybrid"
readonly START_DATE="2000-01-01" # "" for default, or explicit "0001-01-01"
# Additional options for 'branch' and 'hybrid'
readonly GET_REFCASE=false
readonly RUN_REFDIR=""
readonly RUN_REFCASE=""
readonly RUN_REFDATE="" # same as MODEL_START_DATE for 'branch', can be different for 'hybrid'
# Sub-directories
readonly CASE_BUILD_DIR=${CASE_ROOT}/build
readonly CASE_ARCHIVE_DIR=${CASE_ROOT}/archive
readonly CASE_SCRIPTS_DIR=${CASE_ROOT}/case_scripts
readonly CASE_RUN_DIR=${CASE_ROOT}/run
readonly NUM_PES=4
if [[ ${MPS_YES} == "TRUE" ]]; then
readonly PEL_SIM=$(( MPS_NOS * NUM_PES ))
else
readonly PEL_SIM=$(( 4 * NUM_PES ))
fi
readonly PELAYOUT=${PEL_SIM}"x1"
readonly WALLTIME="00:25:00"
readonly STOP_OPTION="nyears"
readonly STOP_N="10"
readonly REST_OPTION="nyears"
readonly REST_N="1"
readonly RESUBMIT="0"
readonly DO_SHORT_TERM_ARCHIVING=false
# Leave empty (unless you understand what it does)
readonly OLD_EXECUTABLE=""
# --- Now, do the work ---
# Make directories created by this script world-readable
umask 022
# Fetch code from Github
fetch_code
# Create case
create_newcase
# Setup
case_setup
# Build
case_build
# Configure runtime options
runtime_options
# Copy script into case_script directory for provenance
copy_script
# Submit
case_submit
# All done
echo $'\n----- All done -----\n'
}
# =======================
# Custom user_nl settings
# =======================
user_nl() {
echo "+++ Configuring SCREAM for 128 vertical levels +++"
./xmlchange SCREAM_CMAKE_OPTIONS="SCREAM_NP 4 SCREAM_NUM_VERTICAL_LEV 128 SCREAM_NUM_TRACERS 10"
}
######################################################
### Most users won't need to change anything below ###
######################################################
#-----------------------------------------------------
fetch_code() {
if [ "${do_fetch_code,,}" != "true" ]; then
echo $'\n----- Skipping fetch_code -----\n'
return
fi
echo $'\n----- Starting fetch_code -----\n'
local path=${CODE_ROOT}
local repo=scream
echo "Cloning $repo repository branch $BRANCH under $path"
if [ -d "${path}" ]; then
echo "ERROR: Directory already exists. Not overwriting"
exit 20
fi
mkdir -p ${path}
pushd ${path}
# This will put repository, with all code
git clone git@github.com:E3SM-Project/${repo}.git .
# Q: DO WE NEED THIS FOR EAMXX?
# Setup git hooks
rm -rf .git/hooks
git clone git@github.com:E3SM-Project/E3SM-Hooks.git .git/hooks
git config commit.template .git/hooks/commit.template
# Check out desired branch
git checkout ${BRANCH}
# Custom addition
if [ "${CHERRY}" != "" ]; then
echo ----- WARNING: adding git cherry-pick -----
for commit in "${CHERRY[@]}"
do
echo ${commit}
git cherry-pick ${commit}
done
echo -------------------------------------------
fi
# Bring in all submodule components
git submodule update --init --recursive
popd
}
#-----------------------------------------------------
create_newcase() {
if [ "${do_create_newcase,,}" != "true" ]; then
echo $'\n----- Skipping create_newcase -----\n'
return
fi
echo $'\n----- Starting create_newcase -----\n'
# Base arguments
args=" --case ${CASE_NAME} \
--output-root ${CASE_ROOT} \
--script-root ${CASE_SCRIPTS_DIR} \
--handle-preexisting-dirs u \
--compset ${COMPSET} \
--res ${RESOLUTION} \
--machine ${MACHINE} \
--compiler ${COMPILER} \
--walltime ${WALLTIME} \
--pecount ${PELAYOUT}"
# Oprional arguments
if [ ! -z "${PROJECT}" ]; then
args="${args} --project ${PROJECT}"
fi
if [ ! -z "${CASE_GROUP}" ]; then
args="${args} --case-group ${CASE_GROUP}"
fi
if [ ! -z "${QUEUE}" ]; then
args="${args} --queue ${QUEUE}"
fi
${CODE_ROOT}/cime/scripts/create_newcase ${args}
if [ $? != 0 ]; then
echo $'\nNote: if create_newcase failed because sub-directory already exists:'
echo $' * delete old case_script sub-directory'
echo $' * or set do_newcase=false\n'
exit 35
fi
}
#-----------------------------------------------------
case_setup() {
if [ "${do_case_setup,,}" != "true" ]; then
echo $'\n----- Skipping case_setup -----\n'
return
fi
echo $'\n----- Starting case_setup -----\n'
pushd ${CASE_SCRIPTS_DIR}
# Setup some CIME directories
./xmlchange EXEROOT=${CASE_BUILD_DIR}
./xmlchange RUNDIR=${CASE_RUN_DIR}
# Short term archiving
./xmlchange DOUT_S=${DO_SHORT_TERM_ARCHIVING}
./xmlchange DOUT_S_ROOT=${CASE_ARCHIVE_DIR}
# Extracts input_data_dir in case it is needed for user edits to the namelist later
local input_data_dir=`./xmlquery DIN_LOC_ROOT --value`
# Custom user_nl
user_nl
MPS_NUMBER=4
./xmlchange --file env_mach_pes.xml NTHRDS="1"
./xmlchange --file env_mach_pes.xml NTHRDS_ATM="1"
./xmlchange --file env_mach_pes.xml NTHRDS_LND="$(( 64 / MPS_NUMBER ))"
./xmlquery NTHRDS_LND
./xmlchange --file env_mach_pes.xml NTHRDS_ICE="$(( 64 / MPS_NUMBER ))"
./xmlquery NTHRDS_ICE
./xmlchange --file env_mach_pes.xml NTHRDS_OCN="1"
./xmlchange --file env_mach_pes.xml NTHRDS_ROF="1"
./xmlchange --file env_mach_pes.xml NTHRDS_CPL="1"
./xmlchange --file env_mach_pes.xml NTHRDS_GLC="1"
./xmlchange --file env_mach_pes.xml NTHRDS_WAV="1"
./xmlchange PIO_NETCDF_FORMAT="64bit_data"
# Finally, run CIME case.setup
./case.setup --reset
# Save provenance invfo
echo "branch hash for EAMxx: $githash_eamxx" > GIT_INFO.txt
echo "master hash for output files: $githash_screamdocs" >> GIT_INFO.txt
popd
}
#-----------------------------------------------------
case_build() {
pushd ${CASE_SCRIPTS_DIR}
# do_case_build = false
if [ "${do_case_build,,}" != "true" ]; then
echo $'\n----- case_build -----\n'
if [ "${OLD_EXECUTABLE}" == "" ]; then
# Ues previously built executable, make sure it exists
if [ -x ${CASE_BUILD_DIR}/e3sm.exe ]; then
echo 'Skipping build because $do_case_build = '${do_case_build}
else
echo 'ERROR: $do_case_build = '${do_case_build}' but no executable exists for this case.'
exit 297
fi
else
# If absolute pathname exists and is executable, reuse pre-exiting executable
if [ -x ${OLD_EXECUTABLE} ]; then
echo 'Using $OLD_EXECUTABLE = '${OLD_EXECUTABLE}
cp -fp ${OLD_EXECUTABLE} ${CASE_BUILD_DIR}/
else
echo 'ERROR: $OLD_EXECUTABLE = '$OLD_EXECUTABLE' does not exist or is not an executable file.'
exit 297
fi
fi
echo 'WARNING: Setting BUILD_COMPLETE = TRUE. This is a little risky, but trusting the user.'
./xmlchange BUILD_COMPLETE=TRUE
# do_case_build = true
else
echo $'\n----- Starting case_build -----\n'
# Turn on debug compilation option if requested
if [ "${DEBUG_COMPILE}" == "TRUE" ]; then
./xmlchange DEBUG=${DEBUG_COMPILE}
fi
# Run CIME case.build
./case.build
# Some user_nl settings won't be updated to *_in files under the run directory
# Call preview_namelists to make sure *_in and user_nl files are consistent.
./preview_namelists
fi
popd
}
#-----------------------------------------------------
runtime_options() {
echo $'\n----- Starting runtime_options -----\n'
pushd ${CASE_SCRIPTS_DIR}
local input_data_dir=`./xmlquery DIN_LOC_ROOT --value`
# Set simulation start date
if [ ! -z "${START_DATE}" ]; then
./xmlchange RUN_STARTDATE=${START_DATE}
fi
./atmchange homme::compute_tendencies=qr,qv,qi,qc
./atmchange eamxx::compute_tendencies=qr,qv,qi,qc
cat << EOF >> user_nl_elm
hist_dov2xy = .true.,.true.
hist_fincl2 = 'H2OSNO','SOILWATER_10CM','TG'
hist_mfilt = 1,120
hist_nhtfrq = 0,-24
hist_avgflag_pertape = 'A','A'
EOF
cat << EOF >> user_nl_cpl
ocn_surface_flux_scheme = 2
EOF
# Segment length
./xmlchange STOP_OPTION=${STOP_OPTION,,},STOP_N=${STOP_N}
# Restart frequency
./xmlchange REST_OPTION=${REST_OPTION,,},REST_N=${REST_N}
# Coupler history
./xmlchange HIST_OPTION=${HIST_OPTION,,},HIST_N=${HIST_N}
# Coupler budgets (always on)
./xmlchange BUDGETS=TRUE
# Set resubmissions
if (( RESUBMIT > 0 )); then
./xmlchange RESUBMIT=${RESUBMIT}
fi
# Run type
# Start from default of user-specified initial conditions
if [ "${MODEL_START_TYPE,,}" == "initial" ]; then
./xmlchange RUN_TYPE="startup"
./xmlchange CONTINUE_RUN="FALSE"
# Continue existing run
elif [ "${MODEL_START_TYPE,,}" == "continue" ]; then
./xmlchange CONTINUE_RUN="TRUE"
elif [ "${MODEL_START_TYPE,,}" == "branch" ] || [ "${MODEL_START_TYPE,,}" == "hybrid" ]; then
./xmlchange RUN_TYPE=${MODEL_START_TYPE,,}
./xmlchange GET_REFCASE=${GET_REFCASE}
./xmlchange RUN_REFDIR=${RUN_REFDIR}
./xmlchange RUN_REFCASE=${RUN_REFCASE}
./xmlchange RUN_REFDATE=${RUN_REFDATE}
echo 'Warning: $MODEL_START_TYPE = '${MODEL_START_TYPE}
echo '$RUN_REFDIR = '${RUN_REFDIR}
echo '$RUN_REFCASE = '${RUN_REFCASE}
echo '$RUN_REFDATE = '${START_DATE}
else
echo 'ERROR: $MODEL_START_TYPE = '${MODEL_START_TYPE}' is unrecognized. Exiting.'
exit 380
fi
cat << EOF >> 6hi.yaml
averaging_type: instant
fields:
physics_pg2:
field_names:
####
- air_temperature_0:=T_mid_where_lev_ge_0_where_lev_lt_15_vert_avg_dp_weighted
- air_temperature_1:=T_mid_where_lev_ge_15_where_lev_lt_28_vert_avg_dp_weighted
- air_temperature_2:=T_mid_where_lev_ge_28_where_lev_lt_46_vert_avg_dp_weighted
- air_temperature_3:=T_mid_where_lev_ge_46_where_lev_lt_62_vert_avg_dp_weighted
- air_temperature_4:=T_mid_where_lev_ge_62_where_lev_lt_78_vert_avg_dp_weighted
- air_temperature_5:=T_mid_where_lev_ge_78_where_lev_lt_96_vert_avg_dp_weighted
- air_temperature_6:=T_mid_where_lev_ge_96_where_lev_lt_115_vert_avg_dp_weighted
- air_temperature_7:=T_mid_where_lev_ge_115_where_lev_le_128_vert_avg_dp_weighted
####
- eastward_wind_0:=U_where_lev_ge_0_where_lev_lt_15_vert_avg_dp_weighted
- eastward_wind_1:=U_where_lev_ge_15_where_lev_lt_28_vert_avg_dp_weighted
- eastward_wind_2:=U_where_lev_ge_28_where_lev_lt_46_vert_avg_dp_weighted
- eastward_wind_3:=U_where_lev_ge_46_where_lev_lt_62_vert_avg_dp_weighted
- eastward_wind_4:=U_where_lev_ge_62_where_lev_lt_78_vert_avg_dp_weighted
- eastward_wind_5:=U_where_lev_ge_78_where_lev_lt_96_vert_avg_dp_weighted
- eastward_wind_6:=U_where_lev_ge_96_where_lev_lt_115_vert_avg_dp_weighted
- eastward_wind_7:=U_where_lev_ge_115_where_lev_le_128_vert_avg_dp_weighted
####
- northward_wind_0:=V_where_lev_ge_0_where_lev_lt_15_vert_avg_dp_weighted
- northward_wind_1:=V_where_lev_ge_15_where_lev_lt_28_vert_avg_dp_weighted
- northward_wind_2:=V_where_lev_ge_28_where_lev_lt_46_vert_avg_dp_weighted
- northward_wind_3:=V_where_lev_ge_46_where_lev_lt_62_vert_avg_dp_weighted
- northward_wind_4:=V_where_lev_ge_62_where_lev_lt_78_vert_avg_dp_weighted
- northward_wind_5:=V_where_lev_ge_78_where_lev_lt_96_vert_avg_dp_weighted
- northward_wind_6:=V_where_lev_ge_96_where_lev_lt_115_vert_avg_dp_weighted
- northward_wind_7:=V_where_lev_ge_115_where_lev_le_128_vert_avg_dp_weighted
####
- total_specific_humidity_0:=qc_plus_qv_plus_qi_plus_qr_where_lev_ge_0_where_lev_lt_15_vert_avg_dp_weighted
- total_specific_humidity_1:=qc_plus_qv_plus_qi_plus_qr_where_lev_ge_15_where_lev_lt_28_vert_avg_dp_weighted
- total_specific_humidity_2:=qc_plus_qv_plus_qi_plus_qr_where_lev_ge_28_where_lev_lt_46_vert_avg_dp_weighted
- total_specific_humidity_3:=qc_plus_qv_plus_qi_plus_qr_where_lev_ge_46_where_lev_lt_62_vert_avg_dp_weighted
- total_specific_humidity_4:=qc_plus_qv_plus_qi_plus_qr_where_lev_ge_62_where_lev_lt_78_vert_avg_dp_weighted
- total_specific_humidity_5:=qc_plus_qv_plus_qi_plus_qr_where_lev_ge_78_where_lev_lt_96_vert_avg_dp_weighted
- total_specific_humidity_6:=qc_plus_qv_plus_qi_plus_qr_where_lev_ge_96_where_lev_lt_115_vert_avg_dp_weighted
- total_specific_humidity_7:=qc_plus_qv_plus_qi_plus_qr_where_lev_ge_115_where_lev_le_128_vert_avg_dp_weighted
####
- PRESsfc:=ps
- surface_temperature:=surf_radiative_T
####
- land_fraction:=landfrac
- ocean_fraction:=ocnfrac
- sea_ice_fraction:=icefrac
####
- tendency_of_total_water_path_due_to_advection:=homme_qc_tend_plus_homme_qv_tend_plus_homme_qi_tend_plus_homme_qr_tend_vert_avg_dp_weighted
####
max_snapshots_per_file: 4
filename_prefix: 6hi
iotype: pnetcdf
output_control:
frequency: 6
frequency_units: nhours
restart:
force_new_file: true
EOF
cat << EOF >> 6ha.yaml
averaging_type: average
fields:
physics_pg2:
field_names:
####
- DSWRFtoa:=SW_flux_dn_at_model_top
- DSWRFsfc:=SW_flux_dn_at_model_bot
####
- DLWRFtoa:=LW_flux_dn_at_model_top
- DLWRFsfc:=LW_flux_dn_at_model_bot
####
- ULWRFtoa:=LW_flux_up_at_model_top
- ULWRFsfc:=LW_flux_up_at_model_bot
####
- USWRFtoa:=SW_flux_up_at_model_top
- USWRFsfc:=SW_flux_up_at_model_bot
####
- LHTFLsfc:=surface_upward_latent_heat_flux
- SHTFLsfc:=surf_sens_flux
####
- PRATEsfc:=precip_total_surf_mass_flux_over_rho_h2o
####
- HGTsfc:=phis_over_gravit
####
max_snapshots_per_file: 4
filename_prefix: 6ha
iotype: pnetcdf
output_control:
frequency: 6
frequency_units: nhours
restart:
force_new_file: true
EOF
./atmchange output_yaml_files="./6hi.yaml"
./atmchange output_yaml_files+="./6ha.yaml"
if [[ ${TUNINGSET} == "default" ]]; then
echo "--------------------------------------------------------------------"
echo "---------------------USING default SST------------------------------"
echo "--------------------------------------------------------------------"
./xmlchange --file env_run.xml --id SSTICE_DATA_FILENAME --val "${input_data_dir}/ocn/docn7/SSTDATA/sst_ice_CMIP6_DECK_E3SM_1x1_2010_clim_c20220426.nc"
elif [[ ${TUNINGSET} == "plus1k" ]]; then
echo "--------------------------------------------------------------------"
echo "---------------------USING P1K SST----------------------------------"
echo "--------------------------------------------------------------------"
./xmlchange --file env_run.xml --id SSTICE_DATA_FILENAME --val "${input_data_dir}/ocn/docn7/SSTDATA/sst_ice_CMIP6_DECK_E3SM_1x1_2010_clim_plus1k_c20220426.nc"
elif [[ ${TUNINGSET} == "minus1k" ]]; then
echo "--------------------------------------------------------------------"
echo "---------------------USING M1K SST----------------------------------"
echo "--------------------------------------------------------------------"
./xmlchange --file env_run.xml --id SSTICE_DATA_FILENAME --val "${input_data_dir}/ocn/docn7/SSTDATA/sst_ice_CMIP6_DECK_E3SM_1x1_2010_clim_minus1k_c20220426.nc"
fi
popd
}
#-----------------------------------------------------
case_submit() {
if [ "${do_case_submit,,}" != "true" ]; then
echo $'\n----- Skipping case_submit -----\n'
return
fi
echo $'\n----- Starting case_submit -----\n'
pushd ${CASE_SCRIPTS_DIR}
# Run CIME case.submit
./case.submit -a="--mail-type=ALL --mail-user=$USER@nersc.gov"
#./case.submit -a="--qos=${Q}"
popd
}
#-----------------------------------------------------
copy_script() {
echo $'\n----- Saving run script for provenance -----\n'
local script_provenance_dir=${CASE_SCRIPTS_DIR}/run_script_provenance
mkdir -p ${script_provenance_dir}
local this_script_name=$( basename -- "$0"; )
local this_script_dir=$( dirname -- "$0"; )
local script_provenance_name=${this_script_name}.`date +%Y%m%d-%H%M%S`
cp -vp "${this_script_dir}/${this_script_name}" ${script_provenance_dir}/${script_provenance_name}
}
#-----------------------------------------------------
# Silent versions of popd and pushd
pushd() {
command pushd "$@" > /dev/null
}
popd() {
command popd "$@" > /dev/null
}
# Now, actually run the script
#-----------------------------------------------------
main