From ad34790cbc8112759a8356d56f084363b8a3cbe8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20J=C3=A4hn?= Date: Thu, 18 Dec 2025 16:17:32 +0100 Subject: [PATCH 01/16] Use conda-forge only --- env/environment.yml | 1 - jenkins/Jenkinsfile | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/env/environment.yml b/env/environment.yml index 98b90e44..0070da5b 100644 --- a/env/environment.yml +++ b/env/environment.yml @@ -1,7 +1,6 @@ name: proc-chain channels: - conda-forge - - defaults dependencies: - python=3.11 - cdo diff --git a/jenkins/Jenkinsfile b/jenkins/Jenkinsfile index 19875218..ba296f34 100644 --- a/jenkins/Jenkinsfile +++ b/jenkins/Jenkinsfile @@ -29,8 +29,10 @@ pipeline { sh 'wget -O ${WORKSPACE}/miniconda.sh https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh' sh 'rm -fr ${WORKSPACE}/miniconda' sh 'bash miniconda.sh -b -p $WORKSPACE/miniconda' + sh 'conda config --remove channels defaults' sh 'conda config --set always_yes yes --set changeps1 no' sh 'conda config --add channels conda-forge' + sh 'conda config --set channel_priority strict' sh 'conda update -n base -c defaults conda' sh 'conda env create -f env/environment.yml' sh '''source ${WORKSPACE}/miniconda/etc/profile.d/conda.sh From 43f2874b1b38986e6a5465844982597940a529bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20J=C3=A4hn?= Date: Thu, 18 Dec 2025 16:17:52 +0100 Subject: [PATCH 02/16] Adapt setup script for euler and santis --- jenkins/scripts/setup-spack.sh | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/jenkins/scripts/setup-spack.sh b/jenkins/scripts/setup-spack.sh index 76ed1a11..ccc10fde 100755 --- a/jenkins/scripts/setup-spack.sh +++ b/jenkins/scripts/setup-spack.sh @@ -11,15 +11,13 @@ SPACK_TAG_COSMO=v0.18.1.12 if [[ $(hostname) == eu-* ]]; then source /cluster/apps/local/env2lmod.sh - module load git/2.31.1 - SPACK_TAG=main -elif [[ $(hostname) == daint* ]]; then - git clone --depth 1 git@github.com:C2SM/icon.git icon-tag - SPACK_TAG=`cat icon-tag/config/cscs/SPACK_TAG_DAINT` + module load git + git clone --depth 1 git@gitlab.dkrz.de:icon/icon-model.git icon-tag + SPACK_TAG=`cat icon-tag/config/ethz/SPACK_TAG_EULER` rm -fr icon-tag -elif [[ $(hostname) == balfrin* ]]; then - git clone --depth 1 git@github.com:C2SM/icon.git icon-tag - SPACK_TAG=`cat icon-tag/config/cscs/SPACK_TAG_BALFRIN` +elif [[ $(hostname) == santis* ]]; then + git clone --depth 1 git@gitlab.dkrz.de:icon/icon-model.git icon-tag + SPACK_TAG=`cat icon-tag/config/cscs/SPACK_TAG_SANTIS` rm -fr icon-tag else error "Unknown hostname: $(hostname)" From 9dace95e2327220bd1e029dc0e55fa4e7cae3ba3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20J=C3=A4hn?= Date: Thu, 18 Dec 2025 16:22:00 +0100 Subject: [PATCH 03/16] Remove icon-art build --- jenkins/scripts/build_icon-art.sh | 41 ------------------------------- 1 file changed, 41 deletions(-) delete mode 100755 jenkins/scripts/build_icon-art.sh diff --git a/jenkins/scripts/build_icon-art.sh b/jenkins/scripts/build_icon-art.sh deleted file mode 100755 index 68d09fd2..00000000 --- a/jenkins/scripts/build_icon-art.sh +++ /dev/null @@ -1,41 +0,0 @@ -#!/bin/bash - -set -e -x - -# Check if script is called correctly -[[ $(git rev-parse --show-toplevel 2>/dev/null) = $(pwd) ]] || error "$0 not launched from toplevel of repository" - -source jenkins/scripts/common.sh - -BRANCH=art -GIT_REMOTE=git@github.com:C2SM/icon.git -MODEL=icon-art - -pushd ext - -# Clone the repo if not already existing -if [[ ! -d "${MODEL}" ]]; then - git clone --depth 1 --recurse-submodules -b ${BRANCH} ${GIT_REMOTE} ${MODEL} -fi - -pushd ${MODEL} - -if [[ $(hostname) == eu-* ]]; then - ./jenkins/scripts/jenkins_euler.sh -b -fc gcc --configure euler.cpu.gcc.O2 -elif [[ $(hostname) == daint* ]]; then - SPACK_TAG=`cat config/cscs/SPACK_TAG_DAINT` - . ../spack-c2sm/setup-env.sh - spack env activate -d config/cscs/spack/${SPACK_TAG}/daint_cpu_nvhpc - spack install -u build -elif [[ $(hostname) == balfrin* ]]; then - SPACK_TAG=`cat config/cscs/SPACK_TAG_BALFRIN` - . ../spack-c2sm/setup-env.sh - spack env activate -d config/cscs/spack/${SPACK_TAG}/daint_cpu_nvhpc - spack install -u build -else - error "Unknown hostname: $(hostname)" -fi - -popd - -popd From 6edbdbdd58819bf6f47314f84c17e996e03dca08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20J=C3=A4hn?= Date: Thu, 18 Dec 2025 16:29:36 +0100 Subject: [PATCH 04/16] Remove daint and icon-art build --- jenkins/scripts/jenkins.sh | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/jenkins/scripts/jenkins.sh b/jenkins/scripts/jenkins.sh index 8fbe49ff..3eb4870b 100755 --- a/jenkins/scripts/jenkins.sh +++ b/jenkins/scripts/jenkins.sh @@ -21,11 +21,12 @@ set -e -x # Check if we are on Euler if [[ $(hostname) == eu-* ]]; then host=euler -elif [[ $(hostname) == daint* ]]; then - host=daint +elif [[ $(hostname) == santis* ]]; then + host=santis +else + echo "Unknown hostname: $(hostname)" fi - # Activate conda environment eval "$(conda shell.bash hook)" conda activate proc-chain @@ -85,14 +86,6 @@ else ./jenkins/scripts/build_icon.sh fi -# Build ICON-ART -if [[ -f ext/icon-art/bin/icon ]]; then - echo icon-art executable already exists - skipping build. -else - echo building icon-art... - ./jenkins/scripts/build_icon-art.sh -fi - # Test COSMO-GHG if [[ "$host" == euler ]]; then echo skipping cosmo-ghg test on Euler... From 6afe8c036761f314588df5bc6efdedeec87d2c9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20J=C3=A4hn?= Date: Thu, 18 Dec 2025 20:26:45 +0100 Subject: [PATCH 05/16] Start adapting eccodes path (todo) --- cases/icon-test-euler/config.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cases/icon-test-euler/config.yaml b/cases/icon-test-euler/config.yaml index 28fd1269..b6f94b33 100644 --- a/cases/icon-test-euler/config.yaml +++ b/cases/icon-test-euler/config.yaml @@ -9,7 +9,7 @@ restart_step: PT6H startdate: 2018-01-01T00:00:00Z enddate: 2018-01-01T12:00:00Z -eccodes_dir: ./input/eccodes_definitions +eccodes_dir: ./ext/spack-c2sm/spack/opt/spack/linux-ubuntu22.04-broadwell/gcc-12.2.0//share/eccodes/definitions iconremap_bin: ./ext/icontools/icontools/iconremap iconsub_bin: ./ext/icontools/icontools/iconsub latbc_filename: ifs_201801_lbc.nc From 7b3bbc6ab337e08b8170ebc32e9d6ee9676a17fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20J=C3=A4hn?= Date: Wed, 14 Jan 2026 14:25:04 +0100 Subject: [PATCH 06/16] Cleanup testing script and adapt ICON build on Euler --- jenkins/scripts/build_icon.sh | 24 +++++------ jenkins/scripts/jenkins.sh | 78 ----------------------------------- 2 files changed, 11 insertions(+), 91 deletions(-) diff --git a/jenkins/scripts/build_icon.sh b/jenkins/scripts/build_icon.sh index ea1ab959..29717888 100755 --- a/jenkins/scripts/build_icon.sh +++ b/jenkins/scripts/build_icon.sh @@ -7,8 +7,8 @@ set -e -x source jenkins/scripts/common.sh -BRANCH=main -GIT_REMOTE=git@github.com:C2SM/icon.git +BRANCH=release-2025.10-public +GIT_REMOTE=https://gitlab.dkrz.de/icon/icon-model.git MODEL=icon pushd ext @@ -21,17 +21,15 @@ fi pushd ${MODEL} if [[ $(hostname) == eu-* ]]; then - ./jenkins/scripts/jenkins_euler.sh -b -fc gcc --configure euler.cpu.gcc.O2 -elif [[ $(hostname) == daint* ]]; then - SPACK_TAG=`cat config/cscs/SPACK_TAG_DAINT` - . ../spack-c2sm/setup-env.sh - spack env activate -d config/cscs/spack/${SPACK_TAG}/daint_cpu_nvhpc - spack install -u build -elif [[ $(hostname) == balfrin* ]]; then - SPACK_TAG=`cat config/cscs/SPACK_TAG_BALFRIN` - . ../spack-c2sm/setup-env.sh - spack env activate -d config/cscs/spack/${SPACK_TAG}/daint_cpu_nvhpc - spack install -u build + # Setup spack + SPACK_TAG=$(cat "config/ethz/SPACK_TAG_EULER") + git clone --depth 1 --recurse-submodules --shallow-submodules -b ${SPACK_TAG} https://github.com/C2SM/spack-c2sm.git + . spack-c2sm/setup-env.sh + # Load module to access external services on compute nodes + module load eth_proxy + # Build ICON + spack env activate -d config/ethz/spack/${SPACK_TAG}/euler_cpu_gcc + srun -N 1 -n 12 --mem-per-cpu=1G spack install -j 12 else error "Unknown hostname: $(hostname)" fi diff --git a/jenkins/scripts/jenkins.sh b/jenkins/scripts/jenkins.sh index 3eb4870b..cedb8ba2 100755 --- a/jenkins/scripts/jenkins.sh +++ b/jenkins/scripts/jenkins.sh @@ -50,34 +50,6 @@ else ./jenkins/scripts/get_data.sh fi -# Build icontools -if [[ -f ext/icontools/icontools/iconremap ]]; then - echo icontools already installed - skipping build... -else - echo building icontools... - ./jenkins/scripts/build_icontools.sh -fi - -# Build int2lm -if [[ "$host" == euler ]]; then - echo skipping int2lm build on Euler... -elif [[ -f ext/int2lm/TESTSUITE/int2lm ]]; then - echo int2lm executable already exists - skipping build... -else - echo building int2lm... - ./jenkins/scripts/build_int2lm.sh -fi - -# Build COSMO-GHG -if [[ "$host" == euler ]]; then - echo skipping cosmo-ghg build on Euler... -elif [[ -f ext/cosmo-ghg/cosmo/ACC/cosmo_gpu ]]; then - echo cosmo executable already exists - skipping build. -else - echo building cosmo... - ./jenkins/scripts/build_cosmo-ghg.sh -fi - # Build ICON if [[ -f ext/icon/bin/icon ]]; then echo icon executable already exists - skipping build. @@ -86,57 +58,7 @@ else ./jenkins/scripts/build_icon.sh fi -# Test COSMO-GHG -if [[ "$host" == euler ]]; then - echo skipping cosmo-ghg test on Euler... -elif [[ -f work/cosmo-ghg-test/2015010106_2015010112/checkpoints/finished/post_cosmo && "$force_execution" == false ]]; then - echo cosmo-ghg test case already finished - skipping test. -else - echo running cosmo-ghg test case... - ./jenkins/scripts/test_cosmo-ghg.sh -fi - -# Test COSMO-GHG (spinup) -if [[ "$host" == euler ]]; then - echo skipping cosmo-ghg-spinup test on Euler... -elif [[ -f work/cosmo-ghg-spinup-test/2015010109_2015010118/checkpoints/finished/post_cosmo && "$force_execution" == false ]]; then - echo cosmo-ghg-spinup test case already finished - skipping test. -else - echo running cosmo-ghg-spinup test case... - ./jenkins/scripts/test_cosmo-ghg-spinup.sh -fi - # Test ICON -if [[ "$host" == euler ]]; then - echo skipping icon test on Euler... -elif [[ -f work/icon-test/2018010106_2018010112/checkpoints/finished/icon && "$force_execution" == false ]]; then - echo icon test case already finished - skipping test. -else - echo running icon test case... - ./jenkins/scripts/test_icon.sh -fi - -# Test ICON-ART -if [[ "$host" == euler ]]; then - echo skipping icon-art-oem test on Euler... -elif [[ -f work/icon-art-oem-test/2018010106_2018010112/checkpoints/finished/icon && "$force_execution" == false ]]; then - echo icon-art test case already finished - skipping test. -else - echo running icon-art-oem test case... - ./jenkins/scripts/test_icon-art-oem.sh -fi - -# Test ICON-ART-GLOBAL -if [[ "$host" == euler ]]; then - echo skipping icon-art-global test on Euler... -elif [[ -f work/icon-art-global-test/2018010106_2018010112/checkpoints/finished/icon && "$force_execution" == false ]]; then - echo icon-art-global test case already finished - skipping test. -else - echo running icon-art-global test case... - ./jenkins/scripts/test_icon-art-global.sh -fi - -# Test ICON (Euler) if [[ "$host" == euler ]]; then if [[ -f work/icon-test-euler/2018010106_2018010112/checkpoints/finished/icon && "$force_execution" == false ]]; then echo icon test case already finished - skipping test. From 0e9594c21f43ff794979192a580536a8f69e29bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20J=C3=A4hn?= Date: Wed, 14 Jan 2026 15:37:38 +0100 Subject: [PATCH 07/16] Avoid double loading spack --- jenkins/scripts/build_icon.sh | 4 ++-- jenkins/scripts/jenkins.sh | 10 ---------- 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/jenkins/scripts/build_icon.sh b/jenkins/scripts/build_icon.sh index 29717888..f4c3fb67 100755 --- a/jenkins/scripts/build_icon.sh +++ b/jenkins/scripts/build_icon.sh @@ -21,12 +21,12 @@ fi pushd ${MODEL} if [[ $(hostname) == eu-* ]]; then + # Load necessary modules + module load stack/2025-06 git eth_proxy # Setup spack SPACK_TAG=$(cat "config/ethz/SPACK_TAG_EULER") git clone --depth 1 --recurse-submodules --shallow-submodules -b ${SPACK_TAG} https://github.com/C2SM/spack-c2sm.git . spack-c2sm/setup-env.sh - # Load module to access external services on compute nodes - module load eth_proxy # Build ICON spack env activate -d config/ethz/spack/${SPACK_TAG}/euler_cpu_gcc srun -N 1 -n 12 --mem-per-cpu=1G spack install -j 12 diff --git a/jenkins/scripts/jenkins.sh b/jenkins/scripts/jenkins.sh index cedb8ba2..aeff8650 100755 --- a/jenkins/scripts/jenkins.sh +++ b/jenkins/scripts/jenkins.sh @@ -31,16 +31,6 @@ fi eval "$(conda shell.bash hook)" conda activate proc-chain -# Setup spack -if [[ -d ext/spack-c2sm ]]; then - echo spack folder already exists - skipping build... -else - echo building spack... - ./jenkins/scripts/setup-spack.sh -fi -echo activating spack... -. ext/spack-c2sm/setup-env.sh - # Preparation size=$(du -sb input | awk '{print $1}') if [[ $size -gt 12000000000 ]]; then From 9916c9a4d0a799ddff9ecac975a6ec8449b46dcf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20J=C3=A4hn?= Date: Wed, 14 Jan 2026 16:24:30 +0100 Subject: [PATCH 08/16] Adjust icon euler test case --- cases/icon-test-euler/config.yaml | 73 +++--- .../icontools_remap_00_lbc_runjob.cfg | 147 ----------- .../icontools_remap_ic_runjob.cfg | 238 ------------------ .../icontools_remap_lbc_rest_runjob.cfg | 121 --------- workflows.yaml | 18 ++ 5 files changed, 51 insertions(+), 546 deletions(-) delete mode 100755 cases/icon-test-euler/icontools_remap_00_lbc_runjob.cfg delete mode 100755 cases/icon-test-euler/icontools_remap_ic_runjob.cfg delete mode 100755 cases/icon-test-euler/icontools_remap_lbc_rest_runjob.cfg diff --git a/cases/icon-test-euler/config.yaml b/cases/icon-test-euler/config.yaml index b6f94b33..35dffc72 100644 --- a/cases/icon-test-euler/config.yaml +++ b/cases/icon-test-euler/config.yaml @@ -1,55 +1,48 @@ -# Configuration file for the 'icon-async-test' case with ICON +# Global ICON simulation initialized from ERA5 (IC only, no LBC). -workflow: icon +workflow: icon-global-era5 constraint: EPYC_7H12 run_on: cpu compute_queue: normal.4h ntasks_per_node: 12 restart_step: PT6H startdate: 2018-01-01T00:00:00Z -enddate: 2018-01-01T12:00:00Z - -eccodes_dir: ./ext/spack-c2sm/spack/opt/spack/linux-ubuntu22.04-broadwell/gcc-12.2.0//share/eccodes/definitions -iconremap_bin: ./ext/icontools/icontools/iconremap -iconsub_bin: ./ext/icontools/icontools/iconsub -latbc_filename: ifs_201801_lbc.nc -inidata_filename: ifs_init_2018010100.nc -output_filename: NWP_LAM -filename_format: _DOM_ -lateral_boundary_grid_order: lateral_boundary +enddate: 2018-01-01T12:00:00Z walltime: - prepare_icon: '00:10:00' - icontools: '00:30:00' - icon: '00:30:00' + prepare_icon: "00:10:00" + era5_ic: "00:40:00" + icon: "00:30:00" -meteo: - dir: ./input/meteo - prefix: ifs_ - nameformat: '%Y%m%d%H' - suffix: .grb - inc: 3 +era5: + dir: ./input/era5 + ml_filename: "era5_ml_{ymd}.grib" + sfc_filename: "era5_surf_{ymd}.grib" -icontools_runjobs: - - icontools_remap_ic_runjob.cfg - - icontools_remap_00_lbc_runjob.cfg - - icontools_remap_lbc_rest_runjob.cfg +era5_partab: ./cases/icon-euler-test/partab_era5_to_icon.txt +era5_ic_runjob_filename: era5_ic_runjob.cfg +inidata_prefix: "era5_init_R02B05_" +inidata_nameformat: "%Y%m%d%H" +inidata_filename_suffix: ".nc" + +meteo: + dir: ./input/meteo + prefix: ifs_ + nameformat: "%Y%m%d%H" + suffix: .grb + inc: 3 input_files: - radiation_grid_filename: ./input/icon/grid/VERIFY_DOM_DOM01.parent.nc - dynamics_grid_filename: ./input/icon/grid/VERIFY_DOM_DOM01.nc - map_file_latbc: ./input/icon/grid/map_file.latbc - lateral_boundary_grid: ./input/icon/grid/lateral_boundary.grid.nc - extpar_filename: ./input/icon/grid/external_parameter_icon_VERIFY_DOM_DOM01_tiles.nc - cldopt_filename: ./input/icon/rad/rrtm_cldopt.nc - lrtm_filename: ./input/icon/rad/rrtmg_lw.nc - map_file_ana: ./input/icon/mapping/map_file.ana + dynamics_grid_filename: ./input/icon/grid/iconR2B05-DOM01.nc + extpar_filename: ./input/icon/grid/extpar_iconR2B05-DOM01.nc + lrtm_filename: ./input/icon/rad/rrtmg_lw.nc + cldopt_filename: ./input/icon/rad/rrtm_cldopt.nc + map_file_ana: ./input/icon/mapping/map_file.ana icon: - binary_file: ./ext/icon/bin/icon - runjob_filename: icon_runjob.cfg - np_tot: 96 - np_io: 1 - np_restart: 1 - np_prefetch: 1 - + binary_file: /cluster/work/climate/lroither/icon_c2sm/icon/bin/icon + runjob_filename: icon_runjob.cfg + np_tot: 96 + np_io: 1 + np_restart: 1 + np_prefetch: 0 diff --git a/cases/icon-test-euler/icontools_remap_00_lbc_runjob.cfg b/cases/icon-test-euler/icontools_remap_00_lbc_runjob.cfg deleted file mode 100755 index 0708bd96..00000000 --- a/cases/icon-test-euler/icontools_remap_00_lbc_runjob.cfg +++ /dev/null @@ -1,147 +0,0 @@ -#!/usr/bin/env bash -#SBATCH --job-name=iconsub -#SBATCH --chdir={cfg.icon_work} -#SBATCH --partition={cfg.compute_queue} -#SBATCH --constraint={cfg.constraint} -#SBATCH --ntasks=1 -#SBATCH --output={logfile} -#SBATCH --open-mode=append - -ulimit -s unlimited - -set -x - -export ECCODES_DEFINITION_PATH={cfg.eccodes_dir}/definitions.edzw-2.12.5-2:{cfg.eccodes_dir}/definitions - -#----------------------------------------------------------------------------- -# PART I: Create auxiliary grid file which contains only the cells of the -# boundary zone. -#----------------------------------------------------------------------------- -cat > NAMELIST_ICONSUB_{cfg.startdate_sim_yyyymmddhh} << EOF_1 -&iconsub_nml - grid_filename = '{cfg.input_files_scratch_dynamics_grid_filename}', - output_type = 4, - lwrite_grid = .TRUE., -/ -&subarea_nml - ORDER = "{cfg.lateral_boundary_grid_order}", - grf_info_file = '{cfg.input_files_scratch_dynamics_grid_filename}', - min_refin_c_ctrl = 1 - max_refin_c_ctrl = 14 -/ -EOF_1 - -srun -n 1 {cfg.iconsub_bin} \ - --nml NAMELIST_ICONSUB_{cfg.startdate_sim_yyyymmddhh} 2>&1 - -#----------------------------------------------------------------------------- -# PART II: Extract boundary data -#----------------------------------------------------------------------------- -rm -f ncstorage.tmp_lbc_{cfg.startdate_sim_yyyymmddhh}* - -set +x -cat > NAMELIST_ICONREMAP_FIELDS_{cfg.startdate_sim_yyyymmddhh} << EOF -! -&input_field_nml ! temperature - inputname = "T" - outputname = "T" - code = 130 - intp_method = 3 -/ -&input_field_nml ! horiz. wind comp. u - inputname = "U" - outputname = "U" - intp_method = 3 -/ -&input_field_nml ! horiz. wind comp. u - inputname = "V" - outputname = "V" - intp_method = 3 -/ -&input_field_nml ! vertical velocity - inputname = "OMEGA" - outputname = "W" - code = 135 - intp_method = 3 -/ -&input_field_nml ! surface pressure - inputname = "LNSP" - outputname = "LNPS" - code = 152 - intp_method = 3 -/ -&input_field_nml ! geopotential - inputname = "Z" - outputname = "GEOSP" - code = 129 - intp_method = 3 -/ -&input_field_nml ! specific humidity - inputname = "QV" - outputname = "QV" - code = 133 - intp_method = 3 -/ -&input_field_nml ! cloud liquid water content - inputname = "CLWC" - outputname = "QC" - code = 246 - intp_method = 3 -/ -&input_field_nml ! cloud ice water content - inputname = "CIWC" - outputname = "QI" - code = 247 - intp_method = 3 -/ -&input_field_nml ! rain water content - inputname = "CRWC" - outputname = "QR" - code = 75 - intp_method = 3 -/ -&input_field_nml ! snow water content - inputname = "CSWC" - outputname = "QS" - code = 76 - intp_method = 3 -/ -EOF - -#----------------------------------------------------------------------------- -# loop over file list: - -echo "DATAFILELIST is {datafile_list}" -for datafilename in {datafile_list} ; do - datafile="${{datafilename##*/}}" # get filename without path - outdatafile=${{datafile%.*}} # get filename without suffix - cat > NAMELIST_ICONREMAP_lbc_{cfg.startdate_sim_yyyymmddhh} << EOF_2C -&remap_nml - in_grid_filename = '{cfg.meteo_dir}/{cfg.meteo_prefix}{cfg.startdate_sim_yyyymmddhh}{cfg.meteo_suffix}' - in_filename = '{cfg.meteo_dir}/${{datafile}}' - in_type = 1 - out_grid_filename = '{cfg.input_files_scratch_lateral_boundary_grid}' - out_filename = '{cfg.icon_input_icbc}/${{outdatafile}}_lbc.nc' - out_type = 2 - out_filetype = 4 - l_have3dbuffer = .false. -! ncstorage_file = "ncstorage.tmp_lbc_{cfg.startdate_sim_yyyymmddhh}" -/ -EOF_2C - - srun -n 1 {cfg.iconremap_bin} -q \ - --remap_nml NAMELIST_ICONREMAP_lbc_{cfg.startdate_sim_yyyymmddhh} \ - --input_field_nml NAMELIST_ICONREMAP_FIELDS_{cfg.startdate_sim_yyyymmddhh} 2>&1 - -done - -#----------------------------------------------------------------------------- -# clean-up - -rm -f nml.log -rm -f NAMELIST_ICONSUB_{cfg.startdate_sim_yyyymmddhh} NAMELIST_ICONREMAP_lbc_{cfg.startdate_sim_yyyymmddhh} NAMELIST_ICONREMAP_FIELDS_{cfg.startdate_sim_yyyymmddhh} - -#----------------------------------------------------------------------------- -exit -#----------------------------------------------------------------------------- - diff --git a/cases/icon-test-euler/icontools_remap_ic_runjob.cfg b/cases/icon-test-euler/icontools_remap_ic_runjob.cfg deleted file mode 100755 index f8d2275d..00000000 --- a/cases/icon-test-euler/icontools_remap_ic_runjob.cfg +++ /dev/null @@ -1,238 +0,0 @@ -#!/usr/bin/env bash -#SBATCH --job-name=iconremap_ic -#SBATCH --chdir={cfg.icon_work} -#SBATCH --partition={cfg.compute_queue} -#SBATCH --constraint={cfg.constraint} -#SBATCH --ntasks=1 -#SBATCH --output={logfile} -#SBATCH --open-mode=append - -ulimit -s unlimited - -set -x - -export ECCODES_DEFINITION_PATH={cfg.eccodes_dir}/definitions.edzw-2.12.5-2:{cfg.eccodes_dir}/definitions - -#----------------------------------------------------------------------------- -# Remap inital data onto local (limited-area) grid -#----------------------------------------------------------------------------- -cat > NAMELIST_ICONREMAP_FIELDS << EOF -! -&input_field_nml ! temperature - inputname = "T" - outputname = "T" - code = 130 - intp_method = 3 -/ -&input_field_nml ! horiz. wind comp. u - inputname = "U" - outputname = "U" - intp_method = 3 -/ -&input_field_nml ! horiz. wind comp. u - inputname = "V" - outputname = "V" - intp_method = 3 -/ -&input_field_nml ! vertical velocity - inputname = "OMEGA" - outputname = "W" - code = 135 - intp_method = 3 -/ -&input_field_nml ! surface pressure - inputname = "LNSP" - outputname = "LNPS" - code = 152 - intp_method = 3 -/ -&input_field_nml ! geopotential - inputname = "Z" - outputname = "GEOSP" - code = 129 - intp_method = 3 -/ -&input_field_nml ! geopotential - inputname = "Z" - outputname = "GEOP_SFC" - code = 129 - intp_method = 3 -/ -&input_field_nml ! specific humidity - inputname = "QV" - outputname = "QV" - code = 133 - intp_method = 3 -/ -&input_field_nml ! cloud liquid water content - inputname = "CLWC" - outputname = "QC" - code = 246 - intp_method = 3 -/ -&input_field_nml ! cloud ice water content - inputname = "CIWC" - outputname = "QI" - code = 247 - intp_method = 3 -/ -&input_field_nml ! rain water content - inputname = "CRWC" - outputname = "QR" - code = 75 - intp_method = 3 -/ -&input_field_nml ! snow water content - inputname = "CSWC" - outputname = "QS" - code = 76 - intp_method = 3 -/ -&input_field_nml ! snow temperature - inputname = "TSN" - outputname = "T_SNOW" - code = 238 - intp_method = 3 -/ -&input_field_nml ! water content of snow - inputname = "SD" - outputname = "W_SNOW" - code = 141 - intp_method = 3 -/ -&input_field_nml ! density of snow - inputname = "RSN" - outputname = "RHO_SNOW" - code = 33 - intp_method = 3 -/ -&input_field_nml ! snow albedo - inputname = "ASN" - outputname = "ALB_SNOW" - code = 32 - intp_method = 3 -/ -&input_field_nml ! skin temperature - inputname = "SKT" - outputname = "SKT" - code = 235 - intp_method = 3 -/ -&input_field_nml ! sea surface temperature - inputname = "SST" - outputname = "SST" - code = 34 - intp_method = 3 -/ -&input_field_nml ! soil temperature level 1 - inputname = "STL1" - outputname = "STL1" - code = 139 - intp_method = 3 -/ -&input_field_nml ! soil temperature level 2 - inputname = "STL2" - outputname = "STL2" - code = 170 - intp_method = 3 -/ -&input_field_nml ! soil temperature level 3 - inputname = "STL3" - outputname = "STL3" - code = 183 - intp_method = 3 -/ -&input_field_nml ! soil temperature level 4 - inputname = "STL4" - outputname = "STL4" - code = 236 - intp_method = 3 -/ -&input_field_nml ! sea-ice cover - inputname = "CI" - outputname = "CI" - code = 31 - intp_method = 3 -/ -&input_field_nml ! water cont. of interception storage - inputname = "SRC" - outputname = "W_I" - code = 198 - intp_method = 3 -/ -&input_field_nml ! surface roughness - inputname = "SR" - outputname = "Z0" - code = 173 - intp_method = 3 -/ -&input_field_nml ! Land/sea mask - inputname = "LSM" - outputname = "LSM" - code = 172 - intp_method = 3 -/ -&input_field_nml ! soil moisture index layer 1 - inputname = "SWVL1" - outputname = "SMIL1" - code = 80 - intp_method = 3 -/ -&input_field_nml ! soil moisture index layer 2 - inputname = "SWVL2" - outputname = "SMIL2" - code = 81 - intp_method = 3 -/ -&input_field_nml ! soil moisture index layer 3 - inputname = "SWVL3" - outputname = "SMIL3" - code = 82 - intp_method = 3 -/ -&input_field_nml ! soil moisture index layer 4 - inputname = "SWVL4" - outputname = "SMIL4" - code = 83 - intp_method = 3 -/ -EOF - -#----------------------------------------------------------------------------- -# loop over file list: - -datafilename={cfg.meteo_dir}/{cfg.meteo_prefix}{cfg.startdate_sim_yyyymmddhh}{cfg.meteo_suffix} -datafile="${{datafilename##*/}}" # get filename without path -outdatafile=${{datafile%.*}} # get filename without suffix - -# create ICON master namelist -# ------------------------ -# For a complete list see Namelist_overview and Namelist_overview.pdf - -cat > NAMELIST_ICONREMAP << EOF -&remap_nml - in_grid_filename = '{cfg.meteo_dir}/{cfg.meteo_prefix}{cfg.startdate_sim_yyyymmddhh}{cfg.meteo_suffix}' - in_filename = '{cfg.meteo_dir}/${{datafile}}' - in_type = 1 - out_grid_filename = '{cfg.input_files_scratch_dynamics_grid_filename}' - out_filename = '{cfg.icon_input_icbc}/${{outdatafile}}.nc' - out_type = 2 - out_filetype = 4 - l_have3dbuffer = .false. -/ -EOF - -srun -n 1 {cfg.iconremap_bin} \ - -vvvvv -q --remap_nml NAMELIST_ICONREMAP \ - --input_field_nml NAMELIST_ICONREMAP_FIELDS 2>&1 - - -#----------------------------------------------------------------------------- -# clean-up - -rm -f ncstorage.tmp* -rm -f nml.log NAMELIST_SUB NAMELIST_ICONREMAP NAMELIST_ICONREMAP_FIELDS - -#----------------------------------------------------------------------------- -exit -#----------------------------------------------------------------------------- diff --git a/cases/icon-test-euler/icontools_remap_lbc_rest_runjob.cfg b/cases/icon-test-euler/icontools_remap_lbc_rest_runjob.cfg deleted file mode 100755 index 7f1d7968..00000000 --- a/cases/icon-test-euler/icontools_remap_lbc_rest_runjob.cfg +++ /dev/null @@ -1,121 +0,0 @@ -#!/usr/bin/env bash -#SBATCH --job-name=iconremap_lbc -#SBATCH --chdir={cfg.icon_work} -#SBATCH --partition={cfg.compute_queue} -#SBATCH --constraint={cfg.constraint} -#SBATCH --ntasks=1 -#SBATCH --output={logfile} -#SBATCH --open-mode=append - -ulimit -s unlimited - -set -x - -export ECCODES_DEFINITION_PATH={cfg.eccodes_dir}/definitions.edzw-2.12.5-2:{cfg.eccodes_dir}/definitions - -#----------------------------------------------------------------------------- -# Extract boundary data -#----------------------------------------------------------------------------- - -rm -f ncstorage.tmp_lbc_{cfg.startdate_sim_yyyymmddhh}* - -cat > NAMELIST_ICONREMAP_FIELDS_{cfg.startdate_sim_yyyymmddhh} << EOF -! -&input_field_nml ! temperature - inputname = "T" - outputname = "T" - code = 130 - intp_method = 3 -/ -&input_field_nml ! horiz. wind comp. u - inputname = "U" - outputname = "U" - intp_method = 3 -/ -&input_field_nml ! horiz. wind comp. v - inputname = "V" - outputname = "V" - intp_method = 3 -/ -&input_field_nml ! vertical velocity - inputname = "OMEGA" - outputname = "W" - code = 135 - intp_method = 3 -/ -&input_field_nml ! surface pressure - inputname = "LNSP" - outputname = "LNPS" - code = 152 - intp_method = 3 -/ -&input_field_nml ! specific humidity - inputname = "QV" - outputname = "QV" - code = 133 - intp_method = 3 -/ -&input_field_nml ! cloud liquid water content - inputname = "CLWC" - outputname = "QC" - code = 246 - intp_method = 3 -/ -&input_field_nml ! cloud ice water content - inputname = "CIWC" - outputname = "QI" - code = 247 - intp_method = 3 -/ -&input_field_nml ! rain water content - inputname = "CRWC" - outputname = "QR" - code = 75 - intp_method = 3 -/ -&input_field_nml ! snow water content - inputname = "CSWC" - outputname = "QS" - code = 76 - intp_method = 3 -/ -EOF - -#----------------------------------------------------------------------------- -# loop over file list: - -echo "DATAFILELIST is {datafile_list_rest}" -for datafilename in {datafile_list_rest} ; do - datafile="${{datafilename##*/}}" # get filename without path - outdatafile=${{datafile%.*}} # get filename without suffix - cat > NAMELIST_ICONREMAP_lbc_{cfg.startdate_sim_yyyymmddhh} << EOF_2C -&remap_nml - in_grid_filename = '{cfg.meteo_dir}/{cfg.meteo_prefix}{cfg.startdate_sim_yyyymmddhh}{cfg.meteo_suffix}' - in_filename = '{cfg.meteo_dir}/${{datafile}}' - in_type = 1 - out_grid_filename = '{cfg.input_files_scratch_lateral_boundary_grid}' - out_filename = '{cfg.icon_input_icbc}/${{outdatafile}}_lbc.nc' - out_type = 2 - out_filetype = 4 - l_have3dbuffer = .false. -! ncstorage_file = "ncstorage.tmp_lbc_{cfg.startdate_sim_yyyymmddhh}" -/ -EOF_2C - - srun -n 1 {cfg.iconremap_bin} -q \ - --remap_nml NAMELIST_ICONREMAP_lbc_{cfg.startdate_sim_yyyymmddhh} \ - --input_field_nml NAMELIST_ICONREMAP_FIELDS_{cfg.startdate_sim_yyyymmddhh} 2>&1 - -done - -#----------------------------------------------------------------------------- -# clean-up - -#rm -f ncstorage.tmp_lbc_{cfg.startdate_sim_yyyymmddhh}* -rm -f nml.log -rm -f NAMELIST_ICONSUB_{cfg.startdate_sim_yyyymmddhh} NAMELIST_ICONREMAP_lbc_{cfg.startdate_sim_yyyymmddhh} NAMELIST_ICONREMAP_FIELDS_{cfg.startdate_sim_yyyymmddhh} - -#----------------------------------------------------------------------------- -exit -#----------------------------------------------------------------------------- - diff --git a/workflows.yaml b/workflows.yaml index abe778d7..4ccc5b9f 100644 --- a/workflows.yaml +++ b/workflows.yaml @@ -165,6 +165,24 @@ icon: previous: - icon +icon-global-era5: + features: + - restart + jobs: + - prepare_icon + - era5_ic + - icon + dependencies: + era5_ic: + current: + - prepare_icon + icon: + current: + - prepare_icon + - era5_ic + previous: + - icon + icon-art: features: - restart From 638fa24f80c864ae8ad2d797a6d0df00fe946088 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20J=C3=A4hn?= Date: Wed, 14 Jan 2026 16:26:05 +0100 Subject: [PATCH 09/16] Add ERA5 IC job --- jobs/era5_ic.py | 82 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 jobs/era5_ic.py diff --git a/jobs/era5_ic.py b/jobs/era5_ic.py new file mode 100644 index 00000000..0ecd6ff2 --- /dev/null +++ b/jobs/era5_ic.py @@ -0,0 +1,82 @@ +#!/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 + +def _compute_inidata_filename(cfg) -> Path: + """ + Replicate the same IC filename logic used by jobs/icon.py, + so that era5_ic produces *exactly* the file ICON will read. + """ + if hasattr(cfg, 'inicond_filename'): + return cfg.icon_input_icbc / cfg.inicond_filename + if (hasattr(cfg, 'inidata_prefix') and hasattr(cfg, 'inidata_nameformat') + and hasattr(cfg, 'inidata_filename_suffix')): + return cfg.icon_input_icbc / str( + cfg.startdate.strftime(cfg.inidata_prefix + + cfg.inidata_nameformat + + cfg.inidata_filename_suffix)) + # fallback: match icon.py default behavior + return cfg.icon_input_icbc / str( + cfg.startdate_sim.strftime(cfg.meteo['prefix'] + + cfg.meteo['nameformat']) + '.nc') + +def main(cfg): + """ + 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 + """ + + 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") + + # 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 + + # Compute the *exact* file that ICON will later read + inidata_filename = _compute_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") From ac08ab423aac31fa8a35cef360a1378762f9de57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20J=C3=A4hn?= Date: Wed, 14 Jan 2026 16:27:50 +0100 Subject: [PATCH 10/16] Modify ICON runjob --- cases/icon-test-euler/icon_runjob.cfg | 390 +++++++------------------- 1 file changed, 103 insertions(+), 287 deletions(-) diff --git a/cases/icon-test-euler/icon_runjob.cfg b/cases/icon-test-euler/icon_runjob.cfg index a2bfbb46..d881a0cc 100755 --- a/cases/icon-test-euler/icon_runjob.cfg +++ b/cases/icon-test-euler/icon_runjob.cfg @@ -8,38 +8,31 @@ #SBATCH --chdir={cfg.icon_work} set +x -ulimit -s unlimited +ulimit -s unlimited -# OpenMP environment variables -# ---------------------------- -export OMP_NUM_THREADS=1 -export ICON_THREADS=1 +# OpenMP environment variables +export OMP_NUM_THREADS=1 +export ICON_THREADS=1 export OMP_SCHEDULE=static -export OMP_DYNAMIC="false" -export OMP_STACKSIZE=200M -# -# MPI variables -# ------------- +export OMP_DYNAMIC="false" +export OMP_STACKSIZE=200M + +# MPI settings no_of_nodes=1 -mpi_procs_pernode={cfg.icon_np_tot} -((mpi_total_procs=no_of_nodes * mpi_procs_pernode)) -# -# blocking length -# --------------- +mpi_procs_pernode={cfg.icon_np_tot} +((mpi_total_procs=no_of_nodes * mpi_procs_pernode)) + +# blocking length nproma=64 # ---------------------------------------------------------------------------- -# create ICON master namelist +# ICON master namelist # ---------------------------------------------------------------------------- - cat > icon_master.namelist << EOF -! master_nml: ---------------------------------------------------------------- &master_nml - lrestart = {cfg.lrestart} ! .TRUE.=current experiment is resumed - read_restart_namelists = .true. + lrestart = {cfg.lrestart} + read_restart_namelists = .true. / - -! master_time_control_nml: --------------------------------------------------- &master_time_control_nml calendar = 'proleptic gregorian' restartTimeIntval = '{cfg.restart_step}' @@ -47,295 +40,118 @@ cat > icon_master.namelist << EOF experimentStartDate = '{cfg.ini_datetime_string}' experimentStopDate = '{cfg.end_datetime_string}' / - -! master_model_nml: repeated for each model ---------------------------------- &master_model_nml - model_type = 1 ! identifies which component to run (atmosphere,ocean,...) - model_name = "ATMO" ! character string for naming this component. - model_namelist_filename = "NAMELIST_{cfg.casename}" ! file name containing the model namelists - model_min_rank = 1 ! start MPI rank for this model - model_max_rank = 65536 ! end MPI rank for this model - model_inc_rank = 1 ! stride of MPI ranks + model_type = 1 + model_name = "ATMO" + model_namelist_filename = "NAMELIST_{cfg.casename}" + model_min_rank = 1 + model_max_rank = 65536 + model_inc_rank = 1 / EOF - -# ---------------------------------------------------------------------- -# model namelists -# ---------------------------------------------------------------------- - +# ---------------------------------------------------------------------------- +# Model namelist +# ---------------------------------------------------------------------------- cat > NAMELIST_{cfg.casename} << EOF -! parallel_nml: MPI parallelization ------------------------------------------- ¶llel_nml - nproma = 128 ! loop chunk length - p_test_run = .FALSE. ! .TRUE. means verification run for MPI parallelization - num_io_procs = {cfg.icon_np_io} ! number of I/O processors - num_restart_procs = {cfg.icon_np_restart} ! number of restart processors - num_prefetch_proc = {cfg.icon_np_prefetch} ! number of processors for LBC prefetching - iorder_sendrecv = 3 ! sequence of MPI send/receive calls + nproma = 128 + p_test_run = .FALSE. + num_io_procs = {cfg.icon_np_io} + num_restart_procs = {cfg.icon_np_restart} + num_prefetch_proc = {cfg.icon_np_prefetch} ! must be 0 for global IC-only + iorder_sendrecv = 3 / - - -! run_nml: general switches --------------------------------------------------- &run_nml - ltestcase = .FALSE. ! real case run - num_lev = 60 ! number of full levels (atm.) for each domain - lvert_nest = .FALSE. ! no vertical nesting - dtime = 60. ! timestep in seconds - ldynamics = .TRUE. ! compute adiabatic dynamic tendencies - ltransport = .TRUE. ! compute large-scale tracer transport - ntracer = 0 ! number of advected tracers - iforcing = 3 ! forcing of dynamics and transport by parameterized processes - msg_level = 13 ! detailed report during integration - ltimer = .TRUE. ! timer for monitoring the runtime of specific routines - timers_level = 10 ! performance timer granularity - check_uuid_gracefully = .TRUE. ! give only warnings for non-matching uuids - output = "nml" ! main switch for enabling/disabling components of the model output - lart = .FALSE. ! main switch for ART - debug_check_level = 10 - restart_filename = "{cfg.icon_restart_out}/{cfg.output_filename}_.nc" - activate_sync_timers = .TRUE. + ltestcase = .FALSE. + num_lev = 60 + lvert_nest = .FALSE. + dtime = 60. + ldynamics = .TRUE. + ltransport = .TRUE. + ntracer = 0 + iforcing = 3 + msg_level = 13 + ltimer = .TRUE. + timers_level = 10 + check_uuid_gracefully = .TRUE. + output = "nml" + lart = .FALSE. + debug_check_level = 10 + restart_filename = "{cfg.icon_restart_out}/{cfg.output_filename}_.nc" + activate_sync_timers = .TRUE. / - -! diffusion_nml: horizontal (numerical) diffusion ---------------------------- -&diffusion_nml - lhdiff_vn = .TRUE. ! diffusion on the horizontal wind field - lhdiff_temp = .TRUE. ! diffusion on the temperature field - lhdiff_w = .TRUE. ! diffusion on the vertical wind field - hdiff_order = 5 ! order of nabla operator for diffusion - itype_vn_diffu = 1 ! reconstruction method used for Smagorinsky diffusion - itype_t_diffu = 2 ! discretization of temperature diffusion - hdiff_efdt_ratio = 24.0 ! ratio of e-folding time to time step - hdiff_smag_fac = 0.025 ! scaling factor for Smagorinsky diffusion -/ - -! dynamics_nml: dynamical core ----------------------------------------------- &dynamics_nml - iequations = 3 ! type of equations and prognostic variables - divavg_cntrwgt = 0.50 ! weight of central cell for divergence averaging - lcoriolis = .TRUE. ! Coriolis force + iequations = 3 + divavg_cntrwgt = 0.50 + lcoriolis = .TRUE. / - -! extpar_nml: external data -------------------------------------------------- &extpar_nml - itopo = 1 ! topography (0:analytical) - extpar_filename = '{cfg.input_files_scratch_extpar_filename}' ! filename of external parameter input file - n_iter_smooth_topo = 1,1 ! iterations of topography smoother - heightdiff_threshold = 3000. ! height difference between neighb. grid points - hgtdiff_max_smooth_topo = 750.,750. ! see Namelist doc - heightdiff_threshold = 2250.,1500. + itopo = 1 + extpar_filename = '{cfg.input_files_scratch_extpar_filename}' + n_iter_smooth_topo = 1,1 + heightdiff_threshold = 3000. + hgtdiff_max_smooth_topo = 750.,750. / - -! initicon_nml: specify read-in of initial state ------------------------------ &initicon_nml - init_mode = 2 ! 7: start from DWD fg with subsequent vertical remapping - lread_ana = .FALSE. ! no analysis data will be read - ifs2icon_filename = "{inidata_filename}" ! initial data filename - ana_varnames_map_file = "{cfg.input_files_scratch_map_file_ana}" ! dictionary mapping internal names onto GRIB2 shortNames - ltile_coldstart = .TRUE. ! coldstart for surface tiles - ltile_init = .FALSE. ! set it to .TRUE. if FG data originate from run without tiles + init_mode = 2 + lread_ana = .FALSE. + ifs2icon_filename = "{inidata_filename}" ! produced by era5_ic job + ana_varnames_map_file = "{cfg.input_files_scratch_map_file_ana}" + ltile_coldstart = .TRUE. + ltile_init = .FALSE. / - -! grid_nml: horizontal grid -------------------------------------------------- &grid_nml - dynamics_grid_filename = "{cfg.input_files_scratch_dynamics_grid_filename}" ! array of the grid filenames for the dycore - radiation_grid_filename = "{cfg.input_files_scratch_radiation_grid_filename}" ! array of the grid filenames for the radiation model - dynamics_parent_grid_id = 0 ! array of the indexes of the parent grid filenames - lredgrid_phys = .TRUE. ! .true.=radiation is calculated on a reduced grid - lfeedback = .TRUE. ! specifies if feedback to parent grid is performed - l_limited_area = .TRUE. ! .TRUE. performs limited area run - ifeedback_type = 2 ! feedback type (incremental/relaxation-based) - start_time = 0. ! Time when a nested domain starts to be active [s] + dynamics_grid_filename = "{cfg.input_files_scratch_dynamics_grid_filename}" + radiation_grid_filename = "{cfg.input_files_scratch_dynamics_grid_filename}" + dynamics_parent_grid_id = 0 + lredgrid_phys = .TRUE. + l_limited_area = .FALSE. ! IMPORTANT: global mode / - -! gridref_nml: grid refinement settings -------------------------------------- -&gridref_nml - denom_diffu_v = 150. ! denominator for lateral boundary diffusion of velocity -/ - -! interpol_nml: settings for internal interpolation methods ------------------ -&interpol_nml - nudge_zone_width = 8 ! width of lateral boundary nudging zone - support_baryctr_intp = .FALSE. ! barycentric interpolation support for output - nudge_max_coeff = 0.07 - nudge_efold_width = 2.0 -/ - -! io_nml: general switches for model I/O ------------------------------------- &io_nml - itype_pres_msl = 5 ! method for computation of mean sea level pressure - itype_rh = 1 ! method for computation of relative humidity - lmask_boundary = .TRUE. ! mask out interpolation zone in output - restart_file_type = 5 + itype_pres_msl = 5 + itype_rh = 1 + restart_file_type = 5 / - -! limarea_nml: settings for limited area mode --------------------------------- -&limarea_nml - itype_latbc = 1 ! 1: time-dependent lateral boundary conditions - dtime_latbc = 10800 ! time difference between 2 consecutive boundary data - nlev_latbc = 90 ! Number of vertical levels in boundary data - latbc_boundary_grid = "{cfg.input_files_scratch_lateral_boundary_grid}" ! Grid file defining the lateral boundary - latbc_path = "{cfg.icon_input_icbc}" ! Absolute path to boundary data - latbc_varnames_map_file = "{cfg.input_files_scratch_map_file_latbc}" - latbc_filename = "{cfg.latbc_filename}" ! boundary data input filename - init_latbc_from_fg = .FALSE. ! .TRUE.: take lbc for initial time from first guess -/ - -! lnd_nml: land scheme switches ----------------------------------------------- -&lnd_nml - ntiles = 1 ! number of tiles - nlev_snow = 3 ! number of snow layers - lmulti_snow = .FALSE. ! .TRUE. for use of multi-layer snow model - idiag_snowfrac = 20 ! type of snow-fraction diagnosis - lsnowtile = .TRUE. ! .TRUE.=consider snow-covered and snow-free separately - itype_root = 2 ! root density distribution - itype_heatcond = 3 ! type of soil heat conductivity - itype_lndtbl = 4 ! table for associating surface parameters - itype_evsl = 4 ! type of bare soil evaporation - itype_root = 2 ! root density distribution - cwimax_ml = 5.e-4 ! scaling parameter for max. interception storage - c_soil = 1.75 ! surface area density of the evaporative soil surface - c_soil_urb = 0.5 ! same for urban areas - lseaice = .TRUE. ! .TRUE. for use of sea-ice model - llake = .TRUE. ! .TRUE. for use of lake model -/ - -! nonhydrostatic_nml: nonhydrostatic model ----------------------------------- -&nonhydrostatic_nml - iadv_rhotheta = 2 ! advection method for rho and rhotheta - ivctype = 2 ! type of vertical coordinate - itime_scheme = 4 ! time integration scheme - ndyn_substeps = 5 ! number of dynamics steps per fast-physics step - exner_expol = 0.333 ! temporal extrapolation of Exner function - vwind_offctr = 0.2 ! off-centering in vertical wind solver - damp_height = 12500.0 ! height at which Rayleigh damping of vertical wind starts - rayleigh_coeff = 1.5 ! Rayleigh damping coefficient - divdamp_order = 24 ! order of divergence damping - divdamp_type = 3 ! type of divergence damping - divdamp_fac = 0.004 ! scaling factor for divergence damping - igradp_method = 3 ! discretization of horizontal pressure gradient - l_zdiffu_t = .TRUE. ! specifies computation of Smagorinsky temperature diffusion - thslp_zdiffu = 0.02 ! slope threshold (temperature diffusion) - thhgtd_zdiffu = 125.0 ! threshold of height difference (temperature diffusion) - htop_moist_proc = 22500.0 ! max. height for moist physics - hbot_qvsubstep = 22500.0 ! height above which QV is advected with substepping scheme -/ - -! nwp_phy_nml: switches for the physics schemes ------------------------------ &nwp_phy_nml - inwp_gscp = 2 ! cloud microphysics and precipitation - inwp_convection = 1 ! convection - lshallowconv_only = .FALSE. ! only shallow convection - inwp_radiation = 1 ! radiation - inwp_cldcover = 1 ! cloud cover scheme for radiation - inwp_turb = 1 ! vertical diffusion and transfer - inwp_satad = 1 ! saturation adjustment - inwp_sso = 1 ! subgrid scale orographic drag - inwp_gwd = 0 ! non-orographic gravity wave drag - inwp_surface = 1 ! surface scheme - latm_above_top = .TRUE. ! take into account atmosphere above model top for radiation computation - ldetrain_conv_prec = .TRUE. - efdt_min_raylfric = 7200. ! minimum e-folding time of Rayleigh friction - itype_z0 = 2 ! type of roughness length data - icapdcycl = 3 ! apply CAPE modification to improve diurnalcycle over tropical land - icpl_aero_conv = 1 ! coupling between autoconversion and Tegen aerosol climatology - icpl_aero_gscp = 1 ! coupling between autoconversion and Tegen aerosol climatology - lrtm_filename = '{cfg.input_files_scratch_lrtm_filename}' ! longwave absorption coefficients for RRTM_LW - cldopt_filename = '{cfg.input_files_scratch_cldopt_filename}' ! RRTM cloud optical properties - dt_rad = 720. ! time step for radiation in s - dt_conv = 120.,90.,90. ! time step for convection in s (domain specific) - dt_sso = 120.,360.,360. ! time step for SSO parameterization - dt_gwd = 360.,360.,360. ! time step for gravity wave drag parameterization -/ - -! nwp_tuning_nml: additional tuning parameters ---------------------------------- -&nwp_tuning_nml - itune_albedo = 1 ! reduced albedo (w.r.t. MODIS data) over Sahara - tune_gkwake = 1.8 - tune_gkdrag = 0.01 - tune_minsnowfrac = 0.3 + inwp_gscp = 2 + inwp_convection = 1 + inwp_radiation = 1 + inwp_cldcover = 1 + inwp_turb = 1 + inwp_satad = 1 + inwp_sso = 1 + inwp_gwd = 0 + inwp_surface = 1 + latm_above_top = .TRUE. + efdt_min_raylfric = 7200. + itype_z0 = 2 + lrtm_filename = '{cfg.input_files_scratch_lrtm_filename}' + cldopt_filename = '{cfg.input_files_scratch_cldopt_filename}' + dt_rad = 720. + dt_conv = 120. + dt_sso = 120. + dt_gwd = 360. / - -! output_nml: specifies an output stream -------------------------------------- &output_nml - filetype = 4 ! output format: 2=GRIB2, 4=NETCDFv2 - dom = 1 ! write domain 1 only - output_bounds = 0., 10000000., 3600. ! start, end, increment - steps_per_file = 1 ! number of steps per file - mode = 1 ! 1: forecast mode (relative t-axis), 2: climate mode (absolute t-axis) - include_last = .TRUE. - output_filename = '{cfg.output_filename}' - filename_format = '{cfg.icon_output}/_DOM_' ! file name base - steps_per_file_inclfirst = .FALSE. - output_grid = .TRUE. - remap = 1 ! 1: remap to lat-lon grid - !north_pole = -170.,40. ! definition of north_pole for rotated lat-lon grid - reg_lon_def = -16.0,0.13,36.0 ! - reg_lat_def = 32.0,0.12,74.0 ! - ml_varlist = 'group:PBL_VARS', - 'group:ATMO_ML_VARS', - 'group:precip_vars', - 'group:land_vars', - 'group:nh_prog_vars', - 'z_mc', 'z_ifc', + filetype = 4 + dom = 1 + output_bounds = 0., 10000000., 3600. + steps_per_file = 1 + mode = 1 + include_last = .TRUE. + output_filename = '{cfg.output_filename}' + filename_format = '{cfg.icon_output}/_DOM_' + output_grid = .TRUE. + remap = 1 + reg_lon_def = -179.5,1.0,179.5 + reg_lat_def = 89.5,-1.0,-89.5 / - -! radiation_nml: radiation scheme --------------------------------------------- -&radiation_nml - irad_o3 = 7 ! ozone climatology - irad_aero = 6 ! aerosols - albedo_type = 2 ! type of surface albedo - vmr_co2 = 390.e-06 - vmr_ch4 = 1800.e-09 - vmr_n2o = 322.0e-09 - vmr_o2 = 0.20946 - vmr_cfc11 = 240.e-12 - vmr_cfc12 = 532.e-12 -/ - -! sleve_nml: vertical level specification ------------------------------------- -&sleve_nml - min_lay_thckn = 20.0 ! layer thickness of lowermost layer - top_height = 23000.0 ! height of model top - stretch_fac = 0.65 ! stretching factor to vary distribution of model levels - decay_scale_1 = 4000.0 ! decay scale of large-scale topography component - decay_scale_2 = 2500.0 ! decay scale of small-scale topography component - decay_exp = 1.2 ! exponent of decay function - flat_height = 16000.0 ! height above which the coordinate surfaces are flat -/ - -! transport_nml: tracer transport --------------------------------------------- -&transport_nml - npassive_tracer = 0 ! number of additional passive tracers - ivadv_tracer = 3, 3, 3, 3, 3, 3 ! tracer specific method to compute vertical advection - itype_hlimit = 3, 4, 4, 4, 4, 4 ! type of limiter for horizontal transport - ihadv_tracer = 52, 2, 2, 2, 2, 22 ! tracer specific method to compute horizontal advection - llsq_svd = .TRUE. ! use SV decomposition for least squares design matrix -/ - -! turbdiff_nml: turbulent diffusion ------------------------------------------- -&turbdiff_nml - tkhmin = 0.75 ! scaling factor for minimum vertical diffusion coefficient - tkmmin = 0.75 ! scaling factor for minimum vertical diffusion coefficient - pat_len = 750.0 ! effective length scale of thermal surface patterns - c_diff = 0.2 ! length scale factor for vertical diffusion of TKE - rat_sea = 7.5 ! controls laminar resistance for sea surface - rlam_heat = 1.5 - ltkesso = .TRUE. ! consider TKE-production by sub-grid SSO wakes - frcsmot = 0.2 ! these 2 switches together apply vertical smoothing of the TKE source terms - imode_frcsmot = 2 ! in the tropics (only), which reduces the moist bias in the tropical lower troposphere - itype_sher = 3 ! type of shear forcing used in turbulence - ltkeshs = .TRUE. ! include correction term for coarse grids in hor. shear production term - a_hshr = 2.0 ! length scale factor for separated horizontal shear mode - icldm_turb = 1 ! mode of cloud water representation in turbulence - ldiff_qi = .TRUE. -/ - EOF -# ---------------------------------------------------------------------- -# run the model! -# ---------------------------------------------------------------------- +# ---------------------------------------------------------------------------- +# Run ICON +# ---------------------------------------------------------------------------- source {cfg.chain_src_dir}/ext/icon/modules.env set -x -mpirun -n $mpi_total_procs ./icon +mpirun -n $mpi_total_procs ./{cfg.icon_execname} set +x From 32c5ef7e65b976ed8e1fd5ce22c81e07623c76ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20J=C3=A4hn?= Date: Wed, 14 Jan 2026 16:34:46 +0100 Subject: [PATCH 11/16] Add ERA5 IC runscript --- cases/icon-test-euler/era5_ic_runjob.cfg | 192 +++++++++++++++++++++++ 1 file changed, 192 insertions(+) create mode 100644 cases/icon-test-euler/era5_ic_runjob.cfg diff --git a/cases/icon-test-euler/era5_ic_runjob.cfg b/cases/icon-test-euler/era5_ic_runjob.cfg new file mode 100644 index 00000000..fbe2f24e --- /dev/null +++ b/cases/icon-test-euler/era5_ic_runjob.cfg @@ -0,0 +1,192 @@ +#!/usr/bin/env bash +#SBATCH --job-name=era5_ic_{cfg.casename}_{cfg.startdate_sim_yyyymmddhh} +#SBATCH --time={cfg.walltime_era5_ic} +#SBATCH --partition={cfg.compute_queue} +#SBATCH --constraint={cfg.constraint} +#SBATCH --ntasks=1 +#SBATCH --output={cfg.logfile} +#SBATCH --open-mode=append +#SBATCH --chdir={cfg.icon_work} + +# --------------------------------------------------------------------- +# ERA5 -> ICON initial conditions (GLOBAL, IC only) +# +# This script is submitted by jobs/era5_ic.py. +# It MUST write the final IC file exactly to: +# {inidata_filename} +# +# Design: +# - Use case config for input locations + partab +# - Use staged ICON files from prepare_icon (cfg.input_files_scratch_*) +# - Keep all intermediate files inside cfg.icon_work +# --------------------------------------------------------------------- +# +set -euo pipefail +set -x +ulimit -s unlimited + +# Optional: load modules needed for cdo/nco on Euler. +# Adjust these to your environment/stack. +module load stack/2024-06 || true +module load cdo/2.2.2 nco/5.1.6 netcdf-c/4.9.2 || true + +# --------------------------------------------------------------------- +# Inputs (from cfg) +# --------------------------------------------------------------------- +ERA5_DIR="{cfg.era5_dir}" +ERA5_ML="{cfg.era5_ml_filename}" +ERA5_SFC="{cfg.era5_sfc_filename}" +# Replace {ymd} placeholder using values prepared in era5_ic.py +ERA5_ML="${{ERA5_ML/\{ymd\}/{cfg.era5_ymd}}}" +ERA5_SFC="${{ERA5_SFC/\{ymd\}/{cfg.era5_ymd}}}" +PARTAB="{cfg.era5_partab}" +GRID_TRI="{cfg.input_files_scratch_dynamics_grid_filename}" +EXTPAR="{cfg.input_files_scratch_extpar_filename}" +OUTFILE="{inidata_filename}" + +# --------------------------------------------------------------------- +# Working directory cleanup +# --------------------------------------------------------------------- +work="{cfg.icon_work}/era5_ic_work" +mkdir -p "$work" +cd "$work" + +# --------------------------------------------------------------------- +# 1) GRIB preprocessing: pick first timestep and convert to NetCDF +# --------------------------------------------------------------------- +# +# Note: your colleague used splitsel,1; keep it to ensure we only have t0. +cdo splitsel,1 "${{ERA5_DIR}}/${{ERA5_ML}}" era5_ml_ +cdo splitsel,1 "${{ERA5_DIR}}/${{ERA5_SFC}}" era5_sfc_ + +# Find the produced split files (avoid hardcoding the exact suffix) +ml_grb="$(ls -1 era5_ml_* | head -n 1)" +sfc_grb="$(ls -1 era5_sfc_* | head -n 1)" +cdo -t ecmwf -f nc copy "$ml_grb" era5_ml.nc +cdo -t ecmwf -f nc copy "$sfc_grb" era5_sfc.nc +cdo merge era5_ml.nc era5_sfc.nc era5_original.nc + +# Rename variables / metadata to ICON-consistent naming via partab +# (Your partab is the "contract" between ERA5 and ICON naming expectations.) +cdo setpartabn,"$PARTAB",convert era5_original.nc tmp.nc + +# Order variables (helps reproducibility and easier diffs) +ncks tmp.nc data_in.nc +rm -f tmp.nc era5_ml.nc era5_sfc.nc era5_original.nc "$ml_grb" "$sfc_grb" + +# --------------------------------------------------------------------- +# 2) Build the ICON triangular grid description for CDO remapping +# --------------------------------------------------------------------- +cdo -s selgrid,1 "$GRID_TRI" triangular-grid.nc + +# --------------------------------------------------------------------- +# 3) Land/sea-aware remapping for sensitive surface variables +# --------------------------------------------------------------------- +# +# Input land-sea mask from renamed ERA5 data +cdo selname,LSM data_in.nc LSM_in.nc +ncrename -h -v LSM,FR_LAND LSM_in.nc + +# Output land fraction from EXTPAR +cdo selname,FR_LAND "$EXTPAR" LSM_out_tmp.nc + +# Add time dimension and align time coordinate +ncecat -O -u time LSM_out_tmp.nc LSM_out_tmp.nc +ncks -h -A -v time LSM_in.nc LSM_out_tmp.nc + +# Build land/ocean masks (input and output) +cdo -L setctomiss,0. -ltc,0.5 LSM_in.nc oceanmask_in.nc +cdo -L setctomiss,0. -gec,0.5 LSM_in.nc landmask_in.nc +cdo -L setctomiss,0. -ltc,0.5 LSM_out_tmp.nc oceanmask_out.nc +cdo -L setctomiss,0. -gec,0.5 LSM_out_tmp.nc landmask_out.nc +cdo setrtoc2,0.5,1.0,1,0 LSM_out_tmp.nc LSM_out.nc +rm -f LSM_in.nc LSM_out_tmp.nc + +# Variables defined only on sea +ncks -h -v SST,CI data_in.nc datasea_in.nc + +# Variables defined on both but should not mix land/sea +ncks -h -v SKT,STL1,STL2,STL3,STL4,ALB_SNOW,W_SNOW,T_SNOW data_in.nc dataland_in.nc + +# Ocean part: mask -> fill -> remap -> unmask +cdo div dataland_in.nc oceanmask_in.nc tmp1_land.nc +cdo div datasea_in.nc oceanmask_in.nc tmp1_sea.nc +cdo setmisstodis tmp1_land.nc tmp2_land.nc +cdo setmisstodis tmp1_sea.nc tmp2_sea.nc +cdo remapdis,triangular-grid.nc tmp2_land.nc tmp3_land.nc +cdo remapdis,triangular-grid.nc tmp2_sea.nc tmp3_sea.nc +cdo div tmp3_land.nc oceanmask_out.nc dataland_ocean_out.nc +cdo div tmp3_sea.nc oceanmask_out.nc datasea_ocean_out.nc +rm -f tmp*_land.nc tmp*_sea.nc oceanmask_in.nc oceanmask_out.nc + +# Land part: mask -> fill -> remap -> unmask +cdo div dataland_in.nc landmask_in.nc tmp1.nc +cdo setmisstodis tmp1.nc tmp2.nc +cdo remapdis,triangular-grid.nc tmp2.nc tmp3.nc +cdo div tmp3.nc landmask_out.nc dataland_land_out.nc +rm -f tmp*.nc landmask_in.nc landmask_out.nc dataland_in.nc datasea_in.nc + +# Merge land+ocean contributions +cdo ifthenelse LSM_out.nc dataland_land_out.nc dataland_ocean_out.nc dataland_out.nc +rm -f dataland_ocean_out.nc dataland_land_out.nc + +# Remap all remaining variables together +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 +cdo -s remapdis,triangular-grid.nc datarest_in.nc era5_final.nc +rm -f datarest_in.nc + +# Fill missing SST/CI after remap (sea-only fields) +cdo setmisstodis -selname,SST,CI datasea_ocean_out.nc datasea_ocean_out_filled.nc +rm -f datasea_ocean_out.nc + +# Merge special remapped variables + land fraction (renamed back to LSM) +ncks -h -A dataland_out.nc era5_final.nc +ncks -h -A datasea_ocean_out_filled.nc era5_final.nc +ncks -h -A -v FR_LAND LSM_out.nc era5_final.nc +ncrename -h -v FR_LAND,LSM era5_final.nc +rm -f LSM_out.nc dataland_out.nc datasea_ocean_out_filled.nc + +# --------------------------------------------------------------------- +# 4) Soil moisture index conversion (ERA5 SWVL -> ICON-style SMIL) +# --------------------------------------------------------------------- +# Extract soil moisture and soil type +ncks -h -v SMIL1,SMIL2,SMIL3,SMIL4,SLT data_in.nc swvl.nc +rm -f data_in.nc + +# IFS soil constants (documented in ERA5 data documentation) +wiltingp=(0 0.059 0.151 0.133 0.279 0.335 0.267 0.151) +fieldcap=(0 0.244 0.347 0.383 0.448 0.541 0.663 0.347) +smi_equation="" +for ilev in {1..4}; do + smi_equation="${smi_equation}SMIL${ilev}=(SMIL${ilev}-${wiltingp[1]})/(${fieldcap[1]}-${wiltingp[1]})*(SLT==1)" + for ist in {2..7}; do + smi_equation="${smi_equation}+(SMIL${ilev}-${wiltingp[$ist]})/(${fieldcap[$ist]}-${wiltingp[$ist]})*(SLT==${ist})" + done + smi_equation="${smi_equation};" +done +cdo expr,"${smi_equation}" swvl.nc smil_in.nc +rm -f swvl.nc + +# Remap SMIL to triangular grid and overwrite +cdo -s remapdis,triangular-grid.nc smil_in.nc smil_out.nc +ncks -A -v SMIL1,SMIL2,SMIL3,SMIL4 smil_out.nc era5_final.nc +rm -f smil_in.nc smil_out.nc + +# --------------------------------------------------------------------- +# 5) Create LNPS (log surface pressure) and finalize dimensions +# --------------------------------------------------------------------- +cdo expr,'LNPS=ln(PS);' era5_final.nc tmp.nc +ncks -A -v LNPS tmp.nc era5_final.nc +rm -f tmp.nc + +# ICON conventions: rename dimensions +ncrename -h -d cell,ncells era5_final.nc +ncrename -h -d nv,vertices era5_final.nc + +# Write final IC file to the exact path ICON will read later +mkdir -p "$(dirname "$OUTFILE")" +ncks era5_final.nc "$OUTFILE" + +# cleanup +rm -f era5_final.nc triangular-grid.nc +echo "Wrote ICON initial condition file: $OUTFILE" From dc7e7427798e3102c90e174ca22e549b5f81f7d1 Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 14 Jan 2026 15:35:13 +0000 Subject: [PATCH 12/16] GitHub Action: Apply Pep8-formatting --- jobs/era5_ic.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/jobs/era5_ic.py b/jobs/era5_ic.py index 0ecd6ff2..a6b51c05 100644 --- a/jobs/era5_ic.py +++ b/jobs/era5_ic.py @@ -1,6 +1,5 @@ #!/usr/bin/env python # -*- coding: utf-8 -*- - """ era5_ic.py Processing-chain job that generates ICON initial conditions (IC) from ERA5 input. @@ -19,8 +18,10 @@ import logging from pathlib import Path from . import tools, prepare_icon + BASIC_PYTHON_JOB = True + def _compute_inidata_filename(cfg) -> Path: """ Replicate the same IC filename logic used by jobs/icon.py, @@ -39,6 +40,7 @@ def _compute_inidata_filename(cfg) -> Path: cfg.startdate_sim.strftime(cfg.meteo['prefix'] + cfg.meteo['nameformat']) + '.nc') + def main(cfg): """ 1) Prepare standard ICON paths (same helper as other jobs) @@ -53,7 +55,8 @@ def main(cfg): prepare_icon.set_cfg_variables(cfg) tools.change_logfile(cfg.logfile) - logging.info("Generate global ICON initial conditions from ERA5 (IC only).") + 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). @@ -61,7 +64,7 @@ def main(cfg): tools.create_dir(cfg.icon_input_icbc, "icon_input_icbc") # 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_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 # Compute the *exact* file that ICON will later read @@ -69,7 +72,8 @@ def main(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_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, From 7b9ef4cf867d76820711583581effa5bc5eadc19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20J=C3=A4hn?= Date: Wed, 14 Jan 2026 16:37:06 +0100 Subject: [PATCH 13/16] Remove setup spack stage (included in build) --- jenkins/Jenkinsfile | 11 ---------- jenkins/scripts/setup-spack.sh | 38 ---------------------------------- 2 files changed, 49 deletions(-) delete mode 100755 jenkins/scripts/setup-spack.sh diff --git a/jenkins/Jenkinsfile b/jenkins/Jenkinsfile index ba296f34..b34b0b64 100644 --- a/jenkins/Jenkinsfile +++ b/jenkins/Jenkinsfile @@ -8,17 +8,6 @@ pipeline { } } stages { - stage('Setup spack') { - steps { - sh './jenkins/scripts/setup-spack.sh' - } - post { - failure { - echo 'Cleaning up workspace' - deleteDir() - } - } - } stage('Preparation') { parallel { stage('Setup miniconda') { diff --git a/jenkins/scripts/setup-spack.sh b/jenkins/scripts/setup-spack.sh deleted file mode 100755 index ccc10fde..00000000 --- a/jenkins/scripts/setup-spack.sh +++ /dev/null @@ -1,38 +0,0 @@ -#!/bin/bash - -set -e -x - -source jenkins/scripts/common.sh - -# Check if script is called correctly -[[ $(git rev-parse --show-toplevel 2>/dev/null) = $(pwd) ]] || error "$0 not launched from toplevel of repository" - -SPACK_TAG_COSMO=v0.18.1.12 - -if [[ $(hostname) == eu-* ]]; then - source /cluster/apps/local/env2lmod.sh - module load git - git clone --depth 1 git@gitlab.dkrz.de:icon/icon-model.git icon-tag - SPACK_TAG=`cat icon-tag/config/ethz/SPACK_TAG_EULER` - rm -fr icon-tag -elif [[ $(hostname) == santis* ]]; then - git clone --depth 1 git@gitlab.dkrz.de:icon/icon-model.git icon-tag - SPACK_TAG=`cat icon-tag/config/cscs/SPACK_TAG_SANTIS` - rm -fr icon-tag -else - error "Unknown hostname: $(hostname)" -fi - -GIT_REMOTE=https://github.com/C2SM/spack-c2sm.git - -rm -fr ext/spack-c2sm - -pushd ext - -# Clone Spack for ICON -git clone --depth 1 --recurse-submodules --shallow-submodules -b ${SPACK_TAG} ${GIT_REMOTE} spack-c2sm - -# Clone Spack for COSMO-GHG -git clone --depth 1 --recurse-submodules --shallow-submodules -b ${SPACK_TAG_COSMO} ${GIT_REMOTE} spack-c2sm-cosmo - -popd From 657dd2ca63b23e205ab4a6f56a128a8d5f0e5a4a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20J=C3=A4hn?= Date: Wed, 14 Jan 2026 16:42:00 +0100 Subject: [PATCH 14/16] Initialize era5_ic job --- jobs/__init__.py | 1 + 1 file changed, 1 insertion(+) diff --git a/jobs/__init__.py b/jobs/__init__.py index a3d75541..393e0ffb 100644 --- a/jobs/__init__.py +++ b/jobs/__init__.py @@ -5,6 +5,7 @@ from . import check_output from . import cosmo from . import emissions +from . import era5_ic from . import icon from . import icontools from . import int2lm From 03b5b10321df9f4affe95e7104825eb3095d1967 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20J=C3=A4hn?= Date: Wed, 14 Jan 2026 16:46:23 +0100 Subject: [PATCH 15/16] Add global_nudging parameter --- cases/icon-test-euler/config.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/cases/icon-test-euler/config.yaml b/cases/icon-test-euler/config.yaml index 35dffc72..19da7857 100644 --- a/cases/icon-test-euler/config.yaml +++ b/cases/icon-test-euler/config.yaml @@ -18,6 +18,7 @@ era5: dir: ./input/era5 ml_filename: "era5_ml_{ymd}.grib" sfc_filename: "era5_surf_{ymd}.grib" + global_nudging: False era5_partab: ./cases/icon-euler-test/partab_era5_to_icon.txt era5_ic_runjob_filename: era5_ic_runjob.cfg From e9c7fe03ed3cfd7610bf754a311b0bf6a0a23b2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michael=20J=C3=A4hn?= Date: Wed, 14 Jan 2026 16:53:01 +0100 Subject: [PATCH 16/16] Restructuring config --- cases/icon-test-euler/config.yaml | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/cases/icon-test-euler/config.yaml b/cases/icon-test-euler/config.yaml index 19da7857..f02fb174 100644 --- a/cases/icon-test-euler/config.yaml +++ b/cases/icon-test-euler/config.yaml @@ -8,6 +8,14 @@ ntasks_per_node: 12 restart_step: PT6H startdate: 2018-01-01T00:00:00Z enddate: 2018-01-01T12:00:00Z +era5_partab: ./cases/icon-euler-test/partab_era5_to_icon.txt +era5_ic_runjob_filename: era5_ic_runjob.cfg +inidata_prefix: "era5_init_R02B05_" +inidata_nameformat: "%Y%m%d%H" +inidata_filename_suffix: ".nc" +output_filename: icon-test-euler +filename_format: _DOM_ +lateral_boundary_grid_order: lateral_boundary walltime: prepare_icon: "00:10:00" @@ -20,12 +28,6 @@ era5: sfc_filename: "era5_surf_{ymd}.grib" global_nudging: False -era5_partab: ./cases/icon-euler-test/partab_era5_to_icon.txt -era5_ic_runjob_filename: era5_ic_runjob.cfg -inidata_prefix: "era5_init_R02B05_" -inidata_nameformat: "%Y%m%d%H" -inidata_filename_suffix: ".nc" - meteo: dir: ./input/meteo prefix: ifs_