Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[develop] Add IMS snow cover obs #181

Draft
wants to merge 11 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,7 @@
url = https://github.com/NOAA-EMC/jcb-algorithms.git
ignore = dirty

[submodule "sorc/IMS_proc"]
path = sorc/IMS_proc
url = https://github.com/NOAA-PSL/land-SCF_proc.git
ignore = dirty
53 changes: 53 additions & 0 deletions parm/jedi/IMS.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
- obs space:
name: SnowDepthIMS
distribution:
name: Halo
halo size: 250e3
simulated variables: [totalSnowDepth]
observed variables: [totalSnowDepth]
obsdatain:
engine:
type: H5File
obsfile: ioda.IMSscf.{{ yyyymmddhh }}.{{ tstub }}.nc
obsdataout:
engine:
type: H5File
obsfile: output/DA/hofx/letkf_hofx_ims_{{ yyyymmddhh }}.nc
obs operator:
name: Identity
obs error:
covariance model: diagonal
obs localizations:
- localization method: Horizontal SOAR
lengthscale: 250e3
soar horizontal decay: 0.000021
max nobs: 1
obs filters:
- filter: Perform Action
filter variables:
- name: totalSnowDepth
action:
name: assign error
error parameter: 40.0
- filter: Bounds Check # negative / missing snow
filter variables:
- name: totalSnowDepth
minvalue: 0.0
- filter: Domain Check # land only
where:
- variable:
name: GeoVaLs/slmsk
minvalue: 0.5
maxvalue: 1.5
- filter: RejectList # no land-ice
where:
- variable:
name: GeoVaLs/vtype
minvalue: 14.5
maxvalue: 15.5
- filter: Background Check # gross error check
filter variables:
- name: totalSnowDepth
threshold: 6.25
action:
name: reject
2 changes: 1 addition & 1 deletion parm/setup_wflow_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ def set_default_parm():
"nprocs_analysis": 6,
"nprocs_fcst_ic": 36,
"obsdir": "",
"obs_ghcn": "YES",
"obs_type": "GHCN",
"output_fh": "1 -1",
"res": 96,
"restart_interval": "12 -1",
Expand Down
6 changes: 3 additions & 3 deletions parm/templates/template.land_analysis.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ workflow:
NPROCS_FORECAST_LND: "{{ nprocs_forecast_lnd }}"
NPROCS_PER_NODE: "{{ nprocs_per_node }}"
OBSDIR: "{{ obsdir }}"
OBS_GHCN: "{{ obs_ghcn }}"
OBS_TYPE: "{{ obs_type }}"
OUTPUT_FH: "{{ output_fh }}"
RES: "{{ res }}"
RESTART_INTERVAL: "{{ restart_interval }}"
Expand Down Expand Up @@ -133,7 +133,7 @@ workflow:
MACHINE: "&MACHINE;"
model_ver: "&model_ver;"
OBSDIR: "&OBSDIR;"
OBS_GHCN: "&OBS_GHCN;"
OBS_TYPE: "&OBS_TYPE;"
PDY: "&PDY;"
SCHED: "&SCHED;"
account: "&ACCOUNT;"
Expand Down Expand Up @@ -238,7 +238,7 @@ workflow:
MACHINE: "&MACHINE;"
model_ver: "&model_ver;"
NPROCS_ANALYSIS: "&NPROCS_ANALYSIS;"
OBS_GHCN: "&OBS_GHCN;"
OBS_TYPE: "&OBS_TYPE;"
PDY: "&PDY;"
RES: "&RES;"
SCHED: "&SCHED;"
Expand Down
14 changes: 12 additions & 2 deletions scripts/exlandda_analysis.sh
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,14 @@ do
cp -p ${sfc_fn} "${sfc_fn}_ini"
done
# Copy obserbation file to work directory
ln -nsf ${COMIN}/obs/GHCN_${YYYY}${MM}${DD}${HH}.nc .
# TODO: Figure out if this var can be passed in through the yaml file
# TODO: same with this var at line 141
TSTUB=C96.mx100_oro_data # oro_C96.mx100
if [ "${OBS_TYPE}" = "GHCN" ]; then
ln -nsf ${COMIN}/obs/GHCN_${YYYY}${MM}${DD}${HH}.nc .
elif [ "${OBS_TYPE}" = "IMS" ]; then
ln -nsf ${COMIN}/obs/ioda.IMSscf.${YYYY}${MM}${DD}.${TSTUB}.nc .
fi

# update coupler.res file
settings="\
Expand Down Expand Up @@ -108,8 +115,10 @@ RESP1=$((RES+1))
mkdir -p output/DA/hofx

cp "${PARMlandda}/jedi/letkfoi_snow.yaml" "${DATA}/letkf_land.yaml"
if [ "${OBS_GHCN}" = "YES" ]; then
if [ "${OBS_TYPE}" = "GHCN" ]; then
cat ${PARMlandda}/jedi/GHCN.yaml >> letkf_land.yaml
elif [ "${OBS_TYPE}" = "IMS" ]; then
cat ${PARMlandda}/jedi/IMS.yaml >> letkf_land.yaml
fi

# update jedi yaml file
Expand All @@ -129,6 +138,7 @@ settings="\
'res': ${RES}
'resp1': ${RESP1}
'driver_obs_only': false
'tstub': C96.mx100_oro_data
" # End of settings variable

fp_template="${DATA}/letkf_land.yaml"
Expand Down
92 changes: 91 additions & 1 deletion scripts/exlandda_prep_obs.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,102 @@ YYYP=${PTIME:0:4}
MP=${PTIME:4:2}
DP=${PTIME:6:2}
HP=${PTIME:8:2}
echo "ptime=$PTIME"
echo "pdy=$PDY"

OBSDIR="${OBSDIR:-${FIXlandda}/DA_obs}"
DATA_GHCN_RAW="${DATA_GHCN_RAW:-${FIXlandda}/DATA_ghcn}"


#TODO: figure out if spack-stack can build this
# set pythonpath for ioda converters
PYTHONPATH=$PYTHONPATH:/scratch2/NCEPDEV/land/data/DA/GDASApp/sorc/iodaconv/src/:/scratch2/NCEPDEV/land/data/DA/GDASApp/build/lib/python3.10

# IMS snow cover data
if [ "${OBS_TYPE}" == "IMS" ]; then
# TODO: figure out if these variables can be sourced
RES=96 #FV3 resolution
TSTUB=C96.mx100_oro_data #oro_C96.mx100
DOY=$(date -d "${YYYY}-${MM}-${DD}" +%j)
echo "DOY is ${DOY}"
# TODO: the date seems to be for the next day. Need to figure out if this impacts the ghcn case

if [[ ${PDY}${cyc} -gt 2014120200 ]]; then
ims_vsn=1.3
imsformat=2 # nc
imsres="4km"
fsuf="nc"
ascii=""
elif [[ ${PDY}${cyc} -gt 2004022400 ]]; then
ims_vsn=1.2
imsformat=2 # nc
imsres="4km"
fsuf="nc"
ascii=""
else # TODO: switch back when we get obs data for 2000 or use a new case
ims_vsn=1.3 #1.1
imsformat=2 #1 # asc
imsres="4km" #"24km"
fsuf="nc" #"asc"
ascii="" #"ascii"
fi

obs_fn="ims${YYYY}${DOY}_${imsres}_v${ims_vsn}.${fsuf}"
# TODO: figure out which data is needed and stage them
#obs_fp="${OBSDIR}/snow_ice_cover/IMS/${YYYY}"
obs_fp="/scratch1/NCEPDEV/stmp4/Edward.Snyder/IMS_snowcover_obs/git-repo/ims_case_data/"
out_fn="ioda.IMSscf.${YYYY}${MM}${DD}.${TSTUB}.nc"

# check obs is available
if [ -f "${obs_fp}" ]; then
echo "IMS observation file: ${obs_fp}"
cp -p "${obs_fp}" .
cp -p "${obs_fp}" "${COMOUTobs}/${out_fn}"
fi

# pre-process and call IODA converter for IMS obs
if [[ -f fims.nml ]]; then
rm -rf fims.nml
fi
# TODO: update fcst_path when we find the right case data
cat >> fims.nml << EOF
&fIMS_nml
idim=$RES, jdim=$RES,
otype=${TSTUB},
jdate=${YYYY}${DOY},
yyyymmddhh=${YYYY}${MM}${DD}.${HH},
fcst_path="/scratch1/NCEPDEV/stmp4/Edward.Snyder/IMS_snowcover_obs/land-DA_update/jedi/restarts/",
imsformat=${imsformat},
imsversion=${ims_vsn},
imsres=${imsres},
IMS_OBS_PATH="${obs_fp}/",
IMS_IND_PATH="${obs_fp}/",
/
EOF
echo "calling fIMS"

# TODO: Do we need to run with mpiexec?
${EXEClandda}/calcfIMS.exe
if [[ $? != 0 ]]; then
echo "fIMS failed"
exit 10
fi

#IMS_IODA=imsfv3_scf2iodaTemp.py # 2024-07-12 temporary until GDASApp ioda converter updated.
#cp ${LANDDADIR}/jedi/ioda/${IMS_IODA} $JEDIWORKDIR

echo "calling ioda converter"
# TODO: create input_fn var
${USHlandda}/imsfv3_scf2iodaTemp.py -i IMSscf.${YYYY}${MM}${DD}.${TSTUB}.nc -o ${out_fn}
if [[ $? != 0 ]]; then
echo "IMS IODA converter failed"
exit 10
fi
cp -p "${out_fn}" "${COMOUTobs}/${out_fn}"
fi

# GHCN snow depth data
if [ "${OBS_GHCN}" = "YES" ]; then
if [ "${OBS_TYPE}" = "GHCN" ]; then
# GHCN are time-stamped at 18. If assimilating at 00, need to use previous day's obs,
# so that obs are within DA window.
obs_fn="ghcn_snwd_ioda_${YYYP}${MP}${DP}${HP}.nc"
Expand Down
14 changes: 14 additions & 0 deletions sorc/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,20 @@ ExternalProject_Add(tile2tile_converter.fd
STEP_TARGETS build
)

# IMS Snow cover obs
list(APPEND IMS_PROC_ARGS
"-DCMAKE_INSTALL_PREFIX=${CMAKE_INSTALL_PREFIX}"
)
list(APPEND TARGET LIST IMS_proc)
ExternalProject_Add(IMS_proc
PREFIX ${CMAKE_CURRENT_BINARY_DIR}/IMS_proc
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/IMS_proc
INSTALL_DIR ${CMAKE_INSTALL_PREFIX}
CMAKE_ARGS ${IMS_PROC_ARGS}
BUILD_ALWAYS TRUE
STEP_TARGETS build
)

# C-Test
add_subdirectory(test)

Expand Down
1 change: 1 addition & 0 deletions sorc/IMS_proc
Submodule IMS_proc added at 7ca1c7
4 changes: 4 additions & 0 deletions sorc/app_build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,10 @@ if [ "${REMOVE}" = true ]; then
printf "... Remove UFS_UTILS.fd ...\n"
rm -rf "${SORC_DIR}/UFS_UTILS.fd"
fi
if [ -d "${SORC_DIR}/IMS_proc" ]; then
printf "... Remove IMS_proc ...\n"
rm -rf "${SORC_DIR}/IMS_proc"
fi

cd "${HOME_DIR}"
git submodule update --init --recursive
Expand Down
Loading