Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
110 commits
Select commit Hold shift + click to select a range
e33ddb8
download_ERA5_input: add variables
jjokella Oct 22, 2025
a951af7
Merge branch 'main' into dev-all-vars-era5-download
jjokella Oct 22, 2025
a330115
Adapt `prepare_ERA5_input` for only using downloaded ERA5
jjokella Oct 23, 2025
f1206bb
Merge branch 'main' into dev-all-vars-era5-download
jjokella Oct 23, 2025
453b96f
add README
jjokella Nov 19, 2025
5b3d6e7
Merge branch 'main' into dev-all-vars-era5-download
jjokella Nov 26, 2025
c5150a4
docs update
jjokella Nov 26, 2025
73fbd91
download_ERA5_input script with descriptive options
jjokella Nov 26, 2025
7c84ec5
add request and dataset as options to `download_ERA5_input`
jjokella Nov 26, 2025
350cdcc
Adapt year, month and day in custom request to input values
jjokella Nov 26, 2025
d0ad203
revert to default request
jjokella Nov 26, 2025
143bebd
custom dataset input can also be read from request file
jjokella Nov 26, 2025
796d6dd
style
jjokella Nov 26, 2025
4467264
doc adaption
jjokella Nov 26, 2025
a7badf9
add custom request for ERA5
jjokella Nov 26, 2025
7850112
dewpoint to specific humidity
jjokella Nov 26, 2025
566f3cb
dewpoint_to_specific_humidity: make filename command line input
jjokella Nov 26, 2025
dd856e9
adapt prepare script for all-downloaded ERA5
jjokella Nov 26, 2025
b868b74
lmeteo: switch for using meteocloud data
jjokella Nov 26, 2025
a1230f3
small adpations
jjokella Nov 26, 2025
c4bdd4d
doc fix
jjokella Nov 26, 2025
12bf81f
unzip optional
jjokella Nov 26, 2025
f7da39d
custom request for seasonal forecast
jjokella Nov 26, 2025
a938a82
add link in custom ERA5 request
jjokella Nov 28, 2025
f65cf6c
custom request for SEAS5
jjokella Nov 28, 2025
11b0546
todos in custom request
jjokella Nov 28, 2025
7eba141
remove seas5 request (moved to own PR)
jjokella Nov 28, 2025
c466e27
whitespace removed
jjokella Dec 1, 2025
fe8b6a0
link in doc of python script
jjokella Dec 1, 2025
0b2d330
python script for 2m->10m conversion of t and q
jjokella Dec 1, 2025
eb7b605
use q10m, t10m in prepare-script
jjokella Dec 1, 2025
609eba0
document usage of 2m->10m script
jjokella Dec 1, 2025
78e0d4c
Merge branch 'main' into dev-seas5
jjokella Dec 2, 2025
f1be5b9
Merge branch 'main' into dev-all-vars-era5-download
jjokella Dec 2, 2025
d8b3f3f
typo
jjokella Dec 4, 2025
123d845
more precise task in SEAS5 request
jjokella Dec 4, 2025
5d44d1f
Merge branch 'dev-all-vars-era5-download' into dev-seas5
jjokella Dec 4, 2025
15c5ebe
script moving mslp to sp
jjokella Dec 4, 2025
58d26c8
update docstrings
jjokella Dec 4, 2025
717adf9
first drafts for conversion Python scripts
jjokella Dec 4, 2025
7c30fa7
Copernicus-Download-Script: More robust default file-target
jjokella Dec 5, 2025
60b9501
Merge branch 'dev-target' into dev-all-vars-era5-download
jjokella Dec 5, 2025
34bd34f
Merge branch 'dev-all-vars-era5-download' into dev-seas5
jjokella Dec 5, 2025
a0973ce
SEAS5-specialty for "day"-field in request
jjokella Dec 5, 2025
c8a63f6
concise leadtime_hour array
jjokella Dec 5, 2025
d0e100c
change naming scheme
jjokella Dec 5, 2025
8fabe1b
start leadtime_hour from 0
jjokella Dec 5, 2025
3010e3b
SEAS5 request for single-site (DE-RuS)
jjokella Dec 5, 2025
c8f1d7c
ERA5 request for single-site (DE-RuS)
jjokella Dec 5, 2025
713a0dc
prepare_ERA5_input: step for renaming "valid_time" to "time"
jjokella Dec 10, 2025
ba0ec5a
prepare_ERA5_input: simplify grep check for time / valid_time
jjokella Dec 10, 2025
121f9ef
much simplified renaming
jjokella Dec 10, 2025
2c714e9
renaming valid_time to time in a switch
jjokella Dec 10, 2025
82eedf6
default: no renaming of time dim/var
jjokella Dec 10, 2025
66201c4
Merge branch 'main' into dev-all-vars-era5-download
jjokella Dec 10, 2025
af29403
Merge branch 'dev-all-vars-era5-download' into dev-seas5
jjokella Dec 10, 2025
4a9a782
adapt wrapper to options
jjokella Dec 10, 2025
37bab6c
download_ERA5_input: if needed, parse year input from custom_request
jjokella Dec 10, 2025
e4062f2
download_ERA5_input: if needed, parse month input from custom_request
jjokella Dec 10, 2025
6bbf3fc
download_ERA5_input: optional input --day
jjokella Dec 10, 2025
ea0037a
change order
jjokella Dec 10, 2025
b1009f3
bugfix: do not rename dimension
jjokella Dec 10, 2025
91fab77
bugfix: add lwgtdsi and lgriddes to inputs
jjokella Dec 10, 2025
2b096f3
Merge branch 'main' into dev-seas5
jjokella Jan 15, 2026
01051e9
Merge branch 'dev-all-vars-era5-download' into dev-seas5
jjokella Jan 15, 2026
d6dc171
SEAS5: request has to be distributed along 3 files
jjokella Jan 15, 2026
2d32f43
mkforcing/seas5_daily_to_6hourly: first draft
jjokella Jan 16, 2026
7947f80
mslp_to_sp.py: Handling of time axis of SEAS5
jjokella Jan 16, 2026
7d03fac
docs: SEAS5 related docs page
jjokella Jan 18, 2026
8aa4da9
SEAS5: accumulated radiation -> flux conversion in 6-hourly step
jjokella Jan 18, 2026
d57d5c2
SEAS5: remapping script prepare_SEAS5_input.sh
jjokella Jan 18, 2026
ab1f294
docs: SEAS5 updates
jjokella Jan 18, 2026
b13b27c
mkforcing/seas5_daily_to_6hourly: output directory check
jjokella Jan 18, 2026
3c17be9
mkforcing/seas5_daily_to_6hourly: preserve original encodings
jjokella Jan 18, 2026
e754ff4
mkforcing/seas5_daily_to_6hourly: filter valid netCDF4 encodings
jjokella Jan 18, 2026
b203617
mkforcing/prepare_SEAS5_input: remove dimension number
jjokella Jan 19, 2026
3a6ceba
mkforcing/prepare_SEAS5_input: time var/dim renaming
jjokella Jan 19, 2026
3861d31
mkforcing/seas5_daily_to_6hourly: thermal radiation conversion
jjokella Jan 19, 2026
8f727be
mkforcing/seas5_daily_to_6hourly: different frequencies
jjokella Jan 19, 2026
22b0722
mkforcing/seas5_daily_to_6hourly: add `valid_time`
jjokella Jan 19, 2026
b7a75b2
mkforcing/seas5_daily_to_6hourly: fix error
jjokella Jan 19, 2026
2b1c181
mkforcing/seas5_daily_to_6hourly: valid_time as integer
jjokella Jan 19, 2026
76d5ce6
mkforcing/seas5_daily_to_6hourly: valid_time in hours
jjokella Jan 19, 2026
4080bec
mkforcing/seas5_daily_to_6hourly: bugfix
jjokella Jan 19, 2026
963dd6d
mkforcing/seas5_daily_to_6hourly: include zero hour
jjokella Jan 19, 2026
77905c8
docs: add `--include-hour-zero` to default command
jjokella Jan 20, 2026
a9b8040
mkforcing/seas5_daily_to_6hourly: tp to precipitation flux
jjokella Jan 20, 2026
5025b86
mkforcing/seas5_daily_to_6hourly: de-accumulated tp
jjokella Jan 20, 2026
63b679b
mkforcing/seas5_daily_to_6hourly: de-accumulated radiation vars
jjokella Jan 20, 2026
397c385
mkforcing/prepare_SEAS5_input: loop over all ens members
jjokella Jan 21, 2026
764e248
mkforcing/prepare_SEAS5_input: fixes
jjokella Jan 21, 2026
09607af
mkforcing/prepare_SEAS5_input: nens as input to script
jjokella Jan 21, 2026
27fba50
docs: add "SEAS5 atmospheric forcing" to toc
jjokella Feb 19, 2026
d8e96e9
dewpoint_to_specific_humidity: source Alduchov1996, parameters
jjokella Mar 16, 2026
f76ce42
Merge branch 'dev-all-vars-era5-download' into dev-seas5
jjokella Mar 16, 2026
a4d27d6
dewpoint_to_specific_humidity: source Alduchov1996, parameters
jjokella Mar 16, 2026
864f76a
Merge branch 'dev-all-vars-era5-download' into dev-seas5
jjokella Mar 16, 2026
e927c2b
Merge branch 'main' into dev-all-vars-era5-download
jjokella Apr 23, 2026
0a9b30a
Merge branch 'dev-all-vars-era5-download' into dev-seas5
jjokella Apr 23, 2026
cff3e56
Merge branch 'main' into dev-seas5
jjokella Apr 24, 2026
41414e2
run_atm_forcing_generator.sh: first draft for runscript
jjokella Apr 24, 2026
9c19e9e
run_atm_forcing_generator.sh: small changes
jjokella Apr 24, 2026
d2a14ed
run_atm_forcing_generator: make executable
jjokella Apr 24, 2026
50e4d26
pyproject.toml: setting the dependencies
jjokella Apr 24, 2026
7bdbed6
run_atm_forcing_generator: create pyvenv
jjokella Apr 24, 2026
1e2e9f0
run_atm_forcing_generator: anchored to SCRIPT_DIRect
jjokella Apr 24, 2026
5360813
mkforcing/download_ERA5_input.py: check custom_request file
jjokella Apr 24, 2026
9acf3d2
run_atm_forcing_generator.sh: fix custom_request paths
jjokella Apr 24, 2026
66edc70
SEAS5: custom-requests broader
jjokella Apr 24, 2026
8f3be57
SEAS5: add domainfile argument
jjokella May 17, 2026
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
2 changes: 2 additions & 0 deletions docs/INDEX.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ For an overview of the needed atmospheric forcing variables for eCLM see [Overvi

For the default creation of atmospheric forcing based on ERA5 data see [eCLM atmospheric forcing based on ERA5](era5forcing).

For the default creation of atmospheric forcing based on SEAS5 data see [eCLM atmospheric forcing based on SEAS5](seas5forcing).

For a Python script that validates eCLM atmospheric forcing files
specified in `datm_in` namelist and stream files see [Checking
Atmospheric Forcing](checkingforcing).
Expand Down
2 changes: 2 additions & 0 deletions docs/_toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ parts:
title: Overview atmospheric forcing
- file: users_guide/era5-forcing
title: ERA5 atmospheric forcing
- file: users_guide/seas5-forcing
title: SEAS5 atmospheric forcing
- file: users_guide/icon-forcing
title: ICON output atmospheric forcing
- file: users_guide/other-forcing
Expand Down
1 change: 1 addition & 0 deletions docs/users_guide/era5-forcing.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Source the provided environment file
source jsc.2024_Intel.sh
```

(era5forcing-download)=
### Download of ERA5 data

`download_ERA5_input.py` contains a prepared retrieval for the `cdsapi` python module.
Expand Down
121 changes: 121 additions & 0 deletions docs/users_guide/seas5-forcing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
(seas5forcing)=
# eCLM atmospheric forcing based on SEAS5

Start by sourcing the provided environment file

```
source jsc.2024_Intel.sh
```

Provide a Python virtual environment including all necessary modules,
in particular `cdsapi` for downloading. It is important to load or
activate the pyvenv after sourcing the environment file, since the
environment file loads Python modules itself.

First usage - creation of pyvenv:
```
python -m venv python_cdsapi
source python_cdsapi/bin/activate
pip install cdsapi
```

Existing pyvenv - activating the pyvenv:
```
source python_cdsapi/bin/activate
```

## Creation of forcing data from SEAS5

Creation of SEAS5 forcing files is adapted from the creation of ERA5
forcing files.

The folder `mkforcing/` contains the scripts that assist the SEAS5
retrieval.

```
cd mkforcing
```

### Download of SEAS5 data

`download_ERA5_input.py` contains a prepared retrieval for the cdsapi python module.

More about cdsapi can be found in [Download of ERA5
data](era5forcing-download).

Usage: Three separate commands have to be executed, one for constant
variables (orography), one for daily variables (e.g. total
precipitation) and one for 6-hourly variables (e.g. temperature).

For each type of output, a dedicated download directory is created.

A main adaption from ERA5 download is the specification of a
customized CDSAPI request using `--request`.

```bash
python download_ERA5_input.py --year <year> --month <month> --dirout cdsapidwn_SEAS5_const --request ../custom_request_SEAS5_const.py
python download_ERA5_input.py --year <year> --month <month> --dirout cdsapidwn_SEAS5_24h --request ../custom_request_SEAS5_24h.py
python download_ERA5_input.py --year <year> --month <month> --dirout cdsapidwn_SEAS5_06h --request ../custom_request_SEAS5_06h.py
```

**Note:** The wrapper script: `./download_ERA5_input_wrapper.sh` is
currently NOT SUPPORTED for SEAS5 download.


### Preparation of SEAS5 data: all variable to 06h

Next, we want to have all variables available in 6-hourly interval

- from constant: `z` has to be ported (same values as before)
- from daily: `strd`, `ssrd` (thermal, solar, each accumulated) and
`tp` (total precipitation), these values would have to be
distributed. For `tp` the value would be divided by four and
assigned to the four corresponding 6-hour intervals. For the
radiations, it would be zero in the first/last interval ("night")
and half the value in the middle two intervals, then converted
to flux (W/m²) by dividing by the time interval.

The script outputs radiation directly as flux variables (`flds`,
`fsds`) in W/m².

```bash
python seas5_daily_to_6hourly.py --const cdsapidwn_SEAS5_const/download_era5_2026_01.nc --daily cdsapidwn_SEAS5_24h/download_era5_2026_01.nc --hourly cdsapidwn_SEAS5_06h/download_era5_2026_01.nc --output cdsapidwn_SEAS5/download_era5_2026_01.nc --frequency 3 --include-hour-zero
```

### Preparation of SEAS5 data: correct input variables

Steps for preparing SEAS5 data as eCLM input data

1. Orography to elevation (adds a variable `elevation` to the netCDF
file)

```bash
python orography_to_elevation.py cdsapidwn_SEAS5/download_era5_2026_01.nc
```

2. Mean sea level pressure to surface pressure

```bash
python mslp_to_sp.py cdsapidwn_SEAS5/download_era5_2026_01.nc --elevation-var elevation
```

3. Humidity computed from dewpoint temperature and surface pressure

```
python dewpoint_to_specific_humidity.py cdsapidwn_SEAS5/download_era5_2026_01.nc
```

4. Temperature and Specific Humidity converted from 2m to 10m

```
python 2m_to_10m_conversion.py cdsapidwn_SEAS5/download_era5_2026_01.nc
```

### Preparation of SEAS5 data: Remapping, Data merging, CLM3.5


Check inputs and replace according to your case.

```
sh prepare_SEAS5_input.sh lwgtdis=true lgriddes=true wgtcaf=../wgtdis_era5caf_to_DE-RuS-$(date +%y%m%d).nc griddesfile=../griddes_DE-RuS_$(date +%y%m%d).txt iyear=2026 imonth=01 author="Johannes KELLER" email="jo.keller@fz-juelich.de" tmpdir=tmpdir pathdata=../cdsapidwn_SEAS5
```
38 changes: 38 additions & 0 deletions mkforcing/custom_request_SEAS5_06h.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
## Download for SEAS5 forecast variables
# https://cds.climate.copernicus.eu/datasets/seasonal-original-single-levels?tab=download

# 6-HOURLY VARIABLES

# Forecast for 7 months

# import cdsapi

dataset = "seasonal-original-single-levels"
request = {
"originating_centre": "ecmwf",
"system": "51",
"variable": [
# # constant
# "orography", # used to convert mslp to sp
# # 24-hourly
# "surface_thermal_radiation_downwards", # Unit conversion from accumulated value [J/m2] to mean rate [W/m2]
# "surface_solar_radiation_downwards", # Unit conversion from accumulated value [J/m2] to mean rate [W/m2]
# "total_precipitation",
# 6-hourly
"mean_sea_level_pressure", # convert to surface pressure, use elevation (hypsometric formula), surface geopotential height (orography)
"10m_u_component_of_wind",
"10m_v_component_of_wind",
"2m_temperature",
"2m_dewpoint_temperature",
],
"year": ["2025"],
"month": ["09"],
"day": ["01"],
"leadtime_hour": [str(h) for h in range(0, 5161, 6)],
"data_format": "netcdf",
"area": [50.870906+0.5, 6.4421445-0.5, 50.870906-0.5, 6.4421445+0.5] # Selhausen
# "area": [74, -42, 20, 69] # Europe
}

# client = cdsapi.Client()
# client.retrieve(dataset, request).download()
38 changes: 38 additions & 0 deletions mkforcing/custom_request_SEAS5_24h.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
## Download for SEAS5 forecast variables
# https://cds.climate.copernicus.eu/datasets/seasonal-original-single-levels?tab=download

# 24-HOURLY / DAILY VARIABLES

# Forecast for 7 months

# import cdsapi

dataset = "seasonal-original-single-levels"
request = {
"originating_centre": "ecmwf",
"system": "51",
"variable": [
# # constant
# "orography", # used to convert mslp to sp
# 24-hourly
"surface_thermal_radiation_downwards", # Unit conversion from accumulated value [J/m2] to mean rate [W/m2]
"surface_solar_radiation_downwards", # Unit conversion from accumulated value [J/m2] to mean rate [W/m2]
"total_precipitation",
# # 6-hourly
# "mean_sea_level_pressure", # convert to surface pressure, use elevation (hypsometric formula), surface geopotential height (orography)
# "10m_u_component_of_wind",
# "10m_v_component_of_wind",
# "2m_temperature",
# "2m_dewpoint_temperature",
],
"year": ["2025"],
"month": ["09"],
"day": ["01"],
"leadtime_hour": [str(h) for h in range(0, 5161, 6)],
"data_format": "netcdf",
"area": [50.870906+0.5, 6.4421445-0.5, 50.870906-0.5, 6.4421445+0.5] # Selhausen
# "area": [74, -42, 20, 69] # Europe
}

# client = cdsapi.Client()
# client.retrieve(dataset, request).download()
38 changes: 38 additions & 0 deletions mkforcing/custom_request_SEAS5_const.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
## Download for SEAS5 forecast variables
# https://cds.climate.copernicus.eu/datasets/seasonal-original-single-levels?tab=download

# CONSTANT VARIABLES

# Forecast for 7 months

# import cdsapi

dataset = "seasonal-original-single-levels"
request = {
"originating_centre": "ecmwf",
"system": "51",
"variable": [
# constant
"orography", # used to convert mslp to sp
# # 24-hourly
# "surface_thermal_radiation_downwards", # Unit conversion from accumulated value [J/m2] to mean rate [W/m2]
# "surface_solar_radiation_downwards", # Unit conversion from accumulated value [J/m2] to mean rate [W/m2]
# "total_precipitation",
# # 6-hourly
# "mean_sea_level_pressure", # convert to surface pressure, use elevation (hypsometric formula), surface geopotential height (orography)
# "10m_u_component_of_wind",
# "10m_v_component_of_wind",
# "2m_temperature",
# "2m_dewpoint_temperature",
],
"year": ["2025"],
"month": ["09"],
"day": ["01"],
"leadtime_hour": [str(h) for h in range(0, 5161, 6)],
"data_format": "netcdf",
"area": [50.870906+0.5, 6.4421445-0.5, 50.870906-0.5, 6.4421445+0.5] # Selhausen
# "area": [74, -42, 20, 69] # Europe
}

# client = cdsapi.Client()
# client.retrieve(dataset, request).download()
10 changes: 8 additions & 2 deletions mkforcing/download_ERA5_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,11 @@ def generate_datarequest(year, monthstr, days,
# Adapt year, month and day to input values
request["year"] = [str(year)]
request["month"] = [monthstr]
request["day"] = days
if dataset == "seasonal-original-single-levels":
# First day of month specified for SEAS5
request["day"] = ["01"]
else:
request["day"] = days

# Temporary filename w/o extension if not provided
auto_detect_extension = target is None
Expand All @@ -159,7 +163,7 @@ def generate_datarequest(year, monthstr, days,
extension = detect_file_type(target)

# Rename to final target with correct extension
final_target = f'{target}{extension}'
final_target = f'download_era5_{year}_{monthstr}{extension}'
os.rename(target, final_target)
target = final_target

Expand Down Expand Up @@ -230,6 +234,8 @@ def generate_datarequest(year, monthstr, days,
custom_request = None
custom_dataset = args.dataset
if args.request:
if not os.path.isfile(args.request):
raise FileNotFoundError(f"Custom request file not found: {args.request}")
import importlib.util
spec = importlib.util.spec_from_file_location("custom_request_module", args.request)
custom_module = importlib.util.module_from_spec(spec)
Expand Down
Loading
Loading