diff --git a/jobs/JGLOBAL_FORECAST_GFS_INITIALIZE b/jobs/JGLOBAL_FORECAST_GFS_INITIALIZE new file mode 100755 index 00000000000..e69f1c843cf --- /dev/null +++ b/jobs/JGLOBAL_FORECAST_GFS_INITIALIZE @@ -0,0 +1,62 @@ +#! /usr/bin/env bash + +source "${HOMEgfs}/ush/preamble.testing.sh" +source "${HOMEgfs}/ush/jjob_header.sh" -e "fcst" -c "base fcst" + +############################################## +# Set variables used in the script +############################################## +# Set wave variables +if [ ${DO_WAVE:-"NO"} = "YES" ]; then + # WAVE component directory + export CDUMPwave=${CDUMPwave:-${CDUMP}wave} + export COMINwave=${COMINwave:-$(compath.py ${envir}/${NET}/${gfs_ver})/${CDUMP}.${PDY}/${cyc}/wave} + export COMOUTwave=${COMOUTwave:-$(compath.py -o ${NET}/${gfs_ver})/${CDUMP}.${PDY}/${cyc}/wave} +fi + +############################################## +# Begin JOB SPECIFIC work +############################################## + +# Restart conditions for GFS cycle come from GDAS +rCDUMP=${CDUMP} +[[ ${CDUMP} = "gfs" ]] && export rCDUMP="gdas" + +# Forecast length for GFS forecast +if [ ${CDUMP} = "gfs" ]; then + export FHMAX=${FHMAX_GFS} + export FHOUT=${FHOUT_GFS} + export FHMAX_HF=${FHMAX_HF_GFS} + export FHOUT_HF=${FHOUT_HF_GFS} +else + export FHMAX_HF=0 + export FHOUT_HF=0 +fi + + +############################################################### +# Run relevant exglobal script +$(which python) ${HOMEgfs}/scripts/exglobal_fv3gfs_forecast_initialize.py + +exit 9999 + + +############################################## +# End JOB SPECIFIC work +############################################## + +############################################## +# Final processing +############################################## +if [ -e "${pgmout}" ] ; then + cat ${pgmout} +fi + +########################################## +# Remove the Temporary working directory +########################################## +cd ${DATAROOT} +[[ ${KEEPDATA} = "NO" ]] && rm -rf ${DATA} + + +exit 0 diff --git a/jobs/rocoto/fv3gfs_init.sh b/jobs/rocoto/fv3gfs_init.sh new file mode 100755 index 00000000000..4c6d8e00d68 --- /dev/null +++ b/jobs/rocoto/fv3gfs_init.sh @@ -0,0 +1,34 @@ +#! /usr/bin/env bash + +# HRW source "${HOMEgfs}/ush/preamble.sh" + +############################################################### +# Source FV3GFS workflow modules +#. ${HOMEgfs}/ush/load_fv3gfs_modules.sh +#status=$? +#[[ ${status} -ne 0 ]] && exit ${status} + +# TODO: clean this up +# HRW source "${HOMEgfs}/ush/detect_machine.sh" +# HRW set +x +# HRW source "${HOMEgfs}/ush/module-setup.sh" +# HRW module use "${HOMEgfs}/sorc/ufs_model.fd/tests" +# HRW module load modules.ufs_model.lua +# HRW module load prod_util +# HRW if [[ "${MACHINE_ID}" = "wcoss2" ]]; then +# HRW module load cray-pals +# HRW fi +# HRW module list +# HRW unset MACHINE_ID +#HRW set_trace + +export job="fcst" +export jobid="${job}.refactor" # HRW + +############################################################### +# Execute the JJOB +${HOMEgfs}/jobs/JGLOBAL_FORECAST_GFS_INITIALIZE +status=$? + + +exit ${status} diff --git a/parm/config/config.fcst b/parm/config/config.fcst index 2a57647644d..19c61cee36c 100644 --- a/parm/config/config.fcst +++ b/parm/config/config.fcst @@ -74,6 +74,7 @@ export FORECASTSH="$HOMEgfs/scripts/exglobal_forecast.sh" #export FORECASTSH="$HOMEgfs/scripts/exglobal_forecast.py" # Temp. while this is worked on export FCSTEXECDIR="$HOMEgfs/exec" export FCSTEXEC="ufs_model.x" +export FCSTYAML="$HOMEgfs/parm/ufs/forecast/gfs.yaml" ####################################################################### # Model configuration diff --git a/parm/config/config.gfs_init b/parm/config/config.gfs_init new file mode 100644 index 00000000000..9d987bead5d --- /dev/null +++ b/parm/config/config.gfs_init @@ -0,0 +1,7 @@ +#!/bin/bash -x + +########## config.gfsinit ########## +# Configuration common to all GFS initialization tasks. + +echo "BEGIN: config.gfsinit" + diff --git a/parm/ufs/forecast/gfs.yaml b/parm/ufs/forecast/gfs.yaml new file mode 100644 index 00000000000..bfff8caab80 --- /dev/null +++ b/parm/ufs/forecast/gfs.yaml @@ -0,0 +1,21 @@ +forecast: + + dirtree_atmos: + mkdir: + - $(DATA)/INPUT + - $(DATA)/RESTART + + dirtree_ocean: + mkdir: + - $(DATA)/MOM6_OUTPUT + - $(DATA)/history + - $(DATA)/INPUT + - $(DATA)/RESTART + + fixed_files: + atmos: ${PARMgfs}/ufs/forecast/gfs/fix/atmos.fixed_files.yaml + land: ${PARMgfs}/ufs/forecast/gfs/fix/land.fixed_files.yaml + ocean: ${PARMgfs}/ufs/forecast/gfs/fix/ocean.fixed_files.yaml + + model_configure: ${PARMufs}/ufs/forecast/gfs/model_configure.IN + nems_configure: ${PARMufs}/ufs/forecast/gfs/nems/nems.configure.atm.IN diff --git a/parm/ufs/forecast/gfs/fix/atmos.fixed_files.yaml b/parm/ufs/forecast/gfs/fix/atmos.fixed_files.yaml new file mode 100644 index 00000000000..5b41f42f6ac --- /dev/null +++ b/parm/ufs/forecast/gfs/fix/atmos.fixed_files.yaml @@ -0,0 +1,87 @@ +copy: +# Atmosphere mosaic file linked as the grid_spec file (atm only) +- [$(FIX_orog)/$(atm_res)/$(atm_res)_mosaic.nc, $(DATA)/INPUT/grid_spec.nc] + +# Atmosphere grid tile files +- [$(FIX_orog)/$(atm_res)/$(atm_res)_grid.tile1.nc, $(DATA)/INPUT/] +- [$(FIX_orog)/$(atm_res)/$(atm_res)_grid.tile2.nc, $(DATA)/INPUT/] +- [$(FIX_orog)/$(atm_res)/$(atm_res)_grid.tile3.nc, $(DATA)/INPUT/] +- [$(FIX_orog)/$(atm_res)/$(atm_res)_grid.tile4.nc, $(DATA)/INPUT/] +- [$(FIX_orog)/$(atm_res)/$(atm_res)_grid.tile5.nc, $(DATA)/INPUT/] +- [$(FIX_orog)/$(atm_res)/$(atm_res)_grid.tile6.nc, $(DATA)/INPUT/] + + + +# oro_data_ls and oro_data_ss files from FIX_ugwd +- [$(FIX_ugwd)/$(atm_res)/$(atm_res)_oro_data_ls.tile1.nc, $(DATA)/INPUT/oro_data_ls.tile1.nc] +- [$(FIX_ugwd)/$(atm_res)/$(atm_res)_oro_data_ls.tile2.nc, $(DATA)/INPUT/oro_data_ls.tile2.nc] +- [$(FIX_ugwd)/$(atm_res)/$(atm_res)_oro_data_ls.tile3.nc, $(DATA)/INPUT/oro_data_ls.tile3.nc] +- [$(FIX_ugwd)/$(atm_res)/$(atm_res)_oro_data_ls.tile4.nc, $(DATA)/INPUT/oro_data_ls.tile4.nc] +- [$(FIX_ugwd)/$(atm_res)/$(atm_res)_oro_data_ls.tile5.nc, $(DATA)/INPUT/oro_data_ls.tile5.nc] +- [$(FIX_ugwd)/$(atm_res)/$(atm_res)_oro_data_ls.tile6.nc, $(DATA)/INPUT/oro_data_ls.tile6.nc] +- [$(FIX_ugwd)/$(atm_res)/$(atm_res)_oro_data_ss.tile1.nc, $(DATA)/INPUT/oro_data_ss.tile1.nc] +- [$(FIX_ugwd)/$(atm_res)/$(atm_res)_oro_data_ss.tile2.nc, $(DATA)/INPUT/oro_data_ss.tile2.nc] +- [$(FIX_ugwd)/$(atm_res)/$(atm_res)_oro_data_ss.tile3.nc, $(DATA)/INPUT/oro_data_ss.tile3.nc] +- [$(FIX_ugwd)/$(atm_res)/$(atm_res)_oro_data_ss.tile4.nc, $(DATA)/INPUT/oro_data_ss.tile4.nc] +- [$(FIX_ugwd)/$(atm_res)/$(atm_res)_oro_data_ss.tile5.nc, $(DATA)/INPUT/oro_data_ss.tile5.nc] +- [$(FIX_ugwd)/$(atm_res)/$(atm_res)_oro_data_ss.tile6.nc, $(DATA)/INPUT/oro_data_ss.tile6.nc] + +# GWD?? +- [$(FIX_ugwd)/ugwp_limb_tau.nc, $(DATA)/ugwp_limb_tau.nc] + +# CO2 climatology +- [$(FIX_am)/co2monthlycyc.txt, $(DATA)/co2monthlycyc.txt] +- [$(FIX_am)/global_co2historicaldata_glob.txt, $(DATA)/co2historicaldata_glob.txt] +- [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2009.txt, $(DATA)/co2historicaldata_2009.txt] +- [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2010.txt, $(DATA)/co2historicaldata_2010.txt] +- [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2011.txt, $(DATA)/co2historicaldata_2011.txt] +- [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2012.txt, $(DATA)/co2historicaldata_2012.txt] +- [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2013.txt, $(DATA)/co2historicaldata_2013.txt] +- [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2014.txt, $(DATA)/co2historicaldata_2014.txt] +- [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2015.txt, $(DATA)/co2historicaldata_2015.txt] +- [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2016.txt, $(DATA)/co2historicaldata_2016.txt] +- [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2017.txt, $(DATA)/co2historicaldata_2017.txt] +- [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2018.txt, $(DATA)/co2historicaldata_2018.txt] +- [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2019.txt, $(DATA)/co2historicaldata_2019.txt] +- [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2020.txt, $(DATA)/co2historicaldata_2020.txt] +- [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2021.txt, $(DATA)/co2historicaldata_2021.txt] +- [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2022.txt, $(DATA)/co2historicaldata_2022.txt] +- [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2023.txt, $(DATA)/co2historicaldata_2023.txt] + +# FIX_am files +- [$(FIX_am)/global_climaeropac_global.txt, $(DATA)/aerosol.dat] +- [$(FIX_am)/ozprdlos_2015_new_sbuvO3_tclm15_nuchem.f77, $(DATA)/global_o3prdlos.f77] +- [$(FIX_am)/global_h2o_pltc.f77, $(DATA)/global_h2oprdlos.f77] +- [$(FIX_am)/global_glacier.2x2.grb, $(DATA)/global_glacier.2x2.grb] +- [$(FIX_am)/global_maxice.2x2.grb, $(DATA)/global_maxice.2x2.grb] +- [$(FIX_am)/global_snoclim.1.875.grb, $(DATA)/global_snoclim.1.875.grb] +- [$(FIX_am)/global_slmask.t1534.3072.1536.grb, $(DATA)/global_slmask.t1534.3072.1536.grb] +- [$(FIX_am)/global_soilmgldas.statsgo.t1534.3072.1536.grb, $(DATA)/global_soilmgldas.statsgo.t1534.3072.1536.grb] +- [$(FIX_am)/global_solarconstant_noaa_an.txt, $(DATA)/solarconstant_noaa_an.txt] +- [$(FIX_am)/global_sfc_emissivity_idx.txt, $(DATA)/sfc_emissivity_idx.txt] +- [$(FIX_am)/RTGSST.1982.2012.monthly.clim.grb, $(DATA)/RTGSST.1982.2012.monthly.clim.grb] +- [$(FIX_am)/IMS-NIC.blended.ice.monthly.clim.grb, $(DATA)/IMS-NIC.blended.ice.monthly.clim.grb] + +# MERRA2 Aerosol Climatology +- [$(FIX_aer)/merra2.aerclim.2003-2014.m01.nc, $(DATA)/aeroclim.m01.nc] +- [$(FIX_aer)/merra2.aerclim.2003-2014.m02.nc, $(DATA)/aeroclim.m02.nc] +- [$(FIX_aer)/merra2.aerclim.2003-2014.m03.nc, $(DATA)/aeroclim.m03.nc] +- [$(FIX_aer)/merra2.aerclim.2003-2014.m04.nc, $(DATA)/aeroclim.m04.nc] +- [$(FIX_aer)/merra2.aerclim.2003-2014.m05.nc, $(DATA)/aeroclim.m05.nc] +- [$(FIX_aer)/merra2.aerclim.2003-2014.m06.nc, $(DATA)/aeroclim.m06.nc] +- [$(FIX_aer)/merra2.aerclim.2003-2014.m07.nc, $(DATA)/aeroclim.m07.nc] +- [$(FIX_aer)/merra2.aerclim.2003-2014.m08.nc, $(DATA)/aeroclim.m08.nc] +- [$(FIX_aer)/merra2.aerclim.2003-2014.m09.nc, $(DATA)/aeroclim.m09.nc] +- [$(FIX_aer)/merra2.aerclim.2003-2014.m10.nc, $(DATA)/aeroclim.m10.nc] +- [$(FIX_aer)/merra2.aerclim.2003-2014.m11.nc, $(DATA)/aeroclim.m11.nc] +- [$(FIX_aer)/merra2.aerclim.2003-2014.m12.nc, $(DATA)/aeroclim.m12.nc] + +# Optical depth +- [$(FIX_lut)/optics_BC.v1_3.dat, $(DATA)/optics_BC.dat] +- [$(FIX_lut)/optics_DU.v15_3.dat, $(DATA)/optics_DU.dat] +- [$(FIX_lut)/optics_OC.v1_3.dat, $(DATA)/optics_OC.dat] +- [$(FIX_lut)/optics_SS.v3_3.dat, $(DATA)/optics_SS.dat] +- [$(FIX_lut)/optics_SU.v1_3.dat, $(DATA)/optics_SU.dat] + +# fd_nems.yaml file +- [$(HOMEgfs)/sorc/ufs_model.fd/tests/parm/fd_nems.yaml, $(DATA)/] diff --git a/parm/ufs/forecast/gfs/fix/land.fixed_files.yaml b/parm/ufs/forecast/gfs/fix/land.fixed_files.yaml new file mode 100644 index 00000000000..ab93ff27a63 --- /dev/null +++ b/parm/ufs/forecast/gfs/fix/land.fixed_files.yaml @@ -0,0 +1,58 @@ +copy: + + # Files from FIX_orog/C??.mx??_frac/fix_sfc + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).facsf.tile1.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).facsf.tile2.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).facsf.tile3.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).facsf.tile4.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).facsf.tile5.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).facsf.tile6.nc, $(DATA)/] + + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).maximum_snow_albedo.tile1.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).maximum_snow_albedo.tile2.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).maximum_snow_albedo.tile3.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).maximum_snow_albedo.tile4.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).maximum_snow_albedo.tile5.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).maximum_snow_albedo.tile6.nc, $(DATA)/] + + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).slope_type.tile1.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).slope_type.tile2.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).slope_type.tile3.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).slope_type.tile4.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).slope_type.tile5.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).slope_type.tile6.nc, $(DATA)/] + + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).snowfree_albedo.tile1.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).snowfree_albedo.tile2.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).snowfree_albedo.tile3.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).snowfree_albedo.tile4.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).snowfree_albedo.tile5.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).snowfree_albedo.tile6.nc, $(DATA)/] + + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).soil_type.tile1.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).soil_type.tile2.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).soil_type.tile3.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).soil_type.tile4.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).soil_type.tile5.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).soil_type.tile6.nc, $(DATA)/] + + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).substrate_temperature.tile1.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).substrate_temperature.tile2.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).substrate_temperature.tile3.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).substrate_temperature.tile4.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).substrate_temperature.tile5.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).substrate_temperature.tile6.nc, $(DATA)/] + + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).vegetation_greenness.tile1.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).vegetation_greenness.tile2.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).vegetation_greenness.tile3.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).vegetation_greenness.tile4.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).vegetation_greenness.tile5.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).vegetation_greenness.tile6.nc, $(DATA)/] + + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).vegetation_type.tile1.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).vegetation_type.tile2.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).vegetation_type.tile3.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).vegetation_type.tile4.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).vegetation_type.tile5.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).vegetation_type.tile6.nc, $(DATA)/] diff --git a/parm/ufs/forecast/gfs/fix/ocean.fixed_files.yaml b/parm/ufs/forecast/gfs/fix/ocean.fixed_files.yaml new file mode 100644 index 00000000000..801f070c49a --- /dev/null +++ b/parm/ufs/forecast/gfs/fix/ocean.fixed_files.yaml @@ -0,0 +1,10 @@ +copy: + + # Orography data tile files + # The following are for "frac_grid = .true." + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/oro_$(atm_res).mx$(ocn_res).tile1.nc, $(DATA)/INPUT/oro_data.tile1.nc] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/oro_$(atm_res).mx$(ocn_res).tile2.nc, $(DATA)/INPUT/oro_data.tile2.nc] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/oro_$(atm_res).mx$(ocn_res).tile3.nc, $(DATA)/INPUT/oro_data.tile3.nc] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/oro_$(atm_res).mx$(ocn_res).tile4.nc, $(DATA)/INPUT/oro_data.tile4.nc] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/oro_$(atm_res).mx$(ocn_res).tile5.nc, $(DATA)/INPUT/oro_data.tile5.nc] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/oro_$(atm_res).mx$(ocn_res).tile6.nc, $(DATA)/INPUT/oro_data.tile6.nc] diff --git a/parm/ufs/forecast/gfs/model_configure.IN b/parm/ufs/forecast/gfs/model_configure.IN new file mode 100644 index 00000000000..99959de98fc --- /dev/null +++ b/parm/ufs/forecast/gfs/model_configure.IN @@ -0,0 +1,36 @@ +start_year: {{ ufswm.atmos.timestamps.year }} +start_month: {{ ufswm.atmos.timestamps.month }} +start_day: {{ ufswm.atmos.timestamps.day }} +start_hour: {{ ufswm.atmos.timestamps.hour }} +start_minute: {{ ufswm.atmos.timestamps.minute }} +start_second: {{ ufswm.atmos.timestamps.second }} +nhours_fcst {{ FHMAX }} +fhrot: {{ 0 }} + +dt_atmos: {{ ufswm.atmos.layout.deltim }} +calendar: "{{ calendar | default("julian") }}" +restart_interval: {{ restart_interval }} +output_1st_tstep_rst: {{ output_1st_tstep_rst | default(".false.") }} + +quilting: {{ ufswm.atmos.layout.quilting }} +write_groups: {{ ufswm.atmos.layout.write_group }} +write_tasks_per_group: {{ ufswm.atmos.layout.wrttask_per_group }} +itasks: 1 +output_history: {{ OUTPUT_HISTORY | default(".true.") }} +write_dopost: {{ WRITE_DOPOST }} +write_nsflip: {{ WRITE_NSFLIP }} +num_files: {{ numfiles | default(2) }} +filename_base: "{{ filename_base_atm | default("atm") }}" "{{ filename_base_sfc | default("sfc") }}" +output_grid: {{ OUTPUT_GRID | default("gaussian_grid") }} +output_file: "{{ OUTPUT_FILETYPE_ATM | default("netcdf") }}" "{{ OUTPUT_FILETYPE_SFC | default("netcdf") }}" +ichunk2d: {{ ufswm.atmos.layout.ichunk2d }} +jchunk2d: {{ ufswm.atmos.layout.jchunk2d }} +ichunk3d: {{ ufswm.atmos.layout.ichunk3d }} +jchunk3d: {{ ufswm.atmos.layout.jchunk3d }} +kchunk3d: {{ ufswm.atmos.layout.kchunk3d }} +ideflate: {{ ideflate | default(1) }} +nbits: {{ nbits | default(14) }} +imo: {{ ufswm.atmos.grids.lonb }} +jmo: {{ ufswm.atmos.grids.latb }} +output_fh: {{ OUTPUT_FH | default(0) }} +iau_offset: {{ IAU_OFFSET | default(0) }} diff --git a/parm/ufs/forecast/gfs/nems/nems.configure.atm.IN b/parm/ufs/forecast/gfs/nems/nems.configure.atm.IN new file mode 100644 index 00000000000..3ca60ccef3a --- /dev/null +++ b/parm/ufs/forecast/gfs/nems/nems.configure.atm.IN @@ -0,0 +1,8 @@ +# ESMF # +logKindFlag: {{ esmf_logkind or "ESMF_LOGKIND_NONE"}} + +EARTH_component_list: ATM +ATM_model: fv3 +runSeq:: + ATM +:: diff --git a/parm/ufs/forecast/gfs/nems/nems.configure.atm_aero.IN b/parm/ufs/forecast/gfs/nems/nems.configure.atm_aero.IN new file mode 100644 index 00000000000..b3fc775034d --- /dev/null +++ b/parm/ufs/forecast/gfs/nems/nems.configure.atm_aero.IN @@ -0,0 +1,47 @@ +############################################# +#### NEMS Run-Time Configuration File ##### +############################################# + +# ESMF # + logKindFlag: @[esmf_logkind] + +# EARTH # +EARTH_component_list: ATM CHM +EARTH_attributes:: + Verbosity = max +:: + +# ATM # +ATM_model: @[atm_model] +ATM_petlist_bounds: @[atm_petlist_bounds] +ATM_attributes:: + Verbosity = max +:: + +# CHM # +CHM_model: @[chm_model] +CHM_petlist_bounds: @[chm_petlist_bounds] +CHM_attributes:: + Verbosity = max +:: + +# Run Sequence # +runSeq:: + @@[coupling_interval_fast_sec] + ATM phase1 + ATM -> CHM + CHM + CHM -> ATM + ATM phase2 + @ +:: + +# CMEPS variables + +DRIVER_attributes:: + mediator_read_restart = .false. +:: + +ALLCOMP_attributes:: + start_type = startup +:: diff --git a/parm/ufs/forecast/gfs/nems/nems.configure.blocked_atm_wav.IN b/parm/ufs/forecast/gfs/nems/nems.configure.blocked_atm_wav.IN new file mode 100644 index 00000000000..159cf6a4589 --- /dev/null +++ b/parm/ufs/forecast/gfs/nems/nems.configure.blocked_atm_wav.IN @@ -0,0 +1,38 @@ +############################################# +#### NEMS Run-Time Configuration File ##### +############################################# + +# ESMF # + logKindFlag: @[esmf_logkind] + +# EARTH # +EARTH_component_list: ATM WAV +EARTH_attributes:: + Verbosity = max +:: + +# ATM # +ATM_model: @[atm_model] +ATM_petlist_bounds: @[atm_petlist_bounds] +ATM_attributes:: + Verbosity = max + DumpFields = true +:: + +# WAV # +WAV_model: @[wav_model] +WAV_petlist_bounds: @[wav_petlist_bounds] +WAV_attributes:: + Verbosity = max +:: + + + +# Run Sequence # +runSeq:: + @@[coupling_interval_sec] + ATM -> WAV + ATM + WAV + @ +:: diff --git a/parm/ufs/forecast/gfs/nems/nems.configure.cpld.IN b/parm/ufs/forecast/gfs/nems/nems.configure.cpld.IN new file mode 100644 index 00000000000..dda18352051 --- /dev/null +++ b/parm/ufs/forecast/gfs/nems/nems.configure.cpld.IN @@ -0,0 +1,111 @@ +############################################# +#### NEMS Run-Time Configuration File ##### +############################################# + +# ESMF # +logKindFlag: @[esmf_logkind] + +# EARTH # +EARTH_component_list: MED ATM OCN ICE +EARTH_attributes:: + Verbosity = 0 +:: + +# MED # +MED_model: @[med_model] +MED_petlist_bounds: @[med_petlist_bounds] +:: + +# ATM # +ATM_model: @[atm_model] +ATM_petlist_bounds: @[atm_petlist_bounds] +ATM_attributes:: + Verbosity = 0 + DumpFields = @[DumpFields] + ProfileMemory = false + OverwriteSlice = true +:: + +# OCN # +OCN_model: @[ocn_model] +OCN_petlist_bounds: @[ocn_petlist_bounds] +OCN_attributes:: + Verbosity = 0 + DumpFields = @[DumpFields] + ProfileMemory = false + OverwriteSlice = true + mesh_ocn = @[MESH_OCN_ICE] +:: + +# ICE # +ICE_model: @[ice_model] +ICE_petlist_bounds: @[ice_petlist_bounds] +ICE_attributes:: + Verbosity = 0 + DumpFields = @[DumpFields] + ProfileMemory = false + OverwriteSlice = true + mesh_ice = @[MESH_OCN_ICE] + stop_n = @[RESTART_N] + stop_option = nhours + stop_ymd = -999 +:: + +# CMEPS warm run sequence +runSeq:: +@@[coupling_interval_slow_sec] + MED med_phases_prep_ocn_avg + MED -> OCN :remapMethod=redist + OCN + @@[coupling_interval_fast_sec] + MED med_phases_prep_atm + MED med_phases_prep_ice + MED -> ATM :remapMethod=redist + MED -> ICE :remapMethod=redist + ATM + ICE + ATM -> MED :remapMethod=redist + MED med_phases_post_atm + ICE -> MED :remapMethod=redist + MED med_phases_post_ice + MED med_phases_prep_ocn_accum + @ + OCN -> MED :remapMethod=redist + MED med_phases_post_ocn + MED med_phases_restart_write +@ +:: + +# CMEPS variables + +DRIVER_attributes:: +:: +MED_attributes:: + ATM_model = @[atm_model] + ICE_model = @[ice_model] + OCN_model = @[ocn_model] + history_n = 0 + history_option = nhours + history_ymd = -999 + coupling_mode = @[CPLMODE] + history_tile_atm = @[ATMTILESIZE] +:: +ALLCOMP_attributes:: + ScalarFieldCount = 2 + ScalarFieldIdxGridNX = 1 + ScalarFieldIdxGridNY = 2 + ScalarFieldName = cpl_scalars + start_type = @[RUNTYPE] + restart_dir = RESTART/ + case_name = ufs.cpld + restart_n = @[RESTART_N] + restart_option = nhours + restart_ymd = -999 + dbug_flag = @[cap_dbug_flag] + use_coldstart = @[use_coldstart] + use_mommesh = @[use_mommesh] + eps_imesh = @[eps_imesh] + stop_n = @[FHMAX] + stop_option = nhours + stop_ymd = -999 +:: diff --git a/parm/ufs/forecast/gfs/nems/nems.configure.cpld_aero_outerwave.IN b/parm/ufs/forecast/gfs/nems/nems.configure.cpld_aero_outerwave.IN new file mode 100644 index 00000000000..e7a13a02c12 --- /dev/null +++ b/parm/ufs/forecast/gfs/nems/nems.configure.cpld_aero_outerwave.IN @@ -0,0 +1,141 @@ +############################################# +#### NEMS Run-Time Configuration File ##### +############################################# + +# ESMF # + logKindFlag: @[esmf_logkind] + +# EARTH # +EARTH_component_list: MED ATM CHM OCN ICE WAV +EARTH_attributes:: + Verbosity = 0 +:: + +# MED # +MED_model: @[med_model] +MED_petlist_bounds: @[med_petlist_bounds] +:: + +# ATM # +ATM_model: @[atm_model] +ATM_petlist_bounds: @[atm_petlist_bounds] +ATM_attributes:: + Verbosity = 0 + DumpFields = @[DumpFields] + ProfileMemory = false + OverwriteSlice = true +:: + +# CHM # +CHM_model: @[chm_model] +CHM_petlist_bounds: @[chm_petlist_bounds] +CHM_attributes:: + Verbosity = 0 +:: + +# OCN # +OCN_model: @[ocn_model] +OCN_petlist_bounds: @[ocn_petlist_bounds] +OCN_attributes:: + Verbosity = 0 + DumpFields = @[DumpFields] + ProfileMemory = false + OverwriteSlice = true + mesh_ocn = @[MESH_OCN_ICE] +:: + +# ICE # +ICE_model: @[ice_model] +ICE_petlist_bounds: @[ice_petlist_bounds] +ICE_attributes:: + Verbosity = 0 + DumpFields = @[DumpFields] + ProfileMemory = false + OverwriteSlice = true + mesh_ice = @[MESH_OCN_ICE] + stop_n = @[RESTART_N] + stop_option = nhours + stop_ymd = -999 +:: + +# WAV # +WAV_model: @[wav_model] +WAV_petlist_bounds: @[wav_petlist_bounds] +WAV_attributes:: + Verbosity = 0 + OverwriteSlice = false + diro = "." + logfile = wav.log + mesh_wav = @[MESH_WAV] + multigrid = @[MULTIGRID] +:: + +# CMEPS warm run sequence +runSeq:: +@@[coupling_interval_slow_sec] + MED med_phases_prep_wav_avg + MED med_phases_prep_ocn_avg + MED -> WAV :remapMethod=redist + MED -> OCN :remapMethod=redist + WAV + OCN + @@[coupling_interval_fast_sec] + MED med_phases_prep_atm + MED med_phases_prep_ice + MED -> ATM :remapMethod=redist + MED -> ICE :remapMethod=redist + ATM phase1 + ATM -> CHM + CHM + CHM -> ATM + ATM phase2 + ICE + ATM -> MED :remapMethod=redist + MED med_phases_post_atm + ICE -> MED :remapMethod=redist + MED med_phases_post_ice + MED med_phases_prep_ocn_accum + MED med_phases_prep_wav_accum + @ + OCN -> MED :remapMethod=redist + WAV -> MED :remapMethod=redist + MED med_phases_post_ocn + MED med_phases_post_wav + MED med_phases_restart_write +@ +:: + +# CMEPS variables + +DRIVER_attributes:: +:: +MED_attributes:: + ATM_model = @[atm_model] + ICE_model = @[ice_model] + OCN_model = @[ocn_model] + WAV_model = @[wav_model] + history_n = 0 + history_option = nhours + history_ymd = -999 + coupling_mode = @[CPLMODE] + history_tile_atm = @[ATMTILESIZE] +:: +ALLCOMP_attributes:: + ScalarFieldCount = 2 + ScalarFieldIdxGridNX = 1 + ScalarFieldIdxGridNY = 2 + ScalarFieldName = cpl_scalars + start_type = @[RUNTYPE] + restart_dir = RESTART/ + case_name = ufs.cpld + restart_n = @[RESTART_N] + restart_option = nhours + restart_ymd = -999 + dbug_flag = @[cap_dbug_flag] + use_coldstart = @[use_coldstart] + use_mommesh = @[use_mommesh] + eps_imesh = @[eps_imesh] + stop_n = @[FHMAX] + stop_option = nhours + stop_ymd = -999 +:: diff --git a/parm/ufs/forecast/gfs/nems/nems.configure.cpld_aero_wave.IN b/parm/ufs/forecast/gfs/nems/nems.configure.cpld_aero_wave.IN new file mode 100644 index 00000000000..9e67af9ba45 --- /dev/null +++ b/parm/ufs/forecast/gfs/nems/nems.configure.cpld_aero_wave.IN @@ -0,0 +1,141 @@ +############################################# +#### NEMS Run-Time Configuration File ##### +############################################# + +# ESMF # + logKindFlag: @[esmf_logkind] + +# EARTH # +EARTH_component_list: MED ATM CHM OCN ICE WAV +EARTH_attributes:: + Verbosity = 0 +:: + +# MED # +MED_model: @[med_model] +MED_petlist_bounds: @[med_petlist_bounds] +:: + +# ATM # +ATM_model: @[atm_model] +ATM_petlist_bounds: @[atm_petlist_bounds] +ATM_attributes:: + Verbosity = 0 + DumpFields = @[DumpFields] + ProfileMemory = false + OverwriteSlice = true +:: + +# CHM # +CHM_model: @[chm_model] +CHM_petlist_bounds: @[chm_petlist_bounds] +CHM_attributes:: + Verbosity = 0 +:: + +# OCN # +OCN_model: @[ocn_model] +OCN_petlist_bounds: @[ocn_petlist_bounds] +OCN_attributes:: + Verbosity = 0 + DumpFields = @[DumpFields] + ProfileMemory = false + OverwriteSlice = true + mesh_ocn = @[MESH_OCN_ICE] +:: + +# ICE # +ICE_model: @[ice_model] +ICE_petlist_bounds: @[ice_petlist_bounds] +ICE_attributes:: + Verbosity = 0 + DumpFields = @[DumpFields] + ProfileMemory = false + OverwriteSlice = true + mesh_ice = @[MESH_OCN_ICE] + stop_n = @[RESTART_N] + stop_option = nhours + stop_ymd = -999 +:: + +# WAV # +WAV_model: @[wav_model] +WAV_petlist_bounds: @[wav_petlist_bounds] +WAV_attributes:: + Verbosity = 0 + OverwriteSlice = false + diro = "." + logfile = wav.log + mesh_wav = @[MESH_WAV] + multigrid = @[MULTIGRID] +:: + +# CMEPS warm run sequence +runSeq:: +@@[coupling_interval_slow_sec] + MED med_phases_prep_ocn_avg + MED -> OCN :remapMethod=redist + OCN + @@[coupling_interval_fast_sec] + MED med_phases_prep_atm + MED med_phases_prep_ice + MED med_phases_prep_wav_accum + MED med_phases_prep_wav_avg + MED -> ATM :remapMethod=redist + MED -> ICE :remapMethod=redist + MED -> WAV :remapMethod=redist + ATM phase1 + ATM -> CHM + CHM + CHM -> ATM + ATM phase2 + ICE + WAV + ATM -> MED :remapMethod=redist + MED med_phases_post_atm + ICE -> MED :remapMethod=redist + MED med_phases_post_ice + WAV -> MED :remapMethod=redist + MED med_phases_post_wav + MED med_phases_prep_ocn_accum + @ + OCN -> MED :remapMethod=redist + MED med_phases_post_ocn + MED med_phases_restart_write +@ +:: + +# CMEPS variables + +DRIVER_attributes:: +:: +MED_attributes:: + ATM_model = @[atm_model] + ICE_model = @[ice_model] + OCN_model = @[ocn_model] + WAV_model = @[wav_model] + history_n = 0 + history_option = nhours + history_ymd = -999 + coupling_mode = @[CPLMODE] + history_tile_atm = @[ATMTILESIZE] +:: +ALLCOMP_attributes:: + ScalarFieldCount = 2 + ScalarFieldIdxGridNX = 1 + ScalarFieldIdxGridNY = 2 + ScalarFieldName = cpl_scalars + start_type = @[RUNTYPE] + restart_dir = RESTART/ + case_name = ufs.cpld + restart_n = @[RESTART_N] + restart_option = nhours + restart_ymd = -999 + dbug_flag = @[cap_dbug_flag] + use_coldstart = @[use_coldstart] + use_mommesh = @[use_mommesh] + eps_imesh = @[eps_imesh] + stop_n = @[FHMAX] + stop_option = nhours + stop_ymd = -999 +:: diff --git a/parm/ufs/forecast/gfs/nems/nems.configure.cpld_outerwave.IN b/parm/ufs/forecast/gfs/nems/nems.configure.cpld_outerwave.IN new file mode 100644 index 00000000000..8f4552a5896 --- /dev/null +++ b/parm/ufs/forecast/gfs/nems/nems.configure.cpld_outerwave.IN @@ -0,0 +1,130 @@ +############################################# +#### NEMS Run-Time Configuration File ##### +############################################# + +# ESMF # +logKindFlag: @[esmf_logkind] + +# EARTH # +EARTH_component_list: MED ATM OCN ICE WAV +EARTH_attributes:: + Verbosity = 0 +:: + +# MED # +MED_model: @[med_model] +MED_petlist_bounds: @[med_petlist_bounds] +:: + +# ATM # +ATM_model: @[atm_model] +ATM_petlist_bounds: @[atm_petlist_bounds] +ATM_attributes:: + Verbosity = 0 + DumpFields = @[DumpFields] + ProfileMemory = false + OverwriteSlice = true +:: + +# OCN # +OCN_model: @[ocn_model] +OCN_petlist_bounds: @[ocn_petlist_bounds] +OCN_attributes:: + Verbosity = 0 + DumpFields = @[DumpFields] + ProfileMemory = false + OverwriteSlice = true + mesh_ocn = @[MESH_OCN_ICE] +:: + +# ICE # +ICE_model: @[ice_model] +ICE_petlist_bounds: @[ice_petlist_bounds] +ICE_attributes:: + Verbosity = 0 + DumpFields = @[DumpFields] + ProfileMemory = false + OverwriteSlice = true + mesh_ice = @[MESH_OCN_ICE] + stop_n = @[RESTART_N] + stop_option = nhours + stop_ymd = -999 +:: + +# WAV # +WAV_model: @[wav_model] +WAV_petlist_bounds: @[wav_petlist_bounds] +WAV_attributes:: + Verbosity = 0 + OverwriteSlice = false + diro = "." + logfile = wav.log + mesh_wav = @[MESH_WAV] + multigrid = @[MULTIGRID] +:: + +# CMEPS warm run sequence +runSeq:: +@@[coupling_interval_slow_sec] + MED med_phases_prep_wav_avg + MED med_phases_prep_ocn_avg + MED -> WAV :remapMethod=redist + MED -> OCN :remapMethod=redist + WAV + OCN + @@[coupling_interval_fast_sec] + MED med_phases_prep_atm + MED med_phases_prep_ice + MED -> ATM :remapMethod=redist + MED -> ICE :remapMethod=redist + ATM + ICE + ATM -> MED :remapMethod=redist + MED med_phases_post_atm + ICE -> MED :remapMethod=redist + MED med_phases_post_ice + MED med_phases_prep_ocn_accum + MED med_phases_prep_wav_accum + @ + OCN -> MED :remapMethod=redist + WAV -> MED :remapMethod=redist + MED med_phases_post_ocn + MED med_phases_post_wav + MED med_phases_restart_write +@ +:: + +# CMEPS variables + +DRIVER_attributes:: +:: +MED_attributes:: + ATM_model = @[atm_model] + ICE_model = @[ice_model] + OCN_model = @[ocn_model] + WAV_model = @[wav_model] + history_n = 0 + history_option = nhours + history_ymd = -999 + coupling_mode = @[CPLMODE] + history_tile_atm = @[ATMTILESIZE] +:: +ALLCOMP_attributes:: + ScalarFieldCount = 2 + ScalarFieldIdxGridNX = 1 + ScalarFieldIdxGridNY = 2 + ScalarFieldName = cpl_scalars + start_type = @[RUNTYPE] + restart_dir = RESTART/ + case_name = ufs.cpld + restart_n = @[RESTART_N] + restart_option = nhours + restart_ymd = -999 + dbug_flag = @[cap_dbug_flag] + use_coldstart = @[use_coldstart] + use_mommesh = @[use_mommesh] + eps_imesh = @[eps_imesh] + stop_n = @[FHMAX] + stop_option = nhours + stop_ymd = -999 +:: diff --git a/parm/ufs/forecast/gfs/nems/nems.configure.cpld_wave.IN b/parm/ufs/forecast/gfs/nems/nems.configure.cpld_wave.IN new file mode 100644 index 00000000000..89ef5101605 --- /dev/null +++ b/parm/ufs/forecast/gfs/nems/nems.configure.cpld_wave.IN @@ -0,0 +1,130 @@ +############################################# +#### NEMS Run-Time Configuration File ##### +############################################# + +# ESMF # +logKindFlag: @[esmf_logkind] + +# EARTH # +EARTH_component_list: MED ATM OCN ICE WAV +EARTH_attributes:: + Verbosity = 0 +:: + +# MED # +MED_model: @[med_model] +MED_petlist_bounds: @[med_petlist_bounds] +:: + +# ATM # +ATM_model: @[atm_model] +ATM_petlist_bounds: @[atm_petlist_bounds] +ATM_attributes:: + Verbosity = 0 + DumpFields = @[DumpFields] + ProfileMemory = false + OverwriteSlice = true +:: + +# OCN # +OCN_model: @[ocn_model] +OCN_petlist_bounds: @[ocn_petlist_bounds] +OCN_attributes:: + Verbosity = 0 + DumpFields = @[DumpFields] + ProfileMemory = false + OverwriteSlice = true + mesh_ocn = @[MESH_OCN_ICE] +:: + +# ICE # +ICE_model: @[ice_model] +ICE_petlist_bounds: @[ice_petlist_bounds] +ICE_attributes:: + Verbosity = 0 + DumpFields = @[DumpFields] + ProfileMemory = false + OverwriteSlice = true + mesh_ice = @[MESH_OCN_ICE] + stop_n = @[RESTART_N] + stop_option = nhours + stop_ymd = -999 +:: + +# WAV # +WAV_model: @[wav_model] +WAV_petlist_bounds: @[wav_petlist_bounds] +WAV_attributes:: + Verbosity = 0 + OverwriteSlice = false + diro = "." + logfile = wav.log + mesh_wav = @[MESH_WAV] + multigrid = @[MULTIGRID] +:: + +# CMEPS warm run sequence +runSeq:: +@@[coupling_interval_slow_sec] + MED med_phases_prep_ocn_avg + MED -> OCN :remapMethod=redist + OCN + @@[coupling_interval_fast_sec] + MED med_phases_prep_atm + MED med_phases_prep_ice + MED med_phases_prep_wav_accum + MED med_phases_prep_wav_avg + MED -> ATM :remapMethod=redist + MED -> ICE :remapMethod=redist + MED -> WAV :remapMethod=redist + ATM + ICE + WAV + ATM -> MED :remapMethod=redist + MED med_phases_post_atm + ICE -> MED :remapMethod=redist + MED med_phases_post_ice + WAV -> MED :remapMethod=redist + MED med_phases_post_wav + MED med_phases_prep_ocn_accum + @ + OCN -> MED :remapMethod=redist + MED med_phases_post_ocn + MED med_phases_restart_write +@ +:: + +# CMEPS variables + +DRIVER_attributes:: +:: +MED_attributes:: + ATM_model = @[atm_model] + ICE_model = @[ice_model] + OCN_model = @[ocn_model] + WAV_model = @[wav_model] + history_n = 0 + history_option = nhours + history_ymd = -999 + coupling_mode = @[CPLMODE] + history_tile_atm = @[ATMTILESIZE] +:: +ALLCOMP_attributes:: + ScalarFieldCount = 2 + ScalarFieldIdxGridNX = 1 + ScalarFieldIdxGridNY = 2 + ScalarFieldName = cpl_scalars + start_type = @[RUNTYPE] + restart_dir = RESTART/ + case_name = ufs.cpld + restart_n = @[RESTART_N] + restart_option = nhours + restart_ymd = -999 + dbug_flag = @[cap_dbug_flag] + use_coldstart = @[use_coldstart] + use_mommesh = @[use_mommesh] + eps_imesh = @[eps_imesh] + stop_n = @[FHMAX] + stop_option = nhours + stop_ymd = -999 +:: diff --git a/parm/ufs/forecast/gfs/nems/nems.configure.leapfrog_atm_wav.IN b/parm/ufs/forecast/gfs/nems/nems.configure.leapfrog_atm_wav.IN new file mode 100644 index 00000000000..a29951d001f --- /dev/null +++ b/parm/ufs/forecast/gfs/nems/nems.configure.leapfrog_atm_wav.IN @@ -0,0 +1,38 @@ +############################################# +#### NEMS Run-Time Configuration File ##### +############################################# + +# ESMF # + logKindFlag: @[esmf_logkind] + +# EARTH # +EARTH_component_list: ATM WAV +EARTH_attributes:: + Verbosity = max +:: + +# ATM # +ATM_model: @[atm_model] +ATM_petlist_bounds: @[atm_petlist_bounds] +ATM_attributes:: + Verbosity = max + DumpFields = true +:: + +# WAV # +WAV_model: @[wav_model] +WAV_petlist_bounds: @[wav_petlist_bounds] +WAV_attributes:: + Verbosity = max +:: + + + +# Run Sequence # +runSeq:: + @@[coupling_interval_slow_sec] + ATM + ATM -> WAV + WAV + @ +:: diff --git a/parm/ufs/forecast/grids/fv3.yaml b/parm/ufs/forecast/grids/fv3.yaml new file mode 100644 index 00000000000..5f3f4ed54f2 --- /dev/null +++ b/parm/ufs/forecast/grids/fv3.yaml @@ -0,0 +1,98 @@ +C48: + DELTIM: 1200 + layout_x: 1 + layout_y: 1 + layout_x_gfs: 1 + layout_y_gfs: 1 + nthreads_fv3: 1 + nthreads_fv3_gfs: 1 + cdmbgwd: 0.071,2.1,1.0,1.0 # mountain blocking, ogwd, cgwd, cgwd src scaling + WRITE_GROUP: 1 + WRTTASK_PER_GROUP: 2 + WRITE_GROUP_GFS: 1 + WRTTASK_PER_GROUP_GFS: 2 + +C96: + DELTIM: 600 + layout_x: 2 + layout_y: 2 + layout_x_gfs: 2 + layout_y_gfs: 2 + nthreads_fv3: 1 + nthreads_fv3_gfs: 1 + cdmbgwd: 0.14,1.8,1.0,1.0 # mountain blocking, ogwd, cgwd, cgwd src scaling + WRITE_GROUP: 1 + WRTTASK_PER_GROUP: 4 + WRITE_GROUP_GFS: 1 + WRTTASK_PER_GROUP_GFS: 4 + +C192: + DELTIM: 450 + layout_x: 4 + layout_y: 6 + layout_x_gfs: 4 + layout_y_gfs: 6 + nthreads_fv3: 1 + nthreads_fv3_gfs: 2 + cdmbgwd: 0.23,1.5,1.0,1.0 # mountain blocking, ogwd, cgwd, cgwd src scaling + WRITE_GROUP: 1 + WRTTASK_PER_GROUP: 64 + WRITE_GROUP_GFS: 2 + WRTTASK_PER_GROUP_GFS: 64 + +C384: + DELTIM: 200 + layout_x: 6 + layout_y: 8 + layout_x_gfs: 8 + layout_y_gfs: 12 + nthreads_fv3: 1 + nthreads_fv3_gfs: 2 + cdmbgwd: 1.1,0.72,1.0,1.0 # mountain blocking, ogwd, cgwd, cgwd src scaling + WRITE_GROUP: 2 + WRTTASK_PER_GROUP: 48 + WRITE_GROUP_GFS: 2 + WRTTASK_PER_GROUP_GFS: 64 + +C768: + DELTIM: 150 + layout_x: 8 + layout_y: 12 + layout_x_gfs: 12 + layout_y_gfs: 16 + nthreads_fv3: 4 + nthreads_fv3_gfs: 4 + cdmbgwd: 4.0,0.15,1.0,1.0 # mountain blocking, ogwd, cgwd, cgwd src scaling + WRITE_GROUP: 2 + WRTTASK_PER_GROUP: 64 + WRITE_GROUP_GFS: 4 + WRTTASK_PER_GROUP_GFS: 64 + +C1152: + DELTIM: 120 + layout_x: 8 + layout_y: 16 + layout_x_gfs: 8 + layout_y_gfs: 16 + nthreads_fv3: 4 + nthreads_fv3_gfs: 4 + cdmbgwd: 4.0,0.10,1.0,1.0 # mountain blocking, ogwd, cgwd, cgwd src scaling + WRITE_GROUP: 4 + WRTTASK_PER_GROUP: 64 # TODO: refine these numbers when a case is available + WRITE_GROUP_GFS: 4 + WRTTASK_PER_GROUP_GFS: 64 # TODO: refine these numbers when a case is available + +C3072: + DELTIM: 90 + layout_x: 16 + layout_y: 32 + layout_x_gfs: 16 + layout_y_gfs: 32 + nthreads_fv3: 4 + nthreads_fv3_gfs: 4 + cdmbgwd: 4.0,0.05,1.0,1.0 # mountain blocking, ogwd, cgwd, cgwd src scaling + WRITE_GROUP: 4 + WRTTASK_PER_GROUP: 64 # TODO: refine these numbers when a case is available + WRITE_GROUP_GFS: 4 + WRTTASK_PER_GROUP_GFS: 64 # TODO: refine these numbers when a case is available + diff --git a/parm/ufs/forecast/ufs.atm.fixed_files.working.yaml b/parm/ufs/forecast/ufs.atm.fixed_files.working.yaml new file mode 100644 index 00000000000..567fd04ce6f --- /dev/null +++ b/parm/ufs/forecast/ufs.atm.fixed_files.working.yaml @@ -0,0 +1,187 @@ +# The following inputs need to be resolved: +# HOMEgfs - path to HOMEgfs directory +# DATA - path to DATA directory where files will be staged and run (DATA must exist) +# atm_res - resolution of the atmospheric cubed-sphere grid e.g C48 +# ocn_res - resolution of the ocean tripolar grid e.g. 100 +# FIX_orog - path to orography fix files +# FIX_ugwd - path to xyz fix files +# FIX_am - path to am fix files +# FIX_aer - path to aer fix files +# FIX_lut - path to lut fix files + +stage: + mkdir: + - $(DATA)/INPUT + - $(DATA)/RESTART + +fix: + copy: + # Atmosphere mosaic file linked as the grid_spec file (atm only) + - [$(FIX_orog)/$(atm_res)/$(atm_res)_mosaic.nc, $(DATA)/INPUT/grid_spec.nc] + + # Atmosphere grid tile files + - [$(FIX_orog)/$(atm_res)/$(atm_res)_grid.tile1.nc, $(DATA)/INPUT/] + - [$(FIX_orog)/$(atm_res)/$(atm_res)_grid.tile2.nc, $(DATA)/INPUT/] + - [$(FIX_orog)/$(atm_res)/$(atm_res)_grid.tile3.nc, $(DATA)/INPUT/] + - [$(FIX_orog)/$(atm_res)/$(atm_res)_grid.tile4.nc, $(DATA)/INPUT/] + - [$(FIX_orog)/$(atm_res)/$(atm_res)_grid.tile5.nc, $(DATA)/INPUT/] + - [$(FIX_orog)/$(atm_res)/$(atm_res)_grid.tile6.nc, $(DATA)/INPUT/] + + # Orography data tile files + # The following are for "frac_grid = .true." + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/oro_$(atm_res).mx$(ocn_res).tile1.nc, $(DATA)/INPUT/oro_data.tile1.nc] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/oro_$(atm_res).mx$(ocn_res).tile2.nc, $(DATA)/INPUT/oro_data.tile2.nc] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/oro_$(atm_res).mx$(ocn_res).tile3.nc, $(DATA)/INPUT/oro_data.tile3.nc] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/oro_$(atm_res).mx$(ocn_res).tile4.nc, $(DATA)/INPUT/oro_data.tile4.nc] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/oro_$(atm_res).mx$(ocn_res).tile5.nc, $(DATA)/INPUT/oro_data.tile5.nc] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/oro_$(atm_res).mx$(ocn_res).tile6.nc, $(DATA)/INPUT/oro_data.tile6.nc] + + # oro_data_ls and oro_data_ss files from FIX_ugwd + - [$(FIX_ugwd)/$(atm_res)/$(atm_res)_oro_data_ls.tile1.nc, $(DATA)/INPUT/oro_data_ls.tile1.nc] + - [$(FIX_ugwd)/$(atm_res)/$(atm_res)_oro_data_ls.tile2.nc, $(DATA)/INPUT/oro_data_ls.tile2.nc] + - [$(FIX_ugwd)/$(atm_res)/$(atm_res)_oro_data_ls.tile3.nc, $(DATA)/INPUT/oro_data_ls.tile3.nc] + - [$(FIX_ugwd)/$(atm_res)/$(atm_res)_oro_data_ls.tile4.nc, $(DATA)/INPUT/oro_data_ls.tile4.nc] + - [$(FIX_ugwd)/$(atm_res)/$(atm_res)_oro_data_ls.tile5.nc, $(DATA)/INPUT/oro_data_ls.tile5.nc] + - [$(FIX_ugwd)/$(atm_res)/$(atm_res)_oro_data_ls.tile6.nc, $(DATA)/INPUT/oro_data_ls.tile6.nc] + - [$(FIX_ugwd)/$(atm_res)/$(atm_res)_oro_data_ss.tile1.nc, $(DATA)/INPUT/oro_data_ss.tile1.nc] + - [$(FIX_ugwd)/$(atm_res)/$(atm_res)_oro_data_ss.tile2.nc, $(DATA)/INPUT/oro_data_ss.tile2.nc] + - [$(FIX_ugwd)/$(atm_res)/$(atm_res)_oro_data_ss.tile3.nc, $(DATA)/INPUT/oro_data_ss.tile3.nc] + - [$(FIX_ugwd)/$(atm_res)/$(atm_res)_oro_data_ss.tile4.nc, $(DATA)/INPUT/oro_data_ss.tile4.nc] + - [$(FIX_ugwd)/$(atm_res)/$(atm_res)_oro_data_ss.tile5.nc, $(DATA)/INPUT/oro_data_ss.tile5.nc] + - [$(FIX_ugwd)/$(atm_res)/$(atm_res)_oro_data_ss.tile6.nc, $(DATA)/INPUT/oro_data_ss.tile6.nc] + + # GWD?? + - [$(FIX_ugwd)/ugwp_limb_tau.nc, $(DATA)/ugwp_limb_tau.nc] + + # CO2 climatology + - [$(FIX_am)/co2monthlycyc.txt, $(DATA)/co2monthlycyc.txt] + - [$(FIX_am)/global_co2historicaldata_glob.txt, $(DATA)/co2historicaldata_glob.txt] + - [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2009.txt, $(DATA)/co2historicaldata_2009.txt] + - [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2010.txt, $(DATA)/co2historicaldata_2010.txt] + - [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2011.txt, $(DATA)/co2historicaldata_2011.txt] + - [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2012.txt, $(DATA)/co2historicaldata_2012.txt] + - [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2013.txt, $(DATA)/co2historicaldata_2013.txt] + - [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2014.txt, $(DATA)/co2historicaldata_2014.txt] + - [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2015.txt, $(DATA)/co2historicaldata_2015.txt] + - [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2016.txt, $(DATA)/co2historicaldata_2016.txt] + - [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2017.txt, $(DATA)/co2historicaldata_2017.txt] + - [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2018.txt, $(DATA)/co2historicaldata_2018.txt] + - [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2019.txt, $(DATA)/co2historicaldata_2019.txt] + - [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2020.txt, $(DATA)/co2historicaldata_2020.txt] + - [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2021.txt, $(DATA)/co2historicaldata_2021.txt] + - [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2022.txt, $(DATA)/co2historicaldata_2022.txt] + - [$(FIX_am)/fix_co2_proj/global_co2historicaldata_2023.txt, $(DATA)/co2historicaldata_2023.txt] + + # FIX_am files + - [$(FIX_am)/global_climaeropac_global.txt, $(DATA)/aerosol.dat] + - [$(FIX_am)/ozprdlos_2015_new_sbuvO3_tclm15_nuchem.f77, $(DATA)/global_o3prdlos.f77] + - [$(FIX_am)/global_h2o_pltc.f77, $(DATA)/global_h2oprdlos.f77] + - [$(FIX_am)/global_glacier.2x2.grb, $(DATA)/global_glacier.2x2.grb] + - [$(FIX_am)/global_maxice.2x2.grb, $(DATA)/global_maxice.2x2.grb] + - [$(FIX_am)/global_snoclim.1.875.grb, $(DATA)/global_snoclim.1.875.grb] + - [$(FIX_am)/global_slmask.t1534.3072.1536.grb, $(DATA)/global_slmask.t1534.3072.1536.grb] + - [$(FIX_am)/global_soilmgldas.statsgo.t1534.3072.1536.grb, $(DATA)/global_soilmgldas.statsgo.t1534.3072.1536.grb] + - [$(FIX_am)/global_solarconstant_noaa_an.txt, $(DATA)/solarconstant_noaa_an.txt] + - [$(FIX_am)/global_sfc_emissivity_idx.txt, $(DATA)/sfc_emissivity_idx.txt] + - [$(FIX_am)/RTGSST.1982.2012.monthly.clim.grb, $(DATA)/RTGSST.1982.2012.monthly.clim.grb] + - [$(FIX_am)/IMS-NIC.blended.ice.monthly.clim.grb, $(DATA)/IMS-NIC.blended.ice.monthly.clim.grb] + + # MERRA2 Aerosol Climatology + - [$(FIX_aer)/merra2.aerclim.2003-2014.m01.nc, $(DATA)/aeroclim.m01.nc] + - [$(FIX_aer)/merra2.aerclim.2003-2014.m02.nc, $(DATA)/aeroclim.m02.nc] + - [$(FIX_aer)/merra2.aerclim.2003-2014.m03.nc, $(DATA)/aeroclim.m03.nc] + - [$(FIX_aer)/merra2.aerclim.2003-2014.m04.nc, $(DATA)/aeroclim.m04.nc] + - [$(FIX_aer)/merra2.aerclim.2003-2014.m05.nc, $(DATA)/aeroclim.m05.nc] + - [$(FIX_aer)/merra2.aerclim.2003-2014.m06.nc, $(DATA)/aeroclim.m06.nc] + - [$(FIX_aer)/merra2.aerclim.2003-2014.m07.nc, $(DATA)/aeroclim.m07.nc] + - [$(FIX_aer)/merra2.aerclim.2003-2014.m08.nc, $(DATA)/aeroclim.m08.nc] + - [$(FIX_aer)/merra2.aerclim.2003-2014.m09.nc, $(DATA)/aeroclim.m09.nc] + - [$(FIX_aer)/merra2.aerclim.2003-2014.m10.nc, $(DATA)/aeroclim.m10.nc] + - [$(FIX_aer)/merra2.aerclim.2003-2014.m11.nc, $(DATA)/aeroclim.m11.nc] + - [$(FIX_aer)/merra2.aerclim.2003-2014.m12.nc, $(DATA)/aeroclim.m12.nc] + + # Optical depth + - [$(FIX_lut)/optics_BC.v1_3.dat, $(DATA)/optics_BC.dat] + - [$(FIX_lut)/optics_DU.v15_3.dat, $(DATA)/optics_DU.dat] + - [$(FIX_lut)/optics_OC.v1_3.dat, $(DATA)/optics_OC.dat] + - [$(FIX_lut)/optics_SS.v3_3.dat, $(DATA)/optics_SS.dat] + - [$(FIX_lut)/optics_SU.v1_3.dat, $(DATA)/optics_SU.dat] + + # Files from FIX_orog/C??.mx??_frac/fix_sfc + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).facsf.tile1.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).facsf.tile2.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).facsf.tile3.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).facsf.tile4.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).facsf.tile5.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).facsf.tile6.nc, $(DATA)/] + + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).maximum_snow_albedo.tile1.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).maximum_snow_albedo.tile2.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).maximum_snow_albedo.tile3.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).maximum_snow_albedo.tile4.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).maximum_snow_albedo.tile5.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).maximum_snow_albedo.tile6.nc, $(DATA)/] + + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).slope_type.tile1.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).slope_type.tile2.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).slope_type.tile3.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).slope_type.tile4.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).slope_type.tile5.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).slope_type.tile6.nc, $(DATA)/] + + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).snowfree_albedo.tile1.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).snowfree_albedo.tile2.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).snowfree_albedo.tile3.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).snowfree_albedo.tile4.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).snowfree_albedo.tile5.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).snowfree_albedo.tile6.nc, $(DATA)/] + + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).soil_type.tile1.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).soil_type.tile2.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).soil_type.tile3.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).soil_type.tile4.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).soil_type.tile5.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).soil_type.tile6.nc, $(DATA)/] + + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).substrate_temperature.tile1.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).substrate_temperature.tile2.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).substrate_temperature.tile3.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).substrate_temperature.tile4.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).substrate_temperature.tile5.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).substrate_temperature.tile6.nc, $(DATA)/] + + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).vegetation_greenness.tile1.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).vegetation_greenness.tile2.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).vegetation_greenness.tile3.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).vegetation_greenness.tile4.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).vegetation_greenness.tile5.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).vegetation_greenness.tile6.nc, $(DATA)/] + + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).vegetation_type.tile1.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).vegetation_type.tile2.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).vegetation_type.tile3.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).vegetation_type.tile4.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).vegetation_type.tile5.nc, $(DATA)/] + - [$(FIX_orog)/$(atm_res).mx$(ocn_res)_frac/fix_sfc/$(atm_res).vegetation_type.tile6.nc, $(DATA)/] + + # fd_nems.yaml file + - [$(HOMEgfs)/sorc/ufs_model.fd/tests/parm/fd_nems.yaml, $(DATA)/] + +diag_table: # This list will be concatenated into a "$(DATA)diag_table.tmpl" + - $(HOMEgfs)/parm/parm_fv3diag/diag_table_header # This MUST ALWAYS be the first! + - $(HOMEgfs)/parm/parm_fv3diag/diag_table_atm + +field_table: # This list will be concatenated into a "$(DATA)field_table" + - $(HOMEgfs)/parm/parm_fv3diag/field_table + +model_configure: # This will be copied as "$(DATA)model_configure.tmpl" + copy: + - [$(HOMEgfs)/sorc/ufs_model.fd/tests/parm/model_configure.IN, $(DATA)/model_configure.tmpl] + +nems_configure: # This will be copied as "$(DATA)/nems.configure.tmpl" + copy: + - [$(HOMEgfs)/sorc/ufs_model.fd/tests/parm/nems.configure.atm.IN, $(DATA)/nems.configure.tmpl] + +input_nml: # This will be copied as "$(DATA)/input.nml.tmpl" + copy: + - [$(HOMEgfs)/sorc/ufs_model.fd/tests/parm/cpld_control.nml.IN, $(DATA)/input.nml.tmpl] diff --git a/parm/ufs/forecast/ufs.atm.fixed_files.yaml b/parm/ufs/forecast/ufs.atm.fixed_files.yaml new file mode 100644 index 00000000000..f3bcf3fd7de --- /dev/null +++ b/parm/ufs/forecast/ufs.atm.fixed_files.yaml @@ -0,0 +1,34 @@ +# The following inputs need to be resolved: +# HOMEgfs - path to HOMEgfs directory +# DATA - path to DATA directory where files will be staged and run (DATA must exist) +# atm_res - resolution of the atmospheric cubed-sphere grid e.g C48 +# ocn_res - resolution of the ocean tripolar grid e.g. 100 +# FIX_orog - path to orography fix files +# FIX_ugwd - path to xyz fix files +# FIX_am - path to am fix files +# FIX_aer - path to aer fix files +# FIX_lut - path to lut fix files + +#dirtree_atmos: +# mkdir: +# - $(DATA)/INPUT +# - $(DATA)/RESTART + +#dirtree_ocean: +# mkdir: +# - $(DATA)/MOM6_OUTPUT +# - $(DATA)/history +# - $(DATA)/INPUT +# - $(DATA)/RESTART + +# Define the path to the respective YAML-formatted files containing +# the fixed-files for the respective UFS component models. +#fix_atmos: !INC ${HOMEgfs}/parm/ufs/forecast/atmos.fixed_files.yaml +#fix_land: !INC ${HOMEgfs}/parm/ufs/forecast/land.fixed_files.yaml +#fix_ocean: !INC ${HOMEgfs}/parm/ufs/forecast/ocean.fixed_files.yaml + + + + + + diff --git a/scripts/exglobal_fv3gfs_forecast_initialize.py b/scripts/exglobal_fv3gfs_forecast_initialize.py new file mode 100644 index 00000000000..ec21d6583d6 --- /dev/null +++ b/scripts/exglobal_fv3gfs_forecast_initialize.py @@ -0,0 +1,106 @@ +#! /usr/env/bin python + +# ----------------------------------------------------------------------------- +# +# Program Name: exglobal_fv3gfs_forecast_init.py +# +# Author(s)/Contacts(s): Henry R. Winterbottom (henry.winterbottom@noaa.gov) +# +# Abstract: A Python 3.5+ script to initialize a global UFS +# forecast application. +# +# History Log: +# +# - 2023-03-28: Henry R. Winterbottom -- Original version. +# +# Usage: user@host:$ python exglobal_ufs_forecast_init.py +# +# ----------------------------------------------------------------------------- + +""" +Script +------ + + exglobal_fv3gfs_forecast_init.py + +Description +----------- + + This script contains a task level interface for the global UFS + forecast initialization application. + +Functions +--------- + + main() + + This is the driver-level function to invoke the tasks within + this script. + +Author(s) +--------- + + + Henry R. Winterbottom; 28 March 2023 + +History +------- + + 2023-03-28: Henry Winterbottom -- Initial implementation. + +""" + +# ---- + +__author__ = "Henry R. Winterbottom" +__maintainer__ = "Henry R. Winterbottom" +__email__ = "henry.winterbottom@noaa.gov" + +# ---- + +import os +import time + +from pygw.configuration import cast_strdict_as_dtypedict +from pygw.logger import Logger +from pygfs.task.fv3gfs_forecast import FV3GFS + +# ---- + +logger = Logger() + +# ---- + + +def main() -> None: + """ + Description + ----------- + + This is the driver-level function to invoke the tasks within this + script. + + """ + + # Take configuration from environment and cast it as Python + # dictionary. + script_name = os.path.basename(__file__) + start_time = time.time() + config = cast_strdict_as_dtypedict(os.environ) + + # Launch the task. + task = FV3GFS(config=config) + task.initialize() + + stop_time = time.time() + msg = f"Completed application {script_name}." + logger.info(msg=msg) + total_time = stop_time - start_time + msg = f"Total Elapsed Time: {total_time} seconds." + logger.info(msg=msg) + +# ---- + + +if __name__ == "__main__": + main() diff --git a/ush/python/pygfs/exceptions.py b/ush/python/pygfs/exceptions.py new file mode 100644 index 00000000000..8ceaff01a61 --- /dev/null +++ b/ush/python/pygfs/exceptions.py @@ -0,0 +1,132 @@ +""" +Module +------ + + pygfs.exceptions (pygfs/exceptions.py) + +Description +----------- + + This module contains all pygfs package exceptions. + +Classes +------- + + ForecastError(msg) + + This is the base-class for exceptions encountered within the + ush/python/pygfs/task/forecast module; it is a sub-class of + WorkflowException. + + FV3GFSError(msg) + + This is the base-class for exceptions encountered within the + ush/python/pygfs/task/fv3gfs module; it is a sub-class of + WorkflowException. + + GridsError(msg) + + This is the base-class for exceptions encountered within the + ush/python/pygfs/utils/grids module; it is a sub-class of + WorkflowException. + + TimestampsError(msg) + + This is the base-class for exceptions encountered within the + ush/python/pygfs/utils/timestamps module; it is a sub-class of + WorkflowException. + + UFSWMError(msg) + + This is the base-class for exceptions encountered within the + ush/python/pygfs/ufswm module; it is a sub-class of + WorkflowException. + +""" + +# ---- + +__author__ = "Henry R. Winterbottom" +__maintainer__ = "Henry R. Winterbottom" +__email__ = "henry.winterbottom@noaa.gov" +__version__ = 0.0 + +# ---- + +from pygw.exceptions import WorkflowException + +# ---- + +# Define all available classes. +__all__ = ["ForecastError", "FV3GFSError", "GridsInfoError", + "TimestampsError", "UFSWMError"] + +# ---- + + +class ForecastError(WorkflowException): + """ + Description + ----------- + + This is the base-class for exceptions encountered within the + ush/python/pygfs/task/forecast module; it is a sub-class of + WorkflowException. + + """ + +# ---- + + +class FV3GFSError(WorkflowException): + """ + Description + ----------- + + This is the base-class for exceptions encountered within the + ush/python/pygfs/task/fv3gfs module; it is a sub-class of + WorkflowException. + + """ + +# ---- + + +class GridsError(WorkflowException): + """ + Description + ----------- + + This is the base-class for exceptions encountered within the + ush/python/pygfs/utils/grids module; it is a sub-class of + WorkflowException. + + """ + +# ---- + + +class TimestampsError(WorkflowException): + """ + Description + ----------- + + This is the base-class for exceptions encountered within the + ush/python/pygfs/utils/timestamps module; it is a sub-class of + WorkflowException. + + """ + +# ---- + + +class UFSWMError(WorkflowException): + """ + Description + ----------- + + This is the base-class for exceptions encountered within the + ush/python/pygfs/ufswm module; it is a sub-class of + WorkflowException. + + """ diff --git a/ush/python/pygfs/task/forecast.py b/ush/python/pygfs/task/forecast.py new file mode 100644 index 00000000000..739a91d10f4 --- /dev/null +++ b/ush/python/pygfs/task/forecast.py @@ -0,0 +1,185 @@ +""" +Module +------ + + pygfs.task.forecast (pygfs/task/forecast.py) + +Description +----------- + + This module contains the base-class module for forecast model + applications. + +Classes +------- + + Forecast(config, model, *args, **kwargs) + + This is the base-class object for the respective Unified + Forecast System (UFS) forecast task; it is a sub-class of + Task. + +""" + +# ---- + +__author__ = "Henry R. Winterbottom" +__maintainer__ = "Henry R. Winterbottom" +__email__ = "henry.winterbottom@noaa.gov" +__version__ = 0.0 + +# ---- + +import os +from typing import Dict + +from pygfs.exceptions import ForecastError +from pygfs.ufswm import UFSWM +from pygfs.utils.logger import Logger +from pygw.file_utils import FileHandler +from pygw.jinja import Jinja +from pygw.task import Task +from pygw.yaml_file import YAMLFile, parse_yamltmpl + +# ---- + + +class Forecast(Task): + """ + Description + ----------- + + This is the base-class object for the respective Unified Forecast + System (UFS) forecast task; it is a sub-class of Task. + + Parameters + ---------- + + config: Dict + + A Python dictionary containing the application configuration + attributes. + + model: str + + A Python string specifying the valid forecast model. + + Raises + ------ + + ForecastError: + + - raised if the YAML key `forecast` could not be determined + from the YAML-formatted configuration file path; see + configuration variable `FCSTYAML`. + + """ + + def __init__(self: Task, config: Dict, model: str, *args, **kwargs): + """ + Description + ----------- + + Creates a new Forecast object. + + """ + + # Define the base-class attributes. + super().__init__(config=config, *args, *kwargs) + self.config = config + self.model = model.lower() + self.logger = Logger(config=self.config).logger + UFSWM(config=self.config, model=self.model) + + # Collect the forecast configuration attributes from the + # external YAML-formatted file path. + try: + self.config.forecast = YAMLFile(path=self.config.FCSTYAML).as_dict()[ + "forecast" + ] + + except KeyError as exc: + msg = ( + "The attribute (e.g., YAML-key) `forecast` could not be determined " + f"from YAML-formatted file {self.config.FCSTYAML}. Aborting!!!" + ) + raise ForecastError(msg=msg) from exc + + def build_model_configure(self: Task) -> None: + """ + Description + ----------- + + This method parses a Jinja2-formatted template and builds the + UFS weather model forecast application `model_configure` file + within the forecast application working directory. + + """ + + model_configure_tmpl = self.config.forecast.model_configure + model_configure_path = os.path.join(self.runtime_config.DATA, "model_configure") + + Jinja(model_configure_tmpl, data=self.config, allow_missing=True).save( + model_configure_path + ) + + def build_nems_configure(self: Task) -> None: + """ + Description + ----------- + + This method parses a Jinja2-formatted template and builds the + UFS weather model forecast application `nems.configure` file + within the forecast application working directory. + + """ + + # Define then NEMS configuration template and write the file + # accordingly. + nems_configure_tmpl = self.config.forecast.nems_configure + nems_configure_path = os.path.join(self.runtime_config.DATA, "nems.configure") + + # HRW: FORCING ALL TEMPLATE VARIABLES TO BE RENDERED IF + # THEY ARE WITHOUT DEFAULT VALUES (IN THE JINJA TEMPLATE); + # IF A VARIABLE IS NOT RENDERED CORRECTLY THE FORECAST + # MODEL WILL FAIL; THIS IS ALSO USEFUL IN THE CASES WHEN A + # USER HAS DEFINE THE INCORRECT nems.configure TEMPLATE. + Jinja(nems_configure_tmpl, data=self.config, allow_missing=False).save( + nems_configure_path + ) + + with open(nems_configure_path, "a", encoding="utf-8") as fout: + fout.write(f"\n\n# Template: {nems_configure_tmpl}.") + + def config_dirtree(self: Task) -> None: + """ + Description + ----------- + + This method builds the directory tree and collects the + fixed-files for the respective forecast application. + + """ + + # Build the directory tree and link the fixed files to the + # working directory; proceed accordingly. + dirtree_config = parse_yamltmpl( + path=self.config.FCSTYAML, data=self.runtime_config + )["forecast"] + FileHandler(dirtree_config.dirtree_atmos).sync() + + atmos_fcst_config = parse_yamltmpl( + path=dirtree_config.fixed_files.atmos, data=self.config + ) + FileHandler(atmos_fcst_config).sync() + land_fcst_config = parse_yamltmpl( + path=dirtree_config.fixed_files.land, data=self.config + ) + FileHandler(land_fcst_config).sync() + + if self.config.coupled: # HRW: THIS NEEDS TO BE UPDATED. + FileHandler(dirtree_config.dirtree_ocean).sync() + ocean_fcst_config = parse_yamltmpl( + path=dirtree_config.fixed_files.ocean, data=self.config + ) + FileHandler(ocean_fcst_config).sync() diff --git a/ush/python/pygfs/task/fv3gfs_forecast.py b/ush/python/pygfs/task/fv3gfs_forecast.py new file mode 100644 index 00000000000..c1eb25506c2 --- /dev/null +++ b/ush/python/pygfs/task/fv3gfs_forecast.py @@ -0,0 +1,220 @@ +""" +Module +------ + + pygfs.task.fv3gfs_forecast (pygfs/task/fv3gfs_forecast.py) + +Description +----------- + + This module contains the base-class module for Finite-Volume + Cubed-Sphere (FV3) Global Forecast System (GFS) forecast model + applications. + +Classes +------- + + FV3GFS(config) + + This is the base-class object for all Finite-Volume + Cubed-Sphere (FV3) Global Forecast System (GFS) forecast model + applications; it is a sub-class of Forecast. + +""" + +# ---- + +__author__ = "Henry R. Winterbottom" +__maintainer__ = "Henry R. Winterbottom" +__email__ = "henry.winterbottom@noaa.gov" +__version__ = 0.0 + +# ---- + +import os +from typing import Dict + +from pygfs.exceptions import FV3GFSError +from pygfs.task.forecast import Forecast +from pygw.decorators import private + +# ---- + + +class FV3GFS(Forecast): + """ + Description + ----------- + + This is the base-class object for all Finite-Volume Cubed-Sphere + (FV3) Global Forecast System (GFS) forecast model applications; it + is a sub-class of Forecast. + + Parameters + ---------- + + config: Dict + + A Python dictionary containing the application configuration + attributes. + + """ + + # The following attributes are mandatory for fixed-file syncing; + # this should not be changed unless absolutely necessary. + FIXED_MAND_ATTR_DICT = { + "DATA": "DATA", + "FIXgfs": "FIXgfs", + "HOMEgfs": "HOMEgfs", + "atm_res": "CASE", + "ocn_res": "OCNRES", + } + + def __init__(self: Forecast, config: Dict): + """ + Description + ----------- + + Creates a new GFS object. + + """ + + # Define the base-class attributes. + super().__init__(config=config, model="FV3GFS") + + # HRW: THIS IS ALREADY DEFINED IN THE RUN-TIME ENVIRONMENT; DO + # WE WANT TO KEEP IT HERE AS IT CURRENTLY HAS NOT BEARING BUT + # COULD BE AN ATTRIBUTE COLLECTED FROM A YAML-FORMATTED + # CONFIGURATION FILE IN THE FUTURE? + # self.fcst_config.coupled = (self.fcst_config.app in [ + # "s2s", "s2sw", "s2swa"]) + + @private + def fixedfiles(self: Forecast) -> Dict: + """ + Description + ----------- + + This method collects the fixed-file attributes from the + run-time environment (e.g., configuration Python dictionary + `config`), checks the validity of the respective files and/or + attributes, and returns a Python dictionary containing the + fixed-file attributes. + + Returns + ------- + + fixedfiles_dict: Dict + + A Python dictionary containing the fixed-file path + attributes. + + Raises + ------ + + FV3GFSError: + + - raised a mandatory configuration attribute (see + `FIXED_MAND_ATTR_DICT`) is not specified within the + run-time environment/configuration. + + - raised if a mandatory directory tree (beneath `FIXgfs`) + is either not a directory or does not exist. + + - raised if an application specific directory tree + (beneath `FIXgfs`) is either not a dictionary or does + not exist. + + """ + + # Define the fixed-file attributes. + for (fixed_attr_key, fixed_attr_value) in self.FIXED_MAND_ATTR_DICT.items(): + + # Define the respective configuration attribute (i.e., + # `fixed_attr_key`) and assign the corresponding value + # `fixed_attr_value`; proceed accordingly. + value = self.config[fixed_attr_value] + + if isinstance(value, dict): + value = self.runtime_config[fixed_attr_value] + + if value is None: + msg = ( + f"The configuration attribute {fixed_attr_key} could not " + "be determined from the run-time environment. Aborting!!!" + ) + raise FV3GFSError(msg=msg) + + setattr(self.config, fixed_attr_key, value) + + # Define the top-level directory-tree path containing the + # respective fixed-files and build the Python dictionary + # required to link the application-specific fixed files. + fix_dirpath = self.config.FIXgfs + + if (not os.path.isdir(fix_dirpath)) or (not os.path.exists(fix_dirpath)): + msg = ( + f"The directory tree {fix_dirpath} is either not a directory " + "or does not exist. Aborting!!!" + ) + raise FV3GFSError(msg=msg) + + # Define the fixed-file directory tree attributes. + fixed_attr_dict = { + "FIX_aer": "aer", + "FIX_am": "am", + "FIX_lut": "lut", + "FIX_orog": "orog", + "FIX_ugwd": "ugwd", + } + + for (fixed_attr_key, fixed_attr_value) in fixed_attr_dict.items(): + + fix_subdirpath = os.path.join(fix_dirpath, fixed_attr_value) + if (not os.path.isdir(fix_subdirpath)) and ( + not os.path.isfile(fix_subdirpath) + ): + msg = ( + f"The directory tree path {fix_subdirpath} is either not " + "a directory does not exist; this may cause unexpected results " + "or failures." + ) + self.logger.warning(msg=msg) + + setattr( + self.config, + fixed_attr_key, + os.path.join(self.config.FIXgfs, fixed_attr_value), + ) + + def initialize(self: Forecast) -> None: + """ + Description + ----------- + + This method initializes the FV3 GFS forecast application + working directory; this includes the following: + + - Configuring the directory tree; + + - Copying the relevant fixed-files; + + - Building of the `model_configure` file for the respective + application; + + - Building the `nems.configure` file for the respective + application. + + """ + + # Update the base-class method attributes. + super().initialize() + + # Build the directory tree and copy the required fixed files + # accordingly. + self.fixedfiles() + self.config_dirtree() + + # Build the respective UFS configuration files. + self.build_model_configure() + self.build_nems_configure() diff --git a/ush/python/pygfs/ufswm.py b/ush/python/pygfs/ufswm.py new file mode 100644 index 00000000000..b2c7248f35f --- /dev/null +++ b/ush/python/pygfs/ufswm.py @@ -0,0 +1,134 @@ +""" +Module +------ + + pygfs.ufswm (pygfs/ufswm.py) + +Description +----------- + + This module contains the base-class module for all Unified + Forecast System (UFS) Weather Model (WM) applications. + +Classes +------- + + UFSWM(config) + + This is the base-class object for all Unified Forecast System + (UFS) Weather Model (WM) applications. + +""" + +# ---- + +__author__ = "Henry R. Winterbottom" +__maintainer__ = "Henry R. Winterbottom" +__email__ = "henry.winterbottom@noaa.gov" +__version__ = 0.0 + +# ---- + +from dataclasses import dataclass +from typing import Dict + +from pygw.decorators import private + +from pygfs.utils.grids import FV3GFS as FV3GFS_grids +from pygfs.utils.layout import FV3GFS as FV3GFS_layout +from pygfs.utils.logger import Logger +from pygfs.utils.timestamps import Timestamps + +# ---- + + +@dataclass +class UFSWM: + """ + Description + ----------- + + This is the base-class object for all Unified Forecast System + (UFS) Weather Model (WM) applications. + + Parameters + ---------- + + config: Dict + + A Python dictionary containing the application configuration + attributes. + + """ + + def __init__(self: dataclass, config: Dict, model: str): + """ + Description + ----------- + + Creates a new UFSWM object. + + """ + + # Define the base-class attributes. + self.config = config + self.model = model.lower() + self.logger = Logger(config=self.config).logger + + # Define the respective forecast model configuration + # attributes. + self.configure() + + @private + def fv3gfs(self: dataclass) -> None: + """ + Description + ----------- + + This method defines the configuration attributes for the UFS + FV3 GFS forecast component model. + + """ + + # Define the configuration attributes for the FV3 GFS forecast + # model. + self.config.ufswm.atmos.grids = FV3GFS_grids( + config=self.config, + res=self.config.CASE, + nlevs=self.config.LEVS, + ).grids + + # HRW: The following may eventually be moved out of this + # method into `configure`; this is dependent on the additional + # UFS component model needs; TBD. + self.config.ufswm.atmos.timestamps = Timestamps( + datestr=self.config.CDATE, fmt="%Y-%m-%d %H:%M:%S" + ).timestamps + + msg = ( + "\nThe atmosphere model configuration is as follows:\n\n" + f"Cubed sphere resolution: {self.config.ufswm.atmos.grids.csres.upper()}\n" + f"Vertical levels: {self.config.ufswm.atmos.grids.nlevs}\n" + f"Number of cubed sphere tiles: {self.config.ufswm.atmos.grids.ntiles}.\n" + ) + self.logger.warn(msg=msg) + + # Define the layout attribuites for the FV3 GFS forecast + # model. + self.config.ufswm.atmos.layout = FV3GFS_layout( + config=self.config, res=self.config.CASE + ).setup() + + def configure(self: dataclass) -> None: + """ + Description + ----------- + + This method collects and defines the configuration attributes + for the respective UFS forecast component model. + + """ + + # UFS WM atmosphere FV3 GFS forecast model. + if self.model == "fv3gfs": + self.fv3gfs() diff --git a/ush/python/pygfs/utils/grids.py b/ush/python/pygfs/utils/grids.py new file mode 100644 index 00000000000..534c9e7e645 --- /dev/null +++ b/ush/python/pygfs/utils/grids.py @@ -0,0 +1,192 @@ +""" +Module +------ + + pygfs.utils.grids (pygfs/utils/grids.py) + +Description +----------- + + This module contains the base-class object for all grid definition + applications; the module also contains sub-classes for the + respective, and supported, Unified Forecast System (UFS) Weather + Model (WM) component models. + +Classes +------- + + FV3GFS(config, res, nlevs) + + This is the base-class object for all FV3 GFS grid attribute + defintions as a function grid-spacing resolution; it is a + sub-class of Grids. + + Grids() + + This is the base-class object for all forecast model grid + attribute computations and definitions. + +""" + +# ---- + +__author__ = "Henry R. Winterbottom" +__maintainer__ = "Henry R. Winterbottom" +__email__ = "henry.winterbottom@noaa.gov" +__version__ = 0.0 + +# ---- + +from typing import Dict, Union + +from dataclasses import dataclass + +from pygfs.exceptions import GridsError +from pygw.attrdict import AttrDict +from pygw.decorators import private + +# ---- + + +@dataclass +class Grids: + """ + Description + ----------- + + This is the base-class object for all forecast model grid + attribute computations and definitions. + + """ + + def __init__(self: dataclass): + """ + Description + ----------- + + Creates a new Grids object. + + """ + + # Define the base-class attributes. + self.grids = AttrDict() + +# ---- + + +class FV3GFS(Grids): + """ + Description + ----------- + + This is the base-class object for all FV3 GFS grid attribute + defintions as a function grid-spacing resolution; it is a + sub-class of Grids. + + Parameters + ---------- + + config: Dict + + A Python dictionary containing the run-time environment + configuration. + + res: str + + A Python string specifying a valid cubed-sphere resolution + (e.g., C48, C96, etc.,) + + nlevs: int + + A Python integer specifying a valid number of staggered + vertical levels. + + """ + + # Define the supported options for the respective forecast model + # attributes; only GFS configurations are currently supported. + FV3GFS_RES_LIST = ["c48", "c96", "c192", "c384"] + FV3GFS_LEVS_LIST = [64, 128] + + def __init__(self: Grids, config: Dict, res: str, nlevs: int): + """ + Description + ----------- + + Creates a new GFSFV3 object. + + """ + + # Define the base-class attributes. + super().__init__() + self.grids.ntiles = 6 + self.grids.nlevs = nlevs + self.grids.csres = res + self.grids.res = int(self.grids.csres[1:]) + + # Validate and build the grids information attributes. + self.check() + self.config() + + @private + def check(self: Grids): + """ + Description + ----------- + + This method checks the validity of both the cubed-sphere + resolution and total number of staggered vertical levels. + + Raises + ------ + + GridsError: + + - raised if the specified cubed-sphere resolution is not a + valid cubed-sphere resolution. + + - raised if the number of staggered vertical levels is not + supported. + + """ + # Check that the base-class object containing the FV3 GFS + # forecast model attributes is valid; proceed accordingly. + if self.grids.csres.lower() not in self.FV3GFS_RES_LIST: + msg = ( + f"The cubed-sphere resolution {self.grids.csres.upper()} is not " + "supported; valid values are: " + f"{', '.join([res.upper() for res in FV3GFS_RES_LIST])}. Aborting!!!" + ) + raise GridsError(msg=msg) + + if self.grids.nlevs not in self.FV3GFS_LEVS_LIST: + msg = (f"The specified number of vertical levels {self.grids.levs}" + f"is not supported; valid values are {','.join(FV3GFS_LEVS_LIST)}. " + "Aborting!!!" + ) + raise GridsError(msg=msg) + + @private + def config(self: Grids): + """ + Description + ----------- + + This method defines the FV3 GFS atmosphere model grid + configuration attributes. + + """ + + # Compute and define the grid attributes using the resolution + # of the cubed-sphere. + grids_dict = { + "jcap": int(self.grids.res * 2) - 2, + "lonb": int(4*self.grids.res), + "latb": int(2*self.grids.res), + "npx": int(self.grids.res + 1), + "npy": int(self.grids.res + 1), + "npz": int(self.grids.nlevs - 1) + } + + [setattr(self.grids, grids_key, grids_value) + for (grids_key, grids_value) in grids_dict.items()] diff --git a/ush/python/pygfs/utils/layout.py b/ush/python/pygfs/utils/layout.py new file mode 100644 index 00000000000..aca176a4f6f --- /dev/null +++ b/ush/python/pygfs/utils/layout.py @@ -0,0 +1,182 @@ +""" +Module +------ + + pygfs.utils.layout (pygfs/utils/layout.py) + +Description +----------- + + This module contains the base-class objects for all Unified + Forecast System (UFS) Weather Model (WM) component model layout + attributes. + +Classes +------- + + Layout() + + This is the base-class object for all Unified Forecast System + (UFS) Weather Model (WM) configuration file attributes. + + FV3GFS(config, res) + + This is the base-class object for defining all FV3 GFS layout + attributes as a function of cubed-sphere resolution; it is a + sub-class of Layout. + +""" + +# ---- + +__author__ = "Henry R. Winterbottom" +__maintainer__ = "Henry R. Winterbottom" +__email__ = "henry.winterbottom@noaa.gov" +__version__ = 0.0 + +# ---- + +from dataclasses import dataclass +from typing import Dict + +from pygw.attrdict import AttrDict +from pygw.decorators import private + +# ---- + + +@dataclass +class Layout: + """ + Description + ----------- + + This is the base-class object for all Unified Forecast System + (UFS) Weather Model (WM) configuration file attributes. + + """ + + def __init__(self: dataclass): + """ + Description + ----------- + + Creates a new Layout object. + + """ + + # Define the base-class attributes. + self.layout = AttrDict() + + +# ---- + + +class FV3GFS(Layout): + """ + Description + ----------- + + This is the base-class object for defining all FV3 GFS layout + attributes as a function of cubed-sphere resolution; it is a + sub-class of Layout. + + Parameters + ---------- + + config: Dict + + A Python dictionary containing the run-time environment + configuration. + + res: str + + A Python string specifying a valid cubed-sphere resolution + (e.g., C48, C96, etc.,) + + """ + + def __init__(self: Layout, config: Dict, res: str): + """ + Description + ----------- + + Creates a new FV3GFS object. + + """ + + # Define the base-class attributes. + super().__init__() + self.config = config + self.csres = res.lower() + self.res = int(self.csres[1:]) + + @private + def c48(self: Layout) -> Dict: + """ + Description + ----------- + + This method defines the FV3 GFS layout attributes for a C48 + cubed-sphere resolution. + + Returns + ------- + + layout_dict: Dict + + A Python dictionary containing the layout attributes for + the respective FV3 GFS cubed-sphere resolution. + + """ + + # Define the FV3GFS C48 cubed-sphere resolution attributes. + layout_dict = { + "deltim": 1200, + "layout_x": 1, + "layout_y": 1, + "layout_x_gfs": 1, + "layout_y_gfs": 1, + "nthreads_fv3": 1, + "nthreads_fv3_gfs": 1, + "cdmbgwd": [0.071, 2.1, 1.0, 1.0], + "write_group": 1, + "wrttask_per_group": 2, + "write_group_gfs": 1, + "wrttask_per_group_gfs": 2, + "quilting": ".false.", + } + + return layout_dict + + def setup(self: Layout): + """ + Description + ----------- + + This method defines the FV3 GFS cubed-sphere resolution layout + attributes. + + """ + + # Define the FV3 GFS layout attributes as a function of the + # cubed-sphere resolution. + layout_methods_dict = {"c48": self.c48} + + layout_dict = layout_methods_dict[self.csres]() + + # Compute additional FV3 GFS layout attributes as a function + # of the cubed-sphere resolution. + layout_chunks_dict = { + "ichunk2d": (4 * self.res), + "ichunk3d": (4 * self.res), + "jchunk2d": (2 * self.res), + "jchunk3d": (2 * self.res), + "kchunk3d": 1, + } + + layout_dict = {**layout_dict, **layout_chunks_dict} + + # Update the base-class Python dictionary. + for (layout_key, layout_value) in layout_dict.items(): + setattr(self.layout, layout_key, layout_value) diff --git a/ush/python/pygfs/utils/logger.py b/ush/python/pygfs/utils/logger.py new file mode 100644 index 00000000000..0b7c94cd903 --- /dev/null +++ b/ush/python/pygfs/utils/logger.py @@ -0,0 +1,34 @@ +from pygw.logger import Logger as pygw_Logger +from pygw.logger import logit as pygw_logit + +from dataclasses import dataclass + +from typing import Dict + +# ---- + + +@dataclass +class Logger: + """ + + """ + + def __init__(self: dataclass, config: Dict, level: str = None): + """ + Description + ----------- + + Creates a new Logger object. + + """ + + # Define the base-class attributes. + if level is None: + if getattr(config, "loglev") is None: + level = "info" + else: + level = config.loglev + + self.logger = pygw_Logger(level=level, colored_log=True) + self.logit = pygw_logit(self.logger) diff --git a/ush/python/pygfs/utils/timestamps.py b/ush/python/pygfs/utils/timestamps.py new file mode 100644 index 00000000000..276a936ffc9 --- /dev/null +++ b/ush/python/pygfs/utils/timestamps.py @@ -0,0 +1,195 @@ +""" +Module +------ + + pygfs.utils.timestamps (pygfs/utils/timestamps.py) + +Description +----------- + + This module contains the base-class module for all time-stamp + attributes definitions and derivations relative to a specified + time-stamp and optional formatting. + +Classes +------- + + Timestamps(datestr, fmt="%Y-%m-%d %H:%M:%S") + + This is the base-class object for all time-stamp attribute + definitions. + +""" + +# ---- + +__author__ = "Henry R. Winterbottom" +__maintainer__ = "Henry R. Winterbottom" +__email__ = "henry.winterbottom@noaa.gov" +__version__ = 0.0 + +# ---- + +import datetime +import sqlite3 +from dataclasses import dataclass + +from pygfs.exceptions import TimestampsError +from pygw.attrdict import AttrDict +from pygw.decorators import private +from pygw.timetools import strftime, strptime + +# ---- + + +@dataclass +class Timestamps: + """ + Description + ----------- + + This is the base-class object for all time-stamp attribute + definitions. + + Parameters + ---------- + + datestr: str + + A Python string specifying the the time-stamp; if the + parameter `fmt` is not specified upon entry, the module + assumes that the time-stamp is formatted as "%Y-%m-%d + %H:%M:%S". + + Keywords + -------- + + fmt: str + + A Python string specifying the POSIX-format for the `datestr` + parameter upon entry. + + Raises + ------ + + TimestampsError: + + - raised if an exception is encountered while discerning the + format of the attribute `datestr` upon entry. + + - raised if an exception is encountered while defining the + derived time-stamp attributes. + + """ + + def __init__(self: dataclass, datestr: str, fmt: str = "%Y-%m-%d %H:%M:%S"): + """ + Description + ----------- + + Creates a new Timestamps object. + + """ + + # Define the base-class attributes. + self.timestamps = AttrDict() + + # Define the time-stamp attributes relative to the application + # initialization time; enforce input attribute `datestr` to be + # Python type string. + try: + time_str = strptime(dtstr=str(datestr), fmt=fmt) + + except Exception as errmsg: + msg = ( + f"Initializing the attributes for input timestamp {datestr} " + f"failed with error {errmsg}. Aborting!!!" + ) + raise TimestampsError(msg=msg) from errmsg + + time_attr_dict = { + "year": "%Y", + "month": "%m", + "day": "%d", + "hour": "%H", + "minute": "%M", + "second": "%S", + "month_name_long": "%B", + "month_name_short": "%b", + "century_short": "%C", + "year_short": "%y", + "weekday_long": "%A", + "weekday_short": "%a", + "day_of_year": "%j", + "day_of_week": "%u", + "timezone": "%Z", + "week_of_year": "%W", + } + + for (time_attr, time_attr_value) in time_attr_dict.items(): + value = strftime(dt=time_str, fmt=time_attr_value) + try: + setattr(self.timestamps, time_attr, int(value)) + except ValueError: + setattr(self.timestamps, time_attr, value) + + # Define the derived time-stamp attributes; proceed + # accordingly. + try: + self.julianday() + self.epoch() + + except Exception as errmsg: + msg = ( + "Defining timestamp attributes failed with error " + f"{errmsg}. Aborting!!!" + ) + raise TimestampsError(msg=msg) from errmsg + + @private + def epoch(self: dataclass): + """ + Description + ----------- + + This method defines the epoch time relative to the respective + timestamp specified upon entry. + + """ + + # Define the epoch time (i.e., number of seconds since 0000 + # UTC 01 January 1970). + self.timestamps.epoch = datetime.datetime( + int(self.timestamps.year), + int(self.timestamps.month), + int(self.timestamps.day), + int(self.timestamps.hour), + int(self.timestamps.minute), + int(self.timestamps.second), + ).timestamp() + + @private + def julianday(self: dataclass): + """ + Description + ----------- + + This method define the Julian day relative to the respective + timestamp specified upon entry. + + """ + + # Define the Julian day. + connect = sqlite3.connect(":memory:") + datestr = ( + f"{self.timestamps.year}-" + f"{self.timestamps.month}-" + f"{self.timestamps.day} " + f"{self.timestamps.hour}:" + f"{self.timestamps.minute}:" + f"{self.timestamps.second}" + ) + + self.timestamps.julian_day = list( + connect.execute(f"select julianday('{datestr}')") + )[0][0] diff --git a/ush/python/pygw/src/pygw/decorators.py b/ush/python/pygw/src/pygw/decorators.py new file mode 100644 index 00000000000..8e4fbd2eca6 --- /dev/null +++ b/ush/python/pygw/src/pygw/decorators.py @@ -0,0 +1,13 @@ +import sys +import functools + + +def private(member): + @functools.wraps(member) + def wrapper(*function_args): + myself = member.__name__ + caller = sys._getframe(1).f_code.co_name + if (not caller in dir(function_args[0]) and not caller is myself): + raise Exception("%s called by %s is private" % (myself, caller)) + return member(*function_args) + return wrapper