Source code for jobs.era5_ic

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
era5_ic.py
Processing-chain job that generates ICON initial conditions (IC) from ERA5 input.

Design goals
------------
- Keep the job modular:
  * all paths and filenames come from cfg / case templates
  * the actual transformation is executed in a Slurm job script produced
    from a case-provided template (similar to icontools runjobs)
- Support global runs:
  * generate a single IC file on the ICON grid
  * do NOT generate LBC files
"""

import logging
from pathlib import Path
from . import tools, prepare_icon

BASIC_PYTHON_JOB = True


[docs] def main(cfg): """Generate ICON initial conditions from ERA5 input. 1. Prepare standard ICON paths (same helper as other jobs) 2. Create a Slurm script from the case template ``cfg.era5_ic_runjob_filename`` 3. Submit it The Slurm script is responsible for: - converting ERA5 GRIB -> NetCDF - renaming variables to ICON-like naming (via a partab) - remapping to the ICON triangular grid - writing the final IC file to ``cfg.icon_input/icbc`` Parameters ---------- cfg : Config Object holding all user-configuration parameters as attributes. """ prepare_icon.set_cfg_variables(cfg) tools.change_logfile(cfg.logfile) logging.info( "Generate global ICON initial conditions from ERA5 (IC only).") # Ensure run + icbc directories exist (prepare_icon usually created them, # but being explicit makes the job robust if invoked in isolation). tools.create_dir(cfg.icon_work, "icon_work") tools.create_dir(cfg.icon_input_icbc, "icon_input_icbc") # Walltime of the Slurm job submitted below, kept separate from # cfg.walltime_era5_ic, which sizes this wrapper job and must therefore # also account for the queue time of the job it waits for. cfg.walltime_jobs_era5_ic = getattr(cfg, 'walltime_jobs', {}).get('era5_ic', cfg.walltime_era5_ic) # Useful formatted dates for the template (avoid bash date gymnastics) cfg.era5_ymd = cfg.startdate_sim.strftime('%Y-%m-%d') # e.g. 2021-01-01 cfg.era5_yyyymmddhh = cfg.startdate_sim.strftime('%Y%m%d%H') # 2021010100 # ------------------------------------------------------------------ # Expand ERA5 input filename patterns from config.yaml # Supports placeholders like {ymd} and {yyyymmddhh}. # This is critical because bash will NOT expand "{ymd}". # ------------------------------------------------------------------ if hasattr(cfg, "era5_ml_filename"): cfg.era5_ml_file = cfg.era5_ml_filename.format( ymd=cfg.era5_ymd, yyyymmddhh=cfg.era5_yyyymmddhh, ) if hasattr(cfg, "era5_sfc_filename"): cfg.era5_sfc_file = cfg.era5_sfc_filename.format( ymd=cfg.era5_ymd, yyyymmddhh=cfg.era5_yyyymmddhh, ) # Make the partab path absolute (case-relative -> absolute) if hasattr(cfg, "era5_partab"): p = Path(str(cfg.era5_partab)) cfg.era5_partab_path = p if p.is_absolute() else (cfg.case_path / p) # Compute the *exact* file that ICON will later read inidata_filename = prepare_icon.get_inidata_filename(cfg) # Case template name (kept configurable) # Put in config.yaml: era5_ic_runjob_filename: era5_ic_runjob.cfg template_name = getattr(cfg, 'era5_ic_runjob_filename', 'era5_ic_runjob.cfg') template = (cfg.case_path / template_name).read_text() script_str = template.format( cfg=cfg, inidata_filename=inidata_filename, ) script = (cfg.icon_work / 'run_era5_ic.job') script.write_text(script_str) logging.info(f"Submitting ERA5 IC generation job: {script}") cfg.submit('era5_ic', script) logging.info("OK")