Skip to content

Commit 32c5ef7

Browse files
committed
Add ERA5 IC runscript
1 parent ac08ab4 commit 32c5ef7

1 file changed

Lines changed: 192 additions & 0 deletions

File tree

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
#!/usr/bin/env bash
2+
#SBATCH --job-name=era5_ic_{cfg.casename}_{cfg.startdate_sim_yyyymmddhh}
3+
#SBATCH --time={cfg.walltime_era5_ic}
4+
#SBATCH --partition={cfg.compute_queue}
5+
#SBATCH --constraint={cfg.constraint}
6+
#SBATCH --ntasks=1
7+
#SBATCH --output={cfg.logfile}
8+
#SBATCH --open-mode=append
9+
#SBATCH --chdir={cfg.icon_work}
10+
11+
# ---------------------------------------------------------------------
12+
# ERA5 -> ICON initial conditions (GLOBAL, IC only)
13+
#
14+
# This script is submitted by jobs/era5_ic.py.
15+
# It MUST write the final IC file exactly to:
16+
# {inidata_filename}
17+
#
18+
# Design:
19+
# - Use case config for input locations + partab
20+
# - Use staged ICON files from prepare_icon (cfg.input_files_scratch_*)
21+
# - Keep all intermediate files inside cfg.icon_work
22+
# ---------------------------------------------------------------------
23+
#
24+
set -euo pipefail
25+
set -x
26+
ulimit -s unlimited
27+
28+
# Optional: load modules needed for cdo/nco on Euler.
29+
# Adjust these to your environment/stack.
30+
module load stack/2024-06 || true
31+
module load cdo/2.2.2 nco/5.1.6 netcdf-c/4.9.2 || true
32+
33+
# ---------------------------------------------------------------------
34+
# Inputs (from cfg)
35+
# ---------------------------------------------------------------------
36+
ERA5_DIR="{cfg.era5_dir}"
37+
ERA5_ML="{cfg.era5_ml_filename}"
38+
ERA5_SFC="{cfg.era5_sfc_filename}"
39+
# Replace {ymd} placeholder using values prepared in era5_ic.py
40+
ERA5_ML="${{ERA5_ML/\{ymd\}/{cfg.era5_ymd}}}"
41+
ERA5_SFC="${{ERA5_SFC/\{ymd\}/{cfg.era5_ymd}}}"
42+
PARTAB="{cfg.era5_partab}"
43+
GRID_TRI="{cfg.input_files_scratch_dynamics_grid_filename}"
44+
EXTPAR="{cfg.input_files_scratch_extpar_filename}"
45+
OUTFILE="{inidata_filename}"
46+
47+
# ---------------------------------------------------------------------
48+
# Working directory cleanup
49+
# ---------------------------------------------------------------------
50+
work="{cfg.icon_work}/era5_ic_work"
51+
mkdir -p "$work"
52+
cd "$work"
53+
54+
# ---------------------------------------------------------------------
55+
# 1) GRIB preprocessing: pick first timestep and convert to NetCDF
56+
# ---------------------------------------------------------------------
57+
#
58+
# Note: your colleague used splitsel,1; keep it to ensure we only have t0.
59+
cdo splitsel,1 "${{ERA5_DIR}}/${{ERA5_ML}}" era5_ml_
60+
cdo splitsel,1 "${{ERA5_DIR}}/${{ERA5_SFC}}" era5_sfc_
61+
62+
# Find the produced split files (avoid hardcoding the exact suffix)
63+
ml_grb="$(ls -1 era5_ml_* | head -n 1)"
64+
sfc_grb="$(ls -1 era5_sfc_* | head -n 1)"
65+
cdo -t ecmwf -f nc copy "$ml_grb" era5_ml.nc
66+
cdo -t ecmwf -f nc copy "$sfc_grb" era5_sfc.nc
67+
cdo merge era5_ml.nc era5_sfc.nc era5_original.nc
68+
69+
# Rename variables / metadata to ICON-consistent naming via partab
70+
# (Your partab is the "contract" between ERA5 and ICON naming expectations.)
71+
cdo setpartabn,"$PARTAB",convert era5_original.nc tmp.nc
72+
73+
# Order variables (helps reproducibility and easier diffs)
74+
ncks tmp.nc data_in.nc
75+
rm -f tmp.nc era5_ml.nc era5_sfc.nc era5_original.nc "$ml_grb" "$sfc_grb"
76+
77+
# ---------------------------------------------------------------------
78+
# 2) Build the ICON triangular grid description for CDO remapping
79+
# ---------------------------------------------------------------------
80+
cdo -s selgrid,1 "$GRID_TRI" triangular-grid.nc
81+
82+
# ---------------------------------------------------------------------
83+
# 3) Land/sea-aware remapping for sensitive surface variables
84+
# ---------------------------------------------------------------------
85+
#
86+
# Input land-sea mask from renamed ERA5 data
87+
cdo selname,LSM data_in.nc LSM_in.nc
88+
ncrename -h -v LSM,FR_LAND LSM_in.nc
89+
90+
# Output land fraction from EXTPAR
91+
cdo selname,FR_LAND "$EXTPAR" LSM_out_tmp.nc
92+
93+
# Add time dimension and align time coordinate
94+
ncecat -O -u time LSM_out_tmp.nc LSM_out_tmp.nc
95+
ncks -h -A -v time LSM_in.nc LSM_out_tmp.nc
96+
97+
# Build land/ocean masks (input and output)
98+
cdo -L setctomiss,0. -ltc,0.5 LSM_in.nc oceanmask_in.nc
99+
cdo -L setctomiss,0. -gec,0.5 LSM_in.nc landmask_in.nc
100+
cdo -L setctomiss,0. -ltc,0.5 LSM_out_tmp.nc oceanmask_out.nc
101+
cdo -L setctomiss,0. -gec,0.5 LSM_out_tmp.nc landmask_out.nc
102+
cdo setrtoc2,0.5,1.0,1,0 LSM_out_tmp.nc LSM_out.nc
103+
rm -f LSM_in.nc LSM_out_tmp.nc
104+
105+
# Variables defined only on sea
106+
ncks -h -v SST,CI data_in.nc datasea_in.nc
107+
108+
# Variables defined on both but should not mix land/sea
109+
ncks -h -v SKT,STL1,STL2,STL3,STL4,ALB_SNOW,W_SNOW,T_SNOW data_in.nc dataland_in.nc
110+
111+
# Ocean part: mask -> fill -> remap -> unmask
112+
cdo div dataland_in.nc oceanmask_in.nc tmp1_land.nc
113+
cdo div datasea_in.nc oceanmask_in.nc tmp1_sea.nc
114+
cdo setmisstodis tmp1_land.nc tmp2_land.nc
115+
cdo setmisstodis tmp1_sea.nc tmp2_sea.nc
116+
cdo remapdis,triangular-grid.nc tmp2_land.nc tmp3_land.nc
117+
cdo remapdis,triangular-grid.nc tmp2_sea.nc tmp3_sea.nc
118+
cdo div tmp3_land.nc oceanmask_out.nc dataland_ocean_out.nc
119+
cdo div tmp3_sea.nc oceanmask_out.nc datasea_ocean_out.nc
120+
rm -f tmp*_land.nc tmp*_sea.nc oceanmask_in.nc oceanmask_out.nc
121+
122+
# Land part: mask -> fill -> remap -> unmask
123+
cdo div dataland_in.nc landmask_in.nc tmp1.nc
124+
cdo setmisstodis tmp1.nc tmp2.nc
125+
cdo remapdis,triangular-grid.nc tmp2.nc tmp3.nc
126+
cdo div tmp3.nc landmask_out.nc dataland_land_out.nc
127+
rm -f tmp*.nc landmask_in.nc landmask_out.nc dataland_in.nc datasea_in.nc
128+
129+
# Merge land+ocean contributions
130+
cdo ifthenelse LSM_out.nc dataland_land_out.nc dataland_ocean_out.nc dataland_out.nc
131+
rm -f dataland_ocean_out.nc dataland_land_out.nc
132+
133+
# Remap all remaining variables together
134+
ncks -h -x -v SKT,STL1,STL2,STL3,STL4,SMIL1,SMIL2,SMIL3,SMIL4,ALB_SNOW,W_SNOW,T_SNOW,SST,CI,LSM data_in.nc datarest_in.nc
135+
cdo -s remapdis,triangular-grid.nc datarest_in.nc era5_final.nc
136+
rm -f datarest_in.nc
137+
138+
# Fill missing SST/CI after remap (sea-only fields)
139+
cdo setmisstodis -selname,SST,CI datasea_ocean_out.nc datasea_ocean_out_filled.nc
140+
rm -f datasea_ocean_out.nc
141+
142+
# Merge special remapped variables + land fraction (renamed back to LSM)
143+
ncks -h -A dataland_out.nc era5_final.nc
144+
ncks -h -A datasea_ocean_out_filled.nc era5_final.nc
145+
ncks -h -A -v FR_LAND LSM_out.nc era5_final.nc
146+
ncrename -h -v FR_LAND,LSM era5_final.nc
147+
rm -f LSM_out.nc dataland_out.nc datasea_ocean_out_filled.nc
148+
149+
# ---------------------------------------------------------------------
150+
# 4) Soil moisture index conversion (ERA5 SWVL -> ICON-style SMIL)
151+
# ---------------------------------------------------------------------
152+
# Extract soil moisture and soil type
153+
ncks -h -v SMIL1,SMIL2,SMIL3,SMIL4,SLT data_in.nc swvl.nc
154+
rm -f data_in.nc
155+
156+
# IFS soil constants (documented in ERA5 data documentation)
157+
wiltingp=(0 0.059 0.151 0.133 0.279 0.335 0.267 0.151)
158+
fieldcap=(0 0.244 0.347 0.383 0.448 0.541 0.663 0.347)
159+
smi_equation=""
160+
for ilev in {1..4}; do
161+
smi_equation="${smi_equation}SMIL${ilev}=(SMIL${ilev}-${wiltingp[1]})/(${fieldcap[1]}-${wiltingp[1]})*(SLT==1)"
162+
for ist in {2..7}; do
163+
smi_equation="${smi_equation}+(SMIL${ilev}-${wiltingp[$ist]})/(${fieldcap[$ist]}-${wiltingp[$ist]})*(SLT==${ist})"
164+
done
165+
smi_equation="${smi_equation};"
166+
done
167+
cdo expr,"${smi_equation}" swvl.nc smil_in.nc
168+
rm -f swvl.nc
169+
170+
# Remap SMIL to triangular grid and overwrite
171+
cdo -s remapdis,triangular-grid.nc smil_in.nc smil_out.nc
172+
ncks -A -v SMIL1,SMIL2,SMIL3,SMIL4 smil_out.nc era5_final.nc
173+
rm -f smil_in.nc smil_out.nc
174+
175+
# ---------------------------------------------------------------------
176+
# 5) Create LNPS (log surface pressure) and finalize dimensions
177+
# ---------------------------------------------------------------------
178+
cdo expr,'LNPS=ln(PS);' era5_final.nc tmp.nc
179+
ncks -A -v LNPS tmp.nc era5_final.nc
180+
rm -f tmp.nc
181+
182+
# ICON conventions: rename dimensions
183+
ncrename -h -d cell,ncells era5_final.nc
184+
ncrename -h -d nv,vertices era5_final.nc
185+
186+
# Write final IC file to the exact path ICON will read later
187+
mkdir -p "$(dirname "$OUTFILE")"
188+
ncks era5_final.nc "$OUTFILE"
189+
190+
# cleanup
191+
rm -f era5_final.nc triangular-grid.nc
192+
echo "Wrote ICON initial condition file: $OUTFILE"

0 commit comments

Comments
 (0)